Technical
Why I Prefer Lambda Destinations Over Dead Letter Queues
When a Lambda function fails on an async invocation, you need somewhere for that failure to land. The classic answer is a dead letter queue. The newer answer is Lambda destinations. After using both in production, destinations win by a mile for most cases. Let me show you why.
What Each One Gives You
A DLQ catches failed invocations and parks them for inspection. You get the event that failed and nothing else. If you want to know what went wrong, you have to reconstruct the failure by rerunning the event.
A destination captures both failed and successful invocations, plus the full context: the request, the response, the error if any, and the execution metadata. You can route successes to one target and failures to another. The target can be SQS, SNS, EventBridge, or another Lambda.
The Practical Advantage
With destinations I can pipe failures straight into a Slack alert, or into an EventBridge bus that triggers recovery logic, or into a DynamoDB table for later review. The routing is declarative. No code in the Lambda handler needs to know about the failure destination.
With a DLQ I have to poll the queue, parse each message, and figure out what happened. It is more plumbing for less information.
# SAM template showing both side by side
MyFunction:
Type: AWS::Serverless::Function
Properties:
# Old way: DLQ, just captures failures
DeadLetterQueue:
Type: SQS
TargetArn: !GetAtt DLQ.Arn
# New way: destinations, richer routing
EventInvokeConfig:
DestinationConfig:
OnFailure:
Destination: !GetAtt FailureBus.Arn
Type: EventBridge
OnSuccess:
Destination: !GetAtt AuditTopic.Arn
Type: SNSWhen DLQs Still Make Sense
For SQS-triggered Lambdas, the queue itself supports a DLQ via its redrive policy. This is independent of Lambda destinations and applies at the queue level. For that specific case, queue DLQs remain the right tool.
Synchronous invocations do not use either mechanism. The caller sees the error directly. Destinations and DLQs both apply to async invocations only.
The Operational Impact
Since switching to destinations, my mean time to detect a Lambda failure dropped from hours to minutes. Failures post to Slack with enough context that I often do not need to dig further. The observability upgrade was the biggest quality-of-life change I made to my Lambda operations this year.
See the Lambda destinations documentation for the full configuration surface. If you are still using DLQs for async Lambdas, destinations are worth the migration.
RELATED READING
The Consulting Shift I Am Making In Year Two
After a year of writing and building, my consulting practice is changing shape. Shorter engagements. Sharper outcomes.
ReadThe Frontend Shift: Shipping Less JavaScript In Year Two
A year ago I reached for Next.js for everything. This year I often reach for nothing.
ReadThe Serverless Lesson I Would Write On A Sticky Note
After a year of shipping serverless projects, one rule explains most of the wins and all of the losses.
Read