our mobile app talks to 3 backend services directly.
A 4th one ships next sprint. The mobile team is already drowning.
Every new service means a new domain to whitelist, a new auth scheme to wire, and a new error shape to parse. You’re asked to reduce coupling before NotificationService lands.
Here’s the setup:
Mobile → UserService (users.api.com)
Mobile → OrderService (orders.api.com)
Mobile → PaymentService (payments.api.com)
…and NotificationService next sprint.
The client is doing routing the backend should be doing. What do you do?
A) Add an API Gateway — single entry point, all services hide behind one domain.
B) Build a BFF (Backend for Frontend) — a dedicated aggregation layer tailored for mobile.
C) Put a Load Balancer in front of all services — single IP, distributed traffic.
D) Switch to GraphQL Federation — one unified schema the client queries.
Three of these are real patterns you’d use in production. Only one of them actually solves the problem in front of you.
Pick one — A, B, C, or D — and tell me why. I’ll drop the full breakdown in the comments (including why two of the wrong answers are close enough to trick senior engineers).
If this is the kind of tradeoff question your team argues about, share it with them. The debate is worth more than the post.
Drop your answer 👇
Top comments (4)
Why A wins (API Gateway):
One domain. One auth flow. One error contract. The client stops caring that UserService, OrderService, and PaymentService live on different hosts — the gateway hides them behind api.yourapp.com/users, /orders, /payments. When NotificationService ships next sprint, you add one route. The mobile app ships zero changes. That’s what “future-proof” actually means at the transport layer: new services cost nothing on the client side.
It also centralizes the things you don’t want scattered across 4 codebases: authN/authZ, rate limiting, request logging, TLS termination, versioning. Netflix, Stripe, and every mature fintech run some form of this.
Why C is wrong (Load Balancer):
A load balancer distributes traffic across identical instances of the same service. It doesn’t route between different services on different domains. Putting an LB in front of UserService + OrderService doesn’t make sense — it has no concept of “send /orders here and /users there.” That’s application-layer routing, which is exactly what an API Gateway does.
Why B is the trap answer (BFF):
BFF is a legitimate pattern — and it’s close enough to fool a lot of senior engineers. But BFF solves a different problem: data shape per client type. Mobile needs a slim payload, web needs a richer one. BFF gives each client its own backend that aggregates and reshapes data.
In this scenario, the pain isn’t payload shape — it’s domain sprawl and coupling. Putting a BFF here trades 4 URLs for 1 URL + 1 extra service you own end-to-end. That’s the wrong tradeoff.
Why D is wrong here (GraphQL Federation):
GraphQL Federation solves schema unification, not transport-layer coupling. You’d still need a gateway in front of the federation, and you’d rewrite every backend service to expose a GraphQL subgraph. That’s a multi-quarter migration to solve a problem you can fix in a sprint with a gateway.