> ## 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.

# Deploy an app with Postgres

> Wire an app to a managed database without committing a connection string.

A managed database is an ordinary service in your project. Your app reaches it by name, and
the connection string is resolved at deploy time rather than committed.

## The whole thing

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

databases:
  - name: db
    engine: postgres
    version: "18"
    diskSizeGB: 20
    memory: 2GB

services:
  - name: api
    runtime: docker
    dependsOn: [db]
    preDeploy: ["npm", "run", "migrate"]
    ports:
      - port: 8080
        public: true
    healthCheckPath: /healthz
    env:
      DATABASE_URL: ${service.db.url}
```

That is the complete spec. Deploying it creates the database, generates a password, attaches
a 20 GB disk, brings the database up, runs your migrations, and then starts the API.

## What each piece does

| Field | Effect |
| - | - |
| `databases:` | Declares a managed database. slipway pins the image, mounts the disk at the engine's data path and generates credentials. |
| `${service.db.url}` | Resolves to `postgresql://postgres:<password>@db:5432/<database>` at deploy time. Nothing is committed. |
| `dependsOn: [db]` | Holds the API back until the database is ready. |
| `preDeploy` | Runs migrations in the freshly built image. The deploy proceeds only on exit 0. |

## The generated password

The first deploy generates a password and stores it as the project secret `DB_PASSWORD`,
named after the database. Later deploys reuse it.

Reference it directly if your app needs it apart from the URL:

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

You can read and rotate it from the database's **Credentials** tab.

## Connecting from your machine

External access is off by default. Turn it on from the database's Connection card and
connect over TLS:

```bash theme={"system"}
psql "postgresql://postgres:<password>@<service>-<id8>-pg.db.<zone>:5432/<database>?sslmode=require"
```

See [Postgres](/data/postgres#external-access).

## Backups

The disk is backed up on a schedule and restorable in place from the **Disks** tab.
Retention is measured in days and depends on your plan.

For a logical export, run `pg_dump` from a sibling service or over external access. See
[Disks](/data/disks).

## Previews get their own database

With [PR previews](/previews/pr-previews) on, each pull request gets a full copy of the
project, database included, seeded from the default snapshot when one is set. Preview code
never touches production data.

```yaml slipway.yaml theme={"system"}
previews:
  generation: automatic
```

## Sizing

Databases run with CPU reserved rather than burstable, so the allocation you pick is what
they get. Start at 1 GB of memory for a small app and watch the Metrics tab.

MySQL needs at least 1 GB and ClickHouse at least 2 GB. See
[CPU and memory](/services/compute).

## Next steps

> **[Postgres](/data/postgres)**
>
> Versions, roles, pgvector and external access.

> **[Disks](/data/disks)**
>
> Snapshots, backups and seeding a clone.


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