AWS Developer Blog

Using Amazon SQS Dead Letter Queues

by Jason Fulghum | on | in Java | Permalink | Comments |  Share

Amazon SQS recently introduced support for dead letter queues. This feature is an important tool to help your applications consume messages from SQS queues in a more resilient way.

Dead letter queues allow you to set a limit on the number of times a message in a queue is processed. Consider an application that consumes messages from a queue and does some sort of processing based on the message. A bug in your application may only be triggered by certain types of messages or when working with certain data in your application. If your application receives one of these messages, it won’t be able to successfully process it and remove it from the queue. Instead, your application will continue to try to process the message again and again. While this message is being continually retried, your queue is likely filling up with other messages, which your application is unable to process because it’s stuck repeatedly processing the bad message.

Amazon SQS dead letter queues enable you to configure your application so that if it can’t successfully process a problematic message and remove it from the queue, that message will be automatically removed from your queue and delivered to a different SQS queue that you’ve designated as a dead letter queue. Another part of your application can then periodically monitor the dead letter queue and alert you if it contains any messages, which you can debug separately.

Using Amazon SQS dead letter queues is easy. You just need to configure a RedrivePolicy on your queue to specify when messages are delivered to a dead letter queue and to which dead letter queue they should be delivered. You can use the AWS Management Console, or you can access the Amazon SQS API directly with the AWS SDK for Java.

// First, we'll need an Amazon SQS client object.
AmazonSQSClient sqs = new AmazonSQSClient(myCredentials);

// Create two new queues:
//     one main queue for our application messages
//     and another to use as our dead letter queue
String qUrl = sqs.createQueue("MyApplicationQueue").getQueueUrl();
String dlqUrl = sqs.createQueue("MyDeadLetterQueue").getQueueUrl();

// Next, we need to get the the ARN (Amazon Resource Name) of our dead
// letter queue so we can configure our main queue to deliver messages to it.
Map attributes = sqs.getQueueAttributes(new GetQueueAttributesRequest(dlqUrl)
    .withAttributeNames(QueueAttributeName.QueueArn)).getAttributes();
String dlqArn = attributes.get(QueueAttributeName.QueueArn.toString());

// The last step is setting a RedrivePolicy on our main queue to configure
// it to deliver messages to our dead letter queue if they haven't been
// successfully processed after five attempts.
String redrivePolicy = String.format(
    "{"maxReceiveCount":"%i", "deadLetterTargetArn":"%s"}",
    5, dlqArn);

sqs.setQueueAttributes(new SetQueueAttributesRequest()
    .withQueueUrl(qUrl)
    .addAttributesEntry(QueueAttributeName.RedrivePolicy.toString(),
                        redrivePolicy));

There’s also a new operation in the Amazon SQS API to help you identify which of your queues are setup to deliver messages to a specific dead letter queue. If you want to know what queues are sending messages to a dead letter queue, just use the AmazonSQS#listDeadLetterSourceQueues operation.

List sourceQueues = sqs.listDeadLetterSourceQueues(
	new ListDeadLetterSourceQueuesRequest()
		.withQueueUrl(dlqUrl)).getQueueUrls();
System.out.println("Source Queues Delivering to " + qUrl);
for (String queueUrl : sourceQueues) {
	System.out.println(" * " + queueUrl);
}

Dead letter queues are a great way to add more resiliency to your queue-based applications. Have you set up any dead letter queues in Amazon SQS yet?