Chapter 6 — Messaging & Eventing
Day 1 — SQS Queues and Dead-Letter Queues
1. Concept Primer
SQS decouples producers from consumers via a durable queue. Standard queues offer at-least-once delivery and best-effort ordering; FIFO queues guarantee exact ordering and exactly-once processing at lower throughput. A dead-letter queue (DLQ) catches messages that fail processing repeatedly, isolating poison messages from the main flow.
2. Hands-on Exercise
Create a queue with a DLQ redrive policy, send a message, and receive/delete it.
3. Exact Commands
floci start && eval $(floci env)
DLQ_ARN=$(aws sqs create-queue --queue-name orders-dlq \
--query 'QueueUrl' --output text | xargs -I{} aws sqs get-queue-attributes \
--queue-url {} --attribute-names QueueArn --query 'Attributes.QueueArn' --output text)
echo "DLQ ARN: $DLQ_ARN"
REDRIVE_POLICY=$(python3 -c "import json;print(json.dumps({'deadLetterTargetArn': '$DLQ_ARN', 'maxReceiveCount': '3'}))")
QUEUE_URL=$(aws sqs create-queue --queue-name orders-queue \
--attributes "{\"RedrivePolicy\":\"$(echo $REDRIVE_POLICY | sed 's/"/\\"/g')\"}" \
--query 'QueueUrl' --output text)
aws sqs send-message --queue-url $QUEUE_URL --message-body "order-created:100"
aws sqs receive-message --queue-url $QUEUE_URL
RECEIPT=$(aws sqs receive-message --queue-url $QUEUE_URL --query 'Messages[0].ReceiptHandle' --output text)
aws sqs delete-message --queue-url $QUEUE_URL --receipt-handle $RECEIPT
4. Gotchas
- Building the redrive policy JSON-inside-JSON string is the fiddliest part — get it
wrong and
create-queuewill silently accept the attribute without a real DLQ link, so verify withget-queue-attributesafterward. - Visibility timeout defaults to 30s — if you're debugging slowly and re-run
receive-messagebefore that window ends, you won't see the message again since it's still "in flight."
5. Self-Check
If a message is received but never explicitly deleted, what happens to it after the visibility timeout expires?
Day 2 — SNS Fan-Out to Multiple SQS Queues
1. Concept Primer
SNS topics broadcast one published message to every subscriber. Combined with SQS, this gives you the classic fan-out pattern: one event, many independent consumers, each processing at its own pace without blocking the others.
2. Hands-on Exercise
Create an SNS topic, subscribe two SQS queues to it, publish once, and confirm both queues received the message independently.
3. Exact Commands
eval $(floci env)
TOPIC_ARN=$(aws sns create-topic --name order-events --query 'TopicArn' --output text)
Q1_URL=$(aws sqs create-queue --queue-name billing-queue --query 'QueueUrl' --output text)
Q2_URL=$(aws sqs create-queue --queue-name shipping-queue --query 'QueueUrl' --output text)
Q1_ARN=$(aws sqs get-queue-attributes --queue-url $Q1_URL --attribute-names QueueArn --query 'Attributes.QueueArn' --output text)
Q2_ARN=$(aws sqs get-queue-attributes --queue-url $Q2_URL --attribute-names QueueArn --query 'Attributes.QueueArn' --output text)
aws sns subscribe --topic-arn $TOPIC_ARN --protocol sqs --notification-endpoint $Q1_ARN
aws sns subscribe --topic-arn $TOPIC_ARN --protocol sqs --notification-endpoint $Q2_ARN
aws sns publish --topic-arn $TOPIC_ARN --message "order-created:200"
aws sqs receive-message --queue-url $Q1_URL
aws sqs receive-message --queue-url $Q2_URL
4. Gotchas
- SNS→SQS subscriptions in real AWS need the queue's access policy to explicitly allow SNS to send to it; Floci is generally more permissive locally, so don't assume a policy you never wrote will also work against a real account.
- Each queue receives its own independent copy of the message — deleting it from one queue does not affect the other.
5. Self-Check
What would you lose if billing-queue and shipping-queue both subscribed directly to
each other instead of both subscribing to one shared SNS topic?