BFFs forever

March 23, 2024

Profile picture

Brought to you Dave Cooper, a web developer in Toronto, Canada who has been building internet things for quite a while now. Say hello on Twitter.

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 that gave engineers much smarter than me many sleepless nights…it was bananas.

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, but with { Error: 500: Message: "Server error" } in the response body? No problem! The BFF, like any best friend, can handle this type of weirdness gracefully, 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-design endpoint in the 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