Data migration validation is the comparison of migrated data against the records, transformations, and business meaning the target is required to preserve. A row count measures the size of a selected population; it does not establish that the right records arrived with the right values.

Take a source containing 10,000 records. Omit one record and load another twice: the target still contains 10,000 rows. Even an equal total leaves errors undetected. Swap balances of 100 and 900 between two customer records: the row count remains two and the total remains 1,000, but both balances belong to the wrong customer.

What each comparison establishes

A count comparison returns the difference in population size. A key comparison identifies missing or unexpected record identities; a separate uniqueness check detects repeated identities. A value comparison identifies differences between corresponding fields after the agreed transformations. A relationship check identifies records whose required links are missing or point to the wrong entities.

Business reconciliation connects those records to a required result: an account balance, an outstanding-order total, or a report for a defined period. Matching a grand total is one reconciliation check. The balance-swapping example shows why the relevant customer, account, period, and currency also belong in the comparison.

These checks answer different questions. Passing one does not supply the result of another.

The transformation contract

The transformation contract specifies which source records belong in the migration, how they map to the target, and which meanings must survive. It also records deliberate changes: deduplication, record splitting, field removal, and corrections to source defects.

Representation and meaning are separate. Converting 12,500 cents to 125.00 dollars changes the stored value while preserving the amount. Converting an unknown amount to zero changes its meaning. Removing the leading zeros from an identifier changes the identifier if those zeros distinguish it from another valid identifier.

The target determines the contract. A read-only archive requires retrievable history; a transactional replacement also requires valid new writes. The source and target do not need identical schemas or equal row counts when the agreed transformation changes their structure. They need an explainable mapping between the selected source population and the expected target result.

The same distinction separates migration fidelity from data accuracy. A faithful copy of an incorrect address remains incorrect. Correcting that address is an additional transformation with its own evidence, rather than an unexplained difference to suppress.

Comparing a consistent state

A comparison needs corresponding source and target states. If the source accepts a payment after extraction and the target has not received it, a balance difference describes two moments in time. It does not by itself identify a transformation defect.

For a fixed extract, the comparison boundary is the extract’s consistent source state. With change data capture, the boundary must account for the changes included on each side. Application comparisons likewise need matched starting data and inputs before their resulting outputs and state changes can be compared.

In AWS Database Migration Service, or AWS DMS, external writes to target tables during validation can make discrepancy reporting inaccurate. The writer and the observation point are therefore part of the interpretation of a validation result.

What zero reported failures leaves unresolved

AWS DMS compares corresponding source and target rows, but its validation excludes views and ignores columns covered by data-masking transformations. Rows under continuous modification can remain unvalidated. A failure count alone does not describe that coverage.

Take one million records selected for comparison: 980,000 checked successfully and 20,000 still pending. The failure count is zero; completed record coverage is 98%. The remaining 2% has no completed result. Coverage by record also leaves a separate question: which fields and relationships were checked inside those records?

An acceptance record therefore needs the selected population, completed checks, differences, exclusions, and unresolved work. An excluded field with a separate accepted check has a disposition. An excluded field with no check remains unvalidated, even when every reported comparison passes.

Existing rows and future writes

PostgreSQL 18 logical replication transfers table data but does not replicate schema changes or sequence state. Values in sequence-backed identity columns arrive as table data; the subscriber’s sequence does not advance to match them.

Suppose the target contains an imported record with identifier 1 while its sequence will next produce 1. Every imported field can match the source, yet a new insert using that sequence fails against the existing unique identifier. Comparing stored rows cannot establish the state required to allocate the next identifier.

Not to be confused with service acceptance

Service acceptance establishes whether the application can perform its required work under the intended operating conditions. Data validation supplies part of that evidence. It does not demonstrate application availability, workload capacity, or recovery.

In April 2018, TSB’s data moved successfully to its new platform, but technical failures immediately disrupted banking services. The Financial Conduct Authority’s December 2022 account distinguishes the successful data transfer from the failed service transition. The case establishes that distinction; it does not identify row-count checking as the cause of the failure.