Antipattern: BFF


The backend-for-frontend (BFF) pattern is when a backend API is designed specifically for the needs of a frontend consumer. The BFF is intended to make frontend development simple, moving all the complexity and “business logic” to the backend and allowing the frontend to deal with a single backend. The backend BFF API closely resembles the flows and screen designs of the frontend.

The initial development experience is often positive. The frontend team can focus on the UI/UX aspects of the application, and the backend team can handle all the downstream integrations and data transformations.

However, when we have a single BFF API that aggregates multiple downstream calls then the API performance is limited to the slowest response. The backend has to wait for all the downstream calls to complete before it can craft its aggregated response for the frontend. If the frontend was allowed to call the downstream systems directly then it would be able to make those calls asynchronously and gradually present the responses to the user as they returned. It would appear to be more performant to the user.

I avoid designing backend APIs that closely resemble the frontend flows. The frontend changes are driven by the latest trends in the UI/UX realm and I want them to be able to change independently of the backend. The backend APIs represent the capabilities of the platform without an opinion on how those capabilities should be consumed. Once the API is mature, we should be able to redesign the frontend flows without needing to change the backend.

For those reasons, many of the systems I’ve designed use a modified version of the BFF pattern where the backend still handles all the downstream integrations and data transformations but it defers the aggregation to the frontend. This allows us to craft consistent APIs that represent the business capabilities while allowing the frontend to compose those calls to support its current UI/UX, and parallelize those calls when necessary.