Yes, in most cases you should put an API layer in front of your legacy system before you replace anything, as long as it has a clear boundary, contract tests and a date to retire it. Done that way, application modernization stops being one risky rewrite and becomes a series of small moves that your new web and mobile apps can ship on right now.
You probably know the situation. There is a core system, maybe a customised ERP, a twenty-year-old Java or .NET monolith, or a database packed with stored procedures, and nobody wants to touch it. The people who wrote it have left. The business wants a customer app, a partner portal or a modern dashboard, and every plan seems to start with "first we rewrite the core".
There is a better order.
What does an API layer in front of a legacy system actually do?
An API layer sits between your new applications and the old core. New apps talk only to the layer, the layer talks to the legacy system, and nothing new ever reaches into the old database directly.
It comes in two shapes. A facade is a thin, clean interface: it exposes the operations you need, such as "get order" or "create customer", and hides the awkward calls behind them. An anti-corruption layer goes further. It translates the legacy model into the model your new apps should use, so a customer record split across four tables with cryptic status codes like ST_7 becomes one clear object with a status of "on hold".
The second shape matters more than most teams expect. Without translation, your new mobile app quietly inherits every odd rule and naming choice of the old core. You have not modernised anything. You have moved the mess onto a newer screen.
Why does this let new apps ship while the core keeps running?
Because the layer separates two timelines. The web and mobile teams build against a stable contract, while the old system keeps doing its job behind it, untouched.
Once that contract exists, you can replace what sits behind any single endpoint later. Move "customer lookup" to a new service, point the layer at it, and the apps never notice. This is the strangler pattern, and the API layer is the piece that makes it possible.
When does an API layer only hide the problem?
A facade hides the problem when it becomes permanent and nobody owns the core behind it. Watch for these signs early:
- The layer is a pass-through. Every endpoint maps one to one onto a legacy call, with the same names and fields. That is a proxy, not a boundary, and it freezes the old model into every new app.
- Business logic is creeping into the layer. Discount rules, eligibility checks or validation get copied into the facade "just for now". You now have two sources of truth that will drift apart.
- Writes go around it. The new app reads through the API, but a batch job or a reporting tool still writes straight into the legacy database. The layer cannot protect data it never sees.
- Nobody can name what moves first. If there is no list of which capability leaves the legacy core first, the layer is just one more system to maintain forever.
The cost of getting this wrong is quiet on day one. It shows up a year later as two systems to patch, releases that still wait on the old core, outages you cannot trace because the failure happens three hops away, and a team that now fears two systems instead of one.
Who does not need an API layer?
If your legacy system already exposes a reasonably clean, documented API and only one new app consumes it, you may not need another layer. Adding one just adds a network hop, a deployment and something else to monitor.
The same goes for a core that is small, well understood and covered by tests. There, a careful staged replacement can be faster than building a boundary you will throw away in a few months. Be honest about which situation you are in before anyone starts building.
What should you require from the team building it?
This is where these projects succeed or fail, and you can ask for every item in writing before work starts.
1. Contract tests on both sides. Each endpoint needs tests that pin down exactly what it accepts and returns, using a tool like Pact or schema checks against an OpenAPI spec. They run against the legacy-backed version today and against any replacement later. If both pass the same suite, you can swap the backend safely. Without them, every migration step is a guess.
2. A written read/write boundary. Reads through the facade are low risk. Writes are where data gets corrupted. Ask for a list of every system that writes to the legacy data store, plus a rule that all new writes go through the layer. If an old job still writes directly, decide whether to route it through the layer or freeze it before anything else moves.
3. Translation, not mirroring. Ask to see the domain model the new apps will use. If it reads like the legacy table names, push back.
4. Visibility from day one. Every request should carry a correlation ID into the logs on both sides of the layer. Timeouts must be set on purpose, because slow legacy calls can blow through a default 30 second timeout and leave users staring at a spinner. When the core is down, the apps should get a clear error, not a hang.
5. A retirement plan with an order. You want a list of capabilities in the order they will move off the core, and a definition of "done" for each. If the team cannot produce this, you are paying for a permanent facade.
In what order should you do it?
A simple sequence works for most teams:
- Map who calls the core today and who writes to its data.
- Pick the one capability the new app needs most, usually a read such as order status or account details.
- Define the contract for it in the new domain language, then write the contract tests.
- Build the layer for that capability only, and ship the new app feature against it.
- Add writes one at a time, each behind its own tests and a way to switch back.
- When a capability has stable contracts, replace its backend and retire that part of the core.
Use simple decision rules along the way. If a capability changes often and blocks the business, move it off the core early. If it is stable and rarely touched, leave it behind the facade longer. If two capabilities share tangled data, move them together or not at all.
The trade-off is plain: you accept an extra component for a while in exchange for shipping now and replacing the core in pieces you can test and reverse.
For a wider view of when to wrap, rebuild or replace, the guide to legacy system modernization walks through each option and its risks.
What is the next step?
If you have a core system nobody wants to touch and a new app waiting on it, send your current architecture or modernisation plan to Geminate Solutions for a free review. You get an NDA before we talk and a reply within 24 hours.
Top comments (0)