Skip to content
All AWS labs
Serverless / HANDS-ON LAB

Build a resilient background order worker

Connect SQS to Lambda, process an order and isolate a failing message in a dead-letter queue.

45 minutesIntermediateConsole + PythonOwn AWS account
THE REAL-WORLD SCENARIO

A business problem worth solving

A shop needs to accept orders even when downstream processing is slow. You will decouple message submission from a worker and deliberately send a poison message to observe retries and failure isolation.

What you will build

A valid order logged by Lambda and a failing order moved to a dead-letter queue after repeated processing attempts.

See the architecture before you build

AWS CLOUD Conceptual lab architecture
Amazon SQS iconOrder queueBuffers incoming orders
AWS Lambda iconOrder workerPolls queue through event source mapping
Amazon CloudWatch iconExecution logsSuccess and failure evidence
Amazon SQS iconSource queue → dead-letter queue after repeated failures
The console sends an order to the source queue. Lambda’s event source mapping polls SQS and invokes the worker. Successful messages are deleted. Repeatedly failing messages move from the source queue to a separate SQS dead-letter queue via its redrive policy.
Where this fits in production

SQS standard queues deliver at least once. Production workers need idempotent side effects, concurrency controls, alarms on queue age and dead-letter depth, and partial batch failure handling when using batches. This lab logs processing only; it does not charge a payment or persist an order.

Know why each service belongs

Amazon SQS icon

Amazon SQS

A managed queue that buffers messages between producers and consumers.

Choose it when: Absorb traffic spikes and retry background work independently of the producer.

Consider the tradeoff: Use SNS for fan-out, EventBridge for event routing, or Kinesis for a replayable stream.

AWS service documentation
AWS Lambda icon

AWS Lambda

Runs event-driven application code without managing servers.

Choose it when: Execute short, stateless tasks in response to events.

Consider the tradeoff: Use ECS or EC2 for long-running workers or specialized runtime requirements.

AWS service documentation
AWS IAM icon

AWS IAM

Policies and roles control which identities can perform actions on AWS resources.

Choose it when: Grant a workload only the actions and resources it needs using temporary role credentials.

Consider the tradeoff: Use IAM Identity Center for workforce sign-in; avoid embedding long-lived credentials in code.

AWS service documentation
Amazon CloudWatch icon

Amazon CloudWatch

Collects logs and metrics to help you understand workload behavior.

Choose it when: Inspect application output, failures and operational signals.

Consider the tradeoff: Use CloudTrail to investigate AWS API activity; it serves a different purpose than application logs.

AWS service documentation

Before you begin

  • A learning-account role with permissions for SQS queues, Lambda functions/event source mappings, CloudWatch Logs, and creating/passing a Lambda execution role.
  • Use us-east-1 for the queues and function. Basic Python knowledge; no real customer data.
Cost & account preparation

SQS requests, Lambda execution and CloudWatch Logs may incur charges. Send two sample messages only, use a three-day log retention and delete the resources afterward.

Use a non-production account, sign in through an IAM role rather than root, and review AWS pricing. Budget alerts notify you; they do not automatically cap spending.

Open your AWS Console
01

Create the source and dead-letter queues

  1. Open SQS in us-east-1 → Create queue. Choose Standard, name it cloudadhar-orders-dlq and retain default SQS-managed encryption and private access. Set retention to 4 days.
  2. Create a second Standard queue named cloudadhar-orders. Set visibility timeout to 60 seconds and message retention to 1 day.
  3. Enable its dead-letter queue setting, select cloudadhar-orders-dlq, and set Maximum receives to 3. Save and copy the source queue ARN from Details.
Checkpoint

The source queue redrive policy points to the DLQ with maxReceiveCount 3.

02

Create a worker with a scoped execution role

  1. Open Lambda → Create function → Author from scratch. Name it cloudadhar-order-worker, select a supported Python 3 runtime and create a new role with basic Lambda permissions.
  2. Under Configuration → Permissions, open the execution role in IAM. Add an inline JSON policy below, replacing SOURCE_QUEUE_ARN with your source queue ARN. Name it ReadLabOrderQueue.
  3. This supplements the basic logging policy. It allows polling only the source queue; no S3, payment or other application permissions are needed.
JSON · execution-role inline policy
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["sqs:ReceiveMessage", "sqs:DeleteMessage", "sqs:GetQueueAttributes"],
    "Resource": "SOURCE_QUEUE_ARN"
  }]
}
Checkpoint

The execution role trusts lambda.amazonaws.com and has logging plus source-queue polling permissions.

03

Deploy the worker and attach the trigger

  1. In the Lambda Code tab, replace lambda_function.py with the code below and select Deploy. Keep handler lambda_function.lambda_handler.
  2. Set Configuration → General configuration → Timeout to 10 seconds and memory to 128 MB.
  3. Choose Add trigger → SQS → cloudadhar-orders. Set batch size to 1 and batching window to 0. Enable the trigger. The 60-second queue visibility timeout is six times the function timeout.
Python · lambda_function.py
import json

def lambda_handler(event, context):
    for record in event["Records"]:
        order = json.loads(record["body"])
        if order.get("force_failure"):
            raise ValueError("Intentional lab failure")
        print(json.dumps({
            "status": "processed",
            "order_id": order["order_id"],
            "message_id": record["messageId"]
        }))
    return {"ok": True}
Checkpoint

The SQS trigger is enabled with batch size 1.

Something not working?

If adding the trigger fails, confirm role permissions and that the queue and function are in the same region. Wait briefly for IAM propagation and retry.

04

Submit a valid order

  1. Open the source SQS queue → Send and receive messages. Send the JSON below as the message body. Do not poll messages manually because that competes with Lambda.
  2. In Lambda → Monitor → View CloudWatch logs, open the newest log stream. Allow a minute for log delivery.
  3. For /aws/lambda/cloudadhar-order-worker, set log retention to 3 days.
JSON · message body
{"order_id":"ORD-1001","force_failure":false}
Checkpoint

A log entry contains status processed and order_id ORD-1001. SQS eventually shows no visible/in-flight messages for this order.

05

Inject a failure and inspect the dead-letter queue

  1. Send the following message to the SOURCE queue. The worker will deliberately fail each time it receives it.
  2. Watch Lambda logs for Intentional lab failure. Allow several minutes for visibility timeouts, retries and metric updates; redrive timing is not exact.
  3. After the DLQ has a visible message, open that DLQ → Send and receive messages → Poll for messages. Inspect its body and verify the failed order ID.
JSON · poison message
{"order_id":"ORD-1002","force_failure":true}
Checkpoint

ORD-1002 appears in cloudadhar-orders-dlq, while ORD-1001 has a success log.

Something not working?

If the DLQ stays empty, verify the source redrive policy, enabled trigger and deployed code. Do not repeatedly poll the source queue; that changes receive counts.

06

Remove the worker and queues

  1. Delete the SQS trigger from Lambda first. Delete cloudadhar-order-worker.
  2. Delete both lab SQS queues, including their messages. Delete the CloudWatch log group /aws/lambda/cloudadhar-order-worker.
  3. In IAM, delete the execution role created for this lab, including its inline policy. Do not remove a role used by another function.
Checkpoint

No lab function, event source mapping, queue, log group or execution role remains.

GO TO THE SOURCE

Official AWS references

Use these service guides and architecture frameworks to go deeper. The diagram above is an original teaching design, not an AWS-certified production blueprint.