This pattern demonstrates the Saga pattern for distributed transactions using AWS Lambda durable functions in Node.js. It coordinates a multi-step travel booking process (flight, hotel, car) with automatic compensating transactions on failure.
The Saga pattern manages distributed transactions by breaking them into a sequence of local transactions. Each step can succeed or fail independently, and if any step fails, compensating transactions automatically undo previously completed steps to maintain data consistency.
This implementation uses a single Lambda durable function that:
- Executes reservation steps sequentially (flight → hotel → car)
- Tracks completed steps automatically via
context.step() - Implements compensating transactions in reverse order on failure
- Maintains state across retries without external storage
- Automatic Checkpointing: Each
context.step()creates a checkpoint - Fault Tolerance: Execution resumes from last checkpoint on failure
- Compensating Transactions: Automatic rollback in reverse order
- No External State Store: Durable functions handle state management
- Failure Simulation: Test different failure scenarios
Reserve Flight → Reserve Hotel → Reserve Car → SUCCESS
Reserve Flight → Reserve Hotel (FAILS) → Cancel Flight → ROLLBACK COMPLETE
Reserve Flight → Reserve Hotel → Reserve Car (FAILS) → Cancel Hotel → Cancel Flight → ROLLBACK COMPLETE
- AWS CLI configured
- SAM CLI installed
- Node.js 22.x
sam build
sam deploy --guidedFollow the prompts:
- Stack Name:
saga-pattern-demo - AWS Region: Your preferred region
- Confirm changes: Y
- Allow SAM CLI IAM role creation: Y
- Disable rollback: N
- Save arguments to configuration file: Y
aws lambda invoke \
--function-name <FunctionName>:prod \
--invocation-type Event \
--payload '{"tripId":"trip-001","userId":"user-123"}' \
--cli-binary-format raw-in-base64-out \
response.jsonaws lambda invoke \
--function-name <FunctionName>:prod \
--invocation-type Event \
--payload '{"tripId":"trip-002","userId":"user-123","simulateFailure":"flight"}' \
--cli-binary-format raw-in-base64-out \
response.jsonaws lambda invoke \
--function-name <FunctionName>:prod \
--invocation-type Event \
--payload '{"tripId":"trip-003","userId":"user-123","simulateFailure":"hotel"}' \
--cli-binary-format raw-in-base64-out \
response.jsonaws lambda invoke \
--function-name <FunctionName>:prod \
--invocation-type Event \
--payload '{"tripId":"trip-004","userId":"user-123","simulateFailure":"car"}' \
--cli-binary-format raw-in-base64-out \
response.jsonsam logs --stack-name saga-pattern-demo --tailOr view in CloudWatch Logs console.
{
"status": "SUCCESS",
"message": "Trip booked successfully",
"tripId": "trip-001",
"userId": "user-123",
"reservations": {
"flight": {
"reservationId": "FL-1234567890",
"from": "SFO",
"to": "NYC",
"date": "2026-03-15",
"status": "CONFIRMED"
},
"hotel": {
"reservationId": "HT-1234567891",
"name": "Grand Hotel NYC",
"checkIn": "2026-03-15",
"checkOut": "2026-03-18",
"status": "CONFIRMED"
},
"car": {
"reservationId": "CR-1234567892",
"type": "SUV",
"pickupDate": "2026-03-15",
"returnDate": "2026-03-18",
"status": "CONFIRMED"
}
}
}{
"status": "FAILED",
"message": "Trip booking failed, all reservations rolled back",
"tripId": "trip-003",
"userId": "user-123",
"error": "Hotel reservation failed - no rooms available",
"compensatedServices": ["flight"]
}- State Management:
context.step()automatically creates checkpoints when completing the operation - Idempotency: Completed steps are executed exactly once, even on retries
- Compensation Tracking:
completedStepsarray tracks what needs rollback - Automatic Recovery: Failed executions resume from last checkpoint
- No External Dependencies: No DynamoDB or Step Functions needed
sam delete --stack-name saga-pattern-demo© 2026 Amazon Web Services, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0