---
id: platform/postgres-schema-rollout
title: Rehearse a Postgres schema change
description: Run a disposable old/new application rehearsal for a compatible column rename before attaching migrate to preDeployCommand.
keywords: [bex, postgres, migration, preDeployCommand, schema, rollout]
last_updated: 2026-09-23
---

Ship schema changes that stay readable by the previous application until you
retire it. Bex [pre-deploy commands](./pre-deploy-commands.md) run the **new**
image before promotion, keep the previous Deployment while the gate runs, and
block that revision on failure. Image [rollback](./rollbacks.md) does not undo
schema or data.

This page points at a downloadable rehearsal you can run on local disposable
Postgres 16 — never against a customer database.

## What the sample rehearses

The [`postgres-schema-rollout`](/examples/postgres-schema-rollout/README.md)
example renames `notes.display_name` to `notes.title` in stages:

1. **initial** — v1 serves `display_name`
2. **add_title** — add nullable `title` (both versions can dual-write)
3. **backfill_title** — copy values and require `title`
4. **cleanup_display_name** — drop `display_name` only after every v1 replica is gone

`npm run migrate` takes a Postgres advisory lock with finite lock and statement
timeouts and stays under the platform's ten-minute pre-deploy deadline. Long
backfills that cannot finish in that window need a separately planned,
resumable procedure — do not hide them behind a command that exits early.

## Run the rehearsal

```bash
curl -fsSLO https://bex.co/examples/postgres-schema-rollout-latest.zip
curl -fsSLO https://bex.co/examples/postgres-schema-rollout-latest.zip.sha256
shasum -a 256 -c postgres-schema-rollout-latest.zip.sha256
unzip postgres-schema-rollout-latest.zip
cd postgres-schema-rollout
npm install
export DATABASE_URL=postgres://rollout:rollout@127.0.0.1:55432/rollout
npm run setup
npm run migrate -- --to backfill_title
npm test
npm run teardown -- --container
```

The sample refuses non-local connection strings and database names that do not
look like rehearsal/tmp/test fixtures.

## Attach to a Blueprint

See `render.yaml` in the sample for a `preDeployCommand: npm run migrate`
shape with a Postgres `connectionString` env binding. Confirm migrate exit
codes and `/healthz` before enabling auto-deploy on a real service.

## Related

- [Pre-deploy commands](./pre-deploy-commands.md)
- [Postgres](./postgres.md)
- [Rollbacks](./rollbacks.md)
- [CI image deploy](./ci-image-deploy.md)
