A story on Frontend Architectures - Everyone deserves a BFF!
Source: Dev.to
Common challenges
- Different shapes of the payload – A generic API can lead to over‑fetching or under‑fetching. One client may receive too much data while another gets too little, forcing multiple endpoint calls and wasting bandwidth.
- Juggling between microservices – SPAs often need to call several microservices, join results, and shape them for the view, increasing complexity and hurting performance.
- Mobile device handling – Mobile, TV, and web SPAs have different payload, caching, and security requirements. A one‑size‑fits‑all API is likely to fail.
- Organisational bottlenecks – With a single backend, the frontend team depends on minor API changes, slowing delivery timelines.
Example API response
Consider a web‑based e‑commerce application with an endpoint /v1/products/102938 that returns:
{
"productId": "PROD-102938",
"name": "ZenBeat Pro Wireless Noise Cancelling Headphones",
"description": "Wireless headphones with active noise cancellation, deep‑bass, and long‑lasting battery life.",
"seller": {
"sellerId": "SELL-908",
"name": "ZenBeat Official Store",
"rating": 4.6
},
"variants": [
{
"variantId": "VAR-1",
"label": "Black",
"price": 9999,
"inStock": true
},
{
"variantId": "VAR-2",
"label": "Silver",
"price": 10499,
"inStock": false
}
],
"reviews": {
"averageRating": 4.4,
"totalReviews": 612,
"topReviews": [
{
"reviewId": "REV-1",
"rating": 5,
"comment": "Excellent sound quality and very comfortable for long use."
},
{
"reviewId": "REV-2",
"rating": 4,
"comment": "Great noise cancellation, battery life could be slightly better."
}
]
},
"faqs": [
{
"question": "Does this support fast charging?",
"answer": "Yes, it supports fast charging and provides up to 5 hours of playback with a 10‑minute charge."
},
{
"question": "Is there a warranty?",
"answer": "Yes, it comes with a 1‑year manufacturer warranty."
}
]
}
Rendering this payload on a mobile device would differ significantly from a desktop view. For example, a mobile app might load FAQs only after a user taps a button, triggering a separate API call. Tailoring the response per client yields:
- Better UX
- Faster rendering
- Reduced network bandwidth
Backend for Frontend (BFF)
The Backend for Frontend (BFF) pattern introduces an intermediate layer between each client type (web, mobile, TV, etc.) and the backend. This layer handles presentation‑specific logic without containing business logic. Think of it as having a dedicated API gateway per client.

BFF with a monolith

When the backend is a monolith, the BFF filters responses and provides a client‑specific entry point.
- What to fetch – The BFF decides which backend resources are needed.
- How to fetch – It can aggregate calls or request only the necessary data.
- What to send – It tailors the payload (e.g., mobile BFF may omit reviews and FAQs, while desktop BFF includes them).
Using a flag like device=mobile to filter data at the backend complicates backend logic. Keeping the backend generic while letting the BFF handle client‑specific shaping also enables response caching.
BFF with microservices

In a micro‑service architecture, the BFF composes only the services required for a given client. For instance, a mobile client might request an AR service to visualize a product in 3D, which a web client would not need.
Advantages
- Isolated client interfaces – Each client can be tweaked independently, leading to faster iteration.
- Sensitive data filtering – The BFF can strip or transform data before it reaches the client.
- Protocol mediation – Legacy clients using XML can receive JSON from the backend, with the BFF handling the conversion.
- Separate security concerns – Security policies can be applied per client type.
- Generic backend – Heavy customization is offloaded to the BFF, allowing the backend to remain simple and act as an aggregator.
Disadvantages
- Network overhead – A single BFF may fan out requests to multiple micro‑services concurrently, increasing bandwidth usage. Efficient, non‑blocking runtimes (Node.js, Go, or reactive Java) are recommended.
- Code duplication – Multiple BFFs often share similar logic (e.g., fetching product and seller details), leading to duplicated code and higher maintenance effort.
- Operational complexity – Adding an extra layer introduces additional responsibilities for deployment, monitoring, and scaling.
By adopting the BFF pattern, teams can deliver tailored APIs for each frontend while keeping the core backend generic and maintainable.