Dual-Write: Cut Over a Database Without a Freeze Window
A dual-write migration lets you cut over a production database without a freeze window. Here is how to run one safely, and when to reach for it instead.
A dual-write migration lets you move a production database off a platform without freezing writes or taking downtime. The idea is simple: for a window, your application writes to both the old system and the new one, you backfill the history, you verify the two match, and then you flip reads to the new database and turn off the old writes. No maintenance window, no "the app is read-only for six hours" email. It is more work than a dump-and-restore, and you should not always use it, but when the system cannot go down, this is the pattern.
Why not just dump and restore
Dump-and-restore is fine when you can afford a freeze. You stop writes, export, import, cut over, done. The problem is the freeze scales with your data. A small database freezes for minutes. A large, busy one freezes for hours, and hours of downtime on a system that takes writes is often unacceptable. That is when dual-write earns its complexity. If you can take the freeze, take it, and follow the simpler path in migrating off managed cloud without downtime. Dual-write is for when you cannot.
The four phases of a dual-write cutover
Backfill first. Copy the existing data from old to new. This runs while the app still reads and writes the old system, so it does not need to be fast, only complete. Snapshot a consistent point and load it into the new database.
Turn on dual writes. Deploy a change so every write goes to both databases. New rows land in both. Now the two systems only differ by whatever changed between your backfill snapshot and the moment dual writes started, which you reconcile with a second, smaller catch-up copy. Keep reads on the old system for now.
Verify they match. This is the phase people rush and regret. Run comparison checks: row counts, checksums on key tables, spot-checks on recent records. Do not flip reads until the new database provably matches the old one under live traffic. Clean data matters here, so do the cleanup before you start, not during, which is the whole argument in cleaning your data before you migrate platforms.
Flip reads, then stop old writes. Once verified, move reads to the new database. Watch it under real load. When you are confident, stop writing to the old system. Keep the old database around, still receiving nothing but intact, until you are certain, then decommission it.
The failure modes to plan for
Dual-write introduces a real risk: a write can succeed on one database and fail on the other, leaving them out of sync. Decide upfront how you handle a partial write. Usually you treat the old system as source of truth during the transition, log any divergence, and reconcile continuously. Your verification checks are what catch drift before it becomes corruption.
Ordering and idempotency matter too. If your dual-write path can double-apply a write on retry, you get subtle divergence. The same idempotency discipline that keeps workflows safe applies here. Have a rollback ready at every phase: if reads look wrong after the flip, you can point back at the old database because it is still current until you stop writing to it. That safety net is the whole reason to keep the old system live through cutover.
When dual-write is overkill
If your write volume is low, your data is small, or a short freeze is acceptable, dual-write is more risk than it removes. The extra code path is itself a source of bugs. Reach for it only when the downtime of a freeze is genuinely unacceptable and the data is large enough that a freeze would be long. For most systems, a planned freeze at a quiet hour is simpler and safer, and moving the box itself is covered in moving a VPS to a new provider without downtime.
I have run both kinds of cutover across the portfolio. The rule I use: match the technique to the cost of downtime, not to how sophisticated you want to look. When the system truly cannot pause, dual-write onto infrastructure you own through HostSSH gets you off a managed platform with nobody noticing. When it can pause, freeze it and go home early. The skill is knowing which situation you are actually in.