> ## Documentation Index
> Fetch the complete documentation index at: https://docs.slipway.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Databases

> Declare a managed Postgres, Redis, MySQL or ClickHouse in four lines.

A `databases:` entry declares a database the project needs. slipway pins the image, attaches
a disk, generates a password and wires it into the project like any other service.

```yaml slipway.yaml theme={"system"}
version: 1

databases:
  - name: db
    engine: postgres
    version: "18"
    diskSizeGB: 10

services:
  - name: api
    runtime: docker
    ports:
      - port: 8080
        public: true
    env:
      DATABASE_URL: ${service.db.url}
```

A database **is** a service. It takes a name in the project, siblings reach it by that name,
and it appears in the console with its own Credentials, Metrics and Backups tabs. Declaring
it under `databases:` rather than `services:` saves you the image tag, the credential
environment, the disk path and the readiness probe.

## Fields

| Field | Type | Required | Notes |
| - | - | - | - |
| `name` | string | **Required.** | The service name. Must not collide with a `services:` entry. |
| `engine` | string | **Required.** | `postgres`, `redis`, `mysql` or `clickhouse`. |
| `version` | string | Optional. | Defaults to the newest offered. `latest` is rejected. |
| `diskSizeGB` | int | **Required except on `redis`.** | Whole GB, up to 1024. |
| `cpu` | cores or millicores | Optional. | Defaults to 0.5 vCPU. |
| `memory` | memory | Optional. | Defaults to the engine's floor, or 512 MiB where it has none. |
| `highAvailability` | boolean | Optional. | Postgres and Redis. Runs a primary plus replicas with automatic failover. `cpu`, `memory` and `diskSizeGB` describe one member, and a disk is required. Can be changed on a live database. |
| `haMembers` | int | Optional. | How many copies `highAvailability` runs. Minimum 3, maximum 20, and 3 is the default. No requirement for an odd number. |
| `connectionPooling` | boolean | Optional. | Postgres only. Runs a PgBouncer pooler (transaction mode) in front of the database at `<name>-pool:5432`; siblings can wire `${service.<name>.pooled_url}`. No extra charge. Can be changed on a live database. |

Quote the version. Unquoted, YAML reads `8.0` as a number and loses the trailing zero.

## Engines

| Engine | `engine:` | Versions | Default | Port | Data path | Memory floor |
| - | - | - | - | - | - | - |
| Postgres | `postgres` | 18, 17, 16, 15 | 18 | 5432 | `/var/lib/postgresql` | 512 MiB |
| Redis | `redis` | 8 | 8 | 6379 | `/data` | 512 MiB |
| MySQL | `mysql` | 8.4, 8.0 | 8.4 | 3306 | `/var/lib/mysql` | 1 GiB |
| ClickHouse | `clickhouse` | 25.3, 24.8 | 25.3 | 8123 HTTP, 9000 native | `/var/lib/clickhouse` | 2 GiB |

`latest` is not a valid version. A managed database has to be reproducible, so the tag is
always pinned.

The memory floor is the smallest allocation the engine runs on. If you configure less,
the deploy fails rather than silently raising it.

`redis` is the only engine that may omit `diskSizeGB`, because a cache with no persistence
is a legitimate thing to want. Every other engine requires a disk, since a database that
loses its data on restart is rarely what anyone means.

An allocation below an engine's memory floor fails the parse and names the number, rather
than being raised silently. Raising it would increase what the service costs without you
choosing it.

## The password

The first deploy generates a strong password and stores it as a project secret named after
the database, uppercased: `db` becomes `DB_PASSWORD`, and `main-cache` becomes
`MAIN_CACHE_PASSWORD`. Later deploys reuse it.

The deploy records a `database_secret_provisioned` event naming the secret, never the value.
Nothing about the password is in your repository.

Reference it like any other secret if your app needs it separately from the connection
string:

```yaml slipway.yaml theme={"system"}
env:
  PGPASSWORD: ${secret.DB_PASSWORD}
```

With the right role you can read and rotate it from the database's **Credentials** tab.

## Connecting

A sibling reaches the database by bare name, and `${service.<name>.url}` resolves to a full
connection string with credentials already in it:

```yaml slipway.yaml theme={"system"}
services:
  - name: api
    runtime: docker
    env:
      DATABASE_URL: ${service.db.url}       # postgresql://postgres:...@db:5432/...
      CACHE_URL:    ${service.cache.url}    # redis://default:...@cache:6379
```

The individual pieces are available too: `host`, `port`, `user`, `password`, `database`, and
`external_url` once external access is on.

See the per-engine pages for what each contains: [Postgres](/data/postgres),
[Redis](/data/redis), [MySQL](/data/mysql), [ClickHouse](/data/clickhouse).

To make a service wait for the database before starting, name it in
[`dependsOn`](/slipway-yaml/services#dependson):

```yaml slipway.yaml theme={"system"}
services:
  - name: api
    runtime: docker
    dependsOn: [db]
```

## Version changes

A managed database keeps the version it was created with. The image tag and the on-disk data
format are the same decision, and an engine will not start against a data directory written
by a newer major version.

To move version, create a new instance on the new version and migrate the data into it with
the engine's own dump and restore tools.

## Data, backups and cost

The disk is an ordinary [disk](/data/disks). It survives redeploys, can be snapshotted and
restored in place, and can back itself up on a schedule. It can be grown later from the
service's Disks tab without a restart, but never shrunk.

You are billed for the database's compute allocation like any other service, plus its
provisioned storage.

A database is not exposed to the internet. External access is a deliberate toggle on its
console page, not something the spec turns on.

> [!NOTE]
>
> Declaring the same engine by hand under `services:` still works, with `image:`, a password
> env and a `disk:`. The `databases:` block is that, with the details filled in, and it is
> what the console's own Database page creates.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.