You are viewing a free preview of this lesson.
Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.
As serverless applications grow beyond single functions, you need architectural patterns to coordinate multiple services. This lesson covers three fundamental patterns — fan-out, choreography, and orchestration — along with practical implementations using AWS services.
A single Lambda function responding to an API Gateway request is straightforward. But real-world applications require:
The patterns in this lesson address these challenges.
Fan-out distributes a single event to multiple consumers for parallel processing.
+---> Lambda A (resize image)
|
Event (S3 upload) --+--> Lambda B (extract metadata)
|
+---> Lambda C (virus scan)
|
+---> Lambda D (update database)
SNS is the simplest fan-out mechanism — publish once, deliver to many:
# SAM Template
Resources:
OrderTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: order-events
SendConfirmationFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/sendConfirmation.handler
Events:
OrderPlaced:
Type: SNS
Properties:
Topic: !Ref OrderTopic
UpdateInventoryFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/updateInventory.handler
Events:
OrderPlaced:
Type: SNS
Properties:
Topic: !Ref OrderTopic
NotifyWarehouseFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/notifyWarehouse.handler
Events:
OrderPlaced:
Type: SNS
Properties:
Topic: !Ref OrderTopic
EventBridge provides more sophisticated routing with content-based filtering:
// Rule 1: Route high-value orders to fraud check
{
"source": ["myapp.orders"],
"detail-type": ["OrderPlaced"],
"detail": {
"total": [{ "numeric": [">=", 500] }]
}
}
// Rule 2: Route all orders to analytics
{
"source": ["myapp.orders"],
"detail-type": ["OrderPlaced"]
}
// Rule 3: Route international orders to customs
{
"source": ["myapp.orders"],
"detail-type": ["OrderPlaced"],
"detail": {
"country": [{ "anything-but": "GB" }]
}
}
| Feature | SNS | EventBridge |
|---|---|---|
| Filtering | Basic attribute filtering | Rich content-based filtering |
| Targets | Lambda, SQS, HTTP, Email, SMS | Lambda, SQS, Step Functions, API destinations, 20+ targets |
| Schema registry | No | Yes |
| Archive and replay | No | Yes |
| Cross-account routing | Manual | Built-in |
| Cost | $0.50 per million messages | $1.00 per million events |
| Best for | Simple fan-out | Complex routing and event-driven architectures |
In choreography, services react to events independently — there is no central coordinator. Each service performs its task and emits an event for the next step.
Order Service Payment Service Shipping Service
| | |
|-- OrderPlaced ------->| |
| |-- PaymentProcessed -->|
| | |-- ShipmentCreated
| | |
|<-- OrderUpdated ------|<-- StatusUpdated -----|
// Order Service — publishes OrderPlaced event
export const createOrder = async (event) => {
const order = JSON.parse(event.body);
await saveOrder(order);
await eventBridge.send(new PutEventsCommand({
Entries: [{
Source: 'myapp.orders',
DetailType: 'OrderPlaced',
Detail: JSON.stringify({ orderId: order.id, total: order.total }),
}],
}));
return { statusCode: 201, body: JSON.stringify(order) };
};
// Payment Service — reacts to OrderPlaced, emits PaymentProcessed
export const processPayment = async (event) => {
const order = event.detail;
const result = await chargeCustomer(order);
await eventBridge.send(new PutEventsCommand({
Entries: [{
Source: 'myapp.payments',
DetailType: 'PaymentProcessed',
Detail: JSON.stringify({ orderId: order.orderId, paymentId: result.id }),
}],
}));
};
// Shipping Service — reacts to PaymentProcessed
export const createShipment = async (event) => {
const payment = event.detail;
await scheduleShipment(payment.orderId);
};
| Advantage | Disadvantage |
|---|---|
| Services are fully decoupled | Hard to see the full workflow at a glance |
| Each service can be deployed independently | Debugging distributed flows is challenging |
| Easy to add new consumers | No single place to handle compensation/rollback |
| Scales naturally | Event ordering can be complex |
Orchestration uses a central coordinator — AWS Step Functions — to manage the workflow. The orchestrator defines the sequence, handles errors, and manages retries.
Subscribe to continue reading
Get full access to this lesson and all 10 lessons in this course.