BFF aggregation pattern: combine multiple service responses in Python

Mock three backend services and aggregate their responses into one unified payload — the BFF pattern every Python microservice gateway relies on.

Easy Python 3.10+ Aug 9, 2026 Microservices patterns 12 views 0 copies

Python code

33 lines
Python 3.10+
from dataclasses import dataclass
from typing import Any


@dataclass
class Service:
    name: str
    data: dict[str, Any]


def get_user_service() -> Service:
    return Service("user", {"id": 1, "name": "Alice"})


def get_orders_service() -> Service:
    return Service("orders", {"total": 299.99, "count": 2})


def get_shipping_service() -> Service:
    return Service("shipping", {"status": "shipped", "tracking": "TRK-123"})


def aggregate_services(services: list[Service]) -> dict[str, Any]:
    result = {}
    for service in services:
        result[service.name] = service.data
    return result


if __name__ == "__main__":
    services = [get_user_service(), get_orders_service(), get_shipping_service()]
    aggregated = aggregate_services(services)
    print(aggregated)

Output

stdout
{'user': {'id': 1, 'name': 'Alice'}, 'orders': {'total': 299.99, 'count': 2}, 'shipping': {'status': 'shipped', 'tracking': 'TRK-123'}}

How it works

Each Service wraps a service name with its JSON-like data payload. aggregate_services iterates through the list and copies each service's data under a key matching its name. The result is a single flat dictionary that front-end clients can consume in one request. In production, each get_*_service would be an HTTP call or gRPC client, but the aggregation function stays the same. Dataclasses keep the mock data structured and easy to extend with new services.

Common mistakes

  • Returning the parallel calls naively (sequential loops add latency) instead of fanning out with asyncio or requests in threads
  • Forgetting to handle partial failures — one service's timeout shouldn't break the whole BFF response
  • Overwriting duplicate service names in the result dict instead of validating unique keys

Variations

  1. Use `asyncio.gather` to call the three service functions concurrently instead of sequentially
  2. Return a typed dataclass for the aggregated payload so downstream consumers get IDE autocomplete and `TypedDict` validation

Real-world use cases

  • A mobile app's home screen API needs user profile, orders summary, and shipping status in one endpoint call.
  • A dashboard BFF combines inventory, pricing, and review data from separate internal services into a unified widget payload.
  • An edge gateway aggregates customer, entitlements, and usage stats before returning a single response to the client.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Microservices patterns

Related tutorials and quizzes for this topic.