inparlor.
engineering#custom-software#modernization#engineering

Modernizing legacy software without downtime

The strangler-fig pattern in plain English, the right order for data migration, parallel-run safety, when a rewrite beats a refactor, and a 90-day plan.

5 min read·May 27, 2026

Marcus Reyes

Principal Engineer · Last updated May 27, 2026

The system runs the business and everyone is afraid of it. The developer who built it left in 2019. The vendor stopped patching it. Every new feature takes a quarter, every deploy is a ceremony, and somewhere in the back of your head is the date when the thing it runs on goes end-of-life.

The instinct is the big rewrite: freeze the old system, build the new one next to it, cut over on a weekend, champagne. That plan has a name in the industry — it's called the way projects die. Eighteen months in, the new system covers 70% of what the old one does, the business has kept changing, and now you're maintaining two systems while shipping zero features.

There's a better way, and it's boring on purpose.

The strangler fig, in plain English

A strangler fig is a tree that grows around another tree, replaces it limb by limb, and eventually stands on its own. That's the pattern: you don't replace the legacy system, you surround it.

Concretely:

  1. Put a thin routing layer in front of the old system — a reverse proxy, an API gateway, sometimes just DNS.
  2. Pick one capability. Build only that in the new stack.
  3. Route that one slice of traffic to the new code. Everything else still hits the old system.
  4. Repeat until the old system handles nothing, then turn it off.

The business never stops. There is no big-bang cutover, no weekend of prayer. Each slice is small enough to reverse if it misbehaves — you flip the route back and you're exactly where you were yesterday.

Migrate data in the right order

Most modernization pain isn't code, it's data. The old system's database is the real legacy: undocumented columns, implicit rules, twenty years of edge cases stored as rows. The order of operations matters more than the technology.

Reads first, writes last.

  1. Mirror the data. Stand up the new database and sync it from the old one — change-data-capture if the old system supports it, scheduled jobs if it doesn't. The old system remains the source of truth.
  2. Point reads at the mirror. New features and carved-out slices read from the new database. If the sync has gaps, you find out from a stale report, not a corrupted order.
  3. Dual-write the first workflow. When a slice needs to write, write to both systems and compare. Disagreements are bugs in your understanding of the old system — every one you catch here is an incident you didn't have.
  4. Flip the source of truth for that slice only. The old system now mirrors from the new one for that table, or stops caring about it entirely.

Teams that invert this — migrate writes first because "that's where the value is" — are choosing to debug data corruption in production. Reads are rehearsal. Rehearse.

Parallel-run: the safety net that actually works

For anything that computes something — invoices, payroll, commissions, eligibility — don't trust tests alone. Run both systems on the same real inputs and diff the outputs.

A parallel run is mechanical: every night, feed yesterday's real transactions through the new code, compare its answers to what the old system actually did, and review every mismatch. At first, the mismatch report is long; most of it will be the old system being wrong in ways the business has silently absorbed for years. You'll have to decide, case by case, whether to replicate the old behavior or fix it — that decision log becomes the most valuable document of the whole project.

When the diff report has been empty for two or three weeks of real volume, you cut over. Not because a test suite passed — because the new system already did the job, in production conditions, and nobody could tell the difference.

When a rewrite actually beats a refactor

Rarely. But not never. A ground-up rewrite is the right call only when most of these are true:

Rewrite vs strangle

Dimension
Rewrite signals
Strangle signals
Platform
The runtime itself is dead — unsupported language version, vendor gone, hardware EOL
The platform is unfashionable but patchable
Size
Small enough that one team can rebuild it in under ~6 months
Years of accumulated behavior nobody fully knows
Spec
The real behavior is documented or simple enough to observe completely
The code is the only spec
Coupling
Standalone tool with clean inputs and outputs
Tentacles into every other system in the company
Business
Can tolerate a feature freeze during the rebuild
The roadmap can't stop

The honest summary: rewrite small, well-understood, decoupled things. Strangle everything else. The systems people most want to rewrite — big, load-bearing, mysterious — are precisely the ones where a rewrite fails.

The 90-day modernization plan

You don't need a two-year roadmap to start. You need 90 days of disciplined groundwork.

Days 1–30: understand and de-risk. Inventory what the system actually does — not what the docs say, what the logs say. Get it into version control if it isn't. Get a staging environment that matches production. Add monitoring so you know what normal looks like. No new code yet; this month pays for the next twenty-four.

Days 31–60: build the seam. Stand up the routing layer in front of the system with 100% of traffic still passing through to the old code. Stand up the new database mirror and let the sync run. Ship the deploy pipeline for the new stack. Nothing user-visible has changed, and that's the point — you've built the machinery of replacement without betting anything on it.

Days 61–90: carve the first slice. Pick that low-risk, visible capability and move it: route its traffic to new code reading from the mirror. Parallel-run anything it computes. Demo it. By day 90 you have proven the pattern end to end, and every slice after this one is repetition, not invention.

From there it's a drumbeat — a slice every few weeks, each one shrinking the legacy footprint, none of them capable of taking the business down. Modernization stops being a project with a terrifying go-live date and becomes a habit with a burndown chart.

The big rewrite asks the business to hold its breath for two years. The strangler fig never asks it to hold its breath at all.

Legacy modernization is core full-stack work for us, usually paired with an integration layer that keeps the old and new systems honest while both are alive — and a maintenance retainer so the new system never becomes the next legacy. Got a system everyone's afraid to touch? Tell us what it runs, and we'll map the first slice.


Read next:

Related:

Work with us

The team that builds this is for hire.

Marcus leads SaaS and web application builds at Inparlor, from first MVP commit to multi-tenant systems carrying real production load.If this is the kind of work you need, here's where to start.

Get the next one

One operating note a month. No drip sequences.

Subscribe for one substantive piece a month plus the occasional working playbook we don't publish elsewhere.

Monthly notes on shipping software. No fluff, unsubscribe any time.

Want to talk?

Get a proposal

Send a 1-page brief; we respond in 48 hours with scope, pricing, and the team that would actually run the engagement.