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.
