Intermediate · Serverless, monitoring and cost control · topic 20 of 50 · 30 min
Event-driven design: API Gateway, SQS, SNS, EventBridge and Step Functions
Explanation
Why decouple?
Imagine a food delivery app where the order API does everything itself, one step after another: save the order, charge the card, tell the restaurant, send an SMS, update the analytics. If the SMS provider is slow, the customer stares at a spinner. If analytics is down, the whole order fails. The parts are tightly coupled: each one depends on all the others being up and fast right now.
Decoupling means putting a message in between. The API saves the order, drops a message saying "order placed" into a queue, and answers the customer at once. Workers pick up the message when they are ready. If a worker crashes, the message waits and is tried again. Each part can be scaled, changed or fixed without touching the others.
API Gateway: the front door
Amazon API Gateway gives your backend a public HTTPS address, checks requests, and passes them to Lambda or another service. It comes in three types: REST APIs, HTTP APIs and WebSocket APIs.
| REST API | HTTP API | |
|---|---|---|
| Features | More: API keys and usage plans, request validation, caching, AWS WAF, private APIs | Fewer, simpler: JWT authorisers, CORS, Lambda and HTTP backends |
| Price and speed | Higher price per million requests | Cheaper and lower latency |
| Choose it when | You need one of its extra features | You want a simple, low-cost API in front of Lambda |
SQS: queues
Amazon SQS (Simple Queue Service) stores messages until a consumer reads them. A producer sends a message; a consumer polls the queue, processes the message, and then deletes it. If the consumer never deletes it, SQS assumes the work failed.
- Standard queues: almost unlimited throughput, at-least-once delivery (a message can occasionally arrive twice) and best-effort order.
- FIFO queues: strict order within a message group and exactly-once processing within a deduplication window. The name must end in .fifo, and throughput is lower.
The visibility timeout is the key idea. When a consumer receives a message, SQS hides it from other consumers for that many seconds (30 by default, up to 12 hours). If the consumer deletes it in time, it is gone. If not, it becomes visible again and another consumer gets it. With Lambda reading the queue, AWS recommends a visibility timeout of at least six times the function timeout.
A message that keeps failing is called a poison message. A dead-letter queue (DLQ) catches it: in the source queue's redrive policy you set maxReceiveCount, say 5. After a message has been received 5 times without being deleted, SQS moves it to the DLQ, where a human can inspect it and later redrive it back.
{
"VisibilityTimeout": "60",
"MessageRetentionPeriod": "345600",
"RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:ap-south-1:111122223333:orders-dlq\",\"maxReceiveCount\":\"5\"}"
}aws sqs create-queue --queue-name orders-dlq
aws sqs create-queue --queue-name orders --attributes file://orders-queue.json
aws sqs send-message --queue-url https://sqs.ap-south-1.amazonaws.com/111122223333/orders \
--message-body '{"orderId":"A1001","city":"Pune"}'
aws sqs receive-message --queue-url https://sqs.ap-south-1.amazonaws.com/111122223333/orders \
--wait-time-seconds 20SNS: publish once, deliver to many
Amazon SNS (Simple Notification Service) is publish/subscribe. A publisher sends one message to a topic; SNS delivers a copy to every subscriber: SQS queues, Lambda functions, HTTPS endpoints, email or SMS. This is called fan-out. Subscribers can use filter policies to receive only the messages they care about. A common pattern is SNS in front of several SQS queues, so each subscriber gets its own durable copy.
EventBridge: an event router and scheduler
Amazon EventBridge has event buses. AWS services, your own apps and some SaaS partners put events on a bus. Rules match events by pattern and send them to targets such as Lambda, SQS or Step Functions. EventBridge Scheduler runs targets on a cron or rate schedule, with time zone support, which replaces many old "cron on a server" jobs.
{
"source": ["foodapp.orders"],
"detail-type": ["OrderPlaced"],
"detail": { "city": ["Pune", "Mumbai"] }
}Step Functions: workflows
AWS Step Functions runs a state machine: a workflow of steps written in JSON (Amazon States Language). Each step can call Lambda or another AWS service, with built-in retries, error catching, branches, waits and parallel steps. Standard workflows can run for up to a year; Express workflows are for short, high-volume runs of up to 5 minutes.
Putting it together: an order on a food delivery app
- The app sends POST /orders to API Gateway, which calls a small Lambda function.
- That function checks the order, saves it to DynamoDB, sends a message to the orders SQS queue, and answers 202 Accepted within a fraction of a second.
- A worker Lambda reads the queue in batches, charges the payment and updates the order status.
- When payment succeeds, the worker publishes OrderConfirmed to an SNS topic. Subscribers: a queue for the restaurant tablet service, a function that sends the SMS and push notification, and a queue for analytics.
- A message that fails 5 times goes to the DLQ, and a CloudWatch alarm on the DLQ size tells the on-call engineer.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Event-driven design: API Gateway, SQS, SNS, EventBridge and Step Functions · 1/8
This lesson is about event-driven design, where parts of a system talk through messages instead of waiting on each other.
Prefer a video by a teacher? Find free videos on “aws sqs sns eventbridge explained decoupling dead letter queue” on YouTube ↗
In real life: Weekend rush at a Bengaluru food delivery startup
On Saturday nights orders jump to ten times the weekday level. Because the order API only saves the order and drops a message on an SQS queue, it answers customers quickly even when the payment provider slows down. The worker functions scale up with the queue length. When one restaurant's tablet integration broke, its messages piled up in the DLQ instead of blocking everyone else, and an alarm on the DLQ reached the on-call engineer within five minutes. After the fix she redrove the messages back to the main queue and no order was lost.
import json
def worker(event, context):
for record in event["Records"]:
order = json.loads(record["body"])
if already_processed(order["orderId"]): # idempotency check
continue
charge_payment(order)
mark_processed(order["orderId"])Practice (0/3 done)
One "order confirmed" message must reach the restaurant service, the SMS service and analytics, each at its own pace. Which pattern fits best?
Simulate an SQS queue with a visibility timeout and a DLQ. Write run_queue(messages, failures, visibility_timeout, max_receive_count). All messages arrive at second 0. One worker works one message per second: at each second t (0, 1, 2 ...) it receives the visible message (visible_at <= t) with the smallest visible_at, ties broken by the original order. Receiving adds 1 to that message's receive count. failures[id] says how many times processing fails before it succeeds (missing means 0). If it fails: when the receive count has reached max_receive_count, move the message to the DLQ; otherwise it becomes visible again at t + visibility_timeout. If it succeeds, it is deleted and (id, t) is added to done. If nothing is visible, the worker just waits for the next second. Stop when the queue is empty and return (done, dlq).
Design the event flow for a college canteen pre-order app: students order from their phones, the kitchen screen shows new orders, the student gets an SMS when food is ready, and the canteen manager gets a daily sales report at 9 pm. Name the AWS service for each step and explain why.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Monitoring with CloudWatch, CloudTrail and ConfigServerless, monitoring and cost control · same module
- Cost control in practiceServerless, monitoring and cost control · same module
- Background jobs and queuesBackend Development · Performance and reliability
- System design: planning a big backendBackend Development · Deployment and scaling
- Events: letting objects notify each otherC# and .NET · Exceptions, delegates, events and async
- GitHub ActionsDevOps: Git, Docker, Kubernetes and CI/CD · CI/CD pipelines
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
A worker received an SQS message but crashed before deleting it. What happens?
Answer: After the visibility timeout ends, the message becomes visible again
Messages are only removed when deleted. When the visibility timeout ends, another consumer can receive it. It goes to the DLQ only after maxReceiveCount receives.
Bank transactions for one account must be processed strictly in order. Which queue type?
Answer: SQS FIFO queue with the account number as the message group ID
FIFO queues keep strict order within a message group, so grouping by account keeps each account in order.
What is a dead-letter queue for?
Answer: Holding messages that failed processing too many times
After maxReceiveCount failed receives, SQS moves the message to the DLQ so it stops blocking work and can be inspected.
Which service runs a Lambda function every weekday at 9 am Indian time?
Answer: EventBridge Scheduler
EventBridge Scheduler runs targets on cron or rate schedules and supports time zones like Asia/Kolkata.
Why must consumers of a standard SQS queue be idempotent?
Answer: Standard queues may deliver a message more than once
Standard queues give at-least-once delivery, so the same message can arrive twice. Processing it twice must be harmless.
In a queue system, what is a worker?Related
Answer: A process that takes jobs from the queue and does them
Producers add jobs; workers (consumers) take them from the queue and run them.
Why put "order.placed" events on a queue?Related
Answer: So the API answers fast and workers handle slow jobs reliably
The queue holds the work safely; the API does not wait for SMS, analytics and other slow tasks.
What is a good name for an event raised after a payment fails?Related
Answer: PaymentFailed
Events are usually named in the past tense.
What gives a Lambda function permission to read from a DynamoDB table?Related
Answer: Its execution role
The execution role is the IAM role Lambda assumes when running your code. Its policy must allow the DynamoDB read.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 2 more topics in “Serverless, monitoring and cost control” before its exam: Monitoring with CloudWatch, CloudTrail and Config, Cost control in practice.
- Module 5 exam: Serverless, monitoring and cost control · 13 questions · 20 min, without help. 4 topics of this module still to finish first.
- Then the next module, Microsoft Azure essentials. 50 topics left in the course before the final exam.