Splitting a monolith is hard. Merging microservices back? Harder — and in 2026's consolidation wave, far more teams are about to learn it.

The plan:

  • 10 tiny services doing related things
  • Merge into 3 domain services
  • Estimated: 6 weeks

The reality: 6 months.

The estimate assumed consolidation was mostly moving code. It wasn't. Every service boundary had accumulated implicit contracts nobody had written down, and each one surfaced only when we tried to delete it.

One example that cost three weeks:

Two services both "owned" the customer address. Profile held the normalized record; Shipping kept a denormalized copy, refreshed by queue events with a few minutes of lag. The merge plan said: delete the copy, read from the single table. Then we found a nightly billing reconciliation job that read the Shipping copy on purpose — its event-driven lag made it an accidental end-of-day snapshot, and invoices depended on addresses not changing mid-run. The duplication was load-bearing. Removing it meant designing an explicit snapshot mechanism that had never existed, for a requirement that had never been documented.

More of what we discovered:

  • Three different message-queue patterns — fire-and-forget events, RPC-over-queue with reply queues, and delayed messages — each with different retry and idempotency semantics that in-process calls don't replicate
  • Service A expected JSON where Service B sent XML, papered over by a translation shim nobody owned
  • Race conditions that only manifested once merged code shared a process and lost the queue's implicit serialization
  • Nobody had the full dependency graph — we had to build one from traffic captures

What actually worked: the Strangler Fig, pointed inward

We abandoned the big-bang merge. Instead we stood up the target domain service empty and moved traffic into it one endpoint at a time through the API gateway: route reads for one resource to the new service, run it in shadow mode comparing responses against the old one, flip when they match, repeat. Each small service strangled down to zero traffic before it was decommissioned — same pattern as strangling a monolith, with the facade routing inward instead of outward. Progress became measurable in dashboards instead of promised in meetings.

Lessons:

  • Consolidation is a rewrite, not a refactor — estimate it as one
  • Document service contracts obsessively, including timing assumptions
  • Maintain a live dependency graph before you need it
  • Strangle services out endpoint-by-endpoint; never big-bang the merge

If you're weighing this path, read how the original split tends to go wrong first — splitting the monolith too fast — because bad boundaries are what make the reverse trip expensive. Boundary work in either direction is where an experienced DevOps and architecture partner earns its keep.

Lesson: Splitting is (somewhat) reversible. The cost of reversal compounds with every year the boundary stands.


← Back to Lessons Learned