The situation
Consider a B2B payments provider whose original monolith has carried the company for years. Volume keeps growing, month-end peaks now approach the limits of a single primary database, and every release has become a coordinated, out-of-hours event.
A rewrite that stops feature work for a year is not an option, and neither is a maintenance window. Customers run payroll and supplier payments through the platform at all hours.
The challenge
Exactly-once money movement
Network retries and partial failures can never result in a payment being lost or applied twice.
No downtime budget
Traffic must shift gradually, with an immediate way back at each stage.
A data model full of history
Years of business rules live in stored procedures that nobody has fully documented.
The approach
- 1
Map and instrumentWeeks 1–4
Trace real transaction paths, record the undocumented rules and add the measurements needed to compare old and new behaviour.
- 2
Build the ledger and backboneWeeks 5–12
Introduce a double-entry ledger and Kafka backbone alongside the monolith, using idempotency keys on every write.
- 3
Shadow and reconcileWeeks 13–18
Mirror production traffic to the new services and reconcile every result against the monolith until differences are explained.
- 4
Gradual cutoverWeeks 19–24
Move customers across in small cohorts behind routing controls, with automatic rollback tied to error budgets.
Key decisions and trade-offs
Strangle the monolith instead of rewriting it
Why: Value arrives early and risk stays contained to one domain at a time.
Trade-off: Two systems run side by side for months, which adds temporary complexity.
Treat the ledger as the source of truth
Why: Double-entry accounting makes errors detectable by design and simplifies audit.
Trade-off: Every product flow has to be remodeled in ledger terms.
Keep PostgreSQL rather than adopt a new database
Why: The team already operates it well, and partitioning meets the projected load.
Trade-off: A future step-change in volume may require revisiting this.
How success is measured
| Measure | Baseline | Target | How it’s measured |
|---|---|---|---|
| Peak throughput | Limited by primary database | 4× current peak | Load test against production-shaped traffic |
| Availability | Unmeasured | 99.95% objective | SLO dashboards on successful authorisations |
| Authorisation latency | Varies at peak | <250ms at p95 | Distributed tracing |
| Reconciliation breaks | Investigated by hand | 0 unexplained each day | Automated daily ledger reconciliation |
Key takeaways
- Shadow traffic finds the undocumented rules that interviews never will.
- Decide what "correct" means in numbers before migrating a single customer.
- Rollback has to be rehearsed, not just designed.