{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://www.rubyschema.org/rails/database.json",
  "title": "Rails Database Configuration",
  "markdownDescription": "Configures database connections for Rails applications. Each top-level key represents an environment (development, test, production, etc.) that can contain either a single database configuration or multiple named database configurations for multi-database setups.\n\nSee the [Rails Guide](https://guides.rubyonrails.org/configuring.html#configuring-a-database) for more information.",
  "type": "object",
  "definitions": {
    "erb": {
      "type": "string",
      "pattern": "^<%=.*%>$"
    },
    "environment": {
      "title": "Database environment",
      "markdownDescription": "A database environment can contain either a single database configuration directly, or multiple named database configurations (e.g., `primary`, `replica`, `cache`) for multi-database setups.",
      "additionalProperties": { "$ref": "#/definitions/database" }
    },
    "database": {
      "title": "Database",
      "markdownDescription": "Database connection configuration. All adapter-specific options are passed through to the underlying database client library.\n\nSee the [Rails Guide](https://guides.rubyonrails.org/configuring.html#configuring-a-database) for more information.",
      "type": "object",
      "properties": {
        "adapter": {
          "markdownDescription": "The database adapter to use. Common values include:\n\n- `postgresql` - PostgreSQL\n- `mysql2` - MySQL/MariaDB\n- `sqlite3` - SQLite\n- `trilogy` - MySQL using the Trilogy client",
          "type": "string",
          "examples": ["postgresql", "mysql2", "sqlite3", "trilogy"]
        },
        "url": {
          "markdownDescription": "Complete database URL in the format `adapter://[username[:password]@]host[:port]/database[?param1=value1&...]`\n\nWhen specified, individual connection parameters (host, port, etc.) can be omitted. The URL can also be read from an environment variable.",
          "type": "string",
          "examples": [
            "postgresql://localhost/blog_development",
            "mysql2://root:password@127.0.0.1:3306/app_production?encoding=utf8mb4",
            "<%= ENV['DATABASE_URL'] %>"
          ]
        },
        "host": {
          "markdownDescription": "Database server hostname or IP address.\n\nFor PostgreSQL, defaults to a Unix-domain socket in /tmp. On machines without Unix-domain sockets, defaults to localhost.",
          "type": "string",
          "examples": ["localhost", "127.0.0.1", "db.example.com"]
        },
        "port": {
          "markdownDescription": "Database server port number.\n\nDefaults:\n- PostgreSQL: 5432\n- MySQL: 3306\n- SQLite: N/A (file-based)",
          "anyOf": [{ "type": "integer" }, { "$ref": "#/definitions/erb" }],
          "examples": [3306, 5432]
        },
        "database": {
          "markdownDescription": "The name of the database to connect to.\n\nFor SQLite, this is the path to the database file (e.g., `storage/development.sqlite3`).",
          "type": "string",
          "examples": [
            "myapp_development",
            "blog_production",
            "storage/development.sqlite3"
          ]
        },
        "username": {
          "markdownDescription": "Database username for authentication.",
          "type": "string",
          "examples": ["deploy", "root", "postgres"]
        },
        "password": {
          "markdownDescription": "Database password for authentication.\n\nIt's recommended to use ERB to read this from an environment variable rather than committing it to version control.",
          "type": "string",
          "examples": ["<%= ENV['DATABASE_PASSWORD'] %>"]
        },
        "pool": {
          "markdownDescription": "Maximum number of database connections in the connection pool.\n\nA connection pool synchronizes thread access to a limited number of database connections. This value should be at least the number of threads your server manages.\n\nFor Puma, this typically should match or exceed `max_threads`. Default is 5.",
          "anyOf": [{ "type": "integer" }, { "$ref": "#/definitions/erb" }],
          "default": 5,
          "examples": [5, 25]
        },
        "timeout": {
          "markdownDescription": "Timeout in milliseconds for acquiring a connection from the pool.\n\nIf a connection cannot be obtained within this time, an error is raised. Default is 5000ms (5 seconds).",
          "anyOf": [{ "type": "integer" }, { "$ref": "#/definitions/erb" }],
          "default": 5000,
          "examples": [5000, 10000]
        },
        "checkout_timeout": {
          "markdownDescription": "Alias for `timeout`. Timeout in seconds for acquiring a connection from the pool.",
          "anyOf": [{ "type": "number" }, { "$ref": "#/definitions/erb" }],
          "examples": [5, 10]
        },
        "encoding": {
          "markdownDescription": "Character encoding to use for the database connection.\n\n- PostgreSQL: Sets `client_encoding` (e.g., `unicode`, `utf8`)\n- MySQL: Sets connection encoding (e.g., `utf8mb4`)\n- SQLite: Sets pragma encoding",
          "type": "string",
          "examples": ["unicode", "utf8", "utf8mb4"]
        },
        "socket": {
          "markdownDescription": "Path to a Unix domain socket for the database connection.\n\nUsed instead of `host` and `port` for local connections. Common for MySQL on many systems.",
          "type": "string",
          "examples": ["/tmp/mysql.sock", "/var/run/postgresql"]
        },
        "migrations_paths": {
          "markdownDescription": "Directory containing migrations for this database, relative to `db/`.\n\nUseful for multi-database setups where each database has its own set of migrations (e.g., `db/primary_migrate`, `db/cache_migrate`).",
          "type": "string",
          "examples": ["primary_migrate", "cache_migrate"]
        },
        "schema_search_path": {
          "markdownDescription": "PostgreSQL-specific: Comma-separated list of schemas to search when a table name is referenced without a schema qualifier.\n\nSets the `search_path` connection variable.",
          "type": "string",
          "examples": ["public,shared", "myapp,public"]
        },
        "prepared_statements": {
          "markdownDescription": "Enable or disable prepared statements for the connection.\n\nDefault is `true`. Disabling can be useful when using PgBouncer in transaction pooling mode.",
          "anyOf": [{ "type": "boolean" }, { "$ref": "#/definitions/erb" }],
          "default": true
        },
        "advisory_locks": {
          "markdownDescription": "PostgreSQL-specific: Enable or disable advisory locks.\n\nAdvisory locks are used by Active Record for database-level locking during migrations. Default is `true`.\n\nSet to `false` when using PgBouncer in transaction pooling mode, as it doesn't support advisory locks.",
          "anyOf": [{ "type": "boolean" }, { "$ref": "#/definitions/erb" }],
          "default": true
        },
        "statement_limit": {
          "markdownDescription": "PostgreSQL-specific: Maximum number of prepared statements to cache per connection.\n\nDefault is 1000. Lower this if you encounter \"prepared statement name is already in use\" errors.",
          "anyOf": [{ "type": "integer" }, { "$ref": "#/definitions/erb" }],
          "default": 1000,
          "examples": [200, 500, 1000]
        },
        "variables": {
          "markdownDescription": "Hash of session variables to set on connection establishment.\n\nFor PostgreSQL, these are set using `SET SESSION key = value`. For MySQL, these are set using `SET @@SESSION.key = value`.",
          "type": "object",
          "additionalProperties": {
            "anyOf": [
              { "type": "string" },
              { "type": "number" },
              { "type": "boolean" },
              { "$ref": "#/definitions/erb" }
            ]
          },
          "examples": [{ "statement_timeout": 5000 }, { "time_zone": "UTC" }]
        },
        "reaping_frequency": {
          "markdownDescription": "Frequency in seconds to periodically run the connection reaper.\n\nThe reaper removes inactive connections from the pool. Default is `nil` (disabled).\n\nUseful in environments where connections may be killed by the database server after inactivity.",
          "anyOf": [
            { "type": "number" },
            { "type": "null" },
            { "$ref": "#/definitions/erb" }
          ],
          "examples": [60, 300]
        },
        "connection_retries": {
          "markdownDescription": "Number of times to retry establishing an initial database connection before giving up.\n\nDefault is 1 (no retries). Useful when the database might not be immediately available on application startup.",
          "anyOf": [{ "type": "integer" }, { "$ref": "#/definitions/erb" }],
          "default": 1,
          "examples": [1, 5, 10]
        },
        "retry_deadline": {
          "markdownDescription": "Maximum time in seconds to spend retrying failed connection attempts.\n\nIf set, Rails will keep retrying connections that fail with connection errors until this deadline is reached. Works in conjunction with `connection_retries`.",
          "anyOf": [
            { "type": "number" },
            { "type": "null" },
            { "$ref": "#/definitions/erb" }
          ],
          "examples": [5, 30, 60]
        },
        "idle_timeout": {
          "markdownDescription": "Time in seconds after which idle connections in the pool may be closed.\n\nDefault is 300 seconds (5 minutes). Set to `nil` to disable.",
          "anyOf": [
            { "type": "number" },
            { "type": "null" },
            { "$ref": "#/definitions/erb" }
          ],
          "default": 300,
          "examples": [300, 600]
        },
        "query_cache": {
          "markdownDescription": "Enable or disable query caching for this database connection.\n\nWhen enabled (default), identical queries within the same request return cached results. Default is `true`.",
          "anyOf": [{ "type": "boolean" }, { "$ref": "#/definitions/erb" }],
          "default": true
        },
        "replica": {
          "markdownDescription": "Indicates this configuration is for a read replica.\n\nSet to `true` for replica databases in a multi-database setup. Rails will route read queries to replicas when configured.",
          "anyOf": [{ "type": "boolean" }, { "$ref": "#/definitions/erb" }],
          "examples": [true, false]
        },
        "sslmode": {
          "markdownDescription": "PostgreSQL-specific: SSL mode for the connection.",
          "type": "string",
          "enum": [
            "disable",
            "allow",
            "prefer",
            "require",
            "verify-ca",
            "verify-full"
          ],
          "markdownEnumDescriptions": [
            "No SSL connection attempted.",
            "Try non-SSL first, then SSL if that fails.",
            "Try SSL first, then non-SSL if that fails (default).",
            "Require SSL connection. Verify that the server certificate is issued by a trusted CA.",
            "Require SSL and verify that the server certificate is issued by a trusted certificate authority.",
            "Require SSL, verify the CA, and verify that the server certificate hostname matches the connection hostname."
          ]
        },
        "sslcert": {
          "markdownDescription": "PostgreSQL-specific: Path to the client SSL certificate file.",
          "type": "string",
          "examples": ["/path/to/client-cert.pem"]
        },
        "sslkey": {
          "markdownDescription": "PostgreSQL-specific: Path to the client SSL private key file.",
          "type": "string",
          "examples": ["/path/to/client-key.pem"]
        },
        "sslrootcert": {
          "markdownDescription": "PostgreSQL-specific: Path to the root SSL certificate authority (CA) file.",
          "type": "string",
          "examples": ["/path/to/ca-cert.pem"]
        },
        "insert_returning": {
          "markdownDescription": "PostgreSQL-specific: Control the use of `RETURNING` clause for `INSERT` statements.\n\nDefault is `true`. When enabled, Rails retrieves the inserted record's values in a single query.",
          "anyOf": [{ "type": "boolean" }, { "$ref": "#/definitions/erb" }],
          "default": true
        },
        "min_messages": {
          "markdownDescription": "PostgreSQL-specific: Minimum message severity level to display. Sets the `client_min_messages` session parameter.",
          "type": "string",
          "enum": [
            "debug5",
            "debug4",
            "debug3",
            "debug2",
            "debug1",
            "log",
            "notice",
            "warning",
            "error"
          ],
          "markdownEnumDescriptions": [
            "Most verbose debugging output.",
            "Verbose debugging output.",
            "Detailed debugging output.",
            "Moderate debugging output.",
            "Basic debugging output.",
            "Log messages for database administrators.",
            "Helpful notices and informational messages.",
            "Warning messages about potential problems.",
            "Only error messages (suppresses all lower severity)."
          ]
        },
        "connect_timeout": {
          "markdownDescription": "Maximum time in seconds to wait while establishing a connection to the database server.\n\nDefault varies by adapter. For PostgreSQL, default is system-dependent (often no timeout).",
          "anyOf": [{ "type": "integer" }, { "$ref": "#/definitions/erb" }],
          "examples": [5, 10, 30]
        },
        "read_timeout": {
          "markdownDescription": "MySQL-specific: Maximum time in seconds to wait for data from the server after a query is sent.",
          "anyOf": [{ "type": "integer" }, { "$ref": "#/definitions/erb" }],
          "examples": [5, 10, 30]
        },
        "write_timeout": {
          "markdownDescription": "MySQL-specific: Maximum time in seconds to wait when writing data to the server.",
          "anyOf": [{ "type": "integer" }, { "$ref": "#/definitions/erb" }],
          "examples": [5, 10, 30]
        },
        "reconnect": {
          "markdownDescription": "MySQL-specific: Whether to automatically reconnect if the connection is lost.\n\nDefault is `false`. Not recommended as it can mask connection issues.",
          "anyOf": [{ "type": "boolean" }, { "$ref": "#/definitions/erb" }],
          "default": false
        },
        "strict": {
          "markdownDescription": "MySQL-specific: Enable strict SQL mode.\n\nDefault is `true`. When enabled, MySQL rejects invalid data and raises errors instead of warnings.",
          "anyOf": [{ "type": "boolean" }, { "$ref": "#/definitions/erb" }],
          "default": true
        },
        "flags": {
          "markdownDescription": "MySQL-specific: Bitmask of MySQL client flags to set.\n\nSee MySQL documentation for available flags. Rarely needed in typical applications.",
          "anyOf": [{ "type": "integer" }, { "$ref": "#/definitions/erb" }]
        }
      },
      "required": ["adapter"]
    }
  },
  "properties": {
    "default": {
      "markdownDescription": "Shared configuration that can be inherited by other environments using YAML anchors and aliases (e.g., `<<: *default`).\n\nCan contain either a single database configuration or multiple named configurations.",
      "oneOf": [
        { "$ref": "#/definitions/environment" },
        { "$ref": "#/definitions/database" }
      ]
    },
    "production": {
      "markdownDescription": "Configuration for the production environment.\n\nCan contain either a single database configuration or multiple named configurations (e.g., `primary`, `replica`).",
      "oneOf": [
        { "$ref": "#/definitions/environment" },
        { "$ref": "#/definitions/database" }
      ]
    },
    "development": {
      "markdownDescription": "Configuration for the development environment.\n\nCan contain either a single database configuration or multiple named configurations.",
      "oneOf": [
        { "$ref": "#/definitions/environment" },
        { "$ref": "#/definitions/database" }
      ]
    },
    "test": {
      "markdownDescription": "Configuration for the test environment.\n\nCan contain either a single database configuration or multiple named configurations.",
      "oneOf": [
        { "$ref": "#/definitions/environment" },
        { "$ref": "#/definitions/database" }
      ]
    }
  },
  "additionalProperties": {
    "markdownDescription": "Custom environment configuration (e.g., `staging`, `qa`).\n\nCan contain either a single database configuration or multiple named configurations.",
    "oneOf": [
      { "$ref": "#/definitions/environment" },
      { "$ref": "#/definitions/database" }
    ]
  }
}
