SaaS technology
Businesses SaaS August 6, 2026 • 8 min read

The BFF Pattern: One API Gateway Is Slowly Killing Your App

For: A mid-level engineering lead at a B2B SaaS company whose single shared API now serves a React web app, a React Native mobile app, and a new partner-facing integration — and every frontend change requires a backend negotiation because the API returns whatever the first client needed three years ago

The Backend-for-Frontend (BFF) pattern splits your one shared API into thin, client-specific API layers — one for web, one for mobile, one for partners — each owned by the team that ships that client. Its real payoff is not smaller JSON payloads. It is giving each surface its own deploy cadence, so a mobile release stops requiring a coordinated backend change and a partner contract stops leaking your internal domain shape. If every frontend change currently needs a backend negotiation, that is the signal.

The problem: one API, three masters

The usual story goes like this. In year one, you shipped a React dashboard against a REST or GraphQL API. It worked. In year two, you added a React Native app, and it inherited that same API — because why build two? In year three, a partner asked for an integration, and someone pointed them at the same endpoints with an API key on top.

Now three things happen at once:

Every ticket becomes a cross-team negotiation. The backend team becomes a bottleneck they did not ask to be. This is the pain the BFF pattern was designed for — originally at SoundCloud around 2015, then popularized by Sam Newman.

The analogy: hotel concierge, not hotel kitchen

Think of your core services as a hotel kitchen. It knows how to cook. It does not know that the room-service guest wants a small tray with a folded napkin, the restaurant guest wants three courses plated a specific way, and the catering client wants forty portions in insulated boxes.

You do not solve this by making the kitchen output every possible plating. You put a concierge in front of each channel. Room service, restaurant, catering — each has its own person who knows their guest, talks to the kitchen in kitchen-terms, and hands the guest exactly what they need.

A BFF is that concierge. It is a thin API layer, one per client type, whose only job is to translate between what that specific client wants and what your core services actually expose.

A minimal worked example

Say you have an Order service and a User service. Your dashboard needs a screen with the current user, their last five orders, and a running total. Today, the React app makes three calls:

GET /users/me
GET /orders?userId=123&limit=5
GET /orders/summary?userId=123

The mobile app needs only the user's name and unread count, but it hits /users/me and gets 40 fields including billing address, feature flags, and a nested organization object.

With a BFF, you introduce two thin services:

web-bff/    → GET /dashboard/home    (one call, shaped for the screen)
mobile-bff/ → GET /home              (returns { name, unreadCount })

Each BFF calls the same underlying User and Order services. The web-bff aggregates three internal calls into one response shaped exactly like the dashboard component tree. The mobile-bff returns two fields. The core services never change.

Crucially, the web team owns web-bff. The mobile team owns mobile-bff. When the dashboard adds a widget, the web team ships a change to web-bff and their React app in the same PR. No backend negotiation. That is the point.

API gateway vs BFF — they are not the same thing

This confusion trips up most teams evaluating the pattern. An API gateway (Kong, AWS API Gateway, Apigee) is a cross-cutting layer: auth, rate limiting, routing, TLS termination. It is generic. It does not know your domain.

A BFF knows your domain intimately. It composes calls, reshapes responses, applies client-specific logic. It sits behind the gateway, not instead of it. In a BFF microservices setup, the typical request path is:

client → API gateway (auth, rate limit) → BFF (compose, reshape) → core services

If someone is pitching "API gateway vs BFF" as an either/or, they are conflating two layers that solve different problems.

Gotchas nobody mentions upfront

The BFF pattern is not free. Before you split, know what you are signing up for.

Code duplication is real, and mostly fine. Two BFFs will both have a function that formats a user's display name. Resist the urge to extract it into a shared library on day one. The whole point is independent change cadence — a shared "bff-common" package quietly recreates the coupling you just paid to remove.

Ownership must be explicit. A BFF owned by nobody becomes a dumping ground. If the web team does not have the skills or appetite to own a Node or Go service, a BFF will rot. This is the single biggest predictor of failure.

You now have more deploy targets. Three BFFs mean three CI pipelines, three sets of logs, three things to monitor. If your platform team is already stretched, this hurts.

Partner BFFs are a contract, not a convenience. The moment you expose a partner-facing BFF, it becomes a public API with versioning obligations. Design it as a contract from day one — OpenAPI spec, semantic versioning, deprecation policy. Do not let it evolve organically the way internal BFFs can.

Latency can go up before it goes down. A BFF adds a network hop. You win it back by collapsing N client calls into one server-side composition, but only if the BFF and core services are in the same region and the BFF does its aggregation in parallel.

When to use it — and when not to

Use a BFF when:

Do not use a BFF when:

How CodeNicely can help

Most of the BFF migrations we run are inside legacy modernization engagements — the shared API grew organically, and now three product surfaces are stepping on each other.

The closest reference here is GimBooks, the YC-backed accounting SaaS we work with. They had the exact shape of the problem in this post: a web dashboard for accountants, a mobile app for small business owners on the go, and integration surfaces for tax and banking partners — all originally served by one API that had drifted toward whichever client shouted loudest. Splitting the client-facing layers from the core ledger and invoicing services let each product team ship on its own cadence without a coordinated release train. If your situation looks similar, that is the engagement pattern to ask us about. We are also happy to tell you when a BFF is the wrong move — sometimes the answer is GraphQL, sometimes it is just cleaning up the existing API.

Frequently Asked Questions

Is the BFF pattern the same as GraphQL?

No, though they overlap. GraphQL lets each client ask for exactly the fields it wants against a single schema — it solves over-fetching. A BFF solves ownership and change cadence: the web team owns the web API surface end-to-end. You can absolutely build a BFF that internally uses GraphQL to talk to core services, and many teams do.

How many BFFs should we have?

One per client experience with meaningfully different needs. Web, mobile, and partner integrations are the common three. Do not split further by feature or team — that is how you end up with fifteen microservices that all do the same thing slightly differently.

Who should own each BFF — frontend or backend?

The team that ships the client. If the web team cannot ship changes to the web BFF, you have recreated the original bottleneck. This usually means frontend engineers picking up Node, Go, or whatever your BFF stack is. If that is a non-starter culturally, the pattern will not work.

Do we need to rewrite our existing API to adopt BFF?

Usually not. The pragmatic path is to leave the existing API as-is, stand up one BFF for the noisiest client (usually mobile), route new traffic through it, and migrate endpoints incrementally. The existing API often becomes the de facto core-services layer with light cleanup.

How do we know if we should actually adopt the BFF pattern?

Signals: frontend changes routinely blocked on backend tickets, one client's needs distorting the API for others, and an incoming partner integration you cannot let couple to your internal model. If two of those three are true, it is worth a serious look. Contact CodeNicely for a personalized assessment of your specific architecture before committing.

Building something in SaaS?

CodeNicely partners with founders and tech teams to ship AI-native products that move metrics. Tell us about the problem you're solving.

Talk to our team