skip to content

You publish to an Amazon SNS topic and the call succeeds, but the subscribed SQS queue in another AWS account never receives anything. Which permission and configuration layers do you check, and in what order?

level: seniorimportance: should knowfreq 42%

answer

  1. publish success proves only the topic side
  2. delivery runs as a service principal
  3. the destination grants its own access
  4. check filtered-out before checking policies
  5. encrypted queue needs a customer managed key

basics

~20 s

Check the topic's access policy, the subscription's confirmation state and filter policy, the destination queue's resource policy allowing the SNS service principal to send, and the KMS key policy if the queue is encrypted. A successful Publish only proves you could write to the topic.

solid answer

~50 s

A successful `Publish` says nothing about delivery — it only means your identity policy and the topic's access policy allowed you to publish. Work outwards. First confirm the subscription is actually confirmed and not still pending, and that its filter policy is not excluding everything, using `NumberOfNotificationsFilteredOut` to tell. Then check the destination: the SQS queue's own resource policy must allow the SNS service principal to `sqs:SendMessage`, normally scoped with `aws:SourceArn` set to the topic ARN — subscribing a queue does not grant that access. If the queue is encrypted, the KMS key policy must let SNS call `kms:GenerateDataKey*` and `kms:Decrypt`, and the AWS managed key for SQS cannot be used at all because its policy is not editable. Cross-account adds the topic policy allowing the other account to `sns:Subscribe`. Finally, `NumberOfNotificationsFailed` and delivery-status logging tell you which layer is refusing.

code

json · 15 lines
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSnsTopicToSend",
      "Effect": "Allow",
      "Principal": {"Service": "sns.amazonaws.com"},
      "Action": "sqs:SendMessage",
      "Resource": "arn:aws:sqs:eu-west-1:444455556666:orders-billing",
      "Condition": {
        "ArnEquals": {"aws:SourceArn": "arn:aws:sns:eu-west-1:111122223333:orders"}
      }
    }
  ]
}

go deeper

for a junior

Know that publishing and delivering are separate authorisation steps, and that the receiving queue needs its own policy allowing SNS to send to it. Naming the topic policy and the queue policy as two distinct things is enough here.

for a middle

Walk the layers in order and explain what each one governs: identity policy, topic access policy, subscription state and filter policy, queue resource policy with aws:SourceArn, and the KMS key policy when the queue is encrypted.

for a senior

Diagnose from evidence rather than guesswork — use the filtered-out, failed and delivered metrics plus delivery-status logging to isolate the layer, know the AWS-managed-key trap by heart, and check SCPs in a multi-account estate.

for a principal

Own the prevention story: standard modules that provision topic, subscription, queue policy and key grant together, guardrails that reject unscoped resource policies, and org-wide conditions such as source-ARN and organisation-ID checks that make confused-deputy wiring impossible by default.

## Why a successful publish proves so little SNS accepts a message the moment the caller is authorised on the topic. Delivery to subscribers happens afterwards, asynchronously, on SNS's own credentials as a service principal — a completely separate authorisation decision that the publisher never sees. So "publish returns a MessageId" and "the queue is empty" are entirely compatible, and every layer between them is a suspect. ## The layers, outward from the publisher **1. The publisher's identity policy.** Does the role have `sns:Publish` on that topic ARN? If not you would see `AuthorizationError` — so a successful publish already clears this one. **2. The topic access policy.** A resource policy on the topic controls who may publish and subscribe, and for cross-account work it is where the other account is granted `sns:Subscribe`. When an AWS service publishes to the topic — S3 event notifications, a CloudWatch alarm, EventBridge — the topic policy must allow that service principal, usually with a condition on `aws:SourceArn` (and `aws:SourceAccount`) to prevent the confused-deputy problem where another customer's bucket points at your topic. **3. The subscription itself.** Two states bite here. A subscription can sit in `PendingConfirmation` — always true for HTTPS until the endpoint echoes the token, and possible cross-account when the subscribe call was made by a principal that does not own the destination. And a **filter policy** silently drops non-matching messages: if the publisher stopped setting an attribute, or sends a number as a string, the subscriber receives nothing and nothing errors. Compare `NumberOfNotificationsFilteredOut` with `NumberOfMessagesPublished` to rule this in or out in seconds. **4. The destination resource policy.** This is the most common actual cause. The SQS queue must have a policy statement allowing the SNS service principal to `sqs:SendMessage` on that queue, conditioned on `aws:SourceArn` matching the topic: ```json { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"Service": "sns.amazonaws.com"}, "Action": "sqs:SendMessage", "Resource": "arn:aws:sqs:eu-west-1:444455556666:orders-billing", "Condition": {"ArnEquals": {"aws:SourceArn": "arn:aws:sns:eu-west-1:111122223333:orders"}} }] } ``` Creating the subscription does **not** create this grant unless a console wizard or IaC module wrote it for you. Cross-account, the queue owner must add it, because a resource policy can only be written by the resource's own account. **5. Encryption.** If the queue uses server-side encryption with a customer managed KMS key, that key's policy must allow the SNS service principal `kms:GenerateDataKey*` and `kms:Decrypt`. And the trap worth knowing cold: a queue encrypted with the **AWS managed key for SQS cannot receive SNS deliveries**, because you cannot modify that key's policy to add SNS. The symptom is exactly this question's symptom — publishes succeed, the queue stays empty. The same applies in reverse for an encrypted topic whose publishers need key access. **6. Organisation-level controls.** In a multi-account estate, a service control policy or a VPC endpoint policy can deny an action that both the identity and resource policies allow. An explicit deny anywhere wins, and an SCP that does not allow the action is equivalent to a deny for principals in that account. ## Making the diagnosis fast Rather than reading five policies in order, read the metrics first and let them point at a layer: - `NumberOfMessagesPublished` high, `NumberOfNotificationsFilteredOut` equally high → filter policy. - `NumberOfNotificationsFailed` climbing → the destination is refusing; it is the queue policy or KMS. - `NumberOfNotificationsDelivered` healthy but the consumer sees nothing → not a delivery problem at all; look at the consumer, or at a second subscription pointing at a different queue. - Subscription ARN literally reads `PendingConfirmation` → nothing was ever delivered. Delivery-status logging on the topic gives per-delivery outcomes in CloudWatch Logs and is the fastest way to see the actual refusal, while CloudTrail shows the `Subscribe` and `SetQueueAttributes` history when someone changed something. ## The habit to demonstrate The reason this question separates candidates is that it rewards a model of AWS authorisation rather than a memorised fix: **identity policy, resource policy, and service-to-service access are three different decisions, and the middle one belongs to whoever owns the destination.** Say that, then walk the layers, and the answer writes itself.

  • Why is aws:SourceArn on the queue policy more than cosmetic?
    Without it the queue accepts messages from any SNS topic in any account that knows the queue ARN — the confused-deputy shape. Scoping the statement to the exact topic ARN (and often `aws:SourceAccount`) means only your topic can write, so an accidental or malicious subscription from elsewhere is refused. The same reasoning applies to a topic policy that lets S3 or CloudWatch publish.
  • What is the specific problem with an SQS queue encrypted using the AWS managed key for SQS?
    You cannot edit that key's policy, so there is no way to grant the SNS service principal `kms:GenerateDataKey*` and `kms:Decrypt`. SNS therefore cannot encrypt a message into the queue, deliveries fail, and the queue stays empty while publishes succeed. The fix is a customer managed key whose policy grants SNS those actions.
  • How do you keep this from recurring across dozens of topic-to-queue pairs?
    Encode the whole pattern once — topic, subscription, queue policy scoped to the topic ARN, customer managed key with the SNS grant, dead-letter queue — as a reusable module in whatever provisions your infrastructure, and forbid hand-wired subscriptions. Then alarm on `NumberOfNotificationsFailed` per topic so a missed grant surfaces in minutes rather than at the next incident.

saying these in an interview costs you the question

  • A successful Publish means every subscriber received it
  • Subscribing a queue grants SNS permission to write to it
  • The publisher's IAM role governs delivery to subscribers
  • Encryption is transparent and never affects delivery
  • Cross-account access only needs a policy on one side

context