Database Migration Testing: How QA Can Catch Data and Schema Bugs Before Production
A database migration can look like a small change.
Add a column.
Rename a field.
Create an index.
Change a data type.
Move data from one table to another.
Add a constraint.
Remove an obsolete field.
From a developer's perspective, the migration may be only a few lines of SQL.
But a database migration can affect almost every part of an application.
A single schema change can impact:
- APIs
- Backend services
- Frontend behavior
- Reports
- Background jobs
- Integrations
- Existing records
- Queries
- Performance
- Data validation
- Authentication
- Billing
- Analytics
And unlike a normal application bug, a bad migration can potentially modify thousands or millions of records.
That makes database migration testing an important part of modern QA.
The question isn't simply:
"Did the migration execute successfully?"
A much better question is:
"Did the database change without breaking existing data, application behavior, performance, or future deployments?"
That is what database migration testing needs to establish.
What Is Database Migration Testing?
Database migration testing is the process of verifying that a database schema or data transformation changes correctly without causing unintended problems.
A migration can involve:
- Creating tables
- Altering columns
- Renaming columns
- Changing data types
- Adding indexes
- Removing indexes
- Adding constraints
- Removing constraints
- Moving data
- Splitting tables
- Combining tables
- Changing relationships
- Updating existing records
Testing should therefore cover both:
Schema correctness
and
Data correctness.
A migration can technically succeed while still producing incorrect data.
For example:
Migration completes successfully.
But:
10% of customer records have incorrect values.
The deployment system may report:
SUCCESS
The application may still have a serious defect.
This is why migration testing needs more than checking whether the SQL command completed.
Why Database Migrations Are Risky
Applications depend heavily on database structure.
Consider an existing table:
customers
with:
- id
- name
- email
- phone
A new release introduces:
- country
The change looks simple.
But now several questions appear.
What happens to existing customers?
Should country be:
- NULL?
- A default value?
- Required?
What happens to APIs?
What happens to reports?
What happens to imports?
What happens to existing automation?
What happens if an older application version is still running?
The database is shared infrastructure.
A schema change can therefore affect many components simultaneously.
Database Migration Testing Is More Than Schema Validation
Schema validation asks:
"Does the database structure look correct?"
Migration testing asks a larger set of questions:
- Did the schema change correctly?
- Did existing data remain correct?
- Were new records handled correctly?
- Are relationships preserved?
- Do existing queries still work?
- Does the application still work?
- Are indexes behaving correctly?
- Did performance change?
- Can the migration be rolled back?
- Can deployments continue safely?
This broader perspective is important.
Start With the Migration's Intended Change
Before testing, QA should understand exactly what the migration is supposed to accomplish.
For example:
Original:
users.email
New:
users.email_address
The intended change might be:
Rename the column without losing any data.
That gives QA a clear expectation:
Before migration:
email = user@example.com
After migration:
email_address = user@example.com
The value should remain unchanged.
Without a clearly defined expected result, migration testing becomes difficult.
Test Schema Changes
The first level of testing is structural.
Verify:
- Table names
- Column names
- Data types
- Nullable properties
- Default values
- Primary keys
- Foreign keys
- Unique constraints
- Indexes
For example:
A migration adds:
status VARCHAR(20) NOT NULL DEFAULT 'active'
QA should verify:
- Column exists.
- Data type is correct.
- NOT NULL behavior is correct.
- Default value is correct.
- Existing records receive the intended value.
Schema changes should be tested explicitly rather than assuming that a successful migration means the schema is correct.
Test Existing Data
This is one of the most important migration tests.
Existing data should be preserved unless the migration explicitly changes it.
Suppose a database contains:
1,000,000 customer records.
A migration transforms:
customer.phone
into:
customer.phone_number
After migration, QA should verify that values haven't been accidentally:
- Deleted
- Truncated
- Duplicated
- Reformatted incorrectly
- Assigned to the wrong records
For large datasets, validation may use counts, checksums, samples and targeted queries rather than manually inspecting records.
Compare Before and After
A useful migration testing strategy is to establish a baseline before the migration.
For example:
Total customers:
100,000
Active customers:
72,000
Customers with phone numbers:
64,000
Customers with subscriptions:
28,000
After migration, compare the expected values.
If:
Total customers:
100,000
Active customers:
72,000
Customers with phone numbers:
42,000
something changed unexpectedly.
This type of before-and-after validation can reveal data loss quickly.
Test Row Counts
Row counts are simple but useful.
For tables that shouldn't lose records, compare:
Before migration:
500,000 rows
After migration:
500,000 rows
If the number changes unexpectedly, investigate.
However, row counts alone aren't sufficient.
The database can have the same number of rows while individual records are incorrect.
That's why row counts should be combined with deeper validation.
Test Data Integrity
Data integrity means the data remains accurate and internally consistent.
For example:
orders.customer_id
should continue referencing:
customers.id
After migration, QA can verify:
- No orphaned records
- Foreign keys remain valid
- Relationships remain intact
- Required fields contain valid values
- Unique constraints remain meaningful
A migration that preserves row counts but breaks relationships is still a failed migration.
Test Foreign Key Relationships
Consider:
customers
↓
orders
↓
order_items
A migration changes one of these tables.
The relationships need to remain correct.
QA should test:
- Existing relationships
- New relationships
- Deleted relationships
- Referential integrity
- Cascading behavior
For example:
If a foreign key is changed, verify that existing orders still point to the correct customers.
Test Default Values
Adding a new column often introduces a default value.
For example:
status = active
Existing records may automatically receive:
active
But is that actually correct?
Maybe some existing records should be:
inactive
or:
unknown.
QA should verify that the migration's default behavior matches the business requirement.
Default values can silently introduce incorrect business states if they're chosen incorrectly.
Test NULL Behavior
Changing a column from nullable to NOT NULL is a common migration risk.
Suppose:
customer.country
currently allows NULL.
The new version requires:
country NOT NULL
What happens to existing records with no country?
The migration may fail.
Or the migration may assign a default.
Or the development team may have a backfill strategy.
QA should test all relevant cases:
- Existing NULL values
- New valid values
- New NULL values
- Application validation
- API behavior
The important question is:
"What happens to data that doesn't satisfy the new constraint?"
Test Data Type Changes
Changing data types can cause data loss or unexpected conversion.
For example:
price:
INTEGER
becomes:
DECIMAL
This may be safe if handled correctly.
But consider:
VARCHAR
becomes:
INTEGER
What happens to:
"100"
versus:
"100.50"
versus:
"unknown"
versus:
""
The migration needs defined behavior for invalid or incompatible values.
QA should test representative data before approving such changes.
Test String Length Changes
Suppose:
VARCHAR(255)
becomes:
VARCHAR(100)
Existing values longer than 100 characters may be:
- Rejected
- Truncated
- Failed
- Migrated incorrectly
QA should deliberately test values around the boundary.
For example:
99 characters
100 characters
101 characters
This is a classic migration boundary test.
Test Numeric Precision Changes
Numeric changes can be dangerous.
For example:
DECIMAL(10,2)
becomes:
DECIMAL(8,2)
Existing values may no longer fit.
QA should test:
- Minimum values
- Maximum values
- Decimal precision
- Negative values
- Large values
- Existing production-like values
The goal is to ensure that the migration doesn't silently alter important financial or business data.
Test Date and Time Changes
Date and time migrations can create subtle problems.
For example:
timestamp without timezone
becomes:
timestamp with timezone
Now questions arise:
- Are existing values interpreted correctly?
- Which timezone is assumed?
- Are dates shifted?
- Are reports affected?
- Do APIs return the expected format?
QA should compare representative timestamps before and after migration.
Timezone-related migration problems can be especially difficult to notice if testing happens only in one region.
Test Column Renames Carefully
Renaming a column can affect more than the database.
Suppose:
user_name
becomes:
username
The migration may be correct.
But existing application code may still query:
user_name
Other dependencies may also reference the old name.
QA should therefore test:
- Application APIs
- Backend queries
- Reports
- Background jobs
- Integrations
- Automation
- Admin tools
A schema rename is often an application-wide change.
Test Index Changes
Indexes can improve performance.
They can also create unexpected migration problems.
A migration may:
- Add an index
- Remove an index
- Change an index
- Add a unique index
QA should verify:
- Index exists
- Correct columns are indexed
- Unique behavior is correct
- Queries still work
- Performance remains acceptable
An index migration shouldn't be considered successful solely because the index appears in the database.
Test Unique Constraints
Suppose a migration adds:
UNIQUE(email)
What happens if existing data contains duplicate emails?
The migration may fail.
Or a cleanup migration may need to run first.
QA should test:
- Existing duplicates
- New duplicate records
- Case sensitivity
- NULL behavior
- Update behavior
Constraint changes can reveal data-quality problems that were previously allowed.
Test Constraints Against Existing Data
Adding a constraint can expose old data that doesn't satisfy the new rule.
For example:
Existing:
orders.amount >= 0
New constraint:
amount > 0
What happens to existing records with:
amount = 0?
A migration should have a defined strategy.
QA should verify both:
Migration behavior
and:
Application behavior after migration.
Test Data Backfills
Many migrations require backfilling data.
For example:
A new column is introduced:
customer_segment
Existing customers need values calculated from historical data.
The workflow might be:
Add column
↓
Calculate values
↓
Update existing records
↓
Validate
QA should test:
- Calculation accuracy
- Missing values
- Edge cases
- Large datasets
- Repeatability
Backfill logic should be tested like application logic because it is effectively transforming business data.
Test Partial Backfills
Large databases may be migrated in batches.
For example:
Batch 1 → 10,000 records
Batch 2 → 10,000 records
Batch 3 → 10,000 records
What happens if the process stops after batch 5?
Can it safely resume?
Will already migrated records be processed again?
QA should test interruption and restart behavior where the migration architecture supports it.
Test Migration Idempotency
A useful migration should ideally have predictable behavior if execution is repeated or partially retried, depending on the migration framework and design.
For example:
Migration runs.
↓
Failure occurs.
↓
Migration is retried.
QA should verify that retrying doesn't create:
- Duplicate data
- Duplicate indexes
- Corrupted records
- Incorrect transformations
The exact retry behavior depends on the migration tooling and architecture, but it should be explicitly understood.
Test Migration Failure
QA shouldn't only test successful migrations.
Force relevant failure conditions.
For example:
- Database connection failure
- Permission failure
- Timeout
- Disk limitation
- Constraint violation
- Invalid data
- Interrupted process
Then verify:
- Failure is reported clearly.
- Database remains consistent.
- Partial changes are handled safely.
- Recovery is possible.
- Deployment doesn't leave the system in an unknown state.
Failure testing is particularly important for large migrations.
Test Rollback
Not every database change can be safely rolled back.
That's why rollback planning needs special attention.
For reversible migrations, test:
Migration
↓
Application behavior
↓
Rollback
↓
Previous application behavior
The database should return to an acceptable state.
But QA should also verify whether rollback is actually supported.
A migration that changes or deletes data may not have a true rollback.
In such cases, recovery may require backups or a separate restoration strategy.
Don't Assume Rollback Is Automatic
A migration framework may provide a rollback command.
That doesn't necessarily mean:
"Everything is perfectly restored."
For example:
A migration deletes a column.
Rollback recreates the column.
But what happens to the data that was previously inside it?
If the data was permanently removed, recreating the column doesn't restore it.
QA should distinguish between:
Schema rollback
and:
Data recovery.
They're not always the same thing.
Test Backward Compatibility
One of the most important migration scenarios is compatibility between application versions.
Consider:
Old Application
↓
Database
↓
New Application
A deployment may temporarily involve multiple application versions.
For example:
Server A:
Version 5.1
Server B:
Version 5.2
Both may access the same database.
If version 5.2 immediately removes something that 5.1 still requires, the deployment can fail.
This is why backward-compatible database changes are important during rolling deployments.
Expand-and-Contract Migration Testing
A safer pattern for many schema changes is:
Expand
↓
Migrate
↓
Switch Application
↓
Contract
Instead of immediately removing an old field, the team may:
1. Add the new field.
2. Keep the old field temporarily.
3. Update the application to support the new field.
4. Backfill existing data.
5. Verify the new path.
6. Stop using the old field.
7. Remove the old field later.
QA should test each phase.
This can reduce deployment risk when multiple application versions coexist.
Test Dual-Write Scenarios
During some migrations, an application may temporarily write to both:
old_column
and:
new_column
QA should verify:
- Both values are correct.
- Updates remain synchronized.
- Reads use the intended source.
- Failure in one write is handled appropriately.
Dual-write logic can create subtle inconsistencies.
It deserves dedicated testing.
Test Read Compatibility
Suppose the database now contains:
new_field
while the application still needs:
old_field.
QA should verify whether the application can continue reading correctly during the transition.
This is especially important for rolling deployments.
The database migration shouldn't accidentally make existing application instances unusable.
Test Write Compatibility
The same applies to writes.
If both old and new application versions are running, can both safely write to the database?
A migration that works perfectly with the new application may still break older instances.
QA should test the actual deployment sequence rather than only the final state.
Test Migration Performance
A migration can be functionally correct but operationally dangerous.
For example:
A migration updates:
50 million rows.
It takes:
3 hours.
During that time it creates:
- Locking
- High CPU usage
- High disk usage
- Slow queries
The migration may technically succeed.
But the application may become unusable.
Therefore migration testing should consider:
- Execution time
- CPU usage
- Memory
- Disk usage
- Lock duration
- Query latency
- Database connections
Test Large Production-Like Data
A migration that succeeds against:
10,000 rows
may behave very differently against:
10 million rows.
Testing should therefore use production-like data volume where the migration's scale makes that relevant.
This can reveal:
- Long execution times
- Lock contention
- Memory problems
- Slow queries
- Transaction size issues
Small datasets can hide migration risks.
Test Database Locks
Some schema operations can lock tables or rows.
QA should investigate:
- Which objects are locked?
- For how long?
- Can users continue reading?
- Can users continue writing?
- Are requests blocked?
- Does application latency increase?
This is especially important for high-traffic applications.
A migration that takes 30 seconds but blocks all writes may be more dangerous than one that takes several minutes with minimal impact.
Test Migration During Active Traffic
When appropriate and safely controlled, test migrations while the application is receiving realistic traffic.
For example:
Users are creating orders.
At the same time:
A database migration runs.
QA can observe:
- Request failures
- Latency
- Data consistency
- Locking
- Error rates
This helps reveal problems that don't appear when the database is idle.
Test Migration During Background Jobs
Applications often have background workers processing data.
For example:
Web application
+
Queue workers
+
Scheduled jobs
All access the database.
A migration can happen while workers are still running.
QA should test whether jobs:
- Continue working
- Fail safely
- Retry correctly
- Process new schema correctly
- Accidentally write incompatible data
This is another reason migration testing needs to consider the entire system.
Test Reports and Analytics
Database changes can affect more than transactional workflows.
Reports may depend on:
- Columns
- Joins
- Aggregations
- Indexes
- Views
After migration, QA should verify important reports.
For example:
Revenue before migration:
₹10,000,000
Revenue after migration:
₹10,000,000
If the number changes unexpectedly, investigate.
A migration may preserve transactional data while breaking analytical queries.
Test Database Views
Views can depend on specific columns and tables.
If a migration:
- Renames a column
- Removes a field
- Changes a relationship
existing views may fail.
QA should identify important views and verify them after migration.
The same principle applies to stored procedures and database functions where they are used.
Test Stored Procedures and Functions
Some applications rely heavily on database-side logic.
Migration testing should consider:
- Stored procedures
- Functions
- Triggers
- Views
- Scheduled database jobs
A schema change can break these even when the main application appears healthy.
Test Triggers
Triggers can create hidden side effects.
For example:
INSERT customer
↓
Trigger creates audit record.
A migration changes the customer table.
Does the trigger still work?
QA should verify:
- Trigger execution
- Expected side effects
- Failure behavior
- Data consistency
Triggers should not be overlooked simply because they aren't visible in application code.
Test Application Behavior After Migration
Database testing alone isn't enough.
Once the migration succeeds, execute application-level tests.
Verify:
- Login
- Registration
- Search
- CRUD operations
- Business workflows
- Reports
- Integrations
- Background jobs
The goal is to confirm that the application still understands the new database structure.
Test APIs After Migration
APIs often expose database-backed data.
After migration, verify:
- Response structure
- Field values
- Filtering
- Sorting
- Pagination
- Updates
- Deletes
- Error handling
A migration can leave the database looking correct while causing an API to return incorrect values.
Test Existing Automated Tests
Existing automation is useful here.
Run relevant:
- Unit tests
- Integration tests
- API tests
- End-to-end tests
- Regression tests
Migration testing shouldn't replace normal application testing.
It should provide an additional layer of confidence before and after the schema change.
AI Can Help Analyze Migration Risk
This is where AI-assisted QA can add value.
An AI system could analyze:
- Migration scripts
- Schema differences
- Application queries
- API contracts
- Existing tests
- Historical migration failures
- Database dependencies
It could identify potential risk areas.
For example:
"Column customer_status is being changed from nullable to NOT NULL. Existing records should be checked for NULL values before deployment."
That doesn't replace QA review.
It provides another layer of analysis.
AI Can Generate Migration Test Scenarios
Given a migration such as:
email VARCHAR(255)
→
email VARCHAR(100)
AI could suggest:
- Existing value under 100 characters
- Exactly 100 characters
- More than 100 characters
- NULL
- Empty string
- Unicode
- Special characters
- Duplicate values
This can help QA engineers identify edge cases faster.
AI Can Compare Before-and-After Database States
A future AI-assisted testing system could compare:
Before migration
and:
After migration
and look for meaningful differences.
For example:
Row count:
Same.
Relationships:
Same.
Required fields:
Same.
But:
Average order amount changed unexpectedly.
The system could flag the discrepancy for human investigation.
The AI doesn't need to declare:
"Migration is broken."
It can say:
"Observed data difference requires validation."
AI Can Identify Application Dependencies
One of the harder migration problems is finding everything affected by a schema change.
Suppose:
customer.email
is renamed.
The dependency may exist in:
- Backend code
- APIs
- Reports
- Scheduled jobs
- Analytics
- Integrations
- Tests
AI can potentially search application code and documentation to identify references.
This can make impact analysis faster.
The final decision should still be reviewed by engineers and QA.
AI Can Analyze Migration Failures
Imagine a migration fails with:
"Constraint violation."
AI can analyze:
- Failed SQL operation
- Database state
- Relevant records
- Migration history
- Schema definition
Then summarize:
"The new unique constraint cannot be created because 247 existing records contain duplicate email values."
That's much more useful than:
"Migration failed."
AI Can Detect Risky Migration Patterns
Certain changes deserve additional scrutiny.
Examples include:
- Dropping columns
- Changing data types
- Adding NOT NULL constraints
- Adding unique constraints
- Large data backfills
- Large table updates
- Table renames
- Foreign key changes
AI can potentially flag these changes before deployment.
For example:
"High-risk migration detected: 25 million rows will be updated in a single operation."
That gives QA and engineering an opportunity to investigate before execution.
Don't Let AI Approve Database Changes Automatically
Database migrations can have irreversible consequences.
AI should not blindly decide:
"Migration safe."
Human review remains important.
A safer workflow is:
Migration Analysis
↓
Risk Identification
↓
Automated Validation
↓
Test Execution
↓
Evidence
↓
Human Approval
This keeps the decision-making process controlled.
A Practical Database Migration Testing Workflow
A strong workflow can look like:
Step 1: Understand the Migration
Identify:
- What changes?
- Why?
- Which tables?
- Which columns?
- Which data?
Step 2: Perform Impact Analysis
Identify:
- Application dependencies
- APIs
- Reports
- Jobs
- Integrations
- Existing tests
Step 3: Capture a Baseline
Record:
- Row counts
- Important aggregates
- Data samples
- Relationships
- Performance indicators
Step 4: Test the Migration on Representative Data
Use realistic data volume and states.
Step 5: Validate Schema
Check structure and constraints.
Step 6: Validate Data
Compare expected before-and-after results.
Step 7: Test Application Behavior
Run critical functional workflows.
Step 8: Test Compatibility
Verify relevant old and new application versions.
Step 9: Test Failure Scenarios
Test interruptions and relevant dependency failures.
Step 10: Test Recovery
Verify restart, retry or rollback behavior.
Step 11: Validate Performance
Measure migration impact.
Step 12: Review Evidence
Only approve the migration when the evidence supports the expected outcome.
Example: Adding a Customer Status Field
Suppose a team adds:
customer.status
with:
DEFAULT 'active'
Existing customers:
1,000,000
A strong test strategy would verify:
Schema
Column exists.
Type is correct.
Default is correct.
Existing Data
All existing customers receive the intended value.
New Data
New customers receive the correct default.
API
Status appears correctly.
Application
Customer workflows remain functional.
Filtering
Search by status works.
Reports
Customer counts remain correct.
Performance
Queries involving status perform acceptably.
Rollback or Recovery
The team has a tested recovery strategy appropriate to the migration.
This is much stronger than simply checking whether the migration completed.
Example: Renaming a Database Column
Suppose:
user_email
becomes:
email_address
The testing strategy should include:
Before:
user_email = test@example.com
After:
email_address = test@example.com
Then verify:
- Existing records preserved
- New records work
- API responses work
- Login works
- Password reset works
- Reports work
- Background jobs work
- Integrations work
Also verify that no important component still depends on the removed field.
Example: Adding a Unique Constraint
Suppose:
becomes:
UNIQUE(email)
Before migration:
Identify duplicates.
If duplicates exist:
The migration should have a defined cleanup strategy.
After migration:
Attempt to create another record with the same email.
Expected:
Application follows the intended duplicate-handling behavior.
This tests both:
Database enforcement
and:
Application handling.
Common Database Migration Testing Mistakes
Mistake 1: Checking Only Migration Success
A successful migration command doesn't prove data correctness.
Mistake 2: Testing Only a Small Dataset
Large-scale problems may remain hidden.
Mistake 3: Ignoring Existing Data
Schema changes can affect historical records.
Mistake 4: Ignoring Application Dependencies
Database changes can break code outside the migration itself.
Mistake 5: Ignoring Rollback
A migration may fail after partially changing the system.
Mistake 6: Ignoring Performance
A functionally correct migration can still create production downtime.
Mistake 7: Ignoring Deployment Order
Old and new application versions may temporarily coexist.
Mistake 8: Ignoring Background Jobs
Workers may interact with the changed schema during deployment.
Mistake 9: Validating Only Schema
Data and business behavior also need verification.
Mistake 10: Assuming the Migration Is Reversible
Deleted data may not be recoverable simply by reversing the schema.
What Should Be Included in a Migration Test Plan?
A practical test plan can include:
Schema
- Tables
- Columns
- Types
- Constraints
- Indexes
Data
- Row counts
- Existing values
- Backfills
- Relationships
- Duplicates
Application
- APIs
- UI workflows
- Business logic
- Reports
Compatibility
- Old application
- New application
- Deployment sequence
Failure
- Interrupted migration
- Constraint failures
- Connection failures
- Timeouts
Recovery
- Retry
- Resume
- Rollback
- Restore
Performance
- Execution time
- Query latency
- Locking
- Resource usage
Database Migration Testing Metrics
Teams can measure migration quality using:
Migration Duration
How long does the migration take?
Data Integrity Rate
How much data remains correct after migration?
Failed Migration Rate
How often do migrations fail?
Rollback Success Rate
How reliably can the system recover?
Application Error Rate
Do application errors increase after migration?
Query Performance Change
Do important queries become slower?
Lock Duration
How long are important tables or rows unavailable?
These metrics can help teams improve migration processes over time.
A Strong Database Migration Testing Architecture
A mature workflow could look like:
Migration Script
↓
Schema Diff
↓
Impact Analysis
↓
Baseline Database
↓
Migration Execution
↓
Schema Validation
↓
Data Integrity Validation
↓
Application Tests
↓
Performance Validation
↓
Recovery Validation
↓
Human Approval
↓
Production Deployment
The Most Important Principle
A database migration is not successful because:
"The migration command returned success."
It is successful when:
The schema is correct.
The data is correct.
The application still works.
Existing workflows remain valid.
Performance remains acceptable.
Deployment compatibility is maintained.
And the team has a reliable recovery strategy.
That is the real definition of migration success.
Final Thoughts
Database migrations are often treated as deployment details.
They shouldn't be.
A database is one of the most important pieces of application infrastructure.
Changing its structure or transforming its data can affect almost every layer of the system.
Good migration testing therefore needs to verify:
- Schema changes
- Existing data
- Data integrity
- Constraints
- Relationships
- Backfills
- Application behavior
- API behavior
- Compatibility
- Performance
- Failure handling
- Recovery
AI can make this process more intelligent by analyzing migration scripts, identifying risky schema changes, finding application dependencies, generating edge cases and comparing before-and-after database states.
But database changes deserve careful human oversight.
The most useful mindset is:
Understand → Analyze → Baseline → Migrate → Validate → Recover
Don't ask only:
"Did the migration run?"
Ask:
"What changed, and can we prove that everything that should have remained correct is still correct?"
Because a database migration can succeed technically while quietly damaging the data that your entire application depends on.
