Shadow account reads without duplicating booking-channel writes
The migration proposal mirrors every request to the replacement and compares responses. Some apparent reads update lastSeenAt, and write mirroring would enable a booking channel twice through different storage paths.
- Focused work estimate
- 3h 30m + prerequisites
- Priority in the scenario
- High
- Engineering practice
- Incremental migration · Side-effect analysis · Observability
Estimated field mix
- System design50%
- Backend30%
- Site reliability20%
Field percentages are editorial estimates of the ticket's engineering focus. They total 100%; they are not measured time, proficiency scores, or ownership evidence.
Pattern topics
- Strangler FigApply
Replace a bounded read surface gradually while keeping command ownership singular and making shadow failures independent of served responses.
Review it, then add it to your workspace.
The board opens an editable draft; nothing is saved until you confirm it. Sign-in and workspace permissions apply, and Demo boards remain ephemeral.
Project context
A fictional B2B scheduling service stores account settings in a legacy module whose database access leaks into HTTP handlers. A replacement must support existing clients and migration by tenant. Build a local modular application, a synthetic two-tenant dataset, and controllable old/new adapters; no baseline repository or fixtures are supplied. Keep the exercise in one application and local database, with no live customer traffic.
Setup prerequisites
- REST contracts
- Tenant authorization
- Transactions
- Dependency injection
Preceding work
Complete these dependencies, or supply their agreed outputs before taking this ticket.
Acceptance criteria
- Define an allowlist of side-effect-free reads that may run against both implementations for synthetic tenant comparison.
- Return the active implementation's response without letting shadow timeouts or failures change client behavior.
- Record bounded field-level parity differences without account content, and route every command to exactly one active implementation.
Implementation constraints
- Use the migration boundary to incrementally replace routes; do not call a mutating operation just because its HTTP verb is GET.
Verification to include
- Inject a replacement timeout and mismatched timezone; verify the active result remains correct and a bounded mismatch is recorded.
- Run an enable-channel command and a last-seen update; assert one write owner and zero shadow side effects.
Deliverables
- Safe shadow-read routing, mismatch report, and side-effect inventory
Rollout and recovery
Enable shadow reads for one synthetic tenant with an independent off switch; disable comparison without changing command ownership.
Value of the work
For the engineer: Practice incremental migration, dependency boundaries, compatibility testing, and removing abstractions that obscure behavior rather than enabling change.
For the team: Inspect a migration plan with measurable parity, explicit write ownership, tenant-safe routing, and rollback limits instead of accepting a rewrite diagram alone.
Evidence boundaries
Outcome Evidence: Tests, patches, and runbooks are requested deliverables. They become Outcome Evidence only through a qualified Mission and immutable Evidence IDs.
Ownership Evidence: Independent adaptation must be observed under a declared verification policy and cite immutable Evidence IDs. Completing a planning ticket establishes no Ownership Evidence.