Stop dangerous database migrations before they reach production.
SchemaRisk is a production-grade PostgreSQL migration safety analyzer.
It understands your migrations the way a senior DBA does — flags dangerous operations, generates safe alternatives, and posts risk reports directly in your pull requests.
Schema migrations fail in production for predictable reasons:
ALTER TABLE ... ALTER COLUMN TYPErewrites the entire table under lockCREATE INDEXwithoutCONCURRENTLYblocks all writes for minutesDROP COLUMNbreaks application code before it's been removedADD COLUMN NOT NULLfails instantly on tables with existing rowsADD COLUMN DEFAULTon PostgreSQL 10 rewrites the table; on PG11+ it's free
SchemaRisk detects all of these, explains exactly why they are dangerous, and gives you the step-by-step safe alternative.
| Feature | Description |
|---|---|
| Risk scoring | Every dangerous operation scored by severity + table size |
| PG version-aware rules | ADD COLUMN DEFAULT behaves differently on PG10 vs PG11+ — SchemaRisk knows this |
| Safe migration generator | Not just "danger detected" — gives you the exact zero-downtime SQL to run instead |
| Repository impact scanner | Finds which files in your codebase reference the changed tables/columns |
| PR comment reports | Posts a full migration report as a GitHub/GitLab PR comment automatically |
guard mode |
Interactive confirmation gate for dangerous operations before they run |
| Schema drift detection | Compares migration files against a live database to find drift |
| SARIF output | GitHub Security tab integration |
cargo install schema-riskgit clone https://github.com/Keystones-Lab/Schema-risk
cd Schema-risk
cargo build --releaseBinary: target/release/schema-risk
# Analyze one migration — know the risk before you deploy
schema-risk analyze migrations/001_add_index.sql
# Use the correct PostgreSQL version for accurate scoring
schema-risk analyze migrations/001.sql --pg-version 14
# Get safe alternatives for everything risky
schema-risk fix migrations/001.sql --dry-run
# Post a full report to your PR
schema-risk ci-report "migrations/*.sql" --format github-comment
# Guard dangerous operations with typed confirmation
schema-risk guard migrations/005_breaking.sql SchemaRisk Analysis 202406_add_index.sql
Migration Risk: HIGH (score: 72)
Tables affected: users
Estimated lock duration: ~90 sec
Index rebuild required: YES
Requires maintenance window: YES
Warnings:
! CREATE INDEX on 'users' without CONCURRENTLY will hold a SHARE lock
for the duration of the index build (cols: email)
Recommendations:
CREATE INDEX CONCURRENTLY idx_email ON users(email);
This migration should NOT be deployed without review
For a dangerous type change like:
ALTER TABLE users ALTER COLUMN email TYPE text;SchemaRisk outputs a complete zero-downtime plan:
-- Step 1: Add shadow column with new type
ALTER TABLE users ADD COLUMN email_v2 text;
-- Step 2: Back-fill in batches (run until 0 rows updated)
UPDATE users
SET email_v2 = email::text
WHERE email_v2 IS NULL
LIMIT 10000;
-- Step 3: Deploy app to write to both columns
-- Step 4: Atomically swap column names
ALTER TABLE users RENAME COLUMN email TO email_old;
ALTER TABLE users RENAME COLUMN email_v2 TO email;
-- Step 5: Drop old column after verifying app health
ALTER TABLE users DROP COLUMN email_old;When a migration is included in a PR, SchemaRisk automatically posts:
** SchemaRisk — Migration Safety Report (PostgreSQL 14)**
File Risk Score Lock Est. Duration 202406_add_index.sqlHIGH 72 SHARE~90s Safe Alternative:
CREATE INDEX CONCURRENTLY idx_email ON users(email);Impact: 12 files reference
users.email
Pass --pg-version to get accurate risk scores for your specific PostgreSQL version.
| Operation | PG10 | PG11+ |
|---|---|---|
ADD COLUMN DEFAULT |
Full table rewrite | Metadata-only |
SET NOT NULL |
Full scan, long lock | CHECK constraint safe alternative on PG12+ |
ALTER COLUMN TYPE |
Full rewrite (all versions) | Full rewrite (all versions) |
# Score correctly for an older production database
schema-risk analyze migrations/ --pg-version 10
# Or target PG14 (default)
schema-risk analyze migrations/ --pg-version 14Analyze one or more SQL files and report risk.
schema-risk analyze migrations/001.sql
schema-risk analyze "migrations/*.sql" --verbose
schema-risk analyze migrations/001.sql --pg-version 14
schema-risk analyze migrations/001.sql --format json
schema-risk analyze migrations/001.sql --format markdown
schema-risk analyze migrations/001.sql --format sarif
schema-risk analyze migrations/001.sql --show-locks
schema-risk analyze migrations/001.sql --scan-dir ./src
schema-risk analyze migrations/001.sql --table-rows "users:5000000,orders:2000000"
schema-risk analyze migrations/001.sql --fail-on criticalApply auto-fixes where supported and show zero-downtime migration plans for everything else.
schema-risk fix migrations/001.sql
schema-risk fix migrations/001.sql --dry-run
schema-risk fix migrations/001.sql --output migrations/001_fixed.sqlGenerate GitHub/GitLab PR comments or JSON CI output.
schema-risk ci-report "migrations/*.sql" --format github-comment
schema-risk ci-report "migrations/*.sql" --format github-comment --pg-version 14
schema-risk ci-report "migrations/*.sql" --format json
schema-risk ci-report "migrations/*.sql" --scan-dir ./services --fail-on criticalShow a detailed, statement-by-statement breakdown.
schema-risk explain migrations/001.sqlRender the schema dependency graph from migration files.
schema-risk graph "migrations/*.sql" # text
schema-risk graph "migrations/*.sql" --format mermaid
schema-risk graph "migrations/*.sql" --format graphvizCompare expected schema (from migrations) against a live database to detect drift.
schema-risk diff "migrations/*.sql" --db-url postgres://user:pass@host/dbIntercept dangerous operations and require explicit confirmation before allowing them to run.
schema-risk guard migrations/005_drop.sql
schema-risk guard migrations/005_drop.sql --dry-run
schema-risk guard migrations/005_drop.sql --non-interactive
# Usage pattern (blocks the migration unless confirmed)
schema-risk guard migration.sql && psql -f migration.sqlCreate a starter schema-risk.yml config file.
schema-risk init
schema-risk init --forceAdd SchemaRisk to your GitHub Actions workflow and get automatic risk reports on every PR that touches migration files.
Copy .github/workflows/schema-risk.yml from this repo into your project, then set PG_VERSION to match your production database:
env:
PG_VERSION: "14" # Set to your production PostgreSQL versionThat's it. Every PR with SQL changes will now receive a comment like this:
HIGH RISK — significant impact on database availability.
Review all findings carefully before merging.
File Risk Score Lock Est. Duration Breaking Changes 202406_add_index.sqlHIGH 72 SHARE~90s 3 file(s) Generated by SchemaRisk — Prevent dangerous migrations before they reach production.
When engineers review PRs, they see the risk report. Engineers on other teams ask "what is SchemaRisk?"
Then they install it too.
This is how devtools grow organically — by being useful in the places developers already work.
| Actor | Detection | Behavior |
|---|---|---|
| Human | Interactive terminal | Shows impact panel and prompts for confirmation |
| CI | CI, GITHUB_ACTIONS, etc. |
Blocks dangerous ops in non-interactive mode |
| Agent | AI provider env indicators | Blocks and emits machine-readable result |
Guard output includes:
- Operation summary
- Risk + lock metadata
- Affected objects
- Likely breakage
- Full audit trail (
.schemarisk-audit.json)
Generate a starter file:
schema-risk initExample:
version: 2
thresholds:
fail_on: high
guard_on: medium
rules:
disabled: []
table_overrides:
sessions:
ignored: true
scan:
root_dir: "."
extensions: [rs, py, go, ts, js, rb, java, kt]
exclude: [target/, node_modules/, vendor/, .git/]
skip_short_identifiers: true
guard:
require_typed_confirmation: true
audit_log: ".schemarisk-audit.json"
block_agents: true
block_ci: false
output:
format: terminal
color: true
show_recommendations: true
show_impact: true| Code | Meaning |
|---|---|
| 0 | Success / below configured threshold |
| 1 | Risk meets or exceeds fail threshold |
| 2 | Parse/IO/database command error |
| 3 | Guard runtime error |
| 4 | Guard blocked execution |
cargo test
cargo clippy -- -D warnings
cargo fmt --allMIT