A Backend for Frontend (BFF) is a thin server-side API tailored to a specific client — the web app, the iOS app, the third-party embed.
The BFF pattern, popularized by Phil Calçado at SoundCloud, addresses a common tension: a single general-purpose API tries to serve web, mobile, and partner clients and ends up serving none of them well. Web wants deeply nested payloads to render a full page in one round-trip; mobile wants minimal payloads to conserve bandwidth and battery; partners want a stable versioned surface with slower change cadence. A BFF splits that responsibility — each client gets its own API layer, owned ideally by the same team that owns the client. Underneath, both BFFs call the same domain services.
Strong signals: multiple client types with materially different data needs; frontend teams frustrated by API shapes that don't match their view models; N+1 problems where the client fans out to many backend services per screen; a desire to move client-specific logic (formatting, aggregation, feature flagging) out of the client without polluting domain services. Weak signals: only one client (web) exists; the team is small enough that one API team can serve everyone. Anti-signals: teams that will use BFFs as a place to smuggle business logic that belongs in domain services.
This is the load-bearing rule. If the platform team owns the BFF, it becomes a bottleneck and drifts toward being a generic API again. When the web team owns the web BFF, changes to it are one PR, one code review, one deploy — no cross-team ticket. Practical implication: BFFs are usually written in the same language and framework as the client (Node.js for web BFFs, sometimes Kotlin for Android, Swift server frameworks are rare but possible). The team's existing skills transfer directly.
Belongs in BFF: client-specific data shaping (rename fields, flatten nested objects, format dates), aggregation across multiple domain calls into a single client response, client-specific caching (page-level cache with client's cache keys), authorization checks specific to what this client shows (hide fields based on plan tier the client renders differently). Does NOT belong: business rules (pricing, entitlement, workflow state transitions), persistent data, anything a second client would need to reimplement. If you find yourself copying logic between two BFFs, it belongs in a shared service, not in each BFF.
GraphQL was in part a response to the same problem BFFs address — letting the client specify what it needs. A single GraphQL gateway can reduce the need for per-client BFFs by letting each client query exactly what it wants. Trade-off: GraphQL centralizes ownership (someone owns the schema; changing it requires that team's approval) where BFFs decentralize it. Hybrid works: GraphQL gateway underneath, thin BFFs on top only for clients with substantial aggregation or protocol translation needs (e.g., a partner BFF exposing REST over the internal GraphQL).
Each BFF is another service to deploy, monitor, and secure. If you have 3 clients, that's 3 additional services with their own on-call, SLOs, and incident history. Set explicit SLOs per BFF (usually tighter than downstream services because they're user-facing). Instrument the fan-out: a single BFF call may hit 5-10 domain services, and knowing which downstream slowed a page load is essential. Use distributed tracing (OpenTelemetry) from day one. Failure isolation: a BFF failure should degrade one client, not cascade — never share databases, caches, or thread pools across BFFs.
Investor directory · Fundraising library · Articles A–Z · Company funding database