ARCHIVED from builddistributedsystem.com on 2026-04-28 — URL: https://builddistributedsystem.com/tracks/proxies/tasks/task-21-2-4-aggregation
TASK

Implementation

API composition (aggregation) enables clients to fetch data from multiple services with a single request. The gateway fans out to backends and composes the response.

Composition patterns:

1. Aggregation (merge results):
   Client → Gateway → [Service A, Service B, Service C]
   Gateway merges: {a: {...}, b: {...}, c: {...}}

2. Composition (transform and combine):
   Client → Gateway → [User Service, Order Service]
   Gateway composes: {user: {...}, orders: [...]}

3. Chaining (sequential calls):
   Client → Gateway → Service A → (use A's result) → Service B

Example: Order details aggregation:

// Client request:
Request:  {"type": "api_request", "msg_id": 1, "method": "GET", "path": "/api/orders/123/details"}

// Gateway fans out to 3 services:
Service A (Orders):   GET /orders/123{"id": 123, "user_id": 456, "items": [...]}
Service B (Users):    GET /users/456{"id": 456, "name": "Alice", "email": "..."}
Service C (Products): GET /products?id=1,2,3[{"id": 1, "name": "Widget"}, ...]

// Gateway composes response:
Response: {"type": "api_response", "in_reply_to": 1, "body": {
  "order": {"id": 123, "items": [...]},
  "user": {"id": 456, "name": "Alice"},
  "products": [{"id": 1, "name": "Widget"}, ...]
}}

Aggregation configuration:

{
  "aggregations": {
    "/api/orders/*/details": {
      "backend_requests": [
        {"service": "orders", "path_template": "/orders/{order_id}"},
        {"service": "users", "path_template": "/users/{user_id}", "source": "orders.user_id"},
        {"service": "products", "path_template": "/products", "source": "orders.items.*.product_id"}
      ],
      "response_template": {
        "order": "$.orders",
        "user": "$.users",
        "products": "$.products"
      },
      "timeout_ms": 2000,
      "failure_strategy": "partial"  // or "fail_fast"
    }
  }
}

Failure strategies:

partial: Return successful services, null for failed
  {"order": {...}, "user": null, "products": [...]}

fail_fast: If any service fails, return error immediately
  {"error": "Service unavailable: users-service"}

ignore: Continue without failed service
  {"order": {...}, "products": [...]}

Sample Test Cases

Aggregate from 3 servicesTimeout: 5000ms
Input
{"src":"client","dest":"gateway","body":{"type":"init","msg_id":1,"aggregations":{"/api/orders/*/details":{"backends":["orders","users","products"]}}}}
{"src":"client","dest":"gateway","body":{"type":"api_request","msg_id":2,"method":"GET","path":"/api/orders/123/details"}}
Expected Output
{"src": "gateway", "dest": "client", "body": {"type": "init_ok", "in_reply_to": 1}}
Partial failure handlingTimeout: 5000ms
Input
{
  "src": "client",
  "dest": "gateway",
  "body": {
    "type": "api_request",
    "msg_id": 1,
    "method": "GET",
    "path": "/api/orders/123/details"
  },
  "failure_strategy": "partial",
  "failed_services": [
    "users"
  ]
}
Expected Output
{"src": "gateway", "dest": "client", "body": {"type": "api_response", "in_reply_to": 1, "body": {"order": {...}, "user": null, "products": [...]}}}

Hints

Hint 1
Gateway fans out requests to multiple backend services
Hint 2
Collect responses from all services
Hint 3
Merge/compose data into a single response for client
Hint 4
Execute requests in parallel for performance
Hint 5
Handle partial failures: return partial data or fail-fast
OVERVIEW

Theoretical Hub

Concept overview coming soon

Key Concepts

API compositionaggregation patterndata compositionparallel requestsbackend fan-outresponse merging
main.py
python
Implement API Composition and Aggregation - Proxies | Build Distributed Systems