Implementing API Composition Patterns
1. Using Backend for Frontend (BFF) Pattern
Web App → Web BFF ┐
Mobile → Mobile BFF├→ [microservices]
Smart TV → TV BFF ┘
| BFF Type | Optimizes For |
|---|---|
| Web | SEO data, larger payloads |
| Mobile | Smaller responses, fewer calls |
| TV/IoT | Slow CPU, simple JSON |
| Partner | Stable contract, masked fields |
2. Implementing API Orchestration
| Step | Action |
|---|---|
| 1 | Receive client request |
| 2 | Decompose into N service calls |
| 3 | Execute with retries/timeouts |
| 4 | Compose response shape |
| 5 | Return unified result |
3. Using API Facade Pattern
| Aspect | Detail |
|---|---|
| Single interface | Hide N implementations |
| Decoupling | Clients don't change with backends |
| Aggregation | Combine multiple calls |
| Translation | Adapt legacy formats |
4. Implementing Aggregator Pattern
Example: Aggregator pseudocode
// Fan-out, fan-in
List<CompletableFuture<Item>> futures = backends.stream()
.map(b -> CompletableFuture.supplyAsync(() -> b.fetch(id)))
.collect(toList());
List<Item> items = futures.stream()
.map(f -> f.completeOnTimeout(null, 2, SECONDS).join())
.filter(Objects::nonNull)
.collect(toList());
5. Configuring Micro-Gateway Pattern
| Property | Value |
|---|---|
| Footprint | < 50 MB RAM |
| Deployment | Per-service or sidecar |
| Examples | Envoy, Traefik, Tyk MDCB |
| Use case | Edge + service mesh hybrid |
6. Setting Up Scatter-Gather Pattern
Request → [scatter] → svc-A, svc-B, svc-C (parallel)
←──── responses
→ [gather] → merge → reply
7. Configuring Chain Pattern
| Step | Action |
|---|---|
| 1 | Call A → response A |
| 2 | Use A.id → call B |
| 3 | Use B.token → call C |
| Latency | Sum of all steps |
8. Using Branch Pattern
Example: Conditional branch
if (req.type == OrderType.PHYSICAL) {
return shippingService.create(req);
} else if (req.type == OrderType.DIGITAL) {
return licenseService.issue(req);
} else {
return subscriptionService.start(req);
}
9. Implementing Splitter Pattern
| Input | Output |
|---|---|
| Bulk array | N parallel single requests |
| Large payload | Multiple chunks to different svcs |
| Multi-action | Fan out to handlers |
10. Setting Up Content-Based Router
Example: Body-field router
local body = cjson.decode(kong.request.get_raw_body() or "{}")
local target
if body.event_type == "payment" then target = "payment-svc"
elseif body.event_type == "refund" then target = "refund-svc"
elseif body.event_type == "chargeback" then target = "dispute-svc"
end
kong.service.set_target(target, 8080)