Next.js as an integration layer for legacy systems: modernise without the big bang

SAP, TYPO3, Salesforce and ageing ERP systems aren't going anywhere. They still have to talk to modern frontends. How Next.js works as an integration layer and Backend for Frontend to decouple legacy step by step, what holds the pattern up, and where it tips over.
10 min readMatthias RadscheitMatthias Radscheit
Happycodingen-US

TL;DR

A Next.js integration layer for legacy systems sits in front of old backends through Route Handlers: it aggregates SAP, ERP and CMS behind a modern frontend without replacing them. That makes Strangler Fig modernisation far more realistic than any big-bang migration, as long as the layer never accumulates business logic and turns into a distributed monolith.

  • Next.js doesn't replace legacy, it wraps it: Route Handlers aggregate several data sources behind one frontend and hide an old SAP, ERP or CMS system behind a modern API layer.
  • The Strangler Fig pattern makes modernisation incremental. Feature by feature moves from the old system into the new layer, instead of betting everything on a big-bang replacement.
  • For pure backend-to-backend integration with no frontend tie, a dedicated platform (Kong, MuleSoft, a backend of your own) is usually the cleaner, language-agnostic choice over a Next.js BFF.
  • The layer adds a network hop: more latency, another deploy, one more point of failure. Server Components should fetch straight from the source, not via your own Route Handler.
  • If the layer accumulates business logic and chains synchronously into SAP, Salesforce and ERP, you get a distributed monolith, harder to operate than what it was meant to replace.

SAP isn't going away. TYPO3 isn't going away. The ERP that has carried the order logic since 2009 isn't going away either. These systems aren't a problem you solve, they're the reality you work in. The question is never how to replace them. It's how to put a modern frontend in front of them without disappearing into a three-year migration.

That is where Next.js gets interesting, and not in the role it's usually sold for. Not as a renderer for the fast marketing site, but as a layer between the browser and the backend zoo. Through Route Handlers, Next.js aggregates several data sources, normalises them, and hands the frontend exactly what it needs. It becomes an integration layer in front of the backend, not a replacement for it. That sounds unspectacular. It is also the reason modernisation becomes realistic at all in a lot of organisations.

Why a Next.js integration layer for legacy systems beats what big-bang replacements promise

The most expensive decision in legacy modernisation is to replace the old system in one go. It sounds clean: a new system, one migration, a cut-over date, and after that everything is better. In practice it's a high-stakes bet with poor odds. For the entire build the project delivers no value, the old system keeps running in parallel, and on go-live day you find out whether two years of work hold up or not. With a SAP Commerce stack, where the implementation moves quickly into the high six-figure to seven-figure range according to partner estimates (those are figures from a migration provider, not an official price list, so read them with the appropriate caution), that bet simply isn't defensible.

The alternative is a Next.js integration layer in front of the legacy estate that breaks the risk apart. Martin Fowler coined the image of the Strangler Fig for this: the fig that grows around a tree and replaces it piece by piece until it stands on its own. In practice that means small additions alongside the old system, taking over behaviour feature by feature, the legacy shrinking while the new thing grows. Fowler is honest about it. The pattern doesn't make the exercise *easy*, and it demands accepting a transitional architecture that looks ugly for a while. But it delivers value from week one, and no single day decides success or failure. Microsoft describes the same Strangler Fig mechanism as a facade that intercepts requests and, depending on progress, routes them to the legacy or to the new service.

The fig needs a layer that owns this routing. A place where it gets decided: this data still comes from SAP, that data already from the new service, and the frontend notices none of it. That place can be Next.js.

What Route Handlers do as an integration layer

Technically the pattern is unspectacular, and that's a good thing. Next.js documents the Backend for Frontend officially, through Route Handlers, the proxy convention and, in the Pages Router, API Routes. A Route Handler takes a request from your own frontend, calls the ERP, the CMS and maybe a pricing service in the background, stitches the responses together, strips out the noise, and returns a clean answer tailored to the UI. The internal systems stay invisible. The frontend never talks to SAP directly. It talks to your layer.

Sam Newman, who coined the BFF term, frames the principle as "one experience, one BFF": the layer belongs to the frontend team and is tailored to exactly one experience. It isn't a universal gateway, it's the bespoke adapter between one specific surface and the messy backend world behind it. That's the strength, and at the same time the limit I'll come back to.

The official documentation is remarkably honest on one point, and decision-makers should commit this sentence to memory: the backend capabilities of Next.js are not a full backend replacement, they're an API layer. That isn't a weakness, it's the correct self-assessment. Using Next.js as a BFF doesn't replace the system of record. It decouples the frontend from its quirks. The order logic stays in the ERP, where it belongs. The layer only makes it consumable.

Combined with the rendering mechanics of Next.js, this becomes more than a proxy. Server Components cut the JavaScript shipped to the browser, and Incremental Static Regeneration serves pre-rendered pages from cache for most requests, which genuinely lowers the load on the legacy systems behind it. An old ERP that had to answer every product page live buckles under traffic. Behind an ISR layer it only answers the cache revalidations. How far response times feed through to conversion in the end I've covered at length elsewhere: the link between performance and revenue isn't a sideshow, it's often the actual business case for the whole exercise.

Which legacy systems you can decouple this way

The pattern isn't limited to e-commerce, even if SAP Commerce gives the textbook example. Its Composable Storefront is an Angular frontend that speaks exclusively through the OCC REST API. Teams that don't like that frontend, and many don't, because it demands Java/Spring *and* Angular competence in-house, can consume the same REST API from a Next.js frontend instead. The commerce engine stays SAP, the experience becomes a different one. I've made the broader case for Next.js and Medusa over SAP Commerce and Angular separately.

The same holds for content. An old TYPO3 or a CMS past its prime serves content through an API, and Next.js renders it in a modern shell. At its core this is the headless approach with WordPress and Next.js, except the "headless" is bolted on after the fact here rather than planned from the start. Anyone reconsidering CMS strategy in general should understand the difference between a CMS and a DXP before building the layer, because the layer's architecture looks different depending on the answer. And anyone still deciding whether TYPO3 should remain the basis at all will find my arguments against TYPO3 in 2026 elsewhere.

Salesforce, Microsoft Dynamics ERP, in-house systems from the noughties: all of them have an API today or can have one put in front with manageable effort. The integration layer aggregates them. The customer sees one surface pulling data from three systems and notices nothing of the fragmentation behind it. That's the real value. The organisational and technical splintering in the backend gets hidden from the user without having to be resolved first. The resolving can come afterwards, feature by feature, on the Strangler Fig cadence.

When a real integration platform is the better choice

Here I have to argue against my own thesis, otherwise the piece would be dishonest. A Next.js BFF is an integration layer *for a frontend*. The moment the task is primarily integration with no frontend tie, backend talking to backend, system syncing with system, data flowing between ERP, CRM and data warehouse, a frontend framework is the wrong tool.

For those cases there are dedicated integration platforms: an API gateway like Kong, integration middleware like MuleSoft, or a backend of your own in the language you prefer. These solve aggregation centrally, language-agnostically and for any number of consumers. They bring rate limiting, protocol transformation, observability and authentication as platform features, not as hand-rolled Route Handler code. When five different consumers need the same aggregated data, a central gateway beats five BFFs duplicating the same logic, and Newman names code duplication between BFFs explicitly as one of the two main risks of the pattern.

The honest rule of thumb: if the aggregation has a direct, specific frontend tie, the Next.js BFF is closer to the problem and faster to build, because it delivers exactly the data in exactly the shape that one surface needs. If the aggregation is a generic backend job, it belongs on an integration platform. Repurpose a frontend framework into an enterprise integration bus and you build yourself a problem you'll pay to take apart later.

The uncomfortable part: the layer adds a hop

Every integration layer has a price, and it's quietly left out of the pitch. It's an extra network hop. More latency, another deploy, another point of failure. The Next.js documentation says this itself with unusual clarity: for on-demand Server Components, fetching through your own Route Handlers is slower, because an extra HTTP round trip sits in the middle. Server Components should fetch straight from the source, not take the detour through your own API layer. Ignore that and you build in latency nobody asked for.

It gets worse when the layer starts to accumulate business logic. A BFF that chains synchronously into SAP, then Salesforce, then the ERP, and waits for each response before making the next call, degenerates into a distributed monolith: separately deployed but tightly coupled services with synchronous chatty calls, latency chains and cascading failures. If the ERP goes down, the whole page goes down. That's harder to operate than the monolith the layer was meant to replace. You've bought the downsides of distribution without any of the upsides.

And even when everything stays clean, the limits of the legacy systems don't disappear, they get papered over. An ERP that can't do real-time stock levels still can't behind an elegant Next.js layer. The caching that lowers the load is at the same time the mechanism that serves stale data. Self-hosted, ISR caching only works automatically with *one* next start instance on a persistent disk; the moment you go multi-instance or CDN, you need a custom cache handler, for example on Redis, with tag coordination across multiple nodes. That's the genuinely hard part of this pattern, and it gets underestimated because the happy path looks so simple. If you'd rather not run this yourself, the trade-offs of Next.js on Hetzner versus Vercel decide a lot of it.

We've stood this layer up self-hosted several times, on Hetzner, via Coolify and Docker, with output: 'standalone'. Entry sits at around 20 to 50 euros a month; a highly available variant with redundant instances and a separate database is more like 150 to 400 euros. A clean first implementation of such a stack we budget at 5,000 to 20,000 euros one-off, with ongoing operation at two to five hours a month. As of mid-2026, treat those as our own partner figures and verify against your own context. That's all manageable, as long as the layer stays a layer and doesn't become a second backend.

What I tell decision-makers

Build the layer as thin as possible. It proxies, it aggregates, it transforms, it caches, nothing more. The moment someone proposes putting "a bit of business logic" in because it's convenient right now, stop. Business logic belongs in the system of record or in a dedicated service, not in the integration layer. That discipline is the difference between an elegant decoupling and a distributed monolith.

Treat the layer as temporary, even if it isn't. The fig is meant to replace the old tree, not clasp it forever. Microsoft warns, rightly, that the routing facade must not ossify into entrenched technical debt. Plan from the start for features to move out of the legacy into real new services and for the layer to shrink accordingly. An integration layer that's just as fat after three years as on day one has missed its point.

And decide honestly whether you have a frontend problem or a backend integration problem. If the aggregation has a frontend tie, Next.js is a good, fast-shipping choice, and knowing when Next.js is the wrong choice is part of making that call honestly. If it's pure backend-to-backend integration, take a platform built for it. The whole mechanism that makes Next.js self-hostable and sovereign to run I've pulled together in the overview of Next.js as a strategic architecture decision. The technology isn't the hard part of this pattern. The discipline is.

Frequently asked questions

Does Next.js replace my SAP or ERP system?
No. Next.js is not a full backend replacement, and the official documentation says so itself. It sits as an integration layer in front: Route Handlers proxy, aggregate and transform data from SAP, ERP or CMS and hide the internal systems behind a modern API. The business logic and the systems of record stay in the backend. The layer only decouples the frontend from the reality of the old systems.
What's the difference between a Next.js BFF and an API gateway platform like Kong or MuleSoft?
A Backend for Frontend is tailored to exactly one frontend experience and ideally owned by the frontend team. It aggregates precisely the data that one surface needs. An API gateway or integration platform solves integration centrally, language-agnostically and for many consumers. For pure backend-to-backend integration with no frontend tie, the platform is usually more dependable. The moment it's about a specific UI, the BFF is closer to the problem.
When does the integration layer itself become the problem?
When it accumulates business logic and chains synchronously into several backends. That produces a distributed monolith: tightly coupled, separately deployed services with latency chains and cascading failures. Even as a pure routing facade it can become a single point of failure and a bottleneck. Once strangulation is complete it has to be thinned out or removed, not left to ossify into permanent technical debt.
Does Next.js caching work self-hosted behind legacy systems?
With a single next start instance on a persistent disk, ISR caching works automatically and takes noticeable load off the legacy backends. With multi-instance or CDN setups you need a custom cache handler, for example on Redis, plus tag coordination across nodes. That distributed cache is the genuinely hard part, and one of the reasons you shouldn't underestimate the layer.

Sources

Related articles

Open for select projects

Let's talk about your project

Book a no-obligation call, send us an email, or use the form – we'd love to hear from you.

150+
Completed projects
15
Years of experience
8
Senior‑level team members