Skip to content

Fifty services sit behind one gateway. Why is every launch waiting on its team?

Who Gets In When the API Is Full? · Part 1 of 6 · 5 min read

Read the worked explanation ↓

Your organization runs eighty services and a gateway cluster. The gateway team deploys four times a day because client response assembly, security checks, and payment eligibility rules all live there. Draw the new boundaries and describe how to migrate without dropping access controls.

Think first

Your organization runs eighty services and a gateway cluster. The gateway team deploys four times a day because client response assembly, security checks, and payment eligibility rules all live there. Draw the new boundaries and describe how to migrate without dropping access controls.

Take a few minutes to form an approach, then compare it with the worked explanation.

Reveal the worked explanation

Interview question. A company has fifty backend services, several web and mobile clients, and a gateway team that owns routing, authentication, authorization, request shaping, response assembly, and a growing collection of product rules. Teams complain that even a small product launch requires a gateway deployment. Design the responsibility boundary and the path to change it.

Imagine working on checkout. Your team adds a new delivery promise, tests the order service, and is ready to launch. Then the work stops. The shared gateway has to learn what a “premium delivery promise” means, decide which users qualify, and assemble a custom checkout response. Another team needs the same gateway to understand loyalty points. A third wants pricing experiments. By the end of the quarter the gateway knows more about the product than some of the services do. It is also the place every release gets stuck.

An API gateway is useful precisely because some jobs are common to every request. Public entry, TLS termination where appropriate, route selection, authentication verification, basic request limits, timeouts, and request-level telemetry are good candidates. They should be predictable across services, controlled by policies with clear owners, and relatively independent of whether the request is about shipping or a playlist. The trouble begins when shared infrastructure turns into the owner of business decisions.

An edge gateway applies common transport and identity checks before routing into domain services, while a separate client-specific BFF handles screen composition.
An edge gateway applies common transport and identity checks before routing into domain services, while a separate client-specific BFF handles screen composition.

A concrete distinction helps. The gateway can verify the signature, issuer, audience, expiry, and relevant claims of a token. That does not mean it should own a rule such as “this tenant may refund this specific order while the parcel is in transit.” The refund service owns the order state and that decision. Some broad authorization policy may be enforced at the edge, but object-level permissions need trustworthy domain context. A gateway relying on a token role alone can accidentally authorize a resource the user does not own.

The same applies to validation. The edge can reject a request with a huge body or malformed content type before consuming expensive downstream capacity. The domain service must still validate quantities, financial boundaries, state transitions, and invariants. Gateway validation does not make backend inputs trusted. Internal callers and misconfigured routes exist. Validation rules may be deliberately duplicated at different trust boundaries for different reasons.

What about response aggregation? Mobile teams dislike calling twenty endpoints to draw one screen. Moving every composition into the global gateway looks efficient at first, but it turns a shared component into a monolith tied to fifty schemas. I'd introduce a backend-for-frontend, or BFF, where the composition is genuinely client-specific. The mobile checkout BFF can combine cart, delivery estimates and available payment methods, enforce a client-facing deadline, and evolve at the speed of that product. Domain services still own their data. The global gateway routes to the BFF without learning checkout's internal rules.

There is an important performance trap in this architecture. A gateway is an extra network hop and usually a shared failure domain. If a policy extension makes a remote configuration or identity-service call on every request, a slow control-plane dependency can become a customer-facing outage. Policies should be distributed and versioned, with bounded evaluation, cached verified material where safe, and explicit expiration. Some high-risk decisions must stop when policy freshness is lost. Ordinary routing should often continue with a known-good configuration. Those choices belong in a documented failure matrix, not one global “always fail open” switch.

Now consider rate limiting. The gateway is a natural place to identify a caller and apply an inexpensive coarse limit. But which identity? A user, client application, tenant, or originating IP leads to different fairness properties. If it only trusts an X-Tenant-Id header supplied by the client, callers can choose somebody else's bucket. The authenticated principal must determine the enforcement identity, with care for delegated credentials and shared accounts. The service may also need a smaller limit based on expensive operations the gateway cannot accurately price.

I would evaluate the existing gateway by listing every plugin, routing rule, remote dependency, owning team, and release reason from the past month. Rules that encode business state move to owning services. Client presentation orchestration moves to BFFs where it lowers client complexity. Cross-cutting policies become versioned declarative configurations with schema validation, safe rollout and rollback, rather than arbitrary code added by every team. We must preserve the old route's security contract during migration and avoid two gateways disagreeing about authorization or quota accounting.

The design also needs a test strategy. Simulate an invalid token, expired policy bundle, unavailable rate-limit service, downstream timeout, oversized payload, and a partial rollout of new routes. Prove that authenticated identity cannot be spoofed through forwarded headers, that logs do not expose secrets, and that a faulty plugin can be rolled back without rebuilding every service. Watch edge added latency, policy-denial rates, route-error distributions and the number of launches needing central code changes.

A common answer in interviews is “put authentication, routing and rate limiting at the gateway.” That is a start, not an architecture. The more consequential decision is what remains outside it. A gateway that is boring and safe to change is valuable infrastructure. A gateway that knows every business workflow is a new distributed monolith standing in front of the old one.

Go deeper

If the gateway terminates TLS, choose where the next trust boundary is established. Service-to-service TLS, workload identity, header sanitation, and explicit forwarding rules matter. Do not accept incoming X-User or X-Forwarded-For values as authoritative unless a trusted edge has replaced or validated them. A BFF is not a bypass around service-level authorization. For low-trust public APIs, a WAF or DDoS layer can sit before the application gateway and absorb traffic the per-request rate-limit service should never need to evaluate. Keep gateway policies observable by version and route.

Check your reasoning

  • Define a clear cross-cutting gateway responsibility contract and policy owner.
  • Keep domain invariants and object-level authorization with owning services.
  • Route client-specific response composition to a BFF only where justified.
  • Identify remote policy dependencies, principal spoofing, versioned rollout and bypass risks.
  • Propose migration, latency telemetry and tests for policy and security regressions.

Common mistake: The gateway validated a signed token, so every backend can skip resource-level authorization.

Which gateway boundary preserves service-level authorization while allowing product teams to evolve independently?

Read the answer explanation

Verify identity at the edge, then let domain services authorize specific resource operations — Identity verification cannot establish ownership of a specific order or the legality of an order state transition.

Apply it elsewhere

Design a gateway and BFF boundary for a streaming-video home screen where device-specific presentation is required but content entitlements must remain correct across web, TV and mobile.

Compare your approach

Separate cross-cutting checks from domain policy, identify authoritative caller identity, defend service-level authorization, limit request-path dependencies, show a safe migration and rollback, and specify how latency and policy errors are measured.

One more constraint

If the gateway validates a user's JWT, may the order service skip checking whether that user owns order 918?

Quick revision

Put stable cross-cutting transport and policy work at the gateway: entry routing, identity verification, coarse protection, deadlines and telemetry. Keep domain invariants and object-level authorization with the service that owns the data. Client-specific composition can live in a BFF. Avoid synchronous control-plane lookups on every request, treat forwarded headers as untrusted, and version gateway configuration so changes can roll out safely. The strongest design prevents the gateway from becoming another shared business monolith.

References