Architecture · · 8 min read

Mid-migration, you run three systems. Your pen test scope lists one.

A legacy migration runs old and new side by side for months, joined by proxies, sync jobs and temporary accounts. That bridge is the riskiest code you own, and last year's test scope has never heard of it.

By Precision Code Studios, Engineering team

Somewhere in your company this month, someone is writing the scope for next year's penetration test, and the quickest way to do it is to open last year's and change the dates. It lists the customer application by its address, the API by its hostname, perhaps the admin portal. It was accurate in January.

Since then, the modernisation started. Account management now runs in a new service. A routing layer in front decides which requests go to the old system and which go to the new one. A nightly job copies customer records between two databases, using a service account that can write to both. The old account pages are gone from the menu but still answer if you know the address. None of that is on the list, because all of it is meant to be gone by summer.

The test will come back clean on what it was asked to test. The way in will be in the middle.

A migration is three systems, for longer than planned

Most legacy modernisation now follows the strangler fig pattern, named after the tropical fig that grows around a host tree and eventually replaces it. You build new pieces beside the old system, move traffic to them one slice at a time, and switch old parts off as they empty. It is the right way to modernise something the business cannot do without. Our earlier article "Eating the monolith, one slice at a time" explains how to carve out the slices. This one is about what holds them together in the meantime.

What the pattern diagrams underplay is the period in between, which is where the system spends most of the project. For that period you are running three things: the old system, the new one, and the machinery that joins them. Call it the bridge. It is built quickly, by people working to a cutover date, and designed to be thrown away. It gets less review than product code because it ships no features. It needs broad access, because its whole job is to touch both sides. And since it is temporary, nobody plans to own it once the migration team moves on.

Three columns: the old system inside a dashed box marked last year's scope, the new services on the right, and an orange bridge between them holding the routing layer, identity handoff, sync job and reconciliation tool, with six numbered weak points.
Last year's scope covers the old system. The six numbered points match the six leaks described below.

Temporary code outlives its plan with remarkable reliability. A migration planned for two quarters takes four, the last slice is always the awkward one, and the bridge built for six months enters its second year with the credentials it started with.

Where the bridge leaks

These are the findings to expect when a system is tested mid-migration. None of them is exotic. Each one starts as a reasonable shortcut taken by a team trying to hit a date.

  • Authorisation checked on one side. The routing layer checks the user's session, then passes the request to the new service with a header saying who the user is. The new service believes the header. If that service can be reached by any path that skips the router, whoever reaches it can claim to be anyone.
  • Retired routes that still answer. Traffic moved to the new endpoint and the old one left the menu, but the code behind it still runs, without the fixes that went into its replacement. OWASP's 2023 API Security Top 10 places improper inventory management, including old API versions left running, ninth on its list.
  • The account that reaches both sides. Sync and dual-write jobs (code that applies every change to both databases) need write access to both. Their credentials usually sit in a pipeline variable or a config file and never get rotated, because the job is going away.
  • Tools built for the team. Pages and scripts for comparing and repairing records between the two systems are written for internal use, protected by a shared password or nothing, and then deployed somewhere the internet can find them.
  • Two ideas of who is logged in. Signing out of the new system does not end the session in the old one. A password reset on one side does not revoke what the other side issued. The exchange of tokens between them accepts more than anyone intended.
  • Logs that never meet. The old system logs to the old place and the new system to the new one. Someone moving across the bridge leaves two half-stories, and nobody's job is to put them together.

Most of these are invisible from the old system's front door and from the new system's front door. They live in the seam, which is why a scope that lists front doors does not find them.

Why the annual test misses it

Scopes are written from asset registers, and the bridge is rarely in the register because it was never meant to be an asset. Testers are often asked to keep away from migration components so the test does not disturb a cutover, which is a bit like skipping the scaffolding inspection because the builders are on it. And the test is booked for the same month every year, so whether it lands before the first slice, at the busiest point or after the old system has gone is a matter of luck.

For some companies this is also a compliance question. PCI DSS, the card industry's security standard, requires in version 4.0.1 that internal and external penetration tests happen at least every 12 months and after any significant infrastructure or application change. If your migration touches the systems that handle card data, moving customer-facing functions onto new services behind a new routing layer is hard to describe as insignificant. Whether a particular cutover counts is for you and your assessor to agree, and that conversation goes better before the cutover than during the audit.

Test at the milestones, not the month

The remedy is to stop booking the test by calendar and tie it to the migration plan. Three points carry most of the value.

  • When the first slice takes real traffic. Test the bridge design: the router, the identity handoff, the sync job, the network paths to the new services. This is the most valuable of the three, because every later slice copies the pattern. A flaw found here is fixed once. Found after the sixth slice, it is fixed six times.
  • At the widest point. Somewhere in the middle, the most components run side by side and the most temporary tools exist. Test the whole seam, including everything added since the first test.
  • After the switch-off. Confirm the old system is actually gone. Old routes return nothing, the sync account is revoked, firewall rules and DNS records are removed, and copies of the old database exist only where you decided they should.
A timeline in which attack surface rises when the first slice goes live, peaks while old and new run together, and falls at switch-off. Annual tests land at arbitrary points; three milestone tests sit at first slice, widest point and switch-off.
The attack surface follows the migration, not the calendar. Book the tests where it changes.

Each of these tests is smaller than a test of the whole estate, and together they can replace the annual test for the systems being migrated rather than sit on top of it. The switch-off check is usually the shortest of all, since most of it is confirming that things are absent.

You may not need all three. If the migration is a single cutover over a weekend with no long coexistence, one test after cutover plus a switch-off check is enough. The three-point pattern earns its cost when old and new will run together for more than a quarter, which, in our experience, describes most migrations of systems that matter.

Write the scope from the migration diagram

The asset register tells a tester what you own. The migration team's architecture diagram tells them what you are running. When we scope a test for a system mid-migration, we start from that diagram and the cutover plan, then put a short set of questions to the people building the bridge. Any buyer can ask the same questions of their own team or of a vendor before a test is booked.

  • What decides where a request goes? And on each path, where is the user's permission checked? If the answer is the router, ask what stops a request from reaching the service without passing through it.
  • Which credentials can touch both sides? Every service account, API key and database user the bridge relies on, each with an owner and an expiry date.
  • What have you built that you plan to delete? Reconciliation tools, feature flags, temporary endpoints, admin scripts. If no such list exists, that is the first finding.
  • When a route moves, what turns off the old one? The answer should be a named step in the cutover runbook. A good intention does not count.
  • Where do the logs from both sides meet? There should be one place where someone can follow a single user across old and new.
  • Who owns the bridge when you leave? If the migration team rolls off before the last slice, someone else inherits the riskiest code in the estate, usually without being told.

Make gone a deliverable

The bridge is safest while the people who built it are still around. A finding on a sync job raised while the migration team is in the room is an afternoon's work. Raised a year after they rolled off, it starts with archaeology: who wrote this, what reads from it, and what breaks if we turn it off.

That argues for putting testing inside the migration budget, as milestones with dates, rather than in a separate security budget running on its own calendar. It also argues for treating decommissioning as work with a definition of done, signed off like a feature. Migration plans are good at celebrating the moment traffic moves. They are poor at recording the moment the old door is bricked up, and nobody is paged when it never happens.

Every migration plan has a date on which the old system is switched off. Very few have a second date, a week later, on which someone tries to get in through it.

The short film: transcript

Mid-migration, the riskiest code is the bridge.: the short version (1:15)

Modernising an old system one slice at a time is the right call. But for months, the most exposed thing you run is the part nobody plans to keep.

Think of the router deciding where each request goes, the nightly job copying customers between databases, the admin page for fixing records. All of it was written fast, by a team chasing a cutover date.

Because it's meant to disappear, nobody rotates its passwords or gives it an owner. And a plan for two quarters has a habit of running to four.

So testers knock on the old front door and the new one, and nobody tries the corridor between them. The report comes back clean, and it's honest about the wrong thing.

The first of those is worth the most. Every later slice copies its design, so a flaw caught early gets fixed once instead of six times over.

Plans celebrate the day traffic moves. Add a second day, a week later, when someone tries to get in through the door you believe is closed.

Book those tests inside the migration plan, while the people who built the bridge are still around to fix what turns up.

Read the full article at Precision Code Studios.

How we help: Custom Engagement. A hybrid of staffing and managed delivery, extended with the specialist services your business needs.

Keep reading

  • Eating the monolith, one slice at a time. (Architecture, January 15, 2026)
    Rewrites fail. Slicing works. How to carve services and micro frontends out of a legacy system, with each new piece able to run on its own or plugged back into the old application.
  • The customer said yes. Then security sent the spreadsheet. (Security, October 22, 2026)
    The deal is agreed. Then the security questionnaire arrives, and a few of its rows are engineering work in disguise. How to find them, answer them honestly and still sign before the holidays.
  • Pen test reports land in November. Code freezes land in December. (Security, October 20, 2026)
    Most of what a penetration test costs arrives after the report: engineering time nobody reserved, on code nobody owns, before a freeze nobody moved. How to sort findings by the work they need, name owners and book the retest now.

All insights