migration-patterns-plugin/skills/dual-write/SKILL.md
Dual-write pattern for safe data store transitions. Use when planning DB migrations, switching storage backends, or reviewing code writing to multiple systems simultaneously.
npx skillsauth add laurigates/claude-plugins dual-writeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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 |
tools
Scaffold a new ComfyUI custom-node repo (pyproject, CI, release-please, vitest+pytest, JS extension skeleton) in the picker/gesture vein. Use when bootstrapping or init-ing a comfyui node pack.
tools
Orchestrate a ComfyUI node pack from idea to registry: scaffold, create + seed the repo, open the gitops adoption PR. Use when releasing or spinning up a new comfyui node pack.
testing
macOS EndpointSecurity/EDR high CPU & battery drain. Use when Kandji ESF / XProtect pegs a core; trace the exec storm via powermetrics + eslogger.
development
odiff pixel-by-pixel image diffing. Use when comparing screenshots, detecting visual regressions, diffing before/after PNGs, asserting golden images.