Prompt

What are the best API composition patterns for microservices?

Technology · Developer Tools / Developer tools2 observationsLast seen Jul 15, 2026

Latest observation

Jul 15, 2026 · Claude

Here's a rundown of the best API composition patterns for microservices:

API Composition (aggregator pattern)

A dedicated composer service (or BFF) calls multiple downstream services in parallel, then merges the results into a single response for the client.

  • Best for read-heavy queries that need data from several services at once — e.g., "get order details" pulling from Order, User, and Shipping services simultaneously.
  • Downside: the composer becomes a single point of coordination, and if one downstream call is slow, it can drag down the whole response unless you set per-call timeouts and fallback behavior.

Backend for Frontend (BFF)

  • A specialized composition layer per client type (web, mobile, partner), rather than one generic aggregator — see earlier discussion for when this is preferred over a shared composer. Best when different clients need meaningfully different shapes or subsets of the same underlying data.

CQRS (Command Query Responsibility Segregation)

Separates the write path (commands going to individual services, each owning its own data) from the read path (a denormalized read model built specifically for queries).

  • Instead of composing data live at request time, a read-optimized view is built ahead of time — often via event listeners that update a materialized view whenever underlying data changes. Best for high-read-volume scenarios where live composition on every request would be too slow or expensive.

Event-driven materialized views (data replication pattern)

Services publish events when their data changes; a separate service subscribes to relevant events and maintains its own local, denormalized copy of the data it needs.

  • Queries are then served entirely from that local copy — no live cross-service calls needed at read time.
  • Trade-off: the read model is eventually consistent, not real-time, so this only works where slightly stale data is acceptable.

GraphQL federation / schema stitching

Multiple services each expose a partial GraphQL schema; a gateway (e.g., Apollo Federation, GraphQL Mesh) stitches them into one unified schema.

The client sends a single GraphQL query, and the federation layer resolves which fields come from which service, composing the response automatically.

Best when clients need flexible, ad-hoc composition (different clients querying different combinations of fields) rather than a fixed, predefined aggregation.

Saga pattern (for write-side composition)

  • Used when a single business operation needs to coordinate write operations across multiple services (not just reads) — e.g., "place order" touching Inventory, Payment, and Shipping.

Two flavors:

  • Orchestration-based: a central saga orchestrator explicitly calls each service in sequence and handles compensating actions if a step fails.
  • Choreography-based: each service reacts to events from the previous step and publishes its own event when done — no central coordinator, but harder to trace the overall flow.

Essential for maintaining consistency across services without distributed transactions, which don't scale well in microservices.

Client-side composition (anti-pattern, generally avoided)

The client itself calls multiple services directly and combines the results.

  • Occasionally acceptable for very simple internal tools, but generally discouraged — it exposes internal service topology to the client, creates tight coupling, and forces every client to reimplement the same composition logic.

Sidecar/service mesh-level composition (limited use)

Some meshes support basic request composition or fan-out at the infrastructure layer.

  • Generally not recommended for real business-logic composition — meshes are built for traffic management (retries, mTLS, load balancing), not for orchestrating business processes. Keep composition logic in an actual service layer, not the mesh.

How to choose

Simple, real-time read aggregation across 2-3 services → API composition/aggregator pattern.

Different clients need different shapes of the same data → BFF.

High-read-volume, can tolerate eventual consistency → CQRS + materialized views.

Clients need flexible, self-service querying across many services → GraphQL federation.

A business operation needs to coordinate writes across multiple services → Saga (orchestration for clearer control flow, choreography for looser coupling).

Practical guidance

  • Prefer async/event-driven composition (CQRS, materialized views) over synchronous fan-out calls wherever staleness is tolerable — it removes the "slowest service determines your latency" problem inherent to live composition.
  • For synchronous composition that is unavoidable, always set timeouts per downstream call and decide explicitly whether partial failure means partial response or total failure — don't let this happen by accident.
  • Keep composition logic out of individual microservices — a service shouldn't be calling other services to build a response for something outside its own domain; that composition logic belongs in a dedicated layer (BFF, aggregator, or federation gateway).
  • For write-side coordination across services, avoid distributed transactions (two-phase commit) — sagas with explicit compensating actions are the standard pattern precisely because distributed transactions don't scale in a microservices context.

Observation history

See 1 earlier observation

Create a free Obsurfable account to unlock historical responses, model comparisons, and deeper brand intelligence.

How did Obsurfable measure this prompt?

Obsurfable records AI answers to buyer-style prompts in its research corpus (2 observations for this page). Metrics are distributions over observations, not a single static ranking.

Which AI systems does Obsurfable collect answers from?

OpenAI, ChatGPT, Google, Gemini, Google AI Mode, Anthropic, Claude, Perplexity, Grok, DeepSeek, Mistral, Copilot, and Meta AI.