From migration-patterns-plugin
Guides dual write migration pattern for safely transitioning between data stores during database migrations, backend switches, schema changes, or multi-system writes.
npx claudepluginhub laurigates/claude-plugins --plugin migration-patterns-pluginThis skill is limited to using the following tools:
Dual write keeps two data stores in sync by writing to both the old and new system on every mutation. This enables gradual migration with rollback safety.
Conducts multi-round deep research on GitHub repos via API and web searches, generating markdown reports with executive summaries, timelines, metrics, and Mermaid diagrams.
Dynamically discovers and combines enabled skills into cohesive, unexpected delightful experiences like interactive HTML or themed artifacts. Activates on 'surprise me', inspiration, or boredom cues.
Generates images from structured JSON prompts via Python script execution. Supports reference images and aspect ratios for characters, scenes, products, visuals.
Dual write keeps two data stores in sync by writing to both the old and new system on every mutation. This enables gradual migration with rollback safety.
| Use this skill when... | Use shadow-mode instead when... |
|---|---|
| Migrating between databases or schemas | Validating read-path behavior under real traffic |
| Switching storage backends (SQL to NoSQL, etc.) | Testing a new service without writing to it |
| Need both systems to stay authoritative during transition | Only need to compare responses, not persist data |
| Planning zero-downtime data migrations | Mirroring traffic to a staging environment |
| Reviewing code that writes to multiple data stores | Evaluating performance of a replacement system |
| Phase | Primary reads | Primary writes | Secondary writes | Duration |
|---|---|---|---|---|
| 1. Prepare | Old | Old | None | Setup |
| 2. Dual write | Old | Old + New | New (async or sync) | Migration window |
| 3. Backfill | Old | Old + New | New | Until parity |
| 4. Shadow read | Old + New (compare) | Old + New | New | Validation |
| 5. Cutover | New | New | Old (optional) | Transition |
| 6. Cleanup | New | New | None | Final |
| Strategy | Consistency | Latency impact | Failure mode |
|---|---|---|---|
| Synchronous | Strong | Higher (2x write) | Fail if either store fails |
| Async secondary | Eventual | Minimal | Secondary may lag |
| Outbox pattern | Eventual | Minimal | Requires message broker |
| Change data capture | Eventual | None (DB-level) | Requires CDC infrastructure |
Client Request
│
▼
┌─────────────┐
│ Application │
│ Layer │
└──────┬──────┘
│ write(data)
▼
┌─────────────┐
│ Dual Write │
│ Adapter │
├──────┬──────┤
│ │ │
▼ │ ▼
Old DB │ New DB
│
Compare on
read (optional)
| Component | Responsibility |
|---|---|
| Write adapter | Routes writes to both stores, handles failures |
| Read comparator | Reads from both, logs discrepancies, returns primary |
| Backfill job | Copies historical data from old to new store |
| Reconciliation | Detects and resolves drift between stores |
| Feature flags | Controls which phase is active per entity/tenant |
The write adapter wraps both stores behind a single interface:
During the shadow read phase:
| Failure scenario | Response | Recovery |
|---|---|---|
| Secondary write fails | Log, continue, enqueue retry | Async retry with backoff |
| Primary write fails | Fail the request (do not write to secondary) | Standard error handling |
| Both fail | Fail the request | Standard error handling |
| Secondary write timeout | Log, continue | Async verification and repair |
| Inconsistency detected | Log with full context | Manual or automated reconciliation |
| Metric | Threshold | How to measure |
|---|---|---|
| Read comparison match rate | > 99.9% | Shadow read comparison logs |
| Backfill completion | 100% | Backfill progress tracker |
| Secondary write success rate | > 99.95% | Write adapter metrics |
| P99 latency impact | < 20% increase | Application metrics |
| Reconciliation gap | 0 unresolved | Reconciliation job output |
| Pitfall | Mitigation |
|---|---|
| Ordering issues between stores | Use idempotent writes, include version/timestamp |
| Transaction boundaries differ | Design writes to be independently valid |
| Schema mismatch between stores | Map fields explicitly, handle nullability differences |
| Backfill conflicts with live writes | Live dual writes take precedence over backfill |
| Performance degradation | Start with async secondary writes |
| Partial failures leave inconsistency | Reconciliation job as safety net |
| Forgetting to dual-write in all code paths | Centralize through write adapter, audit call sites |
| Phase | Rollback action | Data impact |
|---|---|---|
| Dual write | Stop writing to new store | No data loss |
| Shadow read | Stop comparing reads | No data loss |
| Cutover (reads) | Switch reads back to old | No data loss if still dual-writing |
| Cutover (writes) | Reverse write order | May need reconciliation |
| Cleanup | Cannot rollback | Old store decommissioned |
| Context | Approach |
|---|---|
| Code review | Check that all write paths go through the dual-write adapter |
| Architecture review | Verify failure handling, rollback plan, and cutover criteria |
| Implementation | Start with write adapter + async secondary, add comparison later |
| Testing | Simulate secondary failures, verify primary is unaffected |
| Term | Definition |
|---|---|
| Primary store | The authoritative data store (old system during migration) |
| Secondary store | The new data store being migrated to |
| Backfill | Copying historical data from primary to secondary |
| Reconciliation | Detecting and repairing differences between stores |
| Cutover | Switching the primary designation from old to new |
| Match rate | Percentage of shadow reads that return identical results |
| Write adapter | Abstraction layer that routes writes to both stores |