Backend for Frontend (BFF): Building Client-Optimised APIs That Scale

Backend for Frontend (BFF): Building Client-Optimised APIs That Scale
Table of Contents
- The General Purpose API Problem
- How the BFF Pattern Works
- The Aggregation Advantage: N+1 → 1 Server-Side
- BFF Ownership Model: Frontend Teams Own Their Backend
- BFF vs API Gateway: Complementary, Not Competing
- Implementation: Node.js BFF for Mobile
- GraphQL as a BFF: The Self-Describing Alternative
- Authentication in the BFF Layer
- Performance Patterns: Parallel Fetching and Caching
- When BFF is Overkill
- Frequently Asked Questions
- Key Takeaway
The General Purpose API Problem
The traditional approach creates a single API that all clients must work with:
When the desktop needs more data than mobile provides:
How the BFF Pattern Works
Each BFF is a lightweight server-side aggregation layer — it does not contain business logic (that lives in the microservices), only:
- Request aggregation (fan out to multiple services, merge responses)
- Response shaping (strip unnecessary fields, restructure for the client)
- Authentication token transformation (exchange tokens between client and microservice formats)
- Client-specific caching
The Aggregation Advantage: N+1 → 1 Server-Side
The biggest performance gain: moving network fan-out from client to server.
BFF Ownership Model: Frontend Teams Own Their Backend
The critical organisational insight of BFF: the team that owns the frontend owns the BFF.
Traditional model:
BFF model:
This removes the cross-team dependency bottleneck — frontend developers can evolve their API contract at the speed of UI changes, not at the speed of backend sprint planning.
BFF vs API Gateway: Complementary, Not Competing
These two patterns are frequently confused:
| Concern | API Gateway | BFF |
|---|---|---|
| Primary purpose | Security, routing, rate limiting | Client-specific aggregation and shaping |
| Owned by | Platform/infrastructure team | Frontend team |
| Knowledge of client | None — generic | Deep — shaped for specific client |
| Business logic | None | None (only aggregation/shaping) |
| Number of instances | One (or one per environment) | One per client type |
| Authentication | Validates token at entry | May transform tokens for downstream services |
Best practice: Both together.
Implementation: Node.js BFF for Mobile
GraphQL as a BFF: The Self-Describing Alternative
GraphQL intrinsically solves the over/under-fetching problem — clients declare exactly what data they need. A GraphQL BFF gives clients even more control:
GraphQL as a BFF works particularly well when you have many client types with genuinely different data needs and you want a single BFF to serve them all via schema-level flexibility.
Frequently Asked Questions
How many BFFs should I have? One per meaningfully distinct client type — typically: Web BFF, Mobile BFF (or separate iOS/Android if they diverge significantly), and optionally a Third-Party API BFF (a public-facing, versioned, stable API for external partners, which has different versioning requirements than the Web or Mobile BFFs). Resist the temptation to create a BFF per feature team — that creates a maze of entry points.
Does the BFF violate the DRY principle since Web and Mobile BFFs may share similar aggregation code? Use a shared library for common patterns (authentication token handling, service client configuration, error formatting), but explicitly accept duplication in the aggregation endpoints. The BFF endpoints diverge quickly as client needs evolve — shared aggregation code between Web and Mobile BFFs becomes a coupling point that slows both teams. The cost of some duplication is lower than the cost of tight coupling between teams.
Key Takeaway
The Backend for Frontend pattern is fundamentally about team topology and API ownership. It gives frontend teams the autonomy to evolve their API contract at the speed of UI development, without negotiating with backend teams for every new data requirement. The technical benefits — reduced over-fetching, server-side aggregation, client-specific resilience — are real and measurable. Start with a BFF when frontend teams are blocked waiting for backend API changes, or when your mobile app's network performance is suffering from too many sequential requests.
Read next: Circuit Breaker Pattern: Stopping Cascading Failures →
Part of the Software Architecture Hub — comprehensive guides from architectural foundations to advanced distributed systems patterns.
