Backends for Frontends
- Pradeep P
- 2 days ago
- 3 min read
Series: Modern System Design · Layer 2 — Communication
Layer 2 · Post 14 of 14
← Previous: Head-of-Line Blocking → Next: Two Generals Problem
Layer 2 — Communication · Post 98 of 119
Give each client (web, iOS, Android) its own backend so mobile is not stuck with a desktop-shaped API.
What you'll learn
How a BFF differs from a general API gateway
When one backend per client type is worth the extra service
The failure mode: seven BFFs that each reinvent auth and retries
The idea in one minute
Backends for Frontends (BFF) (Sam Newman): do not force every UI through one general-purpose API.
A desktop web page wants a fat graph (user + 20 widgets). An iOS app wants a small payload, fewer round trips, maybe different auth, maybe GraphQL. If both call the same /api/v1/everything, mobile pays for fields it cannot show, or web makes 15 extra calls the API never aggregated.
A BFF is a backend owned by that client team (or dedicated to that client type). It calls downstream services, aggregates and shapes the response, and speaks the protocol that UI needs.
iOS app --> iOS BFF --\
Android --> Android BFF --+--> orders, users, catalog, payments
Web --> Web BFF --/
Post 6's API gateway is usually shared infrastructure (auth, rate limit, TLS, routing). A BFF is experience-specific composition. You can put a BFF behind a gateway.
Why it matters
Chatty mobile APIs are fallacies 2 and 3 (latency, bandwidth) as an architecture smell. Interviews: "how do you keep the mobile app fast without a 40-endpoint waterfall?" Aggregation at a BFF (or GraphQL with a responsible schema) is the expected answer — plus "don't hide a 2-second join behind one mobile call without a budget."
It is also a Conway move (later): the iOS team ships UI and the shape of its API without waiting for a central platform team to add fields.
How it works
One BFF per UI (or per channel). Web, mobile, TV, partners, internal admin. Not necessarily one per screen.
Composition, not business source of truth. Orders still live in the order service. The BFF joins, filters, and caches for that UI. If it starts owning inventory logic, you grew a monolith in a hoodie.
Protocol freedom. gRPC internally, JSON to iOS, maybe GraphQL for web. The BFF is the translator.
Independent deploy. iOS BFF can add a field without bumping a company-wide API version that Android does not need.
Keep the cross-cutting stuff once. Authn/z, tracing, timeouts: library or mesh or gateway. Copy-pasting JWT validation into five BFFs is how you get five CVEs.
BFF vs GraphQL vs "just the gateway." GraphQL can be one BFF-shaped endpoint. A gateway that only routes /ios/** to a service is a BFF. The name is about fit for the client, not a brand of proxy.
A simple example
Product page.
No BFF: iOS calls GET /products/1, GET /users/42, GET /reviews?product=1, GET /inventory/1. Four round trips on LTE. HOL and latency add up.
Web BFF / iOS BFF: GET /ios/product-page/1 returns { product, seller, reviewsPreview, inStock }. Two internal parallel calls with a tight timeout; reviews can be empty rather than blocking (bulkhead / hedge). The web BFF also returns relatedWidgets the phone never asked for.
When the iOS app drops reviews from v4, the iOS BFF stops calling reviews. The web BFF does not change.
Common mistakes
One shared "BFF" used by all clients. You renamed the monolith API.
Business rules only in the BFF. Checkout totals disagree between iOS and web. Push rules down.
N+1 inside the BFF. You saved the phone from chatty HTTP and DDoSed yourself with 50 user-service calls. Batch internally.
BFF per screen × 80 screens. Operational explosion. Group by app or major experience.
Skipping SLOs on the BFF. It is on the user path. Tail latency here is the app's latency (Tail at Scale).
How this shows up in real systems
Netflix, SoundCloud, many mobile-heavy shops: named BFF services per device family.
Next.js / BFF-in-the-SSR-server: the web BFF is often the Node server that called Java internally.
AWS API Gateway + Lambda "per app": can be a BFF; can also be a mess of overlapping functions.
GraphQL BFF: Apollo / Hasura / a custom gateway — still a BFF if one client owns the schema slice.
Recap
A BFF shapes and aggregates for one client type; a gateway shares plumbing.
Keep source of truth in domain services; keep retries and auth from forking five ways.
Next layer of named problems is reliability: Two Generals and friends.
Series: Modern System Design · Layer 2 — Communication
Layer 2 · Post 14 of 14
← Previous: Head-of-Line Blocking → Next: Two Generals Problem



Comments