What limits throughput on a default SQS FIFO queue, and what do the DeduplicationScope and FifoThroughputLimit attributes change?
answer
- ordering is paid for in request quota
- per action, not per queue overall
- batching multiplies the same ceiling
- two attributes, always set together
- dedup scope narrows to the group
basics
~20 sA default FIFO queue is quota-limited to 300 API calls per second per action, roughly 3,000 messages per second when batching ten per call. Setting DeduplicationScope to messageGroup and FifoThroughputLimit to perMessageGroupId enables high throughput mode, which lifts the ceiling but narrows deduplication to each group.
solid answer
~40 sIn its default mode an SQS FIFO queue is capped per API action — about 300 calls per second each for `SendMessage`, `ReceiveMessage` and `DeleteMessage`, which becomes roughly 3,000 messages per second if you batch ten per call. Standard queues have no comparable published ceiling, so this quota is often the reason a FIFO design stalls. High throughput mode raises it substantially by setting two queue attributes together: `DeduplicationScope` to `messageGroup` and `FifoThroughputLimit` to `perMessageGroupId`. The limit then applies per group rather than per queue, so you scale by having many active groups — a coarse group key still bottlenecks. The tradeoff is that deduplication ids are compared only within a group, so the same id sent to two different groups produces two delivered messages. Batching remains the cheapest throughput lever either way.
code
bash · 2 linesaws sqs set-queue-attributes --queue-url "$QUEUE_URL" \
--attributes DeduplicationScope=messageGroup,FifoThroughputLimit=perMessageGroupIdgo deeper
Know that a FIFO queue has a published throughput quota while a standard queue does not, and that sending in batches is the simplest way to move more messages within it.
Explain that the default limit is per API action rather than per queue, and that high throughput mode is enabled by setting DeduplicationScope and FifoThroughputLimit together on the queue.
Diagnose FIFO throttling properly: confirm batching and long polling first, check whether group cardinality is the real constraint, and weigh the narrowed deduplication scope before flipping the attributes.
Own the framing that the quota is the visible price of ordering. Argue for splitting order-sensitive traffic from the bulk stream so most volume never pays it, rather than scaling a queue that should not have been FIFO.
## Where the ceiling comes from Ordering costs coordination, and FIFO queues expose that cost as a request quota rather than as latency. As of 2025 a FIFO queue in the default configuration is limited to 300 transactions per second **per API action**: 300 `SendMessage` calls, 300 `ReceiveMessage` calls and 300 `DeleteMessage` calls per second. Because a batch call carries up to ten messages, batching turns that into roughly 3,000 messages per second in each direction. Standard queues publish no equivalent inbound ceiling, which is the practical difference that bites teams who adopted FIFO for a small stream and then grew into it. When a FIFO producer starts seeing throttling, the cause is almost always this quota rather than anything about consumer capacity. ## What high throughput mode is High throughput mode is not a single toggle; it is two attributes that must be set together on the queue: ```bash aws sqs set-queue-attributes --queue-url "$QUEUE_URL" \ --attributes DeduplicationScope=messageGroup,FifoThroughputLimit=perMessageGroupId ``` `FifoThroughputLimit` takes `perQueue` (the default) or `perMessageGroupId`. `DeduplicationScope` takes `queue` (the default) or `messageGroup`. AWS only permits the high-throughput combination — per-group throughput requires per-group deduplication scope — so setting one without the other is rejected. With both set, the throughput quota applies **per message group** instead of per queue, and the aggregate ceiling rises by orders of magnitude. The exact published figure varies by Region and has been revised upward repeatedly, so quote the shape of the limit rather than a number: it is high enough that group cardinality, not the quota, becomes your constraint. ## The catch: dedup scope moves with it The two attributes are coupled for a reason. In the default mode, SQS maintains one deduplication space for the whole queue, so a repeated `MessageDeduplicationId` is caught no matter which group it lands in. Tracking that space queue-wide is precisely what limits throughput. Switching to `messageGroup` scope means the id is only compared against other sends in the same group. If a producer bug sends the same logical event under two group ids, both are accepted and both are delivered. In practice this is usually harmless, because a well-chosen group key is derived from the same entity as the dedup id — all events for `cust-42` carry group `cust-42`, so retries land in the same group. It becomes a real hazard when the group key is derived from something volatile, like a shard number or a hostname, that can change between the original send and the retry. ## Group cardinality still governs High throughput mode does not remove the one-in-flight-per-group rule. A group is still a serial lane; the change is that the quota no longer counts against a single queue-wide budget. So the scaling story is unchanged in shape: throughput comes from having many concurrently active groups. A queue with three group ids will not benefit from high throughput mode, because three serial lanes were never near 3,000 messages per second anyway. A queue with tens of thousands of entity-keyed groups benefits enormously. If you enable the mode and see no improvement, the group key is the thing to examine, not the setting. ## Cheaper levers first Before reaching for the mode, check the obvious ones. Batching with `SendMessageBatch` and `DeleteMessageBatch` gives a tenfold multiplier on the same quota and reduces cost, since FIFO requests are billed at a higher rate than standard. Long polling reduces wasted receive calls that consume quota while returning nothing. And it is worth re-asking whether the whole stream needs to be ordered: splitting traffic so that only the order-sensitive subset goes to the FIFO queue, with the rest on a standard queue, is frequently the largest win available and removes the ceiling from most of the volume. ## Operationally Both attributes are set with `SetQueueAttributes` on an existing queue, so this is not a migration — no new queue, no producer changes, no drain window. That makes it a reasonable response to sustained throttling, provided you have first confirmed that duplicate sends cannot cross group boundaries in your producer.
- You enable high throughput mode and throughput barely moves. What do you check first?Group cardinality. The mode makes the quota per message group, but a group still allows one in-flight message at a time, so a queue with only a handful of distinct group ids was never quota-bound to begin with. Look at how the group key is derived and whether it can be narrowed to an entity id; also confirm producers and consumers are using batch APIs.
- What new correctness risk does DeduplicationScope=messageGroup introduce?Deduplication ids are compared only inside a group, so the same id sent under two different group ids yields two delivered messages. It is safe when the group key and the dedup id derive from the same entity, and risky when the group key comes from something that can change between a send and its retry, such as a shard index or a producer hostname.
saying these in an interview costs you the question
- Assumes FIFO queues scale like standard queues
- Thinks high throughput mode is a single attribute
- Enables the mode while using very few group ids
- Overlooks that dedup narrows to the group
- Ignores batching as the first throughput lever