Skip to main content

DevOps & Security

Migration Safety Auditor

Analyzes database migrations for destructive operations, lock escalation risks, missing rollback scripts, and production runtime estimates. Useful for catching high-risk migrations before they ship. Backend engineers and DBAs shipping schema changes, SRE teams reviewing migrations before deploy, and startup CTOs whose teams do not have a dedicated database specialist. A single unsafe migration can take a service offline, corrupt data, or require hours of recovery work. AI-generated migrations frequently miss engine-specific hazards: Postgres rewrites a table when you add a NOT NULL column without a default, MySQL cannot add a column without a full table copy under some versions, and a missing rollback script turns a failed deploy into a manual recovery exercise. The cost of catching these issues before a deploy is minutes; the cost of catching them after is measured in incidents.

Nexus CertifiedClaude CodeCodexOpenClawGoogle Antigravity
databasemigrationssafetyrollbackreliability

One-Time Purchase

$19.99

Sample Output

Migration Safety Audit — add_email_verified.sql

Engine: Postgres 15 · Table: users (estimated 12M rows from prior context)

Verdict

UNSAFE — do not deploy as written. The migration acquires long-held locks against the live users table at the index-build step and validates a CHECK constraint against every existing row under AccessExclusiveLock. At 12M rows the lock window is large enough to cause connection-pool exhaustion and 500-level errors. A three-deploy replacement is below.

Risk dimensions

Index build under ShareLock (blocks writes)HIGH
CHECK constraint validates every row under lockMEDIUM
NOT NULL DEFAULT on PG 11+ (literal default fast path)LOW
No rollback script committed alongside the migrationMEDIUM

Migration Under Review

-- add_email_verified.sql

ALTER TABLE users
  ADD COLUMN email_verified BOOLEAN NOT NULL DEFAULT FALSE;

ALTER TABLE users
  ADD COLUMN email_verified_at TIMESTAMPTZ;

CREATE INDEX users_email_verified_idx
  ON users (email_verified);

ALTER TABLE users
  ADD CONSTRAINT users_verified_at_present_when_verified
  CHECK (email_verified = FALSE OR email_verified_at IS NOT NULL);

Findings

Finding 1: ADD COLUMN ... NOT NULL DEFAULT FALSE — historically a full rewrite

Severity: Low (PG 15) Operation: ALTER TABLE ADD COLUMN

In Postgres versions earlier than 11, adding a column with a non-null default required rewriting every row in the table. Postgres 11+ optimizes this for constant defaults (FALSE, literal values) by storing the default in the table's pg_attribute row instead of touching the heap — meaning this specific case is fast, not the catastrophe it would have been on Postgres 10.

However:

  • The optimization applies only to literal defaults. If the default were a function call (e.g. gen_random_uuid()), the rewrite kicks back in.
  • The operation still acquires AccessExclusiveLock on the table for the duration of the metadata update — short, but during that window all reads and writes block. On a 12M-row table at peak traffic this is typically sub-second, but the lock blocks queries that are already running on the table, including long-running analytical queries.

Risk classification: Low-to-Medium for this specific literal-default case on Postgres 15. Would be HIGH if the default were a function call.

Finding 2: CREATE INDEX without CONCURRENTLY blocks writes

Severity: High Operation: CREATE INDEX

CREATE INDEX without CONCURRENTLY acquires ShareLock on the target table for the entire duration of the index build. On a 12M-row table the build is estimated at 45 seconds to 2 minutes depending on hardware and current load. During that window:

  • All INSERT, UPDATE, and DELETE against users block.
  • SELECT queries continue to run, but new write transactions queue up behind the lock.
  • If write throughput exceeds the connection pool size during the block, the application sees connection-pool exhaustion and returns 500s to users.

Additional concern: an index on a low-cardinality boolean column (email_verified: only TRUE or FALSE) is rarely useful. The planner will almost always choose a sequential scan over a 2-value index unless the column is very skewed (e.g. 99.9% one value). If the intent is to find unverified users, a partial index is the right shape:

CREATE INDEX CONCURRENTLY users_email_unverified_idx
  ON users (id)
  WHERE email_verified = FALSE;

Risk classification: HIGH for the locking; the index itself is probably the wrong shape regardless.

Finding 3: ADD CONSTRAINT ... CHECK validates against every existing row

Severity: Medium Operation: ADD CONSTRAINT (CHECK)

Adding a CHECK constraint validates every existing row in the table by default. On 12M rows this is a sequential scan under AccessExclusiveLock — estimated 8 to 25 seconds. Like Finding 2, this blocks writes.

The safe pattern is the two-step NOT VALID / VALIDATE CONSTRAINT dance:

-- Step 1: add the constraint, mark NOT VALID — fast, no row scan
ALTER TABLE users
  ADD CONSTRAINT users_verified_at_present_when_verified
  CHECK (email_verified = FALSE OR email_verified_at IS NOT NULL)
  NOT VALID;

-- Step 2: validate in a separate transaction — takes a ShareUpdateExclusiveLock,
-- which does NOT block writes (only blocks other DDL)
ALTER TABLE users
  VALIDATE CONSTRAINT users_verified_at_present_when_verified;

Risk classification: MEDIUM. Won't cause an outage on a healthy 12M-row table but will visibly degrade write latency for the duration.

Finding 4: No rollback script provided

Severity: Medium Operation: All four

Best practice for any production migration is a corresponding rollback script committed alongside it. The rollback for this migration is straightforward (drop the index, the constraint, and the columns in reverse order), but if the deploy fails partway through, the operator should not be discovering the rollback path on a 2 AM Pager Duty page.


Recommended Replacement

Split into three deploys, each idempotent and reversible:

Three-deploy migration plan: nullable column, then indexed dual-write, then enforced constraints

Deploy 1: Add the columns (fast, online)

-- add_email_verified__part1_columns.sql
ALTER TABLE users
  ADD COLUMN email_verified BOOLEAN NOT NULL DEFAULT FALSE;

ALTER TABLE users
  ADD COLUMN email_verified_at TIMESTAMPTZ;

Rollback:

ALTER TABLE users DROP COLUMN email_verified_at;
ALTER TABLE users DROP COLUMN email_verified;

Deploy 2: Add the constraint (NOT VALID first, then validate)

-- add_email_verified__part2_constraint.sql
ALTER TABLE users
  ADD CONSTRAINT users_verified_at_present_when_verified
  CHECK (email_verified = FALSE OR email_verified_at IS NOT NULL)
  NOT VALID;

Then, after the application has been deployed and is writing data consistent with the constraint, run in a separate transaction:

ALTER TABLE users
  VALIDATE CONSTRAINT users_verified_at_present_when_verified;

Rollback:

ALTER TABLE users DROP CONSTRAINT users_verified_at_present_when_verified;

Deploy 3: Add the partial index (concurrent, no lock)

-- add_email_verified__part3_index.sql
CREATE INDEX CONCURRENTLY users_email_unverified_idx
  ON users (id)
  WHERE email_verified = FALSE;

Notes: CREATE INDEX CONCURRENTLY cannot run inside a transaction. Most migration tooling (Flyway, Liquibase, Drizzle, Prisma) supports flagging a migration as non-transactional; verify the tool's syntax before deploying. If the build fails partway, the resulting index is INVALID and must be dropped and re-created.

Rollback:

DROP INDEX CONCURRENTLY IF EXISTS users_email_unverified_idx;

Pre-Deploy Checklist

  • Confirm Postgres version is 11+ (so the literal-default fast path applies). Below 11, Deploy 1 needs to be restructured to use ADD COLUMN + UPDATE + SET NOT NULL in stages.
  • Confirm the application code reads email_verified defensively. Between Deploy 1 and Deploy 2 application restart, some app instances will return FALSE for all users (including ones who'd previously been treated as verified by other means). Behavior must be acceptable during that window.
  • Confirm CREATE INDEX CONCURRENTLY is supported by the migration tooling and that the migration is flagged as non-transactional.
  • Run all three on a staging environment first to confirm timings and lock behavior against representative data volume.

Post-Deploy Verification

After all three deploys land:

-- 1. Confirm the column exists and the default is captured
SELECT column_name, data_type, column_default, is_nullable
FROM information_schema.columns
WHERE table_name = 'users' AND column_name LIKE 'email_verified%';

-- 2. Confirm the constraint is VALID (not just NOT VALID)
SELECT conname, convalidated
FROM pg_constraint
WHERE conrelid = 'users'::regclass
  AND conname = 'users_verified_at_present_when_verified';

-- 3. Confirm the index is valid and has the expected shape
SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = 'users' AND indexname = 'users_email_unverified_idx';

Expect:

  • is_nullable = NO for email_verified, YES for email_verified_at
  • convalidated = true for the check constraint
  • The partial index WHERE email_verified = FALSE appears in indexdef

Summary

OperationOriginal RiskReplacement Risk
Add email_verified columnLOW (PG 11+ fast path)LOW (unchanged)
Add email_verified_at columnLOWLOW
Add CHECK constraintMEDIUM (full-table validation under lock)LOW (NOT VALID + later VALIDATE)
Add index on email_verifiedHIGH (blocks writes; wrong index shape)LOW (CONCURRENTLY; partial index targeting actual query)
Rollback pathNoneDocumented per deploy
Calendar time to ship1 deploy3 deploys over a few days

Recommendation: Do not deploy the original migration as written. Use the three-part replacement above. Total engineering effort to restructure is approximately 30 minutes; the alternative is a high-confidence incident window during deploy.


This audit reviews a hypothetical migration for illustration. Always run the recommended changes on a representative staging environment before production deploy.

This sample illustrates the skill's output format. Names, metrics, and operational details are illustrative unless the artifact explicitly analyzes public information.

View full sample →

All sales final. No refunds on digital products.

Includes support for Claude Code, Codex, OpenClaw, and Google Antigravity in the same license.

Also in Database Reliability

Bundle price: $55. Compare this skill with the full workflow bundle or Pro access.

Best for

Backend engineering teams shipping schema changes without a dedicated database specialist, SRE teams reviewing migrations before high-traffic deploys, and AI-assisted development workflows where the migration was generated rather than hand-written. Most valuable on Postgres and MySQL workloads with meaningful row counts (>100K rows) where a single unsafe migration translates directly into downtime.

Not ideal for

Greenfield databases where schema is still in flux and lock behavior on small tables does not matter, or for engines outside Postgres / MySQL / SQLite where the rule set differs significantly. Also a poor fit as a substitute for an on-call review when shipping irreversible operations like dropping a column with active reads.

Included in this purchase

  • Claude Code, Codex, OpenClaw, and Google Antigravity skill files.
  • Setup guidance for the right adapter in your workspace.
  • One-time license for the purchased skill version.

Setup

Plan for a short setup in the repository or workspace where the skill will run. Some coding familiarity helps for implementation-heavy outputs.

Claude CodeCodexOpenClawGoogle Antigravity

Related Skills

Incident Response
Outage Response Playbook
Generates structured, role-clear incident response playbooks for specific failure scenarios. Covers detection through resolution and post-mortem — ready to use when an incident actually happens.
Claude CodeCodexOpenClawGoogle Antigravity
outage-responsereliabilityrunbooks

$19.99

One-time license

View Skill
Incident Response
Incident Postmortem Writer
Generates a structured blameless postmortem from incident timelines, alerts, and deploy logs with root cause analysis, impact assessment, and owned action items. Useful for producing first-draft postmortems under operational pressure.
Claude CodeCodexOpenClawGoogle Antigravity
postmortemsincident-responseoperations

$19.99

One-time license

View Skill
Security Scanning
OWASP Top 10 Scanner
Scans code for OWASP Top 10 vulnerability patterns including injection, XSS, IDOR, and insecure deserialization with severity ratings and remediation snippets. Useful for pre-commit security checks and enterprise compliance.
Claude CodeCodexOpenClawGoogle Antigravity
securityowaspvulnerabilities

$19.99

One-time license

View Skill

Future Updates

This purchase includes the current version of the skill. If you want future adapter updates — meaning compatibility and packaging updates as supported platforms evolve — plus new catalog additions included automatically, upgrade to Pro.

Upgrade to Pro