24.1
Event Processing Patterns
Lambda with SQS and SNS, DLQs, fan-out, S3 events, intercepting API calls, and API Gateway to Kinesis.
22 min Reading + animations
Tip: tap or hover any dotted-underlined term to see what it means.
By the end of this lesson you will be able to
- Wire SQS, SNS and Lambda together end to end, and pick the right one from a question’s words: buffer and decouple (SQS), push to many (SNS), run code on an event (Lambda).
- Explain the three retry shapes behind a Lambda function: SQS + Lambda (pollers, visibility timeout, maxReceiveCount, the queue’s DLQ, partial batch responses), SQS FIFO + Lambda (order per message group, a failing message blocks its group), and SNS + Lambda (asynchronous invoke, two Lambda retries, on-failure destination, the subscription DLQ).
- Set up a dead-letter queue correctly for each shape, and redrive messages after a fix.
- Choose SNS → SQS fan-out over writing to several queues from code, and make it work (queue policy, filter policies, S3 events through SNS).
- Design S3 event notifications (event types, prefix and suffix, destinations, the overlap rule, loops) and know when to send S3 events to EventBridge instead.
- React to any AWS API call with CloudTrail + EventBridge, and avoid the Region and read-only traps.
- Ingest a stream through API Gateway straight into Kinesis Data Streams with an AWS service integration, and handle throttling.
#Event processing: the architect’s view
Every building block of this lesson already has its own lesson. Here the question is different: how do several of them fit together, what each hop can and cannot do, and where the whole thing breaks. The notes start with the same warning: this area produces many scenario questions, and they are won by recognising the shape.
| Building block | One-line recap | Taught in |
|---|---|---|
| SQS | A queue: producers send, consumers pull; a buffer that absorbs spikes; messages wait up to 14 days | 13.1, 13.2 |
| SQS FIFO | Order and deduplication per message group | 13.3 |
| SNS | A topic: one publish is pushed to every subscriber | 13.4 |
| Kinesis Data Streams, Firehose | An ordered, replayable stream in shards; delivery of a stream into storage | 13.5, 13.6 |
| Lambda | Code that runs on an event; three invocation types (synchronous, asynchronous, event source mapping) | 15.1, 15.2 |
| API Gateway | The front door of an API; integrations with Lambda, HTTP and AWS services | 15.6 |
| S3 events | A bucket announces object changes | 10.7 |
| EventBridge, CloudTrail | An event bus with rules; the record of every API call | 19.5, 19.6 |
#The core trio: Lambda, SNS and SQS
The notes call these three the foundation of event-driven architecture on AWS, and lesson 13.7 compares them in depth. The short version, with the one correction the exam likes:
- SQS decouples producer and consumer. It is pull-based: an EC2 worker, a container or Lambda takes messages when it is ready.
- SNS is pub/sub and push-based: one publish reaches every subscriber at once (email, SMS, HTTPS, SQS, Lambda, Firehose).
- Lambda runs code when an event happens. With SNS, SNS invokes the function. With SQS, nobody pushes: the Lambda service runs an event source mapping whose pollers read the queue for you.
Why not just call the next service directly? A direct call ties the caller to the callee: the caller waits, fails when the callee fails, and changes whenever a new consumer appears. Every pattern below removes one of those ties.
#Three retry shapes behind a Lambda function
The first slide of the section draws the same function behind three sources and labels each with how it retries. This is the heart of the lesson, because the source decides who retries, how often, in what order, and where a failed message ends.
#SQS + Lambda: the pollers try and retry
- The event source mapping long-polls the queue and receives a batch (up to 10 messages by default; more with a batching window).
- It invokes the function synchronously with the batch. The messages are now in flight, hidden for the queue’s visibility timeout.
- If the function succeeds, Lambda deletes the messages.
- If it fails, nothing is deleted. After the visibility timeout the messages are visible again and are received again. Each receive raises the message’s receive count.
- When the receive count passes the redrive policy’s maxReceiveCount, SQS moves the message to the queue’s DLQ.
Two settings make this shape work well:
- Partial batch responses. By default one exception fails the whole batch, so nine good messages are processed again with the bad one. Turn on
ReportBatchItemFailureson the event source mapping and return the IDs of only the failed messages: Lambda deletes the rest. - Visibility timeout at least 6 times the function timeout. Otherwise a message reappears while the first attempt is still running, and two copies run at once.
A standard queue never blocks behind a bad message: the others keep flowing. And the DLQ is configured on the queue, not on the function, because the function never “owns” the message; the queue does.
#SQS FIFO + Lambda: try, retry, and block
The same polling, with ordering added (13.3):
- Messages are delivered in order per message group ID, and only one batch per group is in flight at a time. Lambda scales with the number of active groups, not with the number of messages.
- When a message fails, it comes back as the head of its group. Every later message of that group waits behind it: head-of-line blocking. That is the slide’s word “blocking”. Other groups are not affected.
- With partial batch responses on a FIFO queue, the function must stop at the first failure and report that message and every later one in the batch as failed, or the order breaks.
- After maxReceiveCount the message goes to a DLQ that must itself be FIFO. The group unblocks, but the later messages now run before the failed one. If order matters more than progress (a ledger where payment 3 depends on payment 2), leave the DLQ off, alarm on the stuck group, and fix the cause.
#SNS + Lambda: asynchronous retries
SNS invokes the function asynchronously (15.1):
- Lambda puts the event in its internal queue and answers 202 at once. For SNS, the delivery has succeeded.
- If the function throws, Lambda retries it twice by default (after about 1 minute, then about 2 more), configurable to 0, 1 or 2. Throttled events are retried for up to the maximum event age (6 hours by default).
- When the retries run out, Lambda sends a record to the on-failure destination (SQS, SNS, EventBridge, another Lambda function, or S3), with the event, the error and the reason. The older alternative is a function DLQ (an SQS queue or SNS topic) that receives only the event. With neither, the event is discarded.
SNS has its own safety net for a different failure: a subscription DLQ (an SQS queue on the subscription) catches messages SNS could not deliver, for example because someone removed the function’s resource policy (a client-side error, not retried). A message that was delivered but failed in the code never reaches the SNS DLQ.
There is no ordering in this shape (SNS FIFO topics deliver only to SQS queues, not to Lambda), and asynchronous delivery is at least once, so the function must be idempotent.
#The three shapes side by side
| SQS + Lambda | SQS FIFO + Lambda | SNS + Lambda | |
|---|---|---|---|
| How Lambda gets the event | Pollers (event source mapping), batch | Pollers, batch, one batch per group | SNS invokes asynchronously |
| Who retries | SQS, by making the message visible again | SQS, same way | Lambda, from its internal queue |
| How often | Every visibility timeout, until maxReceiveCount | Same | 2 retries by default (0–2), up to 6 hours of age |
| Does a failure block others? | No | Yes, its own group | No |
| Failed message ends in | The queue’s DLQ (redrive policy) | A FIFO DLQ | The function’s on-failure destination (preferred) or function DLQ; SNS’s subscription DLQ only for delivery failures |
| No safety net | Loops until retention ends, then lost | Group blocked until it expires, then lost | Discarded after 3 attempts |
Three retry shapes: who retries, how often, and where a bad message ends
A wallet app sends payment events that a Lambda function writes to the ledger. One payment event is broken (a poison pill). Watch the same failure behave differently behind a standard queue, a FIFO queue and an SNS topic.
Scenario
Lambda polls, a bad message comes back after each visibility timeout, and the queue’s DLQ takes it after maxReceiveCount.
The wallet app writes every payment event to a standard SQS queue and moves on. The queue is the buffer: during an Eid rush it simply grows, and nothing is lost while the consumer catches up.
Try the three shapes yourself: pick the source, make the message a poison pill, switch the safety net on and off, and compare the timelines.
Which retry shape? A poison-pill lab
Choose what sits in front of the ledger Lambda function, whether the payment message is broken, and whether the safety net is set up. Press Run to see every attempt, how long it takes, and where the message ends.
Source in front of Lambda
The message
Safety net
Redrive policy to a standard DLQ, maxReceiveCount 3
Pick the three settings, then press Run. Assumptions: function timeout 30 s, visibility timeout 180 s, retention 4 days, Lambda asynchronous retries 2.
Self-checkQuestion
A Lambda function processes an SQS FIFO queue whose message group ID is the customer ID. One message of customer 42 always fails. What happens to the other customers’ messages?
#Dead-letter queues across the shapes
The notes define the idea: when SQS, SNS or Lambda keeps failing on a message and the maximum retries are used up, the message is moved to a separate queue so it is not lost and does not block or loop. Developers read it later to debug. Lesson 13.2 covers the mechanics; here is what an architect must get right.
- On SQS a DLQ is a redrive policy on the source queue:
deadLetterTargetArnplus maxReceiveCount (1 to 1,000; 3 to 10 is common). The DLQ is an ordinary queue you create first. - A poison pill is a message that can never succeed (wrong type, deleted customer, a bug that only this input triggers). Without a DLQ it loops until the retention period ends and then disappears. With a DLQ it leaves after maxReceiveCount tries.
- Same type, same place: a FIFO queue needs a FIFO DLQ, a standard queue a standard DLQ, in the same account and Region.
- Retention longer than the source (usually 14 days): for a standard queue the message keeps its original enqueue time, so a DLQ with the same retention can delete it almost at once.
- Watch it: a CloudWatch alarm on the DLQ’s
ApproximateNumberOfMessagesVisiblegreater than 0. A DLQ nobody looks at is a slower way to lose messages. - Redrive after the fix: “Start DLQ redrive” in the console or
StartMessageMoveTaskmoves messages back to the source queue (or another queue of the same type), optionally at a capped rate.
| Shape | Where the safety net lives | What it receives |
|---|---|---|
| SQS → Lambda | Redrive policy on the queue | Messages received more than maxReceiveCount times |
| SNS → any subscriber | Redrive policy on the subscription (an SQS queue) | Messages SNS could not deliver (client errors, retries exhausted) |
| Asynchronous Lambda (SNS, S3, EventBridge) | On-failure destination (preferred) or function DLQ | Events whose processing failed after the retries |
| EventBridge rule target | DLQ per target (standard SQS queue) | Events that could not be delivered to the target (19.5) |
#Fan-out: deliver one event to many queues
The second slide shows two ways to get one event into three SQS queues.
Option 1: the producer writes to each queue itself. The code calls SendMessage three times, one queue after another. It works on a good day, but:
- There is no transaction across queues. If the process dies after the second write, two consumers have the event and the third never will. Retrying the whole job sends duplicates to the first two.
- Each write adds latency to the producer, and each new consumer means changing and redeploying the producer.
Option 2: fan-out. The producer publishes once to an SNS topic; the queues subscribe to it; SNS pushes a copy into every queue. The producer makes one call and knows nobody. Each consumer has its own queue, so it keeps its own pace, retries and DLQ, and a consumer that is down simply builds a backlog in its queue: the “without data loss” of the exam phrase. SNS retries delivery to SQS for up to 23 days, so the copy is practically guaranteed.
What makes fan-out work in practice (13.4):
- The queue’s access policy must allow the topic to send: principal
sns.amazonaws.com, actionsqs:SendMessage, conditionaws:SourceArn= the topic. The console adds it when you subscribe; the CLI, CloudFormation and Terraform do not, and deliveries fail with access denied. An SSE-KMS queue also needs a customer managed key that allows SNS. - Filter policies on a subscription send each queue only the messages it needs (by message attributes or by the body), instead of every worker discarding most of what it gets.
- Raw message delivery gives the queue exactly the published body, without the SNS JSON envelope.
- Cross-Region and cross-account subscriptions work (queue policy plus topic policy).
- FIFO end to end: an SNS FIFO topic with SQS FIFO queues keeps order and deduplication through the fan-out.
- S3 events → SNS → many queues is the classic way around S3’s rule that one event goes to one destination (next section).
Fan-out: three writes from your code, or one publish to SNS
A bKash-style wallet must send every completed payment to three teams: the ledger, the SMS sender and the fraud check. Option 1 writes to three queues from the code; option 2 publishes once to an SNS topic that the three queues subscribe to.
Scenario
The code sends the same message three times, one queue after another, and crashes half-way.
A payment completes. The service calls SendMessage on the ledger queue with the SDK and waits for the answer.
#S3 event notifications
A bucket can announce what happens to its objects (10.7 has the full detail).
- Event types:
s3:ObjectCreated:*(Put, Post, Copy, CompleteMultipartUpload),s3:ObjectRemoved:*,s3:ObjectRestore:*,s3:Replication:*, plus lifecycle, tagging, ACL and Intelligent-Tiering events. Listen tos3:ObjectCreated:*rather than only:Put, or large multipart uploads are missed. - Filtering: a key prefix and/or suffix only, such as prefix
uploads/and suffix.jpg. No wildcards (the slides’*.jpgis written as the suffix.jpg), no filter on size or metadata. - Destinations: an SNS topic, an SQS queue or a Lambda function, in the same Region as the bucket. Only standard queues and topics: FIFO is not supported as a native destination. The fourth option, EventBridge, is switched on for the whole bucket (next section).
- Permissions: S3 delivers as the service
s3.amazonaws.com, so the destination’s resource policy must allow it (sns:Publish,sqs:SendMessage,lambda:InvokeFunction), ideally limited to the bucket withaws:SourceArnandaws:SourceAccount. A missing permission makes the configuration fail to save. - Timing and delivery: usually within seconds, sometimes a minute or longer; at least once, not ordered (compare the
sequencerfor one key). The key arrives URL-encoded. - How many rules: you can create as many rules as you need, as long as no two overlap.
The overlap rule, made precise: two rules cannot coexist if their event types overlap and their prefixes overlap and their suffixes overlap. So the notes’ “no overlapping rules for the same prefix and suffix” is true per event type: ObjectCreated to a function and ObjectRemoved to a queue on the same prefix is fine; ObjectCreated on uploads/ to a function and to a queue is rejected. Native notifications give one event one destination. To get it to several, send it to one SNS topic and subscribe them all, or use EventBridge.
The recursive loop: a function triggered by uploads/ that writes its output back into uploads/ triggers itself again and again. Write to a different prefix (thumbs/) or bucket. Lambda now detects such S3 loops and stops them after about 16 invocations, but that is a safety net, not a design.
#S3 events through Amazon EventBridge
One bucket setting, Send notifications to Amazon EventBridge, makes S3 send all its events to the default event bus of the same Region. You choose nothing on the S3 side and S3 needs no permission. EventBridge rules then do the filtering and routing (19.5).
| Native notifications | Through EventBridge | |
|---|---|---|
| Filtering | Prefix and suffix only | JSON rules on any event field: key prefix, suffix or wildcard, object size, bucket, requester, source IP, the API that created the object… |
| Destinations | SNS, SQS (standard), Lambda | More than 20 target types: Step Functions, Kinesis Data Streams, Data Firehose, SQS FIFO, ECS tasks, API destinations, another bus…; up to 5 targets per rule |
| Same event, many consumers | No: overlapping rules are rejected | Yes: any number of rules can match one event |
| Extra capabilities | – | Archive and replay, retry policy and DLQ per target, cross-account and cross-Region routing |
| Cost | No charge from S3 | EventBridge charges for events matched and delivered |
Two corrections to the sources. The slide says “over 18 AWS services as destinations” and the notes “18+”: today the EventBridge target list has more than 20 kinds of targets, and the number keeps growing, so remember “many, including Step Functions and Kinesis”. And both say EventBridge can filter on metadata: it filters on the fields in the event (key, size, ETag, version, requester, source IP, reason…), not on the user-defined x-amz-meta- metadata of the object, which is not in the event.
S3 events: a thumbnail, a loop, a rejected rule, and EventBridge
A Dhaka newspaper’s reporters upload photos and videos to a bucket. A function makes thumbnails, the archive team wants the same events, and the video desk needs a workflow only for big files.
Scenario
One rule: object created under uploads/ ending in .jpg → the resize function.
A reporter uploads uploads/eid-rally.jpg from the field. Nobody has to tell the website team; the bucket itself will announce it.
#Intercepting API calls with EventBridge and CloudTrail
Many changes do not produce a service event of their own: nobody announces that a DynamoDB table was deleted or an instance was launched without tags. But every such change is an API call, and CloudTrail records every API call (19.6). CloudTrail delivers those records to the default event bus as events with detail-type AWS API Call via CloudTrail, so a rule can react to any call.
The slide’s example: a user calls DeleteTable on DynamoDB → CloudTrail logs it → an EventBridge rule matches → SNS alerts the team. The notes’ example: someone calls RunInstances → the rule invokes a Lambda function that checks the tags and stops the instance (or tags it, or opens a ticket) when a required tag is missing.
{
"source": ["aws.ec2"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventSource": ["ec2.amazonaws.com"],
"eventName": ["RunInstances"]
}
}
What must be true for it to work:
- A trail with logging on must cover the account (an organization trail counts). Management events are logged by default in a trail; data events (S3 object calls, Lambda invokes) only if you add them.
- Rules are regional. The event arrives on the bus of the Region where the call was recorded. A rule in ap-southeast-1 never sees a call made in eu-west-1.
- Global services such as IAM record their calls in us-east-1, so an IAM rule must live there. Root console sign-ins are recorded in us-east-1, us-east-2 or us-west-2.
- Read-only calls (Get, List, Describe) do not reach a rule in the normal enabled state. Set the rule’s state to
ENABLED_WITH_ALL_CLOUDTRAIL_MANAGEMENT_EVENTS(CLI or CloudFormation) and expect much higher volume. - Near real time: seconds to a few minutes. It detects and reacts; to prevent a call, use IAM, SCPs or the resource’s own protection (DynamoDB deletion protection).
Intercepting API calls: CloudTrail sees the call, EventBridge reacts
A bank’s security team wants to know within minutes when someone deletes a DynamoDB table, and wants every new EC2 instance checked for its owner tag. No polling, no log parsing.
Scenario
The slide’s example: a table is deleted, CloudTrail logs the call, an EventBridge rule sends an SNS alert.
An engineer calls DeleteTable on the payments table, by mistake or on purpose. DynamoDB itself publishes no event for this, but every API call is a CloudTrail record.
#API Gateway straight into Kinesis Data Streams
Behind API Gateway we usually put a Lambda function. But API Gateway can call most AWS APIs directly, with no function in between: an AWS service integration (15.6). The slide’s example is a streaming pipeline:
client → API Gateway → Kinesis Data Streams → Data Firehose → Amazon S3 (.json files)
How it is built:
- A REST API method with integration type AWS, service Kinesis, action PutRecord (or
PutRecordsfor batches). - A mapping template (VTL) that turns the request into the action’s input: stream name, partition key (for example the rider ID, so one rider’s points stay in order on one shard), and the body Base64-encoded as
Data. - An IAM role that API Gateway assumes, allowing exactly
kinesis:PutRecordon that stream. - Integration responses that map Kinesis errors to proper HTTP status codes. With a non-proxy integration, an error without a matching integration response can come back through the default response as a 200 with the error in the body.
- Behind the stream: Firehose buffers records into files in S3 (Athena queries them later), and real-time consumers read the stream directly.
Why remove the Lambda function: it only copied the request, yet it added latency (run time and the occasional cold start), cost per request, and concurrency consumption from the account’s shared pool. Without it there is no code to write, patch or scale. Keep a function only when it does real work (validation a model cannot express, enrichment, routing).
The same trick works for many services: SQS SendMessage, SNS Publish, Step Functions StartExecution, DynamoDB PutItem, S3 objects, EventBridge PutEvents. HTTP APIs offer some of these as ready-made first-class integrations (SQS, Kinesis Data Streams, Step Functions, EventBridge and more).
The limits that matter on this path:
| Limit | Value | What it means |
|---|---|---|
| API Gateway payload | 10 MB | Big uploads go straight to S3 with a presigned URL |
| Kinesis record | 1 MB data blob (the exam number and the default); a stream can be raised to 10 MiB since 2025 | Ping-sized records are the use case |
| Kinesis shard write | 1 MB/s or 1,000 records/s per shard | Too many writes → ProvisionedThroughputExceededException |
| Integration timeout (REST) | 29 s by default (Regional and private APIs can request more since 2024) | Irrelevant for a fast PutRecord, but the exam’s favourite number |
| Account throttle | 10,000 requests/s per Region by default | Stage and method throttling, usage plans |
When the stream is too small, Kinesis throttles the extra writes. Fix it with more shards or on-demand capacity mode, a partition key that spreads the load (a city as key makes one hot shard), client retries with backoff and batching with PutRecords, and API Gateway throttling so a burst is refused at the door.
API Gateway straight into Kinesis: no function in the middle
A Pathao-style ride app sends each rider’s location every few seconds. The slide’s pipeline: client → API Gateway → Kinesis Data Streams → Data Firehose → .json files in S3. Compare it with a Lambda forwarder, and see what happens when the stream is too small.
Scenario
A mapping template turns each request into a PutRecord call; Firehose writes files to S3. No code runs anywhere.
Every few seconds each rider’s app sends POST /pings with the rider ID, latitude and longitude. On an Eid evening that is thousands of requests a second.
#Reading the question: which pattern?
| The scenario says | Pick |
|---|---|
| Decouple, buffer, absorb spikes, workers at their own pace | SQS (+ Lambda or an Auto Scaling group of workers) |
| Strict order per customer/account, no duplicates | SQS FIFO with the customer as message group ID |
| Notify many subscribers, email/SMS, push | SNS |
| One event, many independent workflows, no data loss | SNS + several SQS queues (fan-out) |
| Messages fail repeatedly, poison pill, infinite loop | DLQ via redrive policy (on the queue) |
| Failed asynchronous invocations with error details | Lambda on-failure destination |
| Run code when an object is uploaded | S3 event notification → Lambda / SQS / SNS |
| Filter S3 events by size, several consumers, Step Functions, FIFO, replay | S3 → EventBridge |
| React when a specific API call happens | CloudTrail + EventBridge rule |
| Ingest a stream through a REST API without Lambda | API Gateway AWS service integration → Kinesis Data Streams |
#What goes wrong
- A poison message loops for days: no redrive policy. Add a DLQ with a sensible maxReceiveCount and an alarm on it.
- Good messages are processed twice after one failure in the batch: no partial batch responses. Turn on
ReportBatchItemFailuresand make the consumer idempotent anyway. - Messages are processed by two invocations at once: the visibility timeout is shorter than the function timeout. Use at least six times the function timeout.
- A FIFO group is stuck: its head message keeps failing. Fix the cause, or accept the broken order and add a FIFO DLQ.
- The DLQ was configured on the function, and SQS messages still loop: for SQS sources the DLQ belongs on the queue.
- Failed SNS-triggered events vanish and the SNS DLQ is empty: the delivery succeeded; the failure was in the code. Configure an on-failure destination on the function.
- One fan-out queue receives nothing: its access policy does not allow the topic, or its KMS key does not allow SNS.
- The S3 notification configuration cannot be saved: overlapping rules for the same event type, or a destination policy that does not allow S3, or a FIFO queue as destination.
- The bill explodes after a deploy: a function writes back into the prefix that triggers it.
- The API-call rule never fires: no trail, wrong Region, a global service in us-east-1, or a read-only call.
- Pings disappear at peak: Kinesis throttles, and the integration maps the error to a 200. Add integration responses, more shards or on-demand mode, and client retries.
#Event processing in system design
Put the pieces together for one wallet:
- The mobile API writes high-volume telemetry (screen events, location) through API Gateway → Kinesis → Firehose → S3, no code.
- A completed payment is published once to an SNS topic; ledger, SMS and fraud each have an SQS queue with its own DLQ; the ledger queue is FIFO grouped by account because order matters there.
- Customers’ uploaded KYC documents land in S3; EventBridge rules send large files to a Step Functions review workflow and every upload to an audit FIFO queue.
- CloudTrail + EventBridge rules alert security on
DeleteTable, security-group changes and root sign-ins, in every Region used and in us-east-1. - Every asynchronous Lambda function has an on-failure destination; every queue has an alarm on its DLQ and on the age of its oldest message.
Lesson 15.8 builds complete serverless applications from the same parts, and lesson 24.2 adds caching at every layer of such a design.
#Try it yourself
These commands use the AWS CLI v2 in ap-southeast-1 with made-up names; queues, topics and streams cost money while they exist, so delete them at the end.
# 1. A DLQ and a source queue with a redrive policy (maxReceiveCount 3), DLQ kept 14 days
aws sqs create-queue --queue-name payments-dlq --attributes MessageRetentionPeriod=1209600
aws sqs create-queue --queue-name payments --attributes VisibilityTimeout=180
aws sqs set-queue-attributes \
--queue-url https://sqs.ap-southeast-1.amazonaws.com/111122223333/payments \
--attributes '{"RedrivePolicy":"{\"deadLetterTargetArn\":\"arn:aws:sqs:ap-southeast-1:111122223333:payments-dlq\",\"maxReceiveCount\":\"3\"}"}'
# 2. Let Lambda poll it, with partial batch responses
aws lambda create-event-source-mapping --function-name ledger-writer \
--event-source-arn arn:aws:sqs:ap-southeast-1:111122223333:payments \
--batch-size 10 --function-response-types ReportBatchItemFailures
# { "UUID": "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE", "BatchSize": 10, "State": "Creating",
# "FunctionResponseTypes": [ "ReportBatchItemFailures" ], ... }
# 3. After the fix: move the DLQ's messages back to the source queue
aws sqs start-message-move-task \
--source-arn arn:aws:sqs:ap-southeast-1:111122223333:payments-dlq \
--destination-arn arn:aws:sqs:ap-southeast-1:111122223333:payments \
--max-number-of-messages-per-second 50
# { "TaskHandle": "eyJ0YXNrSWQiOiJkYzE2...EXAMPLE" }
# 4. Asynchronous Lambda: 2 retries, 1 hour maximum age, failures to a queue
aws lambda put-function-event-invoke-config --function-name ledger-writer \
--maximum-retry-attempts 2 --maximum-event-age-in-seconds 3600 \
--destination-config '{"OnFailure":{"Destination":"arn:aws:sqs:ap-southeast-1:111122223333:ledger-failures"}}'
# 5. Fan-out: subscribe a queue to the topic with a filter policy and raw delivery
# (the queue policy must already allow sns.amazonaws.com with aws:SourceArn = the topic)
aws sns subscribe \
--topic-arn arn:aws:sns:ap-southeast-1:111122223333:payment-done \
--protocol sqs --notification-endpoint arn:aws:sqs:ap-southeast-1:111122223333:sms \
--attributes '{"RawMessageDelivery":"true","FilterPolicy":"{\"amount\":[{\"numeric\":[\">\",5000]}]}"}'
# { "SubscriptionArn": "arn:aws:sns:ap-southeast-1:111122223333:payment-done:6f1c2b3a-EXAMPLE" }
# 6. S3: one native rule to Lambda, and EventBridge switched on for the bucket
# (this call replaces the whole notification configuration of the bucket)
aws s3api put-bucket-notification-configuration --bucket news-media-example \
--notification-configuration '{
"LambdaFunctionConfigurations": [{
"LambdaFunctionArn": "arn:aws:lambda:ap-southeast-1:111122223333:function:resize",
"Events": ["s3:ObjectCreated:*"],
"Filter": {"Key": {"FilterRules": [{"Name": "prefix", "Value": "uploads/"},
{"Name": "suffix", "Value": ".jpg"}]}}}],
"EventBridgeConfiguration": {} }'
# 7. A rule that reacts to DeleteTable calls recorded by CloudTrail
aws events put-rule --name alert-delete-table \
--event-pattern '{"source":["aws.dynamodb"],"detail-type":["AWS API Call via CloudTrail"],"detail":{"eventSource":["dynamodb.amazonaws.com"],"eventName":["DeleteTable"]}}'
# { "RuleArn": "arn:aws:events:ap-southeast-1:111122223333:rule/alert-delete-table" }
aws events put-targets --rule alert-delete-table \
--targets Id=sns,Arn=arn:aws:sns:ap-southeast-1:111122223333:security-alerts
# 8. API Gateway → Kinesis: an AWS service integration calling PutRecord
# kinesis-template.json holds the mapping template:
# {"application/json": "{\"StreamName\":\"rider-pings\",\"PartitionKey\":\"$input.path('$.riderId')\",\"Data\":\"$util.base64Encode($input.body)\"}"}
aws apigateway put-integration --rest-api-id a1b2c3d4e5 --resource-id r2s3t4 \
--http-method POST --type AWS --integration-http-method POST \
--uri arn:aws:apigateway:ap-southeast-1:kinesis:action/PutRecord \
--credentials arn:aws:iam::111122223333:role/apigw-kinesis-putrecord \
--request-templates file://kinesis-template.json
# { "type": "AWS", "httpMethod": "POST",
# "uri": "arn:aws:apigateway:ap-southeast-1:kinesis:action/PutRecord", ... }
# Map Kinesis 4xx errors (such as throttling) to a 500 the client can see
# (a 500 method response must exist on the method first)
aws apigateway put-integration-response --rest-api-id a1b2c3d4e5 --resource-id r2s3t4 \
--http-method POST --status-code 500 --selection-pattern '4\d{2}'
# 9. Clean up
aws events remove-targets --rule alert-delete-table --ids sns
aws events delete-rule --name alert-delete-table
aws lambda delete-event-source-mapping --uuid a1b2c3d4-5678-90ab-cdef-11111EXAMPLE
aws sqs delete-queue --queue-url https://sqs.ap-southeast-1.amazonaws.com/111122223333/payments
aws sqs delete-queue --queue-url https://sqs.ap-southeast-1.amazonaws.com/111122223333/payments-dlq
Also try in the console: in SQS, send a message that your function rejects and watch Receive count in Poll for messages climb until it appears in the DLQ; then press Start DLQ redrive. In EventBridge → Rules, create a rule from the AWS API Call via CloudTrail template for EC2 and use the sandbox to test the pattern.
#Summary
Key takeaways
- SQS = pull, buffer, decouple; SNS = push to many; Lambda = code on an event. SQS does not push to Lambda: an event source mapping polls.
- SQS + Lambda: retries by visibility timeout until maxReceiveCount, then the queue’s DLQ; use partial batch responses and a visibility timeout of at least 6× the function timeout. Others are not blocked.
- SQS FIFO + Lambda: order per message group; a failing message blocks its group until it succeeds or moves to a FIFO DLQ (which breaks the group’s order).
- SNS + Lambda: asynchronous; Lambda retries twice by default, then the on-failure destination (preferred, with error details) or function DLQ, else discarded. The SNS subscription DLQ catches only delivery failures.
- DLQ = redrive policy (maxReceiveCount) on the source queue; same type (FIFO→FIFO), same account and Region, longer retention, an alarm, redrive after the fix. Keywords: poison pill, infinite loop, troubleshoot failed messages.
- Fan-out: publish once to SNS, many SQS queues subscribe; queue policy must allow the topic; filter policies; beats writing to each queue from code (no partial failures, no producer changes).
- S3 events: ObjectCreated / Removed / Restore / Replication…, prefix and suffix only, destinations SNS, SQS, Lambda (standard only), overlap rule per event type, seconds to a minute, destination policy must allow S3, avoid recursive loops. S3 → EventBridge: all events, rich filters (size, key…), 20+ target types, many rules per event, archive and replay.
- Intercept API calls: CloudTrail → EventBridge rule (
AWS API Call via CloudTrail) → SNS or Lambda; needs a trail; regional rules; IAM events in us-east-1; read-only calls need the rule to opt in. - API Gateway → Kinesis: AWS service integration with an IAM role and a mapping template; no Lambda = less latency, cost and concurrency; watch shard throughput and map errors.
Answer on your own first, then read the explanation, even when you got it right.
Self-checkQuestion
How does a Lambda function receive messages from a standard SQS queue?
Self-checkQuestion
A question says: the system must buffer orders and tolerate sudden traffic spikes while the processing tier works at its own pace. Which service fits best?
Self-checkQuestion
Where is the dead-letter queue configured when a Lambda function processes messages from an SQS queue?
Self-checkQuestion
A function reads batches of 10 from a standard queue. When one message is invalid, all 10 are processed again later and the ledger gets duplicates. What is the best fix?
Self-checkQuestion
A function has a 2-minute timeout and reads an SQS queue whose visibility timeout is 30 seconds. What problem should you expect?
Self-checkQuestion
A FIFO queue uses the account ID as message group ID. A message for account A always fails and there is no DLQ. Which statement is correct?
Self-checkQuestion
Which two rules apply to the dead-letter queue of an SQS FIFO queue?
Choose 2
Self-checkQuestion
An SNS topic invokes a Lambda function. The function throws an exception for one message every time. With default settings, what happens?
Self-checkQuestion
A team wants failed asynchronous Lambda invocations to be stored together with the error message and stack trace. What should they configure?
Self-checkQuestion
Messages published to an SNS topic stop reaching a Lambda subscriber after someone edits the function’s resource-based policy. Where can the team find those messages, if configured?
Self-checkQuestion
Which two phrases in an exam question point to a dead-letter queue?
Choose 2
Self-checkQuestion
A standard source queue keeps messages 4 days and its DLQ also 4 days. A poison message moves to the DLQ after 3 days in the source. Why might the team never see it?
Self-checkQuestion
An order service calls SendMessage on three queues in turn. Sometimes the inventory and email queues receive an order but the analytics queue does not. What design removes this problem?
Self-checkQuestion
After a queue is subscribed to an SNS topic using a CloudFormation template, it receives no messages, while other queues on the same topic do. What is the most likely cause?
Self-checkQuestion
The fraud workers of a fan-out design are down for two hours. What happens to the payments meant for them?
Self-checkQuestion
A bucket has a notification rule: s3:ObjectCreated:*, prefix images/, to a Lambda function. Which new rule will S3 accept?
Self-checkQuestion
Which two are valid destinations for a native S3 event notification rule?
Choose 2
Self-checkQuestion
A media company must start a Step Functions workflow only for uploaded videos larger than 500 MB, and archive all upload events so they can be reprocessed later. What is the simplest design?
Self-checkQuestion
The notes say S3 events through EventBridge can be filtered on object metadata and sent to 18+ services. What is correct?
Self-checkQuestion
A resize function triggered by uploads/ writes its thumbnails to uploads/thumbs/. The Lambda bill jumps overnight. What happened, and what is the fix?
Self-checkQuestion
A security team wants a Lambda function to run whenever anyone launches an EC2 instance, to check its tags. Which design works?
Self-checkQuestion
An EventBridge rule in ap-southeast-1 should alert when an IAM user is created, but it never fires, although rules for EC2 calls in the same Region work. Why?
Self-checkQuestion
A rule matches the EC2 Describe call that lists instances, from CloudTrail, but it never triggers although the trail logs read events. What must change?
Self-checkQuestion
Which two statements about reacting to API calls with CloudTrail and EventBridge are correct?
Choose 2
Self-checkQuestion
A mobile game sends 5,000 small telemetry events per second to a REST API. Today a Lambda function behind API Gateway only forwards each event to Kinesis Data Streams. How can the team reduce cost and latency with the least effort?
Self-checkQuestion
What does API Gateway need to call Kinesis PutRecord directly in an AWS service integration?
Self-checkQuestion
During a peak, a stream with 4 provisioned shards receives 6,000 records per second through an API Gateway service integration. Which two actions address the problem?
Choose 2
Self-checkQuestion
Besides Kinesis, which AWS services can API Gateway call directly with an AWS service integration?
Self-checkQuestion
A team says: our SNS-triggered function failed for some messages, but the dead-letter queue on the SNS subscription is empty, so nothing was lost. What is wrong with this reasoning?
Self-checkQuestion
An S3 event notification configuration fails to save with an error about validating the destination. What is the most likely cause?