A couple of years back, I was interviewing for a lead engineering role at a large American company. The hiring manager (Director of Engineering) was describing the tech stack, and he mentioned a “BFF layer”. He mentioned it in passing, thank goodness — if he had asked me my thoughts on the approach, I would not have had many great insights.
BFF stands for “backend for frontends”, and when I started with the company I quickly fell in love with that particular piece of the architecture. I had worked with more generalized API gateway implementations (BFF is a variant of the API gateway pattern) but they were mostly just pass-throughs that looked after some basic plumbing, like adding correlation IDs to requests for logging purposes.
This BFF was a Node/Express.js API layer, built by and for UI developers. It had great test coverage, a reliable and predictable caching strategy, solid documentation, and a cool codename. But what I loved most was that it abstracted away complex systems so that front-end engineers would never have to think about them. There was a legacy product API, a headless CMS with flexible but difficult-to-use API contracts, and an e-commerce layer with a baffling array of integration points.
Top 3 things to do with your BFF this weekend
In my time with the team, I had the opportunity to work with this BFF quite a bit. With that experience, I’ve put together a quick list of my favourite things to do with a BFF:
1. Protect the frontend from the idiosyncrasies of legacy systems.
When something goes wrong, does your legacy system happily return a 200 OK
status with { Error: 500: Message: "Server error" }
in the response body? No problem! The BFF, like any best friend, can handle this type of weirdness for you, so consuming apps don’t have to wrestle with it.
2. Bundle together related responses and add granular caching strategies.
If your app sells widgets, maybe the widget inventory comes from a catalog API, and its description comes from a CMS, and its pricing comes from an e-commerce platform. A well-designed BFF can save your front-end team (and the UI design team, frankly) from having to deal with multiple concurrent async requests just for the sake of a showing a single widget. Moreover, you can cache the response from each legacy system separately, with a different TTL; widget descriptions rarely change, prices change a bit more frequently, and inventory changes by the second. The frontend can get all of this rich data and business value from a single request to /product/{id}
.
3. Offload expensive data transformation from the client to the server.
Frontend performance can degrade quickly when fetching, unzipping, and parsing large, unwieldy payloads from multiple systems (to say nothing of the added code complexity). While it’s true that a BFF adds one or more network hops to the request/response lifecycle, for most applications the benefits make this trade-off more than acceptable: removing unwanted cruft, and delivering normalized, consistent responses to consuming apps.
BFFs forever!
Photo by Mayur Gala on Unsplash