What Does SNS Actually Cost to Send?

SNS bills publishing, delivery, and SMS as separate meters, and fan-out to several subscribers multiplies the delivery charge, not the publish charge.

Published September 5, 2026 · Last updated September 6, 2026

A notification service billed at half a cent per thousand requests does not look like a line item worth investigating, and for months it usually isn't. That changes the moment a topic's fan-out grows past a couple of subscribers, someone adds SMS to the mix without checking what a message actually costs once a carrier fee lands on top of it, or a payload quietly grows past the size AWS treats as one message. None of the three looks reckless on its own. Together they turn a service that felt free into a line item somebody has to explain.

Why does SNS have so many different prices?

SNS isn't one meter — it's several, and which one applies depends on the type of topic and the type of subscriber on the other end of a publish.

What you pay forRate
Standard topic API requestsFirst 1,000,000/month free, then $0.50 per 1,000,000 requests
FIFO topic publish requests$0.30 per 1,000,000 requests, plus $0.017 per GB of payload
FIFO subscription messages$0.01 per 1,000,000 messages, plus $0.001 per GB of payload
Mobile push deliveriesFirst 1,000,000/month free, then $0.50 per 1,000,000
Email / Email-JSON deliveriesFirst 1,000/month free, then $2.00 per 100,000
HTTP/S deliveriesFirst 100,000/month free, then $0.06 per 100,000
SQS and Lambda deliveriesNo charge — standard SQS or Lambda pricing applies on the receiving end
Kinesis Data Firehose deliveries$0.19 per 1,000,000 messages

Two chunking rules sit underneath that table and change what "one message" actually means. On Standard topics, every 64KB chunk of a published payload counts as one API request, and the same 64KB chunking applies again on delivery — a single notification with a 256KB payload is billed as four requests to publish and four deliveries per subscriber to send. On FIFO topics, anything from 1KB to 256KB counts as one message, with anything smaller rounded up to a full 1KB.

Why is my bill bigger than "half a cent per message" suggests?

Because publishing is the cheap half, and delivery isn't one meter — it's one meter per subscriber. A single publish to a Standard topic with five subscribers — two SQS queues, one Lambda function, one email address, and one HTTP endpoint — creates five separate delivery events, each priced by its own endpoint type. The SQS and Lambda legs cost nothing. The email leg is $2.00 per 100,000 once the free tier is spent, and the HTTP leg is $0.06 per 100,000. Fan-out breadth, not publish volume, is usually what decides a Standard topic's bill.

SMS makes the picture harder to see rather than harder to pay for. Since November 1, 2024, SMS charges appear on the bill under AWS End User Messaging rather than under SNS, and the per-message rate itself varies by destination country and, in some cases, by carrier within the same country — AWS publishes the numbers for guidance only and tells you to read the actual charge off your usage report after the fact. On top of that variable rate sits a fixed layer that has nothing to do with message volume: sending to US toll-free numbers carries a $0.0025 per-message carrier fee, and most origination identities carry their own recurring cost regardless of how many messages go out — a 10DLC number needs a one-time $4 company registration plus a $10-a-month campaign fee ($2 for a low-volume campaign) and $1 a month per phone number, and a toll-free number leases at $2 a month. None of that shows up on a "price per message" page; it's a second, largely fixed cost sitting underneath the variable one.

How do I find what's actually driving the number?

Start in Cost Explorer, filtered to SNS and grouped by Usage Type — that split separates the publish-request charge from each delivery-protocol charge in one screen. SMS spend, remember, is now a separate service line under AWS End User Messaging rather than SNS, so filter for both if text messages are part of the bill.

To see delivery volume per topic without waiting for the bill to close:

aws cloudwatch get-metric-statistics \
  --namespace AWS/SNS \
  --metric-name NumberOfNotificationsDelivered \
  --dimensions Name=TopicName,Value=order-events \
  --start-time "$(date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ)" \
  --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  --period 86400 \
  --statistics Sum \
  --region us-east-1 \
  --output table

Run the same call with NumberOfMessagesPublished to see the publish side, and NumberOfNotificationsFailed to catch a subscriber that is generating billed delivery attempts without actually receiving anything. If SMS is part of the mix, the SMSMonthToDateSpentUSD metric under the same namespace reports accrued charges since the start of the calendar month — useful for catching a runaway campaign well before it shows up on an invoice.

To see who is actually subscribed to a chatty topic, and on what protocol:

aws sns list-subscriptions-by-topic \
  --topic-arn arn:aws:sns:us-east-1:123456789012:order-events \
  --query 'Subscriptions[].[Protocol,Endpoint]' \
  --output table

How do I bring the bill down without breaking delivery?

Prune subscriptions to dead endpoints. SNS's delivery meters are literally named DeliveryAttempts in AWS's own billing data — they charge per attempt, not per successful delivery. A subscription pointed at an endpoint that has been returning errors for months is still billed on every metered protocol it uses.

Prefer attribute-based filter policies over payload-based ones. Both let a subscriber skip messages it doesn't need, but they're priced completely differently: attribute-based filtering is free, while payload-based filtering bills $0.09 per GB of payload scanned — for every message evaluated against the filter, matched or not. Attribute-based filtering does the same job for free whenever the routing decision can be made on a message attribute instead of the message body.

Route machine-to-machine subscribers through SQS or Lambda wherever the consumer can accept it. Those two delivery types carry no per-notification charge at all. An HTTP endpoint or a mobile push subscription doing the same job as an SQS queue is paying a meter that queue wouldn't.

Keep payloads under 64KB where you control the format. Crossing that boundary multiplies both the publish charge and the delivery charge to every subscriber by however many additional 64KB chunks the payload needs.

Budget SMS origination identities as a fixed cost, separate from message volume. A 10DLC campaign and phone number bill their monthly fee whether you send one message or none; for a use case that only needs occasional SMS, that fixed cost can end up larger than the messages themselves.

What else should I check while I'm in here?

If a topic delivers to an HTTP/S endpoint sitting behind API Gateway — a common shape for a webhook receiver — every SNS delivery attempt is also a billable API Gateway request, so the two per-request meters stack on the exact same message. See what API Gateway costs at scale for the rate on that second meter.

SQS and Lambda deliveries carry no SNS-side charge, which is exactly why they are the cheapest fan-out targets — but "free on the SNS side" is not "free": every message an SQS subscription receives still runs through SQS's own per-request meter once it lands in the queue. See why SQS costs more than you budgeted for what that second meter looks like once a topic fans out to more than one queue.

If topic encryption is turned on with a customer-managed KMS key instead of the AWS managed default, every publish and every delivery attempt now also triggers a KMS GenerateDataKey or Decrypt call, stacking KMS's own per-request charge underneath SNS's. See how much does KMS cost to run for what that layer adds once a topic gets busy.

More broadly, a service that meters publishing, delivery, and a completely separate SMS product all under one console tab is exactly the kind of bill that hides its real driver — the full audit of every meter an AWS bill quietly runs works through where the rest of that pattern shows up, service by service.

How do I catch this before it becomes a real number?

SNS spend rarely spikes on its own — it climbs when a topic gains a new subscriber, when a retry loop starts re-delivering to a failing endpoint, or when an SMS campaign scales up without anyone re-checking the per-message rate for the countries it now reaches. None of those looks like an incident in the moment.

Connect your AWS account read-only, and Parsivex's daily anomaly checks compare every service's spend — SNS included — against its own trailing baseline, so a genuine jump surfaces the next morning instead of buried in a monthly total. For how those daily checks and severity thresholds work, see cost anomaly alerts, or read how scans work for what a connected account scan reads across the rest of your bill.