# SNS fan-out (/connectors/aws/how-to/sns-fan-out)



This guide covers the SNS surface: topic management, subscriptions and the confirmation flow,
message filtering, raw vs enveloped delivery, `PublishBatch`, FIFO topics, and
`MessageStructure=json`. SNS topics are **virtual** BoltDB registry entries (no native channel)
that fan out, at publish time, to SQS subscriptions and HTTP/HTTPS webhooks. The SNS surface ships
**17 actions** (see [Capabilities](/connectors/aws/reference/capabilities)).

## Topic management [#topic-management]

* `CreateTopic` — idempotent on an existing name; a **FIFO** topic uses the `.fifo` suffix.
* `DeleteTopic` — cascades its subscriptions.
* `ListTopics` — ARN-sorted, 100 per page; **not** authorization-filtered.
* `GetTopicAttributes` / `SetTopicAttributes` — the only writable attributes are `DisplayName` and
  `DeliveryPolicy`.

<Callout type="warn">
  **`Policy` is rejected.** Setting a topic `Policy` returns `InvalidParameter`. **Topic-level
  `ContentBasedDeduplication` is not supported** — a set returns `InvalidParameter` and a get always
  returns `"false"`. For FIFO topics, pass an explicit `MessageDeduplicationId` (see below).
</Callout>

## Subscriptions [#subscriptions]

`Subscribe` accepts three protocols only:

| Protocol         | Behavior                                                                                                                                                                                         |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `sqs`            | The endpoint must be a **registry queue ARN**; the subscription is **auto-confirmed** immediately (`Confirmed=true`).                                                                            |
| `http` / `https` | Goes **pending** with a 48 h confirmation token; a `SubscriptionConfirmation` envelope is POSTed best-effort; expired pending subscriptions are swept hourly. Confirm via `ConfirmSubscription`. |
| anything else    | `email` / `email-json` / `sms` / `lambda` / `application` / `firehose` → `InvalidParameter` "protocol not supported".                                                                            |

The writable **subscription attributes** are `RawMessageDelivery` (bool), `FilterPolicy` (JSON,
parsed and validated at set), `FilterPolicyScope`, `RedrivePolicy` (JSON), and `DeliveryPolicy`.

The `http`/`https` confirmation `GET` is **SigV4-exempt** so the `SubscribeURL` embedded in a
`SubscriptionConfirmation` envelope is usable as-is — see
[Authentication](/connectors/aws/how-to/authentication).

## Message filtering [#message-filtering]

A `FilterPolicy` filters which subscriptions receive a publish. All 8 AWS operators are supported:
exact string/number/bool, prefix, suffix, anything-but, numeric comparison/range, exists
true/false, and CIDR. Keys are ANDed, values within a key ORed; an empty policy matches
everything. Write-time limits: ≤ 5 keys, ≤ 150 value combinations. Binary attributes match only
`exists:true`.

<Callout type="warn">
  **`MessageBody`-scope filtering is unsupported.** Only `FilterPolicyScope = MessageAttributes`
  works. Setting `FilterPolicyScope = MessageBody` is **rejected** at the attribute setter with
  `InvalidParameter` "MessageBody scope is not supported". Filter only on `MessageAttributes`. See
  [Capabilities](/connectors/aws/reference/capabilities).
</Callout>

## Raw vs enveloped delivery [#raw-vs-enveloped-delivery]

`RawMessageDelivery` controls the delivered shape:

* **Enveloped** (`false`, the default) — the body is the SNS `Notification` JSON:
  `{Type:"Notification", MessageId, TopicArn, Subject?, Message, Timestamp, SignatureVersion:"1",
  Signature:"", SigningCertURL:"", UnsubscribeURL, MessageAttributes?}`. Each `MessageAttributes`
  entry is `{Type, Value}` (Binary is base64).
* **Raw** (`true`) — for an SQS subscription, the bare message bytes plus the attribute tag codec
  and `sns_topic_arn` / `sns_subject` tags; for an HTTP subscription, the bare payload with
  attributes mapped to `x-amz-sns-attr-{name}` headers.

<Callout type="warn">
  **SNS notifications are unsigned.** `Signature` and `SigningCertURL` are present in the envelope
  but **empty** (`SignatureVersion` is `"1"`). No SDK-side signature verification can be performed.
  Do not rely on verifying SNS message signatures. See
  [Reliability](/connectors/aws/how-to/reliability).
</Callout>

<Callout type="info">
  **Raw-HTTP attribute deviation.** Real AWS drops message attributes for raw HTTP delivery; this
  connector instead maps them to `x-amz-sns-attr-{name}` headers. See
  [Channel mapping](/connectors/aws/reference/channel-mapping).
</Callout>

## Fan-out semantics [#fan-out-semantics]

`Publish` / `PublishBatch` fan out to every **confirmed**, filter-matching subscription:

* there is **one `MessageId` per publish**, shared across all deliveries;
* all `sqs` deliveries of one publish go out in a single `SendQueueMessagesBatch`;
* per-target failures (deleted queue, unauthorized, oversize, FIFO mismatch) are **dropped with a
  metric and do not fail the publish**;
* **zero matching subscriptions → the publish succeeds** and the message is dropped;
* a per-target Casbin `write` check applies on each `sqs.{queue}`.

`MessageStructure=json` is supported: pass a JSON object with a string `default` key plus optional
per-protocol string overrides.

## FIFO topics [#fifo-topics]

A `.fifo` topic restricts `Subscribe` to the `sqs` protocol onto a `.fifo` queue (`http` / `https`
are rejected). `Publish` / `PublishBatch`:

* **require `MessageGroupId`** (and **reject** it on a standard topic);
* treat `MessageDeduplicationId` as optional — topic-level content-based dedup is unsupported, so
  pass it explicitly.

Group and dedup ids propagate into the FIFO queue-message build. See
[Reliability](/connectors/aws/how-to/reliability) for the full FIFO ordering and dedup detail.

## Error quick reference [#error-quick-reference]

| Trigger                                                               | AWS error code                     |
| --------------------------------------------------------------------- | ---------------------------------- |
| `Subscribe` with `email` / `sms` / `lambda` / `firehose` / … protocol | `InvalidParameter`                 |
| `Subscribe` with `FilterPolicyScope=MessageBody`                      | `InvalidParameter`                 |
| `Publish` with `MessageGroupId` to a **standard** topic               | `InvalidParameter`                 |
| FIFO topic `Subscribe` with `http` / a non-FIFO queue                 | `InvalidParameter`                 |
| Set a topic `Policy` / topic-level `ContentBasedDeduplication`        | `InvalidParameter`                 |
| `Publish` with `TargetArn` / `PhoneNumber`                            | `InvalidParameter`                 |
| Topic / subscription not in the registry                              | `NotFound` (404)                   |
| `Publish` to a topic with zero matching subscriptions                 | *none — succeeds, message dropped* |

## Related [#related]

<Cards>
  <Card title="SQS queues and consumers" href="/connectors/aws/how-to/sqs-queues-and-consumers" description="The SQS surface end to end — send/receive/delete, visibility, long polling, batch, FIFO, and DLQ." />

  <Card title="Reliability" href="/connectors/aws/how-to/reliability" description="The SNS retry → circuit-breaker → DLQ pipeline and FIFO ordering and dedup." />

  <Card title="Authentication" href="/connectors/aws/how-to/authentication" description="The ConfirmSubscription SigV4 exemption used by HTTP/HTTPS subscription confirmation." />
</Cards>
