Backend for Frontend (BFF)
Dedicated backend services for each frontend client: mobile BFF, web BFF, API composition, and avoiding the one-size-fits-all API problem.
The One-Size-Fits-All API Problem
When a single API serves both a mobile app and a web dashboard, trade-offs accumulate quickly. The web app needs rich, deeply nested data for its complex UI. The mobile app needs lean, battery-friendly payloads. Neither client gets exactly what it needs: the web app makes multiple round trips, the mobile app downloads fields it never displays, and every change to one client's needs risks breaking the other.
The Backend for Frontend (BFF) pattern, popularized by Sam Newman (author of *Building Microservices*), solves this by giving each frontend client type its own dedicated backend service. The BFF acts as an API composition layer tailored to one client's exact needs.
BFF Architecture
What the BFF Does
- API Composition — Aggregates multiple downstream service calls into a single response, eliminating client-side chattiness.
- Response Shaping — Returns only the fields the client needs (no over-fetching or under-fetching).
- Protocol Translation — The web BFF may use REST/JSON while the mobile BFF uses Protocol Buffers for smaller payloads.
- Auth Token Handling — The BFF can exchange OAuth tokens, refresh sessions, and strip sensitive fields before sending to the client.
- Rate Limiting / Throttling — Enforce per-client quotas independently.
BFF vs API Gateway
This is a common point of confusion in interviews. An API Gateway and a BFF serve different purposes and are often used together:
| Dimension | API Gateway | BFF |
|---|---|---|
| Ownership | Platform / infrastructure team | Frontend product team |
| Scope | All clients, all services | One specific client type |
| Logic | Thin — routing, auth, rate limiting | Rich — composition, transformation, business logic |
| Customization | Generic cross-cutting concerns | Highly tailored to one client's UI needs |
| Deployment | One gateway per environment | One BFF per client type |
Typical Topology
In practice: Client → API Gateway (auth, SSL termination, rate limiting) → BFF (composition, shaping) → Microservices. The API Gateway handles the 'edge' concerns, the BFF handles the 'client-specific' concerns.
Real-World Example: SoundCloud
SoundCloud is widely credited as the origin of the BFF pattern. When they added a native mobile client alongside their web app, they realized a single API was not serving either well. They created separate backend services, each owned and evolved by the team closest to that frontend. The web team could ship API changes at their own pace without coordinating with mobile, and vice versa.
Pitfalls and Trade-offs
- Code duplication — Business logic that belongs in a downstream service can creep into multiple BFFs. Keep BFFs as thin as possible; push shared logic downstream.
- Team ownership — A BFF should be owned by the frontend team it serves, not a separate backend team. When ownership is misaligned, the BFF becomes a bottleneck.
- Proliferation — Resist creating a BFF per feature or per screen. One BFF per major client type (web, mobile, third-party partner) is the right granularity.
- Latency — An extra hop is introduced. Ensure BFFs make downstream calls in parallel where possible (using `Promise.all` or equivalent).
Avoid Business Logic in BFFs
A BFF that accumulates business rules becomes the new monolith. If you find yourself writing 'if customer is premium, apply 20% discount' in the BFF, that logic belongs in a downstream service. BFFs should compose and shape, not decide.
Interview Tip
In an interview designing a system with both a mobile app and a web dashboard (e.g., Uber, Instagram, Airbnb), proactively mention the BFF pattern. Say: 'To avoid over-fetching on mobile and under-fetching on web, I would introduce a BFF per client type, owned by the respective frontend teams, sitting behind a shared API gateway.' This demonstrates product awareness and architecture depth beyond just 'put an API gateway in front'.