Safe Migrations
PgBeam lints DDL for the changes that lock tables or lose data. Table rewrites, ACCESS EXCLUSIVE locks, missing CONCURRENTLY, unsafe drops and type changes, NOT NULL without a default. Warn or block.
A generated migration is one of the most dangerous things an agent can run. The
syntax is valid, the statement succeeds, and it takes an ACCESS EXCLUSIVE lock
on a hot table for the duration of a full rewrite. Safe migrations catch that
before it reaches your database. PgBeam parses every DDL statement, checks it
against a set of known-dangerous patterns, and either warns or blocks based on
your policy.
This runs for agent credentials and human credentials. A platform engineer's
hand-written ALTER TABLE gets the same lint as an agent's generated one.
What the linter flags
| Pattern | Why it is risky |
|---|---|
| Table rewrite | Rewrites every row and holds a lock for the whole operation. |
ACCESS EXCLUSIVE lock on a hot table | Blocks all reads and writes to the table while it runs. |
Missing CONCURRENTLY | CREATE INDEX without CONCURRENTLY locks the table for writes. |
| Unsafe drop | DROP COLUMN / DROP TABLE destroys data with no undo. |
| Unsafe type change | ALTER COLUMN ... TYPE that forces a rewrite or can lose data. |
NOT NULL without a default | Adding NOT NULL to an existing column rewrites and can fail mid-flight. |
Lint a migration before you run it
migrations:lint checks a DDL script and returns findings without touching your
database. Use it in CI, in a pre-commit hook, or as a tool the agent calls before
it proposes a change.
curl -X POST \
"https://api.pgbeam.com/v1/projects/{projectId}/migrations:lint" \
-H "Authorization: Bearer $PGBEAM_TOKEN" \
-H "Content-Type: application/json" \
--data '{
"sql": "ALTER TABLE orders ADD COLUMN status text NOT NULL DEFAULT '\''new'\'';\nCREATE INDEX ON orders (status);"
}'{
"findings": [
{
"rule": "missing_concurrently",
"severity": "warn",
"statement": "CREATE INDEX ON orders (status)",
"message": "CREATE INDEX without CONCURRENTLY locks the table for writes. Use CREATE INDEX CONCURRENTLY.",
"suggestion": "CREATE INDEX CONCURRENTLY ON orders (status)"
}
],
"verdict": "warn"
}From the CLI:
pgbeam migrations lint --file migration.sqlWarn or block at the wire
The lint also runs inline when an agent or analyst issues DDL through PgBeam. Set the policy's enforcement level for migrations:
- Warn: the statement runs, the finding is recorded, and a
migration_flaggedevent fires. Use this once you trust the workflow and want a record. - Block: a statement with a finding at or above the threshold is refused on the wire, with the rule and suggestion in the error so the agent can fix it.
pgbeam policies create migrator \
--mode read-write \
--migrations blockERROR: migration blocked: unsafe_drop. DROP COLUMN destroys data with no undo.
Hint: deprecate the column first, then drop it in a later release.Related
- Sandbox writes: run DDL against a throwaway branch.
- Approvals: hold flagged DDL for human sign-off.
- Audit export: forward
migration_flaggedevents. - Policies: set the migration enforcement level.
Sandbox Writes
Let an agent write freely against an instant, isolated branch of your database, or run every write in always-rollback dry-run mode. Production is never touched.
SCRAM-SHA-256 Auth
Authenticate credentials with SCRAM-SHA-256 so the password never crosses the wire. Cleartext-over-TLS stays available as a fallback for clients that need it.