5 Best Practices for Backends-for-Frontends - WunderGraph
State of GraphQL Federation 2026
Prithwish Nath
August 5, 2023·10min read
Edited on June 9, 2026 by Brendan Bondurant
TL;DR
Backend for Frontend (BFF) is a pattern where each client type, such as web or mobile, gets a dedicated API layer optimized for its needs. This reduces over-fetching, simplifies client logic, and decouples frontend and backend release cycles. For teams scaling across many services, GraphQL Federation extends these benefits by providing a shared, unified API layer with stronger governance and composition workflows. WunderGraph's current product is Cosmo, an open-source GraphQL Federation platform — referenced in Practice 2 and the section below.
The Backend for Frontend (BFF) pattern remains a useful way to tailor APIs to specific client experiences, especially when web, mobile, and other interfaces have different data needs. Many teams later discover that as the number of services, teams, and client experiences grows, they need a more systematic way to compose and govern those APIs across the organization. That is where GraphQL Federation increasingly becomes the next step.
From BFF to Federation
In many organizations, BFFs begin as a practical way to tailor APIs to different client experiences. Over time, though, teams often end up duplicating orchestration logic, ownership boundaries become blurry, and each BFF becomes another surface that has to be maintained, monitored, and evolved.
GraphQL Federation addresses that scaling problem differently. Instead of creating separate custom aggregation layers for each client, teams contribute domain-owned services to a shared graph, giving frontend teams one unified API while preserving backend ownership and clearer schema governance.
This does not mean BFFs disappear entirely. A BFF can still make sense for client-specific policy, presentation shaping, or edge concerns. But when multiple BFFs start solving the same cross-service composition problem, federation is often the cleaner long-term model.
Best practices to follow when implementing the BFF pattern: do's and don'ts.
Photo by Arnold Francisca on Unsplash
The Backends-for-Frontends (BFF) pattern is an interesting solution to a problem many teams face — meaningfully decoupling the frontend from the backend, insulating the former from changes to the latter.
In this article, I’m going to quickly explain the BFF pattern, and then focus on some of the best practices you should be following when implementing it. If you’d like to know more about the pattern itself, I’d recommend reading Sam Newman’s BFF pattern post. For lessons learned the hard way, see 7 key lessons from building production BFFs.
What is the BFF pattern?
BFF stands for Backend For Frontend, and it's a very clever way to architect your application in a way so that no matter how many different frontend experiences you offer, the core backend services remain intact.
What does this do differently? Well, sometimes you might be offering very distinct frontend experiences — multiple apps that are meant to re-use your backend services, while each offering very different UXs to your users.
Think of a limited mobile UX, vs. a feature-rich desktop app, vs. a reporting SMS interface. These are three very different UI/UX, all consuming the same business logic at their core. But if you try to create a unique and generic set of microservices that can cater to all of those UI's needs, you run the risk of introducing unnecessary coupling between the frontend and backend. This always leads to bloated and difficult-to-maintain codebases, and business logic leaking into the frontend.
1. Create one BFF per User Experience
The primary role of a BFF should be to handle the needs of its specific frontend client — and no more.
Look at the above diagram, the microservices are still there, they're the ones that own the "core business logic". The extra layer added by the BFF is only there to help solve problems that are specific to each UX.
What do I mean by that? In the above example, I proposed 3 different clients for our APIs:
- SMS
- Mobile
- Desktop app
Each of them provides a unique user experience — but what's critical here is that we're talking about serving specific needs based on the UI/UX provided, not the specific needs of each separate client implementation.
2. Do not reinvent the wheel
Implementing the BFF pattern can be as hard and difficult or as simple and trivial as you want.
My suggestion would be to try and find a framework that gives you the ability to easily implement this pattern without you having to do much.
3. Watch out for the fan-out antipattern
With the BFF pattern, there is always a chance that you'll end up with what is known as a "fan-out" problem.
This is when your BFF is responsible for orchestrating API requests to multiple backend services, or third-party APIs — thus introducing multiple points of failure.
Potential solutions to these problems include:
- Circuit breaker pattern.
- Caching.
- Service monitoring.
As architectures grow, the challenge is not just avoiding fan-out failures but maintaining control over an expanding set of service dependencies, client-specific integrations, and schema changes.
4. Handle Errors Consistently on the BFF
If they did, they'd all report errors in wildly different ways. You need to ensure your BFF knows how to handle these errors in a consistent, unified manner, and translate those errors back to the UI in meaningful ways.
5. Use TypeScript and schema contracts to keep frontend and BFF development aligned
Using a NodeJS-based server such as Express.js or NestJS for your BFF lets you use TypeScript on both the frontend and the backend.
Conclusion
In the end, BFF is nothing fancy or strange, but rather, yet another layer of abstraction that sits between your UI and the core business logic.
By incorporating these five best practices, you'll be well on your way to building scalable, maintainable, and performant BFFs.