
Your frontend deserves its own backend
Posted 15 Mar 2026
In recent years, across different customers and projects, I keep running into the same problem. Teams build an API for integration with other components, and then connect their SPA and management application to that same API. One service, serving everyone.
It works — until it doesn't. As the frontend evolves endpoints need to change because they need different data shapes. Changes in endpoints sooner or later break its consumers.
Another risk arises from piling on too many responsibilities in a single service. This became clear at one customer, when sensitive management endpoints — strictly intended for internal tooling — ended up in the API exposed to external integration consumers. Not through malice, but because everything lived in the same API surface and nobody had drawn the line.
General purpose vs single-purpose
The core of the issue is that not all endpoints are alike. There are different expectations for calls that are consumed within a module versus calls that are consumed outside your module, or even your team. These are best represented with the API and BFF paradigms.
An API is a contract with the world. It has consumers you may not know about, and it must never break them. You version it carefully, you deprecate slowly, and you think hard before changing a response shape. It speaks JSON or XML, always.
A BFF is the opposite. It exists to serve exactly one client — your SPA, your mobile app, your management application. It can return whatever shape that client needs, including HTML fragments if you're using HTMX. It should evolve freely alongside the client, owned by the same team, deployed on the same cadence.
Sam Newman, who coined the BFF pattern, describes them as a "Single-purpose Edge Services for UIs and external parties". Single-purpose is the key word.
Given the difference in expectations it makes sense to separate these endpoints into independent services.
Keep 'em separated
So how do you determine whether your endpoints are an API or a BFF? There are three main concerns:
Coupling and evolution. A BFF changes when the UI changes — endpoint names, response shapes, query parameters, all fair game. An API must guarantee stability for every consumer. These two requirements are fundamentally incompatible in a single service.
Format. An API speaks JSON or XML, always. A BFF can return whatever the client needs. If you're building with HTMX, your BFF might return HTML fragments directly. Trying to accommodate both from one service forces compromises that benefit neither.
Authentication model. A BFF authenticates users — it sits at the boundary where a person logs in via OIDC and gets a session. An API authenticates machines — services and integrations using client credentials. These are different trust models with different security boundaries. When you mix them in one service, you either over-expose functionality to machine consumers or under-restrict what authenticated users can reach.
The rule of thumb
If something other than your own frontend is calling it, it's not a BFF — it's an API. Build it accordingly from the start. Do not allow any other client to access a BFF.
Conversely, do not give in to the temptation to add presentation specific endpoints for a client to an API. Create a new service and apply client specific adaptations there.
This applies to third parties too. If an external party wants to build their own application on top of your platform, they should implement their own BFF on top of your APIs. Not consume yours directly from their frontend.
The cost argument
Splitting an API surface makes sense conceptually but when you need to deploy multiple services for your module, it costs real money. This is the most common counter argument, and it's worth taking seriously. A service is a unit of deployment with its own pipeline, infrastructure, and operational overhead.
The reframe is this: if your BFF and your API evolve at different paces and for different reasons, they should be separate deployment units. That's not overhead — that's the design working correctly. The cost of separation is visible. The cost of not separating shows up later, in a production incident or a security review.
In a modern container environment the marginal cost of an additional service is low. The incident cost is not.
Separation pays off
When you enforce the distinction between APIs and BFFs, frontend teams can iterate without fear of breaking integration consumers. API consumers get the stability guarantees they need. Management functionality stays where it belongs — behind a BFF that only the management application can reach.
Next time you add an endpoint, ask yourself: who is this for? Does this endpoint belong here? Split your services to fit their purpose.
Leave a comment