Aggregator Design Pattern in Microservices – A Complete Guide

In a microservices architecture, individual services handle specific business functionalities. However, modern applications often require data from multiple services to be aggregated into a single response. The Aggregator Design Pattern provides a structured approach to achieving this, ensuring efficiency, performance, and better client experience.

This guide covers:

  • What is the Aggregator Pattern?
  • How it relates to API Gateway
  • Benefits and challenges
  • Implementation strategies
  • A real-world e-commerce example (with database integration)
  • Step-by-step implementation using Spring Boot

1️⃣ What is the Aggregator Design Pattern?

Definition

The Aggregator Pattern is a microservices design pattern where a service collects responses from multiple independent microservices and merges them into a unified response for the client.

📌 Key Concept:

  • A client makes a single request.
  • The Aggregator Service fetches required data from multiple microservices.
  • It processes and merges responses.
  • The client receives a combined response instead of calling each service separately.

2️⃣ Aggregator Design Pattern vs API Gateway

Key Differences

Feature Aggregator Design Pattern API Gateway Pattern
Primary Role Merges data from multiple microservices Routes requests to the correct service
Processing Combines responses before sending them to the client Directly forwards requests without modifying data
Performance Impact Can introduce slight latency due to aggregation Lightweight since it mainly routes traffic
Use Case When multiple microservices need to be queried When managing authentication, load balancing, and rate limiting

When to Use Which?

  • Use Aggregator Pattern when the client needs data from multiple microservices in a single response.
  • Use API Gateway when managing authentication, security, and routing requests.
  • Both can be used together – an API Gateway can route traffic to an Aggregator Service, which then retrieves and merges data.

3️⃣ Why Use the Aggregator Pattern?

Key Benefits

Simplifies Client API Calls – Reduces the number of requests needed from the client. 

Reduces Network Load – Instead of multiple requests, one optimized call is made. 

Improves Performance – Aggregates only the required data. 

Enhances Security – Prevents direct client access to all microservices. 

Better Maintainability – Keeps microservices independent while optimizing client-side consumption.

Challenges & Solutions

Challenge Solution
Increased Latency Use asynchronous calls (WebFlux, Reactive programming)
Single Point of Failure Deploy the aggregator as a highly available service
Data Inconsistency Implement event-driven updates for data synchronization

4️⃣ Real-World Example: E-Commerce Microservices 🛒

Scenario:

A customer requests an order summary, which includes:

  • Product details (Product Service - MySQL)
  • Order details (Order Service - PostgreSQL)
  • Payment status (Payment Service - MongoDB)

Instead of calling multiple microservices, the Aggregator Service collects, merges, and returns the data in a single API response.

Workflow:

1️⃣ Client requests order summary → Aggregator fetches Product, Order, and Payment data

2️⃣ Aggregator processes data → It merges responses into a single JSON object

3️⃣ Final response is returned → The client gets all required information in one API call.

5️⃣ Step-by-Step Implementation Using Spring Boot

Step 1: Define Microservices & Databases

Each microservice has its own dedicated database.

services:
  product-service:
    db: MySQL
  order-service:
    db: PostgreSQL
  payment-service:
    db: MongoDB
  aggregator-service:
    db: No database (Fetches from other services)

Step 2: Implement Product Service

✅ Product Controller

@RestController
@RequestMapping("/products")
public class ProductController {
    @GetMapping("/{id}")
    public Product getProduct(@PathVariable Long id) {
        return new Product(id, "Laptop", 1200);
    }
}

Step 3: Implement Order Service

✅ Order Controller

@RestController
@RequestMapping("/orders")
public class OrderController {
    @GetMapping("/{id}")
    public Order getOrder(@PathVariable Long id) {
        return new Order(id, 1L, "CONFIRMED");
    }
}

Step 4: Implement Payment Service

✅ Payment Controller

@RestController
@RequestMapping("/payments")
public class PaymentController {
    @GetMapping("/{id}")
    public Payment getPayment(@PathVariable Long id) {
        return new Payment(id, "PAID");
    }
}

Step 5: Implement API Gateway for Routing Requests

API Gateway Configuration (application.properties)

server.port=8080
spring.application.name=api-gateway
eureka.client.service-url.default-zone=http://localhost:8761/eureka/
spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id=true

API Gateway Routing (application.yml)

spring:
  cloud:
    gateway:
      routes:
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/products/**
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/orders/**
        - id: payment-service
          uri: lb://payment-service
          predicates:
            - Path=/payments/**
        - id: aggregator-service
          uri: lb://aggregator-service
          predicates:
            - Path=/aggregator/**

Step 6: Implement Feign Clients in Aggregator Service (Calls Multiple Services)

@FeignClient(name = "product-service")
public interface ProductClient {
    @GetMapping("/products/{id}")
    Product getProductById(@PathVariable Long id);
}

@FeignClient(name = "order-service")
public interface OrderClient {
    @GetMapping("/orders/{id}")
    Order getOrderById(@PathVariable Long id);
}

@FeignClient(name = "payment-service")
public interface PaymentClient {
    @GetMapping("/payments/{id}")
    Payment getPaymentById(@PathVariable Long id);
}

Step 7: Implement Aggregator Service with Service Layer

Aggregator Service Layer

@Service
public class AggregatorService {
    private final ProductClient productClient;
    private final OrderClient orderClient;
    private final PaymentClient paymentClient;

    @Autowired
    public AggregatorService(ProductClient productClient, OrderClient orderClient, PaymentClient paymentClient) {
        this.productClient = productClient;
        this.orderClient = orderClient;
        this.paymentClient = paymentClient;
    }

    public AggregatedResponse getOrderDetails(Long orderId) {
        Order order = orderClient.getOrderById(orderId);
        Product product = productClient.getProductById(order.getProductId());
        Payment payment = paymentClient.getPaymentById(orderId);
        return new AggregatedResponse(order, product, payment);
    }
}

Aggregator Controller

@RestController
@RequestMapping("/aggregator")
public class AggregatorController {
    private final AggregatorService aggregatorService;

    @Autowired
    public AggregatorController(AggregatorService aggregatorService) {
        this.aggregatorService = aggregatorService;
    }

    @GetMapping("/order-details/{orderId}")
    public AggregatedResponse getOrderDetails(@PathVariable Long orderId) {
        return aggregatorService.getOrderDetails(orderId);
    }
}

6️⃣ Testing the Implementation

# Fetch aggregated order details via API Gateway
curl -X GET http://localhost:8080/aggregator/order-details/1

🎯 Conclusion

The Aggregator Design Pattern simplifies microservices data retrieval by combining multiple API responses into a single response. This enhances performance, security, and scalability.

🚀 Key Takeaways:

✔ Reduces network overhead

✔ Improves performance and client-side simplicity

✔ Works well with API Gateway, Feign Clients, and event-driven architectures

Ensures modular and scalable microservices communication.

By implementing the Aggregator Pattern, you can optimize API communication in microservices! 🚀

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare