skip to content

You set an Amazon SQS FIFO queue's redrive policy to point at a standard queue as its dead-letter queue. What happens, and what are SQS's rules for what a DLQ may be?

level: juniorimportance: should knowfreq 42%

answer

  1. it is just another queue
  2. the two queues must agree on shape
  3. FIFO messages carry a field standard queues lack
  4. no crossing account or Region lines
  5. named only by the source's RedrivePolicy

basics

~20 s

SQS rejects the configuration. A dead-letter queue must be the same type as its source queue — FIFO for FIFO, standard for standard — and must live in the same AWS account and Region. Otherwise it is an ordinary queue you create yourself.

solid answer

~40 s

The `SetQueueAttributes` call fails. SQS enforces that a FIFO queue's dead-letter queue is itself a FIFO queue, and a standard queue's DLQ is a standard queue, because the DLQ has to be able to hold the message with its delivery semantics intact — a FIFO message carries a `MessageGroupId` that a standard queue has nowhere to put. The DLQ must also be in the same AWS account and the same Region as the source queue; there is no cross-account or cross-Region dead-lettering. Beyond that, a DLQ is not a distinct resource type. You create a normal queue, and it becomes a dead-letter queue purely because another queue's `RedrivePolicy` names its ARN in `deadLetterTargetArn`. The same queue can serve several sources, and a DLQ may itself have a redrive policy pointing at a third queue.

code

bash · 6 lines
bash
aws sqs create-queue --queue-name orders-dlq.fifo \
  --attributes FifoQueue=true,MessageRetentionPeriod=1209600

aws sqs set-queue-attributes \
  --queue-url https://sqs.eu-west-1.amazonaws.com/111122223333/orders.fifo \
  --attributes '{"RedrivePolicy":"{\"deadLetterTargetArn\":\"arn:aws:sqs:eu-west-1:111122223333:orders-dlq.fifo\",\"maxReceiveCount\":\"5\"}"}'

go deeper

for a junior

Recall that a DLQ is an ordinary queue of the same type as its source, in the same account and Region, wired up by the source queue's RedrivePolicy.

for a middle

Explain why the type must match — a FIFO message's MessageGroupId has nowhere to live in a standard queue — and that the DLQ keeps its own retention, visibility, and encryption settings.

for a senior

Show the operational consequences: raise the DLQ's retention above the source's, give it an alarm and an owner, and decide deliberately between one DLQ per source and a shared one.

for a principal

Own the cross-account story. Since dead-lettering cannot cross an account or Region boundary, define how failures are forwarded to a central triage surface without pretending redrive can do it.

## There is no such thing as a DLQ resource The first thing to internalise is that Amazon SQS has exactly two kinds of queue: standard and FIFO. There is no `CreateDeadLetterQueue` API and no flag that marks a queue as a DLQ. You create an ordinary queue, and it *becomes* a dead-letter queue the moment some other queue's `RedrivePolicy` names it: ```json { "deadLetterTargetArn": "arn:aws:sqs:eu-west-1:111122223333:orders-dlq", "maxReceiveCount": 5 } ``` That relationship is one-directional and lives on the *source* queue. Reading the target queue's attributes tells you nothing about who is pointing at it — which is exactly why SQS later added `RedriveAllowPolicy` on the target side, so a queue can control who is allowed to name it. ## The three hard constraints **Same type.** A FIFO source queue requires a FIFO dead-letter queue; a standard source requires a standard DLQ. The reason is semantic, not arbitrary. A FIFO message carries a `MessageGroupId` and optionally a `MessageDeduplicationId`, and those are structural parts of a FIFO message that a standard queue has no field for. Moving the message would silently discard information you need to reason about the failure or to replay it in order. So SQS refuses the configuration outright rather than degrading it. Note that FIFO queue names must end in the `.fifo` suffix, so the mismatch is usually visible just by reading the two ARNs side by side. **Same account.** The DLQ must be owned by the same AWS account as the source queue. You cannot dead-letter into a central security or platform account's queue. If you want failures to end up somewhere central, the pattern is to dead-letter locally and then forward — a consumer on the DLQ, an EventBridge rule, or a Lambda that republishes cross-account with an explicit resource policy. **Same Region.** Likewise, no cross-Region dead-lettering. A queue in `eu-west-1` cannot dead-letter to a queue in `us-east-1`. Aggregation across Regions is again a forwarding problem, not a redrive-policy problem. ## What a DLQ inherits, and what it does not The DLQ has its own independent attributes, and forgetting this is the source of most DLQ surprises: - Its own `MessageRetentionPeriod`. It does **not** inherit the source queue's, and — importantly — a moved message's expiry is still computed from its original enqueue time, so a DLQ left at the four-day default can lose evidence quickly. - Its own `VisibilityTimeout`, used when *you* poll the DLQ to triage. - Its own encryption settings and access policy. If the source queue uses a customer-managed KMS key, the DLQ needs workable key configuration of its own for you to read what lands there. - Its own `RedrivePolicy`, optionally. Nothing stops a DLQ from having a DLQ, though in practice a queue you only drain manually rarely needs one. ## Sharing one DLQ across sources Several source queues may point at the same dead-letter queue, and this is a legitimate design when the queues belong to one service and one on-call rotation: one alarm, one triage surface. The cost is that messages from different sources arrive intermingled and the message body itself may not identify where it came from, so you either accept that ambiguity or you keep a DLQ per source queue. The per-source DLQ is the more common default precisely because it makes ownership, alarms, and replay unambiguous — and because the replay operation moves messages back to their originating queue, which is only well-defined if you know what that queue was. ## The interview version of this If you are asked "how do you set up a DLQ", the complete answer is: create a second queue of the *same type* in the *same account and Region*, set the source queue's `RedrivePolicy` to that queue's ARN with a `maxReceiveCount`, raise the DLQ's retention period well above the source's, and put an alarm on the DLQ so somebody finds out that it has messages. The configuration is three lines; the operational plumbing around it is the part interviewers are actually probing.

  • Your compliance team wants every failed message in a central audit account. How do you satisfy that given the same-account rule?
    Dead-letter locally, then forward. Put a consumer on the DLQ — a Lambda or a small worker — that republishes to a queue, topic, or bus in the audit account, authorised by a resource policy there. The redrive policy itself cannot cross accounts, so the boundary crossing has to be an explicit, auditable hop that you own.
  • Can one dead-letter queue serve several source queues, and when would you avoid that?
    Yes, and it is reasonable when the sources belong to one service with one on-call rotation: one alarm, one triage surface. Avoid it when the sources have different owners or different replay semantics, because messages arrive intermingled and the replay operation is cleanest when a DLQ maps to exactly one origin queue.

saying these in an interview costs you the question

  • Thinks a dead-letter queue is a distinct AWS resource type
  • Believes a FIFO queue can dead-letter into a standard queue
  • Assumes the DLQ can live in a central cross-account security account
  • Says the DLQ inherits the source queue's retention period
  • Thinks the DLQ setting lives on the target queue rather than the source

context