Service Designhigh

API Gateway vs Backend for Frontend (BFF)

An API gateway is a single entry point that routes, authenticates, and rate-limits calls to backend services. A BFF is a client-specific backend that aggregates data and shapes responses for a particular frontend (mobile, web, third-party).

Memory anchor

API Gateway = the hotel front desk (handles check-in, directions, complaints for everyone). BFF = a personal concierge for VIP guests (knows exactly what YOU want and fetches it all in one trip).

Expected depth

A generic API gateway handles cross-cutting concerns: auth, rate limiting, TLS termination, request routing, and observability. It is not responsible for business logic. A BFF sits between the gateway and the client, aggregating calls to multiple downstream services into the exact payload shape the frontend needs — eliminating over-fetching and reducing round trips. This is especially valuable for mobile clients with bandwidth constraints. Typically you have one BFF per client type: mobile BFF, web BFF, partner API BFF.

Deep — senior internals

The BFF pattern solves the 'generic API is a lowest common denominator' problem — a single API serving all clients forces each client to do expensive data transformation on the client side. The risk of BFF is that it becomes a dumping ground for business logic that belongs in domain services. Strong discipline is required: BFFs should contain only presentation logic (data aggregation, transformation, caching for UX performance) and must call downstream services for business decisions. GraphQL can serve as a BFF technology — it allows clients to declare the exact shape they need, avoiding the need for multiple BFF deployments, but it introduces its own complexities (N+1 resolver problem, query depth limiting, authorization complexity at the field level).

🎤Interview-ready answer

I place an API gateway at the edge for cross-cutting concerns and deploy BFFs per major client type. The mobile BFF, for example, might aggregate a product detail page call that would otherwise require 4 separate API calls from the app — reducing startup time and battery usage. I keep business rules out of BFFs by enforcing a rule: if the logic would break a unit test if moved to the BFF, it belongs in a domain service.

Common trap

Building a BFF that directly accesses other services' databases rather than calling their APIs. This recreates the coupling you were trying to avoid.

Related concepts