scale.addons.postgres.storage to an existing slot is rejected:
pg_dump and pg_restore, so the new deployment starts from your current data instead of replaying the chain from block zero.
First, find out what is actually using the space
The right fix depends on whether the disk holds data or dead weight.- A high
n_dead_tuprelative ton_live_tupmeans bloat, not data. Follow Update-heavy tables instead — tuningfillfactorand autovacuum fixes the cause, and this page only moves the problem to a new disk. - The database is genuinely much smaller than the disk — for example 100 Gb of data on a 700 Gb volume, usually the result of an earlier over-provision or a backfill that has since been cleaned up. That is what this page is for.
How the switch works
You never shrink anything in place. You stand up a second deployment, seed its database from the first, and then move your production tag across:1. Deploy the new slot without a processor
The new deployment must come up with an empty database and leave it alone. If migrations run first, they create tables that collide with the ones in your dump; if the processor starts first, it begins indexing from block zero and writes state you are about to overwrite. Suppress both in a temporary manifest:init: false skips migrations, because the dump already carries the full schema. The placeholder processor is required — every manifest needs one — but it must not touch the database.
Pin the Postgres version and set the disk you actually want:
deploy.addons.postgres.version to the same major version the source deployment runs. Changing the version on a slot later requires a hard reset, and the two databases must match for a clean restore.
squid.restore.yaml — complete temporary manifest
squid.restore.yaml — complete temporary manifest
slot: or tag: field so Cloud assigns a fresh slot:
2. Dump the source database
Use the directory format. Unlike a plain SQL file it supports parallel dump and restore, which is what keeps this practical as the database grows.--no-owner --no-privileges— the dump otherwise records the source deployment’s database role, which does not exist in the new deployment, and everyALTER ... OWNER TOfails on restore.--jobs— opens one connection per worker against a consistent snapshot. Keep it at or below the deployment’sexternal_access.max_connections.
--schema.
3. Restore into the new slot
--exit-on-error stops at the first failure rather than leaving a half-populated database that looks healthy. Without it pg_restore reports errors and carries on, and you find out only once the processor is running.
Confirm that both the entity tables and the processor’s recorded height arrived:
4. Attach the real processor
Redeploy the same slot with your normal manifest — realinit, processor and api — pinning slot: to the new slot and keeping the same storage: and Postgres version::
migrations table came across in the dump, so there is nothing left to apply. The processor reads the restored height and resumes from there, indexing only the blocks produced since the dump.
Watch it close the gap:
5. Verify before switching
Wait for the new deployment to reportSYNCED in sqd view, then compare the two slots rather than trusting the status alone:
- entity counts on the tables that matter to you;
- a checksum over a representative table on both slots, which should agree once both are at the chain head:
- the same query against both canonical API URLs;
- the processor logs, for restarts or migration errors.
6. Move the tag, then remove the old slot
How large a database can this move?
The dump is usually the cheap half. The restore has to rebuild every index from scratch, and that is what dominates the wall clock — expect hours for tens of gigabytes and considerably longer beyond a few hundred. Both halves run over the public database endpoint, so your own bandwidth counts too. Before committing to a maintenance plan, measure it: restore your dump into a scratch slot and time it. That number, not an estimate, tells you how long the two slots overlap and how far the new processor will have to catch up.For databases where a logical copy is no longer practical, contact SQD. Copies at the storage layer avoid the rebuild entirely and are much faster at that scale, but they have to be performed on our side.
Troubleshooting
Related
- Postgres addon — storage, profiles, and connection limits.
- Slots and tags — the tag switch this procedure ends with.
- Update-heavy tables — the fix when the disk holds bloat rather than data.
- Schema changes and backfills — when the new deployment also needs different data.