100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

What is the API Composition Pattern?

Learn the API composition pattern: how a gateway or aggregator joins multiple microservice responses, and when to use CQRS instead.

mediumQ205 of 224 in System Design Est. time: 5 minsLast updated:
Open Code Lab

Expected Interview Answer

API composition is a query pattern where a dedicated composer (an API gateway, BFF, or aggregator service) invokes several microservices in parallel or sequence and joins their results in application code, because the underlying data now lives in separate databases that cannot be joined with SQL.

When a monolith splits into microservices, each service owns its own database, so a query that once meant one SQL join across tables now means calling multiple services and stitching responses together. The composer sends requests to each contributing service (in parallel when they are independent, or in sequence when one input depends on a prior result), waits for all responses, and merges them into a single payload the client can consume. This keeps the join logic out of individual services and out of the client, but it pushes latency to the slowest participating call, requires the composer to handle partial failures gracefully (return degraded data or fail the whole request), and does not scale well past a handful of services because fan-out cost and failure surface grow with each added dependency. For read-heavy composite views spanning many services or requiring in-memory filtering across large datasets, CQRS with a precomputed read model is usually the better fit.

  • Keeps per-service databases private, avoiding cross-service joins and coupling
  • Reuses existing service APIs without new infrastructure
  • Simple to reason about and implement compared to building a materialized view
  • Works well for a small, bounded number of participating services

AI Mentor Explanation

API composition is like a scorer who needs the full match report and must separately call the ground curator for pitch data, the umpire for wicket details, and the broadcaster for player stats, then staple all three into one summary sheet. None of those three sources shares a single filing cabinet, so the scorer is the only place the combined picture exists. If the broadcaster is slow to respond, the whole report waits on that one call before it can be handed over. That runtime stitching of independently owned records into one answer is exactly what API composition does across microservices.

Step-by-Step Explanation

  1. Step 1

    Client sends one query

    The client asks the composer (gateway or aggregator service) for a composite view, not the individual services.

  2. Step 2

    Composer fans out requests

    It calls each contributing microservice, in parallel where possible, in sequence where one call depends on another’s result.

  3. Step 3

    Composer waits and joins

    Responses are collected and merged in application code into a single combined payload.

  4. Step 4

    Handle partial failure

    If one downstream call fails or times out, the composer decides whether to return partial data or fail the whole request.

What Interviewer Expects

  • Explains why cross-service SQL joins are no longer possible after database-per-service decomposition
  • Describes parallel vs sequential fan-out and where the composer sits (gateway/BFF/aggregator)
  • Discusses the latency-to-slowest-call and partial-failure trade-offs
  • Knows when to switch to CQRS with a materialized view instead of composition

Common Mistakes

  • Assuming the pattern scales to dozens of participating services without latency or failure cost
  • Forgetting to handle a slow or failed downstream call gracefully
  • Confusing API composition with a simple reverse proxy that does not merge data
  • Not recognizing when a read-heavy composite view should become a precomputed CQRS view instead

Best Answer (HR Friendly)

API composition means one service or gateway calls several other microservices and combines their answers into a single response for the client, because the data now lives in separate databases that cannot be joined directly. It is simple and works great for a handful of services, but if the query needs many services or needs to be fast, we would build a dedicated read model instead.

Code Example

Composer joining three microservice calls
async function getOrderDetail(orderId) {
  const [order, customer, shipment] = await Promise.all([
    orderService.get(orderId),
    customerService.getByOrderId(orderId),
    shippingService.getByOrderId(orderId),
  ])

  if (!order) {
    throw new NotFoundError(`order ${orderId} not found`)
  }

  return {
    id: order.id,
    status: order.status,
    items: order.items,
    customerName: customer ? customer.name : "unknown",
    trackingNumber: shipment ? shipment.trackingNumber : null,
  }
}

Follow-up Questions

  • How would you handle one of the three downstream calls timing out?
  • When would you replace API composition with CQRS and a materialized read model?
  • How do you avoid the composer becoming a bottleneck as more services are added?
  • What is the difference between API composition done at a gateway versus inside a dedicated BFF?

MCQ Practice

1. Why does API composition become necessary after splitting a monolith into microservices?

Database-per-service means related data lives in separate stores, so joins must happen in application code via composition instead of SQL.

2. What is the main latency risk of the API composition pattern?

Because the composer waits on all fanned-out calls before merging, the overall response time is bounded by the slowest one.

3. When does API composition typically stop being a good fit?

As the number of participating services and aggregation complexity grows, a precomputed CQRS read model usually outperforms runtime composition.

Flash Cards

What is API composition?A pattern where a composer service calls multiple microservices and merges their responses into one answer.

Why is it needed in microservices?Because each service owns its own database, so cross-service joins can no longer be done in SQL.

Main downside of API composition?Latency is bounded by the slowest downstream call, and partial failures must be handled explicitly.

When to switch away from it?When many services or heavy aggregation are involved — use CQRS with a materialized read model instead.

1 / 4

Continue Learning