Modernise continuously, not big-bang.
Strangler-pattern modernisation that runs alongside your roadmap — feature work continues while risk leaves the system step by step.
- Assess
- Characterise
- Extract & shadow
- Retire & repeat
The goal isn’t to move fast.
A big-bang rewrite freezes your roadmap, takes longer than anyone estimates, and lands all of its risk on one cutover date. The team spends a long time rebuilding a replica of a system that keeps changing underneath them. The business stops asking for features because the answer is always “after the migration”. Then a single weekend decides whether the programme was a success. We modernise the other way: grow new services around the old system, route traffic to them incrementally, and retire the monolith once it is already doing nothing.
The pattern has a name — the strangler fig — and a discipline underneath it. Characterisation tests pin what the system does today. Seams are carved along business boundaries, not technical convenience. The new service runs in shadow against live traffic until its outputs match an agreed bar, reads move across a percentage at a time, and writes follow only after the reads have been uneventful for an agreed period. Where the system is genuinely unknown, we start with Legacy Re-engineering first; where the destination is a different platform as well as a different design, Cloud Migration runs in the same programme.
It’s to move continuously, without ever being one deploy away from disaster. A modernisation programme that cannot ship a business feature while it runs has already failed, whatever the architecture diagram says.
Four rules we do not bend.
Modernisation goes wrong in predictable ways. These are the constraints we hold to on every programme, and the ones we will argue about before the contract is signed.
Characterisation first
Pin current behaviour with tests before changing anything, so you know the moment something breaks. We capture real inputs and outputs from production traffic and replay them against both the old and the new implementation. Until that net exists, every refactor is a guess with a deployment attached.
Seam-finding
Carve along real business boundaries, not technical convenience. A seam is worth extracting when it owns its own data, has a countable number of callers, and changes for one business reason — pricing, invoicing, notifications, document generation. Each extracted service earns its independence by shipping value on its own release train, which is also how we know the boundary was right.
Shadow & dual-write
New and old run in parallel with outputs compared on live traffic before any read cuts over. Differences arrive as a diff stream on a dashboard rather than as a customer complaint, and the acceptance bar for cutover is a match rate agreed in writing beforehand. Data follows the same rule: dual-write with reconciliation, usually over Kafka and change data capture, not one migration weekend.
Reversible cutovers
Every step has a rehearsed rollback — rehearsed on a real environment with the real data volume, not described on a wiki page. Traffic moves behind a flag that an on-call engineer can flip back, and the old path stays warm until the new one has survived a full business cycle. Cutover days hold no surprises; that is the point.
How the work runs, day to day.
Seams are found in the traffic, not in the diagram.
Every monolith has an architecture document, and every architecture document is a description of what someone intended in 2014. We work from evidence instead: call graphs from static analysis, request traces from an instrumented runtime, table access patterns from the database, and change history from the repository. The seams that come out of that exercise are rarely the modules the diagram shows. They are the clusters of behaviour that share data and change together, and they get ordered by risk-adjusted payback — how much incident load, release friction and infrastructure cost each one removes against how hard it is to extract.
- Dependency and call-graph analysis over the running system, not the documentation
- A modernisation order the business can read: what leaves the monolith first, and what it buys
- Each seam sized as a small deliverable, so progress stays visible
- 01Assess
- 02Characterise
- 03Extract
- 04Shadow
- 05Cut over
- 06Retire
The loop, run once per seam
Shadow running turns opinion into a diff.
The argument about whether the new service is correct ends the day it starts seeing live traffic. Requests are mirrored to the extracted service; its responses are compared against the monolith’s and recorded, but never returned to the caller. Mismatches are grouped by shape, so many differences usually turn out to be a few bugs — a rounding rule, a null handled differently, a legacy behaviour nobody had written down and the business still depends on. Only when the match rate holds above the agreed threshold across a full cycle, including month-end, does any read move over. Writes are dual-written and reconciled on a schedule until the reconciliation report stays uninteresting over an agreed period.
- Mirrored traffic with response diffing, grouped by difference shape rather than by request
- Written cutover criteria: match rate, period covered, and who signs it off
- Dual-write with scheduled reconciliation, so the data question is answered before the traffic question
Retirement is a deletion, not a rename.
Most modernisation programmes stall in the same place: the new service is live, the old code is still there, and now two implementations have to be maintained by one team. We treat retirement as part of the seam, not as a tidy-up afterwards. Once traffic is fully on the new path and the rollback window has closed, the old routes, jobs, tables and permissions are deleted, and the decommissioning log records what went, when, and what replaced it. That log is what turns modernisation into a cost reduction rather than an extra system.
- A rollback window with a defined end date, agreed at cutover rather than left open
- Dead code, scheduled jobs, database objects and credentials removed together
- A decommissioning log per seam, so the estate map stays true as the programme runs
What each side of the table gets.
A façade, an event backbone and a smaller blast radius.
A routing layer in front of the monolith is the first thing we build, because it is what makes everything after it reversible. New services sit behind it, publish domain events, and read their own data. Your engineers work in the programme, not next to it — pairing on the first seam, owning the second.
- Routing façade, feature flags and traffic splitting from the start
- Domain events over Kafka with change data capture off the legacy database
- Contract tests between the façade, the monolith and every extracted service
The roadmap keeps moving while the estate changes.
Feature work continuing is a design constraint on our side, not a promise on yours. Where a requested change touches a seam we have already extracted, it lands in the new service on its own release train instead of the monolith release — so the delivery benefit arrives while the programme is running, not after it ends.
- New features land in new services wherever the seam already exists
- Release cadence per service, so one risky change no longer blocks the safe ones
- A visible order of seams, so product can pull a boundary forward when the roadmap needs it
Risk leaves the system on a schedule you can audit.
Each seam is a small, costed piece of work with a stated payback: fewer incidents, a shorter release cycle, or infrastructure that can finally be scaled down. Nothing depends on a single date, so there is no year in which the programme is all cost and no value. Every cutover carries a rehearsed rollback, and every retirement is recorded.
- Spend tied to seams delivered, not to a multi-year rewrite budget
- Rehearsed rollback on every cutover, evidenced rather than asserted
- Decommissioning log as the audit trail for what has actually left the estate
What every programme includes, and what depends on your estate.
Four phases, repeated per seam.
Assess
System archaeology: dependencies, data flows, risk map, and the modernisation order that pays back fastest. We read the code, trace the traffic and interview the people who know where the bodies are buried, then put the seams in an order the business can argue with. The output is a roadmap with a costed first seam, not a slide about target architecture.
Characterise
Golden-master and contract tests around the behaviours the business actually depends on. Real production inputs and outputs are captured and replayed, edge cases the documentation never mentioned are recorded as tests, and the suite runs in CI from that point onward. This is the phase that makes every later change safe, and the one most rewrites skip.
Extract & shadow
The highest-value seams are extracted first and run in shadow against live traffic until outputs match the agreed bar, then reads cut over gradually behind a flag and writes follow with reconciliation. Feature work continues throughout — in the new service where the seam exists, in the monolith where it does not.
Retire & repeat
Old paths are deleted, not just abandoned: routes, jobs, tables, credentials and dashboards go together, and the decommissioning log records the change. Then the loop restarts on the next seam, with the previous one’s evidence making the estimate better each time.
What you have at the end of each seam.
- Modernisation roadmap ordered by risk-adjusted payback
- Characterisation test suite over legacy behaviour
- Extracted services with parallel-run evidence
- Rehearsed rollback procedures for every cutover
- Decommissioning log — what was retired, when, and what replaced it
When this is the right call.
Choose incremental modernisation when the system still earns money, when the roadmap cannot stop for a year, and when the risk of a single cutover date is unacceptable to the business — regulated estates, order and billing systems, anything where a bad weekend becomes a regulatory conversation. It is also the right call when the estate is large enough that nobody can hold it in their head: seams give you a way to make progress without first understanding everything. And it fits organisations that intend to own the result, because their engineers work inside the programme from the first seam.
It is the wrong call for a small application that one team can rewrite in a few weeks with the old one still running — the machinery costs more than the problem. It is wrong when the business logic is genuinely obsolete and the honest answer is a new product rather than a migrated one, which is a conversation for Product Discovery. And it will not work where nobody will be released to answer questions about the legacy behaviour: shadow running finds the differences, but only your people can say which of them are bugs and which are the business.
Frequently asked questions
Where this service usually sits.
Tell us what you’re building.
Describe what exists today and what you need. An engineer reads it and replies in writing with how we would approach it, and the model that fits.