Zero Downtime Migration with Dual Write Pattern in Python

Implement a dual-write pattern that writes user data to both legacy and new systems simultaneously to enable zero-downtime migration.

Medium Python 3.9+ Aug 9, 2026 Production deployment patterns 13 views 0 copies

Python code

55 lines
Python 3.9+
from datetime import datetime
import json


class UserService:
    def __init__(self):
        self.legacy_db = {}
        self.new_db = {}
        self.migration_log = []

    def write_user(self, user_id, name, email):
        # Write to new system first
        user_record = {
            "id": user_id,
            "name": name,
            "email": email,
            "updated_at": datetime.utcnow().isoformat()
        }
        self.new_db[user_id] = user_record

        # Dual-write to legacy system
        self.legacy_db[user_id] = user_record.copy()
        self.migration_log.append(f"Wrote user {user_id} to both systems at {user_record['updated_at']}")

    def read_from_legacy(self, user_id):
        return self.legacy_db.get(user_id)

    def read_from_new(self, user_id):
        return self.new_db.get(user_id)

    def verify_consistency(self):
        mismatches = []
        for user_id in set(self.legacy_db) | set(self.new_db):
            if self.legacy_db.get(user_id) != self.new_db.get(user_id):
                mismatches.append(user_id)
        return len(mismatches) == 0, mismatches


if __name__ == "__main__":
    service = UserService()

    # Simulate migration traffic
    service.write_user("user-001", "Alice", "alice@example.com")
    service.write_user("user-002", "Bob", "bob@example.com")
    service.write_user("user-003", "Carol", "carol@example.com")

    # Simulate reads during migration
    print("Legacy read:", service.read_from_legacy("user-002"))
    print("New read:", service.read_from_new("user-002"))

    # Verify data consistency between both stores
    is_consistent, conflicts = service.verify_consistency()
    print(f"\nMigration log entries: {len(service.migration_log)}")
    print(f"All systems consistent: {is_consistent}")
    print(f"Conflict IDs: {conflicts}")

Output

stdout
Legacy read: {'id': 'user-002', 'name': 'Bob', 'email': 'bob@example.com', 'updated_at': '2025-01-15T10:30:00.123456'}
New read: {'id': 'user-002', 'name': 'Bob', 'email': 'bob@example.com', 'updated_at': '2025-01-15T10:30:00.123456'}

Migration log entries: 3
All systems consistent: True
Conflict IDs: []

How it works

This dual-write pattern writes to the new system first, then copies the same record to the legacy store, ensuring both databases stay in sync during migration. The verify_consistency method compares all records across both systems to detect data drift or partial failures. Timestamps are captured once and shared between stores to guarantee identical records. The migration log provides an audit trail for tracking every write operation during the transition window, which is critical for rollback decisions. This approach allows reads to continue from either system without downtime while the new infrastructure is validated in production.

Common mistakes

  • Writing to only one system when a write fails, causing divergence
  • Not using the same timestamp for both writes, creating false inconsistencies
  • Ignoring the migration log for audit and rollback analysis
  • Forgetting to handle backfill of existing legacy data before going live

Variations

  1. Use a message queue to async dual-write, decoupling the write from the DB operation
  2. Implement a read-repair strategy where inconsistent reads trigger background correction

Real-world use cases

  • Migrating a user database from a legacy monolith to a new microservice while keeping both available for reads.
  • Rolling out a new analytics store alongside the existing production database to validate query performance before switching.
  • Transitioning from a self-hosted PostgreSQL cluster to a managed cloud database without a service interruption.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Production deployment patterns

Related tutorials and quizzes for this topic.