Backend for Frontend (BFF): API Patterns for Mobile and Web Clients
The Backend for Frontend (BFF) pattern gives each client type (mobile, web, admin) its own backend service that aggregates and optimises data from downstream APIs. It solves the problem of one API trying to serve clients with fundamentally different needs. This guide covers when BFF is worth the overhead, how to structure it on Azure, and when simpler alternatives are better.
The problem BFF solves
Most applications start with a single API that serves all clients. Early on, this works. The web app and the mobile app need roughly the same data, and one set of endpoints handles both.
The problems emerge as clients diverge:
- The mobile app needs smaller payloads. It fetches the same endpoints as the web app but discards half the fields. Bandwidth is wasted, and the app feels slower than it should.
- The web dashboard needs aggregated data. A single screen requires data from three different microservices. The front-end makes three calls and stitches them together, adding latency and complexity to the client.
- The internal admin tool needs richer access. Admin users need fields and operations that should never be exposed to external clients. The API accumulates permission checks and conditional logic.
- Versioning becomes painful. A change that benefits the web app breaks the mobile app. Every API change requires coordination across all client teams.
The single API becomes a bottleneck: too fat for mobile, too thin for dashboards, too permissive for security, and too coupled for independent releases.
What BFF looks like in practice
A BFF architecture introduces a thin service layer between each client type and the downstream services.
Mobile App ──▶ Mobile BFF ──▶ ┌─ User Service
├─ Order Service
Web App ──▶ Web BFF ──▶ ├─ Product Service
└─ Analytics Service
Admin Tool ──▶ Admin BFF ──▶
Each BFF:
- Aggregates data from multiple downstream services into a single response tailored to its client
- Transforms payloads to match the client’s needs (fewer fields for mobile, richer data for admin)
- Owns its own API contract and can evolve independently of other BFFs
- Handles client-specific auth flows (PKCE for mobile, session cookies for web, service tokens for admin)
The downstream services remain generic and reusable. The client-specific logic lives in the BFF, not in the downstream services or the front end.
BFF vs single API vs API gateway
These three patterns solve different problems and often coexist.
Single API
One API serves all clients. This is the right starting point for most projects and remains the right architecture when:
- All clients need the same data in the same shape
- The API surface is small (under ~30 endpoints)
- There is one client team or the client teams are tightly coordinated
- Payload optimisation is not a priority
When it breaks down: when client requirements diverge enough that the API accumulates client-specific logic, conditional fields, and endpoint sprawl.
API gateway
A gateway like Azure API Management handles cross-cutting concerns: routing, authentication, rate limiting, and monitoring. It does not contain business logic.
The gateway works well with both single-API and BFF architectures:
- Single API + gateway: the gateway fronts one backend
- BFF + gateway: the gateway fronts multiple BFFs, routing by client type or API version
The gateway is not a replacement for BFF. It operates at a different layer.
BFF
BFF adds a per-client service layer that contains client-specific aggregation and transformation logic. It makes sense when:
- Different client types have genuinely different data and performance requirements
- Client teams want to iterate independently on their API contracts
- You need different auth patterns per client type
- Payload optimisation matters (mobile bandwidth, admin tool data richness)
The cost: more services to build, deploy, and maintain. Only adopt BFF when the complexity of a single API exceeds the complexity of multiple BFF services.
Implementing BFF on Azure
Architecture
A typical BFF deployment on Azure:
- Azure API Management as the unified gateway, routing to BFF backends by path prefix or custom header
- BFF services on Azure App Service (simple) or Azure Container Apps (if you want autoscaling and container flexibility)
- Downstream services on App Service, AKS, or Azure Functions
- Azure Entra ID for authentication, with each BFF validating tokens appropriate to its client type
Routing strategy
APIM routes traffic to the correct BFF based on a path prefix:
/api/mobile/*routes to the mobile BFF/api/web/*routes to the web BFF/api/admin/*routes to the admin BFF
Alternatively, use a custom X-Client-Type header. The path prefix approach is simpler and more transparent for debugging.
Auth per client type
Each BFF handles the auth flow appropriate to its client:
- Mobile BFF: OAuth 2.0 with PKCE, refresh tokens, biometric-triggered re-auth. See our mobile app backends service for the full pattern.
- Web BFF: OAuth 2.0 authorization code flow with session cookies (BFF-for-SPA pattern) or bearer tokens. The BFF keeps tokens server-side, away from the browser.
- Admin BFF: Azure Entra ID with role-based access control (RBAC) and conditional access policies.
APIM validates the token at the gateway layer. The BFF validates claims and applies client-specific authorization logic.
Data aggregation
Each BFF calls downstream services and composes the response. Keep this layer thin:
- Aggregate data from multiple services into a single response
- Filter fields the client does not need
- Apply client-specific formatting (date formats, currency, locale)
- Add pagination, sorting, and filtering optimised for the client’s UI
Avoid putting business logic in the BFF. If the BFF is making decisions about how data should behave (not just how it should look), that logic belongs in a downstream service.
Caching
BFFs are excellent caching points. Each BFF knows exactly what its client needs and how often that data changes:
- Mobile BFF: aggressive caching with ETags and short TTLs for frequently changing data, long TTLs for reference data
- Web BFF: cache aggregated dashboard responses with a TTL matched to the reporting refresh interval
- Admin BFF: minimal caching (admins usually need fresh data)
Use Azure Redis Cache or in-memory caching in the BFF process, depending on scale.
When to use GraphQL instead of BFF
GraphQL and BFF solve overlapping problems. Both address the “different clients need different data shapes” challenge.
GraphQL as BFF replacement: a single GraphQL API lets each client query exactly the fields it needs. The mobile app requests a compact field set; the web dashboard requests a richer set. No separate BFF services needed.
When GraphQL works better than BFF:
- The data model is graph-shaped (entities with deep relationships)
- Client teams want maximum flexibility to change queries without backend changes
- You have the team skills to manage schema design, resolver performance, and query cost control
When BFF works better than GraphQL:
- Different clients need fundamentally different auth flows (not just different data shapes)
- Some clients need non-query operations (file uploads, streaming, WebSocket connections) that GraphQL handles awkwardly
- The team is more comfortable with REST-style services than GraphQL schema management
- You need strict control over what data each client type can access (BFF makes this explicit per service)
For a deeper comparison of API styles, see our guide on REST vs GraphQL vs gRPC.
Common mistakes
Building BFFs too early. Start with a single API. Only introduce BFFs when client requirements genuinely diverge and the single API is accumulating client-specific complexity. Premature BFF adoption adds operational cost without benefit.
Putting business logic in the BFF. The BFF should aggregate, transform, and optimise. If it is calculating prices, enforcing business rules, or managing state, that logic should be in a downstream service where all BFFs (and future clients) can use it.
One BFF per application, not per client type. If your iOS and Android apps have identical data needs, they share one mobile BFF. Do not create separate BFFs for separate applications that happen to be on the same platform.
Ignoring the operational cost. Each BFF is a service that needs deployment pipelines, monitoring, alerting, and on-call coverage. Factor this into your architecture decision. Three BFFs means three times the operational surface area of a single API.
Inconsistent error handling. Each BFF should return errors in a consistent format (RFC 9457 problem details is a good standard). Downstream service errors should be translated, not leaked through to the client as raw internal errors.
Where to start
If you are considering BFF for your architecture:
- Document where your current API serves clients differently. Look for conditional logic, client-specific query parameters, and endpoints used by only one client type. These are the pressure points where a single API is stretching.
- Evaluate whether GraphQL could solve the problem. If the issue is primarily data shape flexibility and all clients share the same auth model, GraphQL may be a simpler solution than multiple BFF services.
- Start with one BFF for the client type that differs most. Usually this is mobile (smaller payloads, different auth flow, offline support) or admin (richer data access, stricter auth). Keep the other clients on the single API until they need their own BFF.
For help designing a BFF architecture or evaluating whether it is the right fit, see our mobile app backends and API and integration services or book a consultation.
Frequently asked questions
What is the Backend for Frontend pattern?
How is BFF different from an API gateway?
When should I not use BFF?
How many BFFs should I have?
Can I use GraphQL as a BFF?
How does BFF work with Azure API Management?
Related guides
Planning an Integration Strategy: A Guide for Business and Technology Leaders
Integration projects fail when the strategy is wrong, not when the technology is wrong. A practical guide to planning an integration programme that moves at AI-augmented speed.
Mobile API Best Practices: Building Backends That Scale
How to design, secure, and operate APIs for mobile apps. Protocol choice, authentication flows, offline sync, push notifications, versioning, and Azure architecture patterns.
API Versioning Strategies That Actually Work at Scale
URL path, header, and query parameter versioning compared. Breaking vs non-breaking changes, deprecation workflows, Azure APIM versioning, and a practical policy template.