
Every comparison of SQS vs RabbitMQ eventually says the same thing about cost: SQS is cheap at low volume, a broker is cheaper at high volume. That is true, and it does not help anyone, because nobody says where “high” starts. This post is for the backend engineer on AWS who already knows both tools work and needs to know which one costs less at their message rate, before the architecture review rather than after the first bill.
Every rate below comes from the AWS Price List API for us-east-1, read on 13 November 2026. A short awk script turns those rates into monthly bills at 1, 10, 100, 1,000 and 10,000 messages per second, for two message sizes and two batch sizes. It then solves for the exact rate where each broker size becomes cheaper than SQS. The script and its raw output are printed in full, so you can rerun them when a price moves.
Prices read 2026-11-13
Region: US East (N. Virginia), on-demand, no Savings Plans, no free trial credits
AWS Price List offer files, us-east-1:
AWSQueueService published 2026-11-11T15:35:51Z
AmazonMQ published 2026-09-11T12:44:56Z
AmazonMSK published 2026-11-11T00:23:59Z
AWSDataTransfer published 2026-11-11T19:19:41Z
Calculator: GNU Awk 5.0.0 in Git Bash 5.2.37 on Windows 11 Pro
Month length: 730 hours (2,628,000 seconds)
Excluded: NAT gateway and internet transfer, CloudWatch, support plans, engineer time
The vendor pages behind these files are Amazon SQS pricing, Amazon MQ pricing and Amazon MSK pricing. None of them shows a last-updated date, so the offer file publication dates above are the honest timestamps.
The Short Answer
Unbatched, SQS standard costs more than a three-node RabbitMQ cluster on mq.m7g.large at about 209 messages per second. With batches of ten, the same crossover moves to about 2,090 messages per second, ten times higher. For 32 KB messages with clients spread across three Availability Zones, batched SQS never costs more, because the broker’s cross-AZ traffic alone outgrows the SQS bill.
In other words, batching decides the answer more than the choice of service does. Most teams that think they have outgrown SQS are paying for unbatched calls.
Where the Prices Came From
The AWS pricing pages render from the same offer files the Price List API serves. Reading the JSON directly sidesteps rate tables that load through JavaScript and summaries that round. This PowerShell pulls one file and prints every on-demand rate:
# Downloads the us-east-1 offer file and prints usage type, unit, price and description
$s = 'AWSQueueService' # also run with 'AmazonMQ', 'AmazonMSK' and 'AWSDataTransfer'
$u = "https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/$s/current/us-east-1/index.json"
$j = Invoke-RestMethod -Uri $u
$j.publicationDate
foreach ($sku in $j.terms.OnDemand.PSObject.Properties) {
$a = $j.products.($sku.Name).attributes
foreach ($t in $sku.Value.PSObject.Properties) {
foreach ($pd in $t.Value.priceDimensions.PSObject.Properties) {
$v = $pd.Value
'{0} | {1} | {2} | {3}-{4} | {5}' -f $a.usagetype, $v.unit, $v.pricePerUnit.USD,
$v.beginRange, $v.endRange, $v.description
}
}
}
SQS Rates
The full SQS output is eight lines, pasted unedited:
Global-Requests | Requests | 0.0000000000 | 0-1000000 | First 1,000,000 Amazon SQS Requests per month are free
Requests-RBP | Requests | 0.0000004000 | 0-100000000000 | $0.40 per million Amazon SQS standard requests in Tier1 in US East (N Virginia)
Requests-RBP | Requests | 0.0000003000 | 100000000000-200000000000 | $0.30 per million Amazon SQS standard requests in Tier2 in US East (N Virginia)
Requests-RBP | Requests | 0.0000002400 | 200000000000-Inf | $0.24 per million Amazon SQS standard requests in Tier3 in US East (N Virginia)
Requests-Fair-RBP | Requests | 0.0000001000 | 0-Inf | $0.10 per million Amazon SQS fair queue requests in US East (N. Virginia)
Requests-FIFO-RBP | Requests | 0.0000005000 | 0-100000000000 | $0.50 per million Amazon SQS FIFO requests in Tier1 in US East (N Virginia)
Requests-FIFO-RBP | Requests | 0.0000004000 | 100000000000-200000000000 | $0.40 per million Amazon SQS FIFO requests in Tier2 in US East (N Virginia)
Requests-FIFO-RBP | Requests | 0.0000003500 | 200000000000-Inf | $0.35 per million Amazon SQS FIFO requests in Tier3 in US East (N Virginia)
Tier 2 starts at 100 billion requests a month. The busiest workload in this post, 10,000 unbatched messages per second, makes about 79 billion, so every bill below sits in tier 1.
Amazon MQ for RabbitMQ Rates
The AmazonMQ file lists several dozen rates, most of them for ActiveMQ or older m5 instances. These are the RabbitMQ lines the calculator uses:
USE1-RabbitMQ-Single-InstanceUsage:mq.m7g.large | Hrs | 0.2734000000 | 0-Inf | $0.2734 per Hrs for RabbitMQ-Single-InstanceUsage:mq.m7g.large in US East (N. Virginia)
USE1-RabbitMQ-3-InstanceUsage:mq.m7g.large | Hrs | 0.8201000000 | 0-Inf | $0.8201 per Hrs for RabbitMQ-3-InstanceUsage:mq.m7g.large in US East (N. Virginia)
USE1-RabbitMQ-3-InstanceUsage:mq.m7g.xlarge | Hrs | 1.6402000000 | 0-Inf | $1.6402 per Hrs for RabbitMQ-3-InstanceUsage:mq.m7g.xlarge in US East (N. Virginia)
USE1-RabbitMQ-3-InstanceUsage:mq.m7g.2xl | Hrs | 3.2803000000 | 0-Inf | $3.2803 per Hrs for RabbitMQ-3-InstanceUsage:mq.m7g.2xl in US East (N. Virginia)
USE1-TimedStorage-RabbitMQ-ByteHrs | GB-Mo | 0.1000000000 | 0-Inf | Storage (Amazon EBS) used by RabbitMQ brokers (GB-months) in US East (N. Virginia)
Note that the three-instance price is per cluster, not per node: $0.8201 is three times the single-instance $0.2734, rounded. Also, neither the AmazonMQ nor the AmazonMSK file carries any reserved terms, so there is no commitment discount to model.
MSK and Data Transfer Rates
MSK appears as a reference point, because the next question after “SQS or RabbitMQ” is often “or Kafka”. The broker and storage lines, followed by the intra-region transfer lines from AWSDataTransfer:
USE1-Kafka.m7g.large | hours | 0.2040000000 | 0-Inf | $0.204 per broker hour for Kafka.m7g.large in US East (N. Virginia)
USE1-Kafka.Storage.GP2 | GB-Mo | 0.1000000000 | 0-Inf | $0.10 per GB-Mo for storage in US East (N. Virginia)
DataTransfer-Regional-Bytes | IntraRegion | US East (N. Virginia) -> US East (N. Virginia) | 0.0100000000 | $0.010 per GB - regional data transfer - in/out/between EC2 AZs or using elastic IPs or ELB
USE1-DataTransfer-xAZ-Out-Bytes | IntraRegion-xAZ-Out | US East (N. Virginia) -> US East (N. Virginia) | 0.0000000000 | $0.00 per GB - regional data transfer - in/out/between EC2 Azs or using elastic IPs or ELB
USE1-DataTransfer-xAZ-In-Bytes | IntraRegion-xAZ-In | US East (N. Virginia) -> US East (N. Virginia) | 0.0000000000 | $0.00 per GB - regional data transfer - in/out/between EC2 Azs or using elastic IPs or ELB
The transfer file is ambiguous on its own: a $0.010 regional line sits next to two $0.00 cross-AZ lines. The EC2 on-demand pricing page settles it in plain words: data “across Availability Zones in the same AWS Region is charged at $0.01/GB in each direction.” The calculator therefore uses $0.02 per GB that crosses an AZ.
SQS vs RabbitMQ: What Each One Bills
The two services meter completely different things, which is why their bills cross at all. This table is the short answer to “what am I paying for”:
| SQS standard | SQS FIFO | Amazon MQ for RabbitMQ | MSK provisioned | |
|---|---|---|---|---|
| Fixed fee | none | none | per broker-hour | per broker-hour |
| Per-message fee | $0.40 per million requests | $0.50 per million requests | none | none |
| Free tier | 1M requests a month | shared with standard | none | none |
| Storage | included | included | $0.10 per GB-month of EBS | $0.10 per GB-month |
| In-region transfer | free | free | standard cross-AZ rates | standard cross-AZ rates |
| Transfer inside the cluster | not applicable | not applicable | free | free for replication |
The cluster transfer rows come from the vendor pages. Amazon MQ states that “for Amazon MQ for RabbitMQ clusters, there are no additional charges for data transfer fees within the cluster”, while also charging “standard AWS data transfer charges for data transferred in and out of Amazon MQ”. SQS, by contrast, says it does not charge for data transfer “if all resources are in the same AWS region.” Three details decide almost every number below.
Why One Message Costs Three SQS Requests
An SQS message is not one request. The producer calls SendMessage, the consumer calls ReceiveMessage, and after processing it calls DeleteMessage. That is three billed requests per message, so $0.40 per million requests is really $1.20 per million messages when nothing is batched.
Batching changes the arithmetic. SendMessageBatch, ReceiveMessage with up to ten messages and DeleteMessageBatch each count once for up to ten messages. As a result, a fully batched pipeline pays 0.3 requests per message, or $0.12 per million messages.
The 64 KB Chunk Rule in SQS Pricing
Batching has a ceiling, though, and it is payload size. The SQS pricing page is explicit: “Each 64 KB chunk of a payload is billed as 1 request (for example, an API action with a 1 MiB payload is billed as 16 requests).” A batch of ten 1 KB messages is one request. A batch of ten 32 KB messages, however, is 320 KB, which bills as five.
Delete calls carry receipt handles, not payloads, so they stay at one request per batch. Consequently, a batched 32 KB pipeline pays 1.1 requests per message instead of 0.3.
Cross-AZ Traffic: The Line Broker Comparisons Skip
A highly available broker lives in three Availability Zones, and so do its clients. With clients spread evenly, two out of three connections land on a node in another AZ. Every message makes two trips, publish and consume, and each trip crosses an AZ two times in three, billed at $0.02 per GB.
For 1 KB messages that is about $0.025 per million messages, which barely registers. For 32 KB messages, it is about $0.81 per million, more than batched SQS charges for the whole message lifecycle. SQS has no such line, because in-region transfer to SQS is free.
The Workload Assumptions
A price comparison is only as honest as its assumptions, so here they are in full:
- Message rate: a steady 1, 10, 100, 1,000 or 10,000 messages per second, all month.
- Message size: 1 KB, a typical JSON event, and 32 KB, a fat event carrying a full order or document.
- SQS batching: batch size 1 (every call carries one message) and batch size 10 (every call is full).
- SQS requests: send, receive and delete each billed, with the 1 million monthly free requests subtracted once.
- RabbitMQ storage: 200 GB of EBS per node, the default limit that AWS’s own pricing example uses, which bills $60 a month for a three-node cluster.
- MSK: three kafka.m7g.large brokers with 100 GB each, as a reference column.
- Cross-AZ: clients in three AZs, two-thirds of traffic crossing on both publish and consume, shown as its own column because many setups pin clients differently.
Long-polling idle consumers are left out. Specifically, one consumer waiting 20 seconds per ReceiveMessage on an empty queue makes 131,400 requests a month, which the free tier absorbs for up to seven idle pollers.
The Cost Script
The calculator is a single awk program, so it runs in any Bash, including Git Bash on Windows, with no installs. Every rate sits at the top with the offer file it came from:
#!/usr/bin/env bash
# queue-cost.sh: monthly cost of SQS vs RabbitMQ on Amazon MQ vs MSK, us-east-1.
# Rates from the AWS Price List API (us-east-1 offer files) read 2026-11-13.
awk 'BEGIN {
SQS_STD = 0.0000004; SQS_FIFO = 0.0000005; SQS_FREE = 1000000; # AWSQueueService
CHUNK_KB = 64; # each 64 KB of payload = 1 request
MQ_1 = 0.2734; MQ_3L = 0.8201; # AmazonMQ: single m7g.large, 3-node m7g.large
MQ_3XL = 1.6402; MQ_32XL = 3.2803; # 3-node m7g.xlarge, 3-node m7g.2xlarge
MQ_GB = 0.10; MQ_VOL = 200; # EBS GB-month, default 200 GB per node
MSK_L = 0.204; MSK_GB = 0.10; MSK_VOL = 100; # AmazonMSK: kafka.m7g.large, 100 GB each
XAZ_GB = 0.02; XAZ_SHARE = 2 / 3; # $0.01 out + $0.01 in, 2 of 3 AZs cross
HRS = 730; SECS = HRS * 3600;
mq1 = MQ_1 * HRS + 1 * MQ_VOL * MQ_GB
mq3 = MQ_3L * HRS + 3 * MQ_VOL * MQ_GB
mq3xl = MQ_3XL * HRS + 3 * MQ_VOL * MQ_GB
mq32x = MQ_32XL * HRS + 3 * MQ_VOL * MQ_GB
msk = 3 * MSK_L * HRS + 3 * MSK_VOL * MSK_GB
printf "Fixed monthly cost: MQ single m7g.large %.2f | MQ 3-node m7g.large %.2f | 3-node m7g.xlarge %.2f | 3-node m7g.2xlarge %.2f | MSK 3x m7g.large %.2f\n\n",
mq1, mq3, mq3xl, mq32x, msk
split("1 32", KB, " "); split("1 10 100 1000 10000", RATE, " ")
for (k = 1; k <= 2; k++) {
kb = KB[k]
printf "Message size %d KB\n", kb
printf "%7s %14s | %9s %9s %9s %9s | %9s %9s %9s | %9s\n", "msg/s", "msgs/month",
"SQS b1", "SQS b10", "FIFO b1", "FIFO b10", "MQ 1x", "MQ 3x", "MSK 3x", "xAZ"
for (i = 1; i <= 5; i++) {
r = RATE[i]; m = r * SECS
printf "%7d %14d | %9.2f %9.2f %9.2f %9.2f | %9.2f %9.2f %9.2f | %9.2f\n", r, m,
sqs(m, kb, 1, SQS_STD), sqs(m, kb, 10, SQS_STD), sqs(m, kb, 1, SQS_FIFO), sqs(m, kb, 10, SQS_FIFO),
mq1, mq3, msk, xaz(m, kb)
}
printf "\n"
}
split("MQ single m7g.large|MQ 3-node m7g.large|MQ 3-node m7g.xlarge|MQ 3-node m7g.2xlarge|MSK 3x m7g.large", NAME, "|")
FIX[1] = mq1; FIX[2] = mq3; FIX[3] = mq3xl; FIX[4] = mq32x; FIX[5] = msk
for (k = 1; k <= 2; k++) {
kb = KB[k]
printf "Crossover: messages per second where SQS costs the same as the broker (%d KB messages)\n", kb
printf "%-26s %10s %10s %10s %10s\n", "broker (with storage)", "SQS b1", "SQS b10", "FIFO b1", "FIFO b10"
for (b = 1; b <= 5; b++) for (x = 0; x <= 1; x++) {
printf "%-26s %10s %10s %10s %10s\n", NAME[b] (x ? " +xAZ" : ""),
fmt(cross(FIX[b], x, kb, 1, SQS_STD)), fmt(cross(FIX[b], x, kb, 10, SQS_STD)),
fmt(cross(FIX[b], x, kb, 1, SQS_FIFO)), fmt(cross(FIX[b], x, kb, 10, SQS_FIFO))
}
printf "\n"
}
}
function fmt(v) { return v < 0 ? "never" : sprintf("%.0f", v) }
# SQS bill: send and receive pay per 64 KB chunk of the batch payload, delete pays 1 per batch.
function sqs(msgs, kb, batch, price, chunks, reqs) {
chunks = int((kb * batch + CHUNK_KB - 1) / CHUNK_KB)
reqs = msgs / batch * (2 * chunks + 1)
reqs = reqs > SQS_FREE ? reqs - SQS_FREE : 0
return reqs * price
}
# Cross-AZ bytes: every message crosses on publish and on consume, 2 of 3 times.
function xaz(msgs, kb) { return msgs * kb / 1048576 * 2 * XAZ_SHARE * XAZ_GB }
# Bisection on msg/s until the SQS bill equals the broker bill.
function cross(fixed, withx, kb, batch, price, lo, hi, mid, n, d) {
lo = 0; hi = 1000000
for (n = 0; n < 100; n++) {
mid = (lo + hi) / 2
d = sqs(mid * SECS, kb, batch, price) - fixed - (withx ? xaz(mid * SECS, kb) : 0)
if (d > 0) hi = mid; else lo = mid
}
return mid >= 999999 ? -1 : mid
}'
The crossover is a bisection rather than a closed formula, because the free tier and the chunk rounding make the SQS bill piecewise. When SQS never overtakes the broker below a million messages per second, the script prints “never”. Moreover, every rate is a named constant, so a price change means editing one line and rerunning.
Raw Output of the Cost Script
The output below is pasted unedited, all amounts in US dollars per month:
Fixed monthly cost: MQ single m7g.large 219.58 | MQ 3-node m7g.large 658.67 | 3-node m7g.xlarge 1257.35 | 3-node m7g.2xlarge 2454.62 | MSK 3x m7g.large 476.76
Message size 1 KB
msg/s msgs/month | SQS b1 SQS b10 FIFO b1 FIFO b10 | MQ 1x MQ 3x MSK 3x | xAZ
1 2628000 | 2.75 0.00 3.44 0.00 | 219.58 658.67 476.76 | 0.07
10 26280000 | 31.14 2.75 38.92 3.44 | 219.58 658.67 476.76 | 0.67
100 262800000 | 314.96 31.14 393.70 38.92 | 219.58 658.67 476.76 | 6.68
1000 2628000000 | 3153.20 314.96 3941.50 393.70 | 219.58 658.67 476.76 | 66.83
10000 26280000000 | 31535.60 3153.20 39419.50 3941.50 | 219.58 658.67 476.76 | 668.33
Message size 32 KB
msg/s msgs/month | SQS b1 SQS b10 FIFO b1 FIFO b10 | MQ 1x MQ 3x MSK 3x | xAZ
1 2628000 | 2.75 0.76 3.44 0.95 | 219.58 658.67 476.76 | 2.14
10 26280000 | 31.14 11.16 38.92 13.95 | 219.58 658.67 476.76 | 21.39
100 262800000 | 314.96 115.23 393.70 144.04 | 219.58 658.67 476.76 | 213.87
1000 2628000000 | 3153.20 1155.92 3941.50 1444.90 | 219.58 658.67 476.76 | 2138.67
10000 26280000000 | 31535.60 11562.80 39419.50 14453.50 | 219.58 658.67 476.76 | 21386.72
Crossover: messages per second where SQS costs the same as the broker (1 KB messages)
broker (with storage) SQS b1 SQS b10 FIFO b1 FIFO b10
MQ single m7g.large 70 698 56 558
MQ single m7g.large +xAZ 71 885 57 672
MQ 3-node m7g.large 209 2090 167 1672
MQ 3-node m7g.large +xAZ 214 2652 170 2014
MQ 3-node m7g.xlarge 399 3988 319 3191
MQ 3-node m7g.xlarge +xAZ 407 5061 325 3842
MQ 3-node m7g.2xlarge 778 7785 623 6228
MQ 3-node m7g.2xlarge +xAZ 795 9878 634 7500
MSK 3x m7g.large 151 1513 121 1211
MSK 3x m7g.large +xAZ 155 1920 123 1458
Crossover: messages per second where SQS costs the same as the broker (32 KB messages)
broker (with storage) SQS b1 SQS b10 FIFO b1 FIFO b10
MQ single m7g.large 70 190 56 152
MQ single m7g.large +xAZ 217 never 122 never
MQ 3-node m7g.large 209 570 167 456
MQ 3-node m7g.large +xAZ 649 never 366 never
MQ 3-node m7g.xlarge 399 1088 319 870
MQ 3-node m7g.xlarge +xAZ 1239 never 698 never
MQ 3-node m7g.2xlarge 778 2123 623 1699
MQ 3-node m7g.2xlarge +xAZ 2419 never 1361 never
MSK 3x m7g.large 151 413 121 330
MSK 3x m7g.large +xAZ 470 never 265 never
Monthly Cost at 1 KB Messages
For small JSON events, the comparison is mostly SQS request charges against a flat broker fee. US dollars per month, with the three-node RabbitMQ cluster on mq.m7g.large including its cross-AZ line:
| Messages per second | SQS unbatched | SQS batched (10) | RabbitMQ 3-node m7g.large | RabbitMQ + cross-AZ |
|---|---|---|---|---|
| 1 | 2.75 | 0.00 | 658.67 | 658.74 |
| 10 | 31.14 | 2.75 | 658.67 | 659.34 |
| 100 | 314.96 | 31.14 | 658.67 | 665.35 |
| 1,000 | 3,153.20 | 314.96 | 658.67 | 725.50 |
| 10,000 | 31,535.60 | 3,153.20 | 658.67 | 1,327.00 |
Below 100 messages per second, the broker loses badly in either mode. At 10 messages per second, for instance, batched SQS costs $2.75 against $658.67. At 1,000 messages per second the picture splits: unbatched SQS is almost five times the cluster, while batched SQS is still under half of it.
Keep in mind that the broker columns assume one cluster handles the load. AWS does not publish a messages-per-second figure for any RabbitMQ instance size, so whether an m7g.large cluster sustains 10,000 messages per second is a question this post cannot answer from a price list.
Monthly Cost at 32 KB Messages
Larger messages change both sides. SQS batches stop collapsing into one request, and the broker’s cross-AZ line grows with every byte:
| Messages per second | SQS unbatched | SQS batched (10) | RabbitMQ 3-node m7g.large | RabbitMQ + cross-AZ |
|---|---|---|---|---|
| 1 | 2.75 | 0.76 | 658.67 | 660.81 |
| 10 | 31.14 | 11.16 | 658.67 | 680.06 |
| 100 | 314.96 | 115.23 | 658.67 | 872.54 |
| 1,000 | 3,153.20 | 1,155.92 | 658.67 | 2,797.34 |
| 10,000 | 31,535.60 | 11,562.80 | 658.67 | 22,045.39 |
The unbatched SQS column is identical to the 1 KB table, because a 32 KB message still fits in a single 64 KB chunk. The batched column, by contrast, is almost four times higher. Meanwhile, the cross-AZ line at 10,000 messages per second is $21,386.72, more than thirty times the cluster itself.
At What Message Rate Does RabbitMQ Become Cheaper Than SQS?
For 1 KB messages, a three-node RabbitMQ cluster on Amazon MQ mq.m7g.large becomes cheaper than SQS standard at about 209 messages per second when SQS calls are unbatched. With full batches of ten, the crossover moves to about 2,090 messages per second, roughly 5.5 billion messages a month.
The full table, 1 KB messages, cross-AZ traffic included:
| Broker | SQS unbatched | SQS batched | FIFO unbatched | FIFO batched |
|---|---|---|---|---|
| RabbitMQ single m7g.large | 71 | 885 | 57 | 672 |
| RabbitMQ 3-node m7g.large | 214 | 2,652 | 170 | 2,014 |
| RabbitMQ 3-node m7g.xlarge | 407 | 5,061 | 325 | 3,842 |
| RabbitMQ 3-node m7g.2xlarge | 795 | 9,878 | 634 | 7,500 |
| MSK 3x kafka.m7g.large | 155 | 1,920 | 123 | 1,458 |
Read the rows as “if my load needs this broker size”. If a three-node m7g.xlarge cluster is what your throughput requires, batched SQS stays cheaper up to about 5,000 messages per second. FIFO crosses earlier in every row, because its requests cost 25% more.
Why 32 KB Messages Never Cross Over When Batched
With 32 KB messages and clients in three AZs, the batched SQS columns read “never” for every broker. The reason is per-message arithmetic. Batched SQS charges 1.1 requests per 32 KB message, about $0.44 per million. The broker’s cross-AZ traffic charges about $0.81 per million for the same messages. Since the broker’s marginal cost per message is higher than SQS’s, adding traffic only widens the gap.
That result depends entirely on the cross-AZ assumption. If every client sits in the same AZ as a single-instance broker, the cross-AZ line drops to zero and the crossover returns to 190 messages per second. That setup, however, gives up the availability most teams bought a managed broker for.
What This Price Comparison Does Not Measure
Several things that matter in production are out of scope, and each one can move the crossover:
- Broker throughput. The Amazon MQ sizing guidelines and resource limit tables give connections, channels and queues per instance, but no messages per second. No broker was deployed for this post.
- Protocol overhead. AMQP frames, headers and acknowledgements add bytes beyond the payload, so the cross-AZ figures are a lower bound.
- Kafka fetch-from-follower. MSK consumers configured with
client.rackcan read from a replica in their own AZ, which removes the consume half of the cross-AZ line for the MSK rows. - People. A broker needs someone who understands quorum queues, memory alarms and upgrade windows. SQS needs none of that, and no price list includes it.
- Commitment and private pricing. The AmazonMQ and AmazonMSK offer files carry no reserved terms, and negotiated discounts on any of these services are not public.
Batching SQS in Node.js
Since batching moves the crossover by a factor of ten, it is the first change to make before any migration. This consumer receives up to ten messages per call with long polling and deletes them in one batch:
import {
SQSClient,
ReceiveMessageCommand,
DeleteMessageBatchCommand,
} from '@aws-sdk/client-sqs';
const client = new SQSClient({});
const QUEUE_URL = process.env.QUEUE_URL;
export async function pollOnce(handleMessage) {
const { Messages = [] } = await client.send(new ReceiveMessageCommand({
QueueUrl: QUEUE_URL,
MaxNumberOfMessages: 10, // one billed request for up to ten messages
WaitTimeSeconds: 20, // long polling: empty queues cost 3 requests a minute, not thousands
}));
if (Messages.length === 0) return 0;
const done = [];
for (const msg of Messages) {
try {
await handleMessage(JSON.parse(msg.Body));
done.push({ Id: msg.MessageId, ReceiptHandle: msg.ReceiptHandle });
} catch (err) {
// Leave it undeleted: it reappears after the visibility timeout, then goes to the DLQ
console.error(`Failed ${msg.MessageId}:`, err);
}
}
if (done.length > 0) {
const res = await client.send(new DeleteMessageBatchCommand({ QueueUrl: QUEUE_URL, Entries: done }));
// Batch calls succeed as a whole even when single entries fail, so check each one
for (const f of res.Failed ?? []) console.error(`Delete failed for ${f.Id}: ${f.Code}`);
}
return Messages.length;
}
The partial-failure check matters as much as the batching. DeleteMessageBatch returns HTTP 200 even when individual entries fail, and an undeleted message comes back as a duplicate. On the producer side, SendMessageBatchCommand works the same way with a Failed array that needs the same loop.
When to Use Amazon MQ for RabbitMQ
- Your sustained rate sits well above the crossover for the cluster size you need, and your messages are small enough that cross-AZ traffic stays a minor line.
- You depend on AMQP features SQS lacks: topic exchanges with routing keys, per-message priorities, or many consumers on one exchange without an SNS fan-out.
- You are lifting an existing RabbitMQ workload to AWS and rewriting producers and consumers for SQS would cost more engineering time than the broker costs in a year.
- Consumers need push delivery with prefetch limits instead of polling.
When NOT to Use Amazon MQ for RabbitMQ
- Your traffic is under about 70 messages per second. Below that even a single-instance broker costs more than unbatched SQS, and a three-node cluster costs more up to about 209.
- Messages are tens of kilobytes and clients run in several AZs. The cross-AZ line can cost more than the broker and more than batched SQS.
- Load is spiky with long idle stretches. SQS bills nothing for an idle queue beyond long polls, while a broker bills every hour.
- Nobody on the team wants to own broker upgrades, memory alarms and queue-length policies.
Common Mistakes When Pricing SQS vs RabbitMQ
- Comparing unbatched SQS against a broker. Batching moves the crossover ten times higher, and it is a code change, not a migration.
- Counting one SQS request per message. Send, receive and delete are three, so $0.40 per million requests is $1.20 per million messages.
- Ignoring the 64 KB chunk rule. Ten 32 KB messages in one batch bill as five requests, not one.
- Leaving out cross-AZ transfer for the broker. SQS in-region transfer is free, broker traffic is not, and at 32 KB the gap reverses the conclusion.
- Using message group IDs on a standard queue without noticing the fair queue line. The pricing page says those requests are “charged both fair queue rates and standard queue rates”, an extra $0.10 per million.
- Sizing the broker by price instead of load. A cluster that is cheaper on paper but runs at its memory alarm costs an outage, not a saving.
A Realistic Scenario: The Queue Bill That Prompted a Migration Plan
Consider a small platform team running an order-events pipeline on SQS standard for a mid-sized e-commerce product. Traffic has grown to a few hundred messages per second at peak, and the SQS line now runs into several hundred dollars a month. Someone proposes moving to a three-node RabbitMQ cluster on Amazon MQ, citing the fixed $658.67 a month as a ceiling.
Before approving a multi-week migration, the team checks the consumers. They call ReceiveMessage with the default of one message, and each handler deletes its own message. Switching to ten-message receives and batched deletes, plus SendMessageBatch on the producers, cuts the request count by roughly a factor of ten on this post’s numbers. At 300 messages per second, that takes the bill from around $946 a month to under $95.
The broker migration gets shelved. Not because RabbitMQ is worse, but because the trigger for it was a cost problem that a two-day change solved. The team keeps the crossover table instead, and revisits it if sustained traffic approaches 2,000 messages per second.
How This Fits With the Rest of Your Messaging Stack
Cost is one axis of the choice. For ordering guarantees, replay, fan-out and operational load across all three options, the RabbitMQ vs Kafka vs SQS comparison covers the feature side this post skips. Whichever queue you pick, consumers that fall behind need a plan, and the guide on backpressure patterns for queues covers what to do when producers outrun them.
Publishing to a queue from inside a database transaction is a second source of duplicate and lost messages, and the transactional outbox pattern solves it on both SQS and RabbitMQ. If the consumers run on Lambda, the per-request economics stack with the compute ones, which the Lambda vs Fargate vs EC2 cost comparison prices the same way. For more line items worth auditing on the same bill, see the AWS cost optimization tips.
Conclusion
On SQS vs RabbitMQ cost, the crossover is real but higher than most teams assume. A three-node Amazon MQ cluster on mq.m7g.large beats unbatched SQS at about 209 messages per second, and batched SQS at about 2,090. For large messages with clients across AZs, batched SQS may never lose at all.
Batch your SQS calls first, then rerun the script with your own rate and message size before planning a migration. Prices were read on 13 November 2026 and change without notice, so rerun the numbers before quoting them.