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

# Named volumes

> Persist data across deploys, and seed every preview from a snapshot of real data.

The top-level `volumes:` block declares persistent volumes your services can mount, Compose-style. A volume survives redeploys, and slipway seeds every new preview from the volume's latest snapshot — so reviewers get realistic, isolated data instead of an empty database.

```yaml theme={"system"}
volumes:
  pgdata: {}            # a named volume — capacity is set by your plan

services:
  db:
    image: postgres:16
    env:
      POSTGRES_PASSWORD: ${secret.PG_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
  api:
    build: { context: ./api }
    env:
      DATABASE_URL: postgres://postgres:${secret.PG_PASSWORD}@db:5432/postgres
```

Bring any image — Postgres, MySQL, a search index, an uploads folder. Slipway manages the **volume** and its **snapshots**, not your credentials.

## Declaring volumes

| Where        | Syntax                                                                                             |
| ------------ | -------------------------------------------------------------------------------------------------- |
| Top level    | `volumes:` → `pgdata:` — each key declares a named volume. Capacity is set by your plan, not here. |
| In a service | `volumes:` → `- pgdata:/path` — references a declared volume; the path must be absolute.           |

A volume mounted by two or more services is shared between them (this needs a cluster with shared-storage support).

## Sizing and the storage budget

Volume **capacity is set by your plan**, not in `slipway.yaml` — every volume is provisioned at your plan's default size. A `size:` key in the spec is **ignored** (the deploy logs a warning if it finds one); this keeps a single repo from reserving a huge slice of shared storage.

Your plan includes a total **storage budget** across every named volume, and slipway bills on the storage you **actually use** — the bytes written, not the volume's reserved size — so a half-empty volume only counts for what's in it. Watch usage in the sidebar's **Usage** panel and on **Settings → Billing**.

<Note>
  The budget only counts volumes on slipway's own cluster. Volumes on a [cluster you bring yourself](/clusters/byok) live on your storage and don't count.
</Note>

## How seeding works

There's no separate "base" database to manage — the snapshot history *is* the durable lineage:

1. **First deploy** — the volume comes up empty.
2. **Load data** — run your app and add data, or load a dump.
3. **Take a snapshot** — from the deployment page or `sw snapshot`.
4. **Every preview after that** — gets its own isolated copy, pre-seeded from the latest snapshot. A destructive migration in one PR never touches another.

Snapshots are manual — slipway never auto-snapshots, because the first deploy's volume is empty. Take one when there's data worth keeping.

## Snapshots

Each volume keeps a numbered history, newest first. Manage them from a deployment page (**Snapshot now** + the history table) or the CLI:

```bash theme={"system"}
sw snapshot   <deployment-id> --volume pgdata --note "seed data"   # capture the live volume
sw snapshots  <repo-id>       --volume pgdata                       # list history
sw restore    <deployment-id> --volume pgdata --snapshot 3          # revert in place
```

`sw restore` reverts a deployment's live volume to an earlier snapshot. It takes a safety snapshot of the current state first, so the revert is itself undoable. Retention follows your plan (default 10 per volume) — the oldest are pruned past the cap, and the latest is never pruned.

<Warning>
  Slipway snapshots whatever is on the volume. If you load production data, it ends up in every preview seeded from that snapshot — sanitise on the way in. Slipway is a preview tool, not a backup tool.
</Warning>

## Any engine works

Seeding is a raw block-level copy, so slipway doesn't need to understand the engine — Postgres, MySQL, Mongo, SQLite-on-disk, a Lucene index, or a plain uploads folder all snapshot and restore identically. Mount the volume wherever the image writes.

## Limitations

* **Snapshots need snapshot-capable storage.** On a cluster without it (e.g. local `k3d`), volumes still work but **Snapshot now** degrades gracefully with a clear message.
* **One replica.** A volume-mounted service runs at a single replica.
* **Per-repo lineage.** Snapshot history belongs to a `(repo, volume)` pair; cross-repo snapshot sharing isn't available.
* **No anonymisation tooling.** Sanitise data on the way in, not after.
