Backends for Frontends, and What Comes After: Value-Added Services and Domain Gateways
BFFs fix client sprawl, then duplicate authorization logic across themselves. The three-layer fix: edge, value-added services, and per-domain gateways.
On this page
Breaking up a monolith moves complexity, it does not delete it. The monolith’s single API hid how many things it took to build a track page. Once the services are separate, every client must know. The architecture question is where that knowledge should live, and the honest answer changes as you grow.
Step one: a gateway per client type
A Backend for Frontend is an API gateway dedicated to one kind of client. A mobile BFF for iOS and Android, a web BFF for the site and embeds, and separate ones for public and partner APIs. All external traffic passes through one of them.
Each BFF owns edge concerns: authentication, rate limiting, header sanitisation and cache control. Shared edge code lives in an internal library that rolls out to every BFF quickly, and teams outside the platform group contribute code under review by a core team, the “inner source” model.
What it buys
Step two: the BFF layer starts to rot
Every one of those wins has a mirror image.
| Problem | How it happens |
|---|---|
| Logic creep | Foundational services are tiny and CRUD-only, so all feature integration lands in the BFF. Clients also push their own logic upstream (“it is just the client’s backend”), such as pagination |
| Duplication | The same rule gets implemented in several BFFs, and the copies drift as each evolves |
| Authorization drift | A visibility rule needs data from Track and Playlist services, so each BFF fetches both and re-implements the check. One slips |
| Proliferation | A BFF for every small use case multiplies deploys, on-call and maintenance. Full autonomy is also an illusion: front-end and back-end people must still collaborate |
Access rules must exist in exactly one place. If two codebases independently decide who may see a track, they will eventually disagree, and the disagreement is a data exposure. This was the strongest argument for the next layer.
Step three: value-added services own the aggregates
The fix was a middle tier. The new shape has three layers:
Clients
|
EDGE SERVICES (BFFs: auth, rate limit, caching, response shaping)
|
VALUE-ADDED SERVICES (own core aggregates and their rules)
|
FOUNDATIONAL SERVICES (low-level building blocks)
A value-added service borrows vocabulary from domain-driven design: a domain bounds the concern, entities have identity and lifecycle, value objects describe them, and aggregates group related entities. A Track service and a Playlist service build these aggregates once, including the context-dependent rules. The Track service, for example, filters out tracks geo-blocked in a territory.
BFFs stop calling foundational services. They ask for aggregates, and all the shared code lives in one place.
Migrating without breaking anything
- Extract and document the logic
Analyse what the BFFs actually do for the entity, and write it down. Hidden behaviour is the main risk.
- Pin it with tests
Write automated tests to prove the new service matches the old logic, plus integration tests on response shape.
- Migrate endpoint by endpoint, comparing as you go
Move endpoints (around fifty for playlists) to the new service while comparing old and new responses in production.
The costs of that layer
- Fan-out. As features grow, an aggregate pulls from more services, and one request becomes many network calls.
- One size fits no one. A feature only mobile uses is wasted work for web if the full aggregate is always built.
The answer to the second one is partial responses: the caller sends a field mask naming the parts it wants, and the service fetches and returns only those. The same endpoint serves lean and rich clients, and downstream calls shrink with the mask.
Step four: domain gateways
SoundCloud serves two audiences in one product: listeners consuming a catalogue, and creators uploading and distributing music. Those are different domains with different owners. One shared value-added service for both worked until coupling and complexity slowed everyone.
A domain gateway is a value-added service scoped to one business domain. The consumer gateway and the creator gateway each present their own view of an entity, owned by their own team, over the same foundational services. It acts as a facade and an anti-corruption layer: the domain’s model is protected from changes in the layers beneath and beside it.
It deliberately trades some duplication for autonomy, and is worth it only when domains have genuinely different access patterns and feature sets.
Which layer solves which problem
| Symptom | Reach for |
|---|---|
| Clients juggle many services | BFF |
| Different clients need different payload shapes | BFF, or field masks on shared endpoints |
| Same business rule copied across gateways | Value-added service |
| Authorization logic diverging | Value-added service, single owner |
| One service serving two teams with conflicting needs | Domain gateways |
| Too many gateways to operate | Merge them. You have outgrown the pattern |
Do
Keep BFFs thin: authentication, rate limits, shaping and caching. Put business and authorization rules in one service per aggregate. Add partial responses before adding endpoints. Introduce domain gateways only when two teams are really colliding.
Don't
Create a BFF per screen, or let each one reimplement visibility rules from raw service data. You will own the duplication and the security review.
Takeaway
Architecture here is a chain of fixes, each created by the last. Services broke the monolith, BFFs hid the services from clients, value-added services pulled duplicated rules out of the BFFs, and domain gateways stopped one service from serving two masters. Start with the smallest layer that solves your current pain, and add the next only when you can name the duplication it removes.
Frequently asked questions
What is a Backend for Frontend?
A dedicated backend gateway for one kind of client, such as mobile, web or partner API. It shapes responses to that client's needs and handles edge concerns like authentication, rate limiting and caching, so other clients are not forced into one compromise API.
What is the main risk of the BFF pattern?
Business logic leaks into the BFFs and gets duplicated across them. Authorization rules are the dangerous case: if three BFFs each implement them from raw service data, the copies drift and one eventually grants access it should not.
What is a value-added service layer?
A layer between edge gateways and low-level services that builds and owns core aggregates such as a track or playlist, including visibility and authorization rules. Every BFF asks it for the aggregate instead of re-assembling it from foundational services itself.
What does a field mask do in an API?
It lets a caller name exactly which fields of a resource it wants back, so a shared endpoint can serve a lean response to one client and a rich one to another. It controls payload size and downstream fan-out without creating a new endpoint per client.
Sources & further reading
- SoundCloud Developers: Service Architecture Part 1, Backends for Frontends
- SoundCloud Developers: Service Architecture Part 2, Value-Added Services
- SoundCloud Developers: Service Architecture Part 3, Domain Gateways
- Microsoft Azure Architecture Center: Backends for Frontends pattern
- Google AIP-161: Field masks
/* Comments */
Comments are offline right now — we reconnect automatically, nothing is lost.