Database Migration Risk Checker
Check SQL migration risk before release, flag destructive DDL, blocking index builds, large-table backfills, and rollout actions.- {{ error }}
| Aspect | Value | Review detail | Copy |
|---|---|---|---|
| {{ row.aspect }} | {{ row.value }} | {{ row.detail }} |
| Severity | Signal | Evidence | Statement | Next action | Copy |
|---|---|---|---|---|---|
|
No SQL finding rows available
Paste migration SQL to build the finding ledger, or use the sample migration to review the scanner output.
|
|||||
| {{ row.severityLabel }} | {{ row.signal }} | {{ row.evidence }} | {{ row.statementLabel }} | {{ row.action }} | |
| Phase | Action | Trigger | Review note | Copy |
|---|---|---|---|---|
| {{ row.phase }} | {{ row.action }} | {{ row.trigger }} | {{ row.note }} |
Introduction
A database migration changes a live system at the same time application traffic, background jobs, replicas, and older application versions may still be using the old shape of the data. The SQL can be valid and still be a poor release step if it holds a write lock, rewrites a large table, validates old rows, deletes data, or moves too much data inside a deploy transaction.
Migration risk usually comes from the gap between syntax and production behavior. A small staging table may hide a rewrite that takes hours on a table with tens of millions of rows. An index that builds quickly during a quiet test may block checkout writes during peak traffic. A required column, foreign key, unique index, or broad update may look like a normal schema change while the engine scans existing rows or generates enough log volume to slow replicas.
Several terms carry most of the meaning in a migration review. Data definition language, or DDL, changes the shape of objects such as tables, columns, indexes, and constraints. Data manipulation language, or DML, changes rows. Locks protect readers, writers, and metadata while those changes run. A table rewrite rebuilds stored data, while a backfill updates existing rows so old data fits the new schema.
The same statement can need different treatment across database engines. PostgreSQL index creation has a reduced-blocking form, but that form cannot be wrapped in an ordinary transaction block. MySQL and MariaDB expose algorithm and lock choices for many InnoDB changes. SQL Server index work may allow reduced-blocking or resumable behavior depending on edition and operation. Portable SQL review therefore needs both the statement text and the engine context.
- Destructive statements need restore proof and dependency review before release.
- Index, constraint, and required-column changes need attention on hot tables because validation and lock waits can dominate runtime.
- Broad updates, deletes, and insert-select backfills should usually be split into observable batches instead of hidden inside a schema migration.
- Large migrations with many unrelated statements are harder to pause, retry, and roll back cleanly.
A static risk score is a preflight signal, not a production guarantee. It helps decide where to slow down, split a release step, add rehearsal evidence, or demand an owner-approved rollback boundary. Final approval still depends on production-size testing, current database settings, table statistics, replica health, monitoring, and application compatibility during roll forward and rollback.
How to Use This Tool:
Review one migration change set at a time. The most useful report comes from matching the pasted SQL, engine choice, traffic profile, and table inventory to the same release decision.
- Enter a
Migration labelthat matches the ticket, pull request, migration class, or deploy step. The label appears in exported review material so the findings stay tied to the right change. - Choose
Database engine. PickPostgreSQL,MySQL / MariaDB, orSQL Serverwhen the production engine is known; useGeneric SQLonly when you want portable destructive, locking, and broad-DML checks. - Set
Production traffic.Hot table write pathandCritical write pathraise the impact of lock, rewrite, and backfill findings compared with a quiet maintenance window. - Add known names to
Large or hot tables. Values such asorders:28000000,invoices hot, orpublic.events:120mlet the report connect a statement to production table size or write pressure. - Paste the migration into
Migration SQL, drop a SQL, TXT, or LOG file onto the field, useBrowse, or pressLoad samplewhen you want to see the review shape before using your own SQL. - Use
Normalizeif pasted SQL has messy trailing spaces or blank lines. If a red alert saysPaste SQL migration text before reviewing riskor no statements can be separated, add executable SQL with semicolons where needed before trusting the tabs. - Start with Migration Review Brief. Check
Risk score,Release stance,SQL statements,Risk findings,Large table coverage, and the lock, rewrite, backfill, and destructive signal counts. - Open SQL Finding Ledger next. Sort your attention by
Severity, then useEvidence,Statement, andNext actionto decide which migration step needs redesign, rehearsal, or approval. - Use Mitigation Checklist, Statement Risk Ladder, and JSON for handoff. If one statement carries most of the risk, split it into its own observable deploy step before attaching the review to a release ticket.
Before acting on a low score, confirm that Large table coverage is not No inventory for tables you know are large, hot, or tied to revenue, authentication, billing, ingest, or queue processing.
Interpreting Results:
Read Release stance as the first decision cue. A critical finding forces Release hold even when the numeric score would otherwise be lower. Scores below the hold threshold can still demand redesign when the highest finding touches a known large table, a non-concurrent index build, an unbounded update, or a validation-heavy constraint.
| Release stance | Score condition | How to respond |
|---|---|---|
Release hold |
S >= 80 or any critical finding |
Do not run the migration as a blind deploy step. Require a named owner, runbook, rehearsal evidence, monitoring plan, and rollback boundary. |
High-risk review |
55 <= S < 80 with no critical finding |
Pause for focused review because several strong signals combine under the selected traffic assumption. |
Needs rollout plan |
30 <= S < 55 |
Attach timing, lock-timeout, batching, validation, and rollback notes before production execution. |
Low static signal |
S < 30 |
No major static pattern was found, but staging evidence and engine lock checks still matter. |
The SQL Finding Ledger carries the clearest evidence. Treat Drop table operation, Truncate operation, Explicit table lock, Full table rewrite operation, and MySQL copy algorithm as immediate release-review items. Findings such as PostgreSQL non-concurrent index build, Required column without default, NOT NULL validation, and Large table backfill often become safe only after a staged plan is proven on production-size data.
False confidence is most likely when table context is missing. If the migration touches a table that operators already know is large or hot, but Large table coverage says No inventory, add the table name or row count and rerun before treating the stance as low risk.
Technical Details:
Operational database risk comes from the work an engine must do to keep catalog metadata, table storage, indexes, constraints, and concurrent sessions consistent. A schema statement may need a metadata lock before it starts and another lock when it commits. A storage rewrite may copy table data into a new physical shape. A constraint or unique index may scan existing rows before it can be trusted. A broad DML statement may create enough undo, write-ahead log, or replication traffic to outlast the deploy window.
Reduced-blocking options change the review, but they rarely remove all work. PostgreSQL CREATE INDEX CONCURRENTLY avoids blocking ordinary writes, yet it performs more phases and cannot run inside a normal transaction block. MySQL and MariaDB can fail fast when requested ALGORITHM or LOCK choices are not supported. SQL Server ONLINE = ON and resumable index operations can reduce interruption for supported cases, but not every object, edition, or operation qualifies.
Formula Core
The displayed score is a capped, rounded sum of scored findings multiplied by the selected traffic factor. Informational findings explain the review result but contribute 0.
S is the displayed Risk score, M is the traffic multiplier, and w is each finding weight. Critical, high, medium, low, and informational findings weigh 34, 24, 12, 5, and 0. Traffic multipliers are 0.85 for a low-traffic or maintenance-window review, 1.00 for steady production traffic, 1.18 for a hot write path, and 1.35 for a critical write path.
If a migration has one high finding and two medium findings under hot-table traffic, the score is round(1.18 x (24 + 12 + 12)) = 57, so the stance becomes High-risk review. The same findings during a low-traffic maintenance window produce round(0.85 x 48) = 41, which still needs a rollout plan because the static findings have not disappeared.
Rule Core
| Risk family | Matched patterns | Review consequence |
|---|---|---|
| Destructive change | DROP TABLE, TRUNCATE, DROP COLUMN, CASCADE, and unbounded DELETE. |
Require restore evidence, dependency review, app-version compatibility, and explicit approval. |
| Lock-sensitive DDL | PostgreSQL index builds without CONCURRENTLY, SQL Server index work without ONLINE = ON, MySQL index work without LOCK=NONE or an in-place or instant algorithm, explicit LOCK TABLE, and unqualified ALTER TABLE. |
Pin reduced-blocking options where supported, or schedule a write pause with lock-timeout and owner notes. |
| Rewrite or storage rebuild | VACUUM FULL, CLUSTER, MySQL ALGORITHM=COPY, character set conversion, engine changes, broad type changes, and volatile defaults. |
Model runtime, disk headroom, lock wait, replica delay, and rollback cost on production-size data. |
| Validation-heavy change | Required columns without defaults, SET NOT NULL, unique indexes, foreign keys, checks, unique constraints, and primary-key additions. |
Precheck bad rows, validate separately where supported, and make the validation step observable. |
| Backfill or bulk DML | UPDATE without WHERE, large-table UPDATE or DELETE, and large-table INSERT INTO ... SELECT. |
Move data movement into idempotent batches with throttling, progress markers, and lag monitoring. |
| Release shape | More than 12 parsed SQL statements in one migration. |
Split unrelated or high-risk statements into separately observable release steps. |
Parsing and Table Context
SQL comments are removed before statement review, and semicolon splitting preserves quoted strings, quoted identifiers, bracketed identifiers, and PostgreSQL dollar-quoted blocks. Table references are extracted from common ALTER TABLE, CREATE INDEX, REINDEX, DROP TABLE, TRUNCATE, UPDATE, DELETE, INSERT INTO, MERGE INTO, and LOCK TABLE shapes.
| Inventory clue | How it is read | Why it changes the review |
|---|---|---|
orders:28000000 |
The table name is orders and the row count is 28000000. |
A parsed count of at least 10000000 is treated as large for statement weighting. |
invoices hot |
The table is marked as a hot write path even without a numeric row count. | Lock, rewrite, and backfill signals are more serious when the touched table is known to be busy. |
public.events:120m |
The schema-qualified name is normalized for matching, and 120m is read as 120000000 rows. |
Schema-qualified and base table names can both connect parsed SQL statements to supplied inventory. |
Static SQL matching is intentionally conservative. Dynamic SQL, migration-framework behavior, triggers, edition-specific database features, current indexes, catalog statistics, and live lock queues are outside the text review. Any unrecognized statement that changes tables on a production path still deserves manual database review.
Limitations and Privacy Notes:
The SQL review runs in the browser and does not execute statements or connect to a database. It cannot verify real row counts, index definitions, blocking sessions, disk headroom, replica lag, application read/write compatibility, backup quality, or rollback success.
- Use the report as a release preflight aid, not as final approval to run production DDL or DML.
- Keep sensitive SQL out of shared tickets unless your team has approved that disclosure.
- Rehearse high-risk findings on production-size data before relying on timing, lock, or replication assumptions.
Advanced Tips:
- Keep
Database enginepinned to the production engine when reviewing online index, rewrite, or validation behavior;Generic SQLis useful for portable destructive checks but less precise for engine-specific lock options. - Use exact schema-qualified table names in
Large or hot tableswhen migrations reference schemas, then include the base name as well if your SQL generator sometimes omits the schema. - Treat every
Known large table touchedfinding as a prompt to separate timing, lock timeout, rollback, and monitoring notes for that statement instead of burying the work inside a larger deploy. - Compare Statement Risk Ladder with SQL Finding Ledger before splitting a migration; the ladder shows which statement carries concentrated risk, while the ledger explains the exact pattern and next action.
- When the score drops after choosing a maintenance window, keep the original hot-traffic run in the review record if the production table is normally busy. The lower multiplier changes the release assumption, not the underlying SQL behavior.
Worked Examples:
Adding an index on a busy PostgreSQL table
A reviewer enters orders:28000000 in Large or hot tables, chooses PostgreSQL, selects Hot table write path, and reviews CREATE INDEX idx_orders_created_at ON orders(created_at);. SQL Finding Ledger reports PostgreSQL non-concurrent index build and Known large table touched. The practical fix is to use CREATE INDEX CONCURRENTLY outside a transaction or schedule a write pause with explicit monitoring.
Required column plus an unbounded backfill
A migration adds ALTER TABLE invoices ADD COLUMN state text NOT NULL; and follows it with UPDATE invoices SET state = 'pending';. With invoices hot in the table inventory, the report raises Required column without default, Unbounded UPDATE, and Known large table touched. If the resulting Release stance is High-risk review or Release hold, split the change into nullable column creation, batched backfill, verification, and later constraint enforcement.
Borderline score from several medium signals
Under Steady production traffic, a migration with two medium validation findings and one low lock finding scores 29/100, which can sit just below Needs rollout plan. Changing the traffic profile to Hot table write path can move the same findings above the 30 threshold. That is a cue to verify the real write path before deciding the stance is safe enough for a normal deploy.
Troubleshooting a score that looks too low
A reviewer expects a risky result for an events-table migration, but Migration Review Brief shows Low static signal and Large table coverage says No inventory. Adding events:120m or the exact schema-qualified table name to Large or hot tables lets the report connect the parsed statement to table size, then rerunning gives a more credible finding count and release stance.
FAQ:
Does this run my migration?
No. It reviews pasted SQL text in the browser, builds a static risk report, and does not connect to a database or execute any statement.
Why did table inventory change the score?
The table inventory tells the review which parsed statements touch known large or hot tables. That can raise the severity of lock, validation, rewrite, and backfill findings.
Why is a concurrent PostgreSQL index still risky?
CREATE INDEX CONCURRENTLY is flagged when the migration text also contains a transaction wrapper such as BEGIN or COMMIT, because PostgreSQL does not allow that form inside an ordinary transaction block.
What should I do with a release hold?
Use the Mitigation Checklist to draft the runbook, approval owner, rehearsal evidence, monitoring plan, and rollback boundary before the migration reaches production.
Why does the tool say no SQL statements were separated?
Check that Migration SQL contains executable SQL rather than only comments or log text. Add semicolons between statements when the pasted source is ambiguous, then run the review again.
Glossary:
- DDL
- Data definition language, the SQL that changes schema objects such as tables, columns, indexes, and constraints.
- DML
- Data manipulation language, the SQL that changes rows, such as
UPDATE,DELETE, andINSERT INTO ... SELECT. - Backfill
- A data movement step that updates existing rows so old data matches a new schema or application expectation.
- Table rewrite
- A storage rebuild that can copy table data into a new physical shape and may require heavy locking or extra disk headroom.
- Release hold
- The highest stance, used when the static score or a critical finding says the migration needs explicit approval and a runbook before production execution.
References:
- CREATE INDEX, PostgreSQL Documentation.
- ALTER TABLE, PostgreSQL Documentation.
- InnoDB and Online DDL, MySQL 8.4 Reference Manual.
- Guidelines for online index operations, Microsoft Learn.
- How to change database default character set and collation in MySQL or MariaDB, Simplified Guide.
- How to create a PostgreSQL database backup, Simplified Guide.