Ravindra BagaleCourses & study guides मराठी Track your progress

AWS SDK SNS Examples: Topics, Subscriptions, Publish and Filters (Python, PHP, Node.js)

SNS pushes one message to many listeners at once: email, SMS, SQS queues and Lambda. We create a topic, subscribe an email and an SQS queue, publish with attributes, filter who gets what, and send an SMS — from Python, PHP and Node.js. The example: delay alerts for a train operator with Emma in Manchester and Arjun in Mumbai.

What you'll learn in this chapter

  • Create a topic
  • Subscribe email and SQS
  • Publish with message attributes
  • Apply filter policies
  • Send a direct SMS

1. The big picture: the station announcement

Why do we need this?

When a train is late, one announcement goes over every speaker, the app, and the display board at once. The announcer does not phone each passenger. An SNS topic is the announcement system; subscribers are the speakers.

What is it?

Publish once to a TopicArn; SNS delivers to every confirmed subscription. A filter policy on a subscription matches message attributes so each listener hears only what it cares about.

How to do it (step by step)

One publish, many deliveriesCreateTopicSubscribe (email, sqs, lambda)Confirm emailPublish with attributesFilter policy decides delivery
An SQS subscriber needs a queue policy that allows the topic to send.

2. Create a topic

Why do we need this?

Emma runs operations for the Manchester–Leeds line and Arjun for Mumbai suburban trains; both need one alerts channel.

What is it?

CreateTopic is idempotent: the same name returns the same TopicArn.

How to do it (step by step)

  1. Python (boto3).
import boto3, json
sns = boto3.client("sns", region_name="eu-west-2")
arn = sns.create_topic(Name="train-delays", Tags=[{"Key": "team", "Value": "ops"}])["TopicArn"]
print(arn)

Expected output:

arn:aws:sns:eu-west-2:123456789012:train-delays
  1. Node.js (v3).
import { SNSClient, CreateTopicCommand } from "@aws-sdk/client-sns";
const sns = new SNSClient({ region: "eu-west-2" });
const { TopicArn } = await sns.send(new CreateTopicCommand({ Name: "train-delays" }));
console.log(TopicArn);

Expected output:

arn:aws:sns:eu-west-2:123456789012:train-delays
  1. PHP (v3).
<?php
require "vendor/autoload.php";
$sns = new Aws\Sns\SnsClient(["region" => "eu-west-2"]);
$arn = $sns->createTopic(["Name" => "train-delays"])["TopicArn"];
echo $arn, PHP_EOL;

Expected output:

arn:aws:sns:eu-west-2:123456789012:train-delays
  1. Verify: list topics.
aws sns list-topics --region eu-west-2 --query "Topics[?contains(TopicArn,'train')].TopicArn" --output text

Expected output:

arn:aws:sns:eu-west-2:123456789012:train-delays

3. Subscribe email and a queue

Why do we need this?

Emma wants an email; the Mumbai passenger app reads from an SQS queue.

What is it?

Email subscriptions stay PendingConfirmation until the link is clicked. SQS subscriptions confirm at once if the queue policy allows sns.amazonaws.com.

How to do it (step by step)

  1. Python: subscribe an email.
r = sns.subscribe(TopicArn=arn, Protocol="email",
    Endpoint="emma@rail.example.co.uk", ReturnSubscriptionArn=True)
print(r["SubscriptionArn"])

Expected output:

arn:aws:sns:eu-west-2:123456789012:train-delays:4a1b...  (pending until Emma clicks Confirm)
  1. Node.js: subscribe an SQS queue with raw delivery.
import { SubscribeCommand } from "@aws-sdk/client-sns";
const r = await sns.send(new SubscribeCommand({
  TopicArn, Protocol: "sqs",
  Endpoint: "arn:aws:sqs:eu-west-2:123456789012:mumbai-app",
  Attributes: { RawMessageDelivery: "true" }, ReturnSubscriptionArn: true,
}));
console.log(r.SubscriptionArn);

Expected output:

arn:aws:sns:eu-west-2:123456789012:train-delays:9c7d...
  1. PHP: allow the topic to send to the queue.
<?php
$sqs = new Aws\Sqs\SqsClient(["region" => "eu-west-2"]);
$policy = ["Version" => "2012-10-17", "Statement" => [[
  "Effect" => "Allow", "Principal" => ["Service" => "sns.amazonaws.com"],
  "Action" => "sqs:SendMessage", "Resource" => "arn:aws:sqs:eu-west-2:123456789012:mumbai-app",
  "Condition" => ["ArnEquals" => ["aws:SourceArn" => $arn]]]]];
$sqs->setQueueAttributes(["QueueUrl" => $queueUrl, "Attributes" => ["Policy" => json_encode($policy)]]);
echo "policy set", PHP_EOL;

Expected output:

policy set
  1. Verify: list subscriptions on the topic.
aws sns list-subscriptions-by-topic --topic-arn $ARN --query "Subscriptions[].[Protocol,SubscriptionArn]" --output text

Expected output:

email   PendingConfirmation
sqs     arn:aws:sns:eu-west-2:123456789012:train-delays:9c7d...

4. Publish and filter

Why do we need this?

Mumbai passengers should not get Manchester delays, and only delays over 10 minutes should email Emma.

What is it?

Publish with MessageAttributes; set a FilterPolicy on each subscription. Numeric and string matching are supported.

How to do it (step by step)

  1. Python: set a filter on the email subscription.
sns.set_subscription_attributes(SubscriptionArn=email_sub,
    AttributeName="FilterPolicy",
    AttributeValue=json.dumps({"city": ["manchester"], "minutes": [{"numeric": [">", 10]}]}))
print("filter ok")

Expected output:

filter ok
  1. Node.js: publish a Mumbai delay.
import { PublishCommand } from "@aws-sdk/client-sns";
const r = await sns.send(new PublishCommand({
  TopicArn, Subject: "Delay",
  Message: JSON.stringify({ train: "Virar fast 08:12", minutes: 15 }),
  MessageAttributes: {
    city: { DataType: "String", StringValue: "mumbai" },
    minutes: { DataType: "Number", StringValue: "15" } },
}));
console.log(r.MessageId);

Expected output:

e2a1c0d4-5b6f-5a0e-9d7c-1f2e3d4c5b6a  (queue gets it, Emma does not)
  1. PHP: publish a Manchester delay.
<?php
$r = $sns->publish(["TopicArn" => $arn, "Subject" => "Delay: 07:45 to Leeds",
  "Message" => "The 07:45 to Leeds is 22 minutes late. Refund up to £8.40.",
  "MessageAttributes" => [
    "city" => ["DataType" => "String", "StringValue" => "manchester"],
    "minutes" => ["DataType" => "Number", "StringValue" => "22"]]]);
echo $r["MessageId"], PHP_EOL;

Expected output:

7b3f...  (Emma gets the email)
  1. Verify: read the message on the queue.
aws sqs receive-message --queue-url $MUMBAI_URL --wait-time-seconds 10 --query "Messages[0].Body" --output text

Expected output:

{"train":"Virar fast 08:12","minutes":15}

5. Send an SMS

Why do we need this?

A single passenger in Pune who booked by phone gets a text, no topic needed.

What is it?

Publish with PhoneNumber in E.164 format. Accounts start in the SMS sandbox, so verify the number first; set SMSType to Transactional for alerts.

How to do it (step by step)

  1. Python.
r = sns.publish(PhoneNumber="+919800012345",
    Message="Deccan Queen delayed 20 min. New dep 07:35.",
    MessageAttributes={"AWS.SNS.SMS.SMSType": {"DataType": "String", "StringValue": "Transactional"}})
print(r["MessageId"])

Expected output:

0c9a2f1e-...
  1. Node.js.
const r = await sns.send(new PublishCommand({ PhoneNumber: "+447700900123", Message: "Your 07:45 to Leeds is now 08:07." }));
console.log(r.MessageId);

Expected output:

3d8e...
  1. PHP: add a sandbox number to verify.
<?php
$sns->createSMSSandboxPhoneNumber(["PhoneNumber" => "+919800012345", "LanguageCode" => "en-US"]);
echo "OTP sent", PHP_EOL;

Expected output:

OTP sent
  1. Verify: check sandbox status.
aws sns get-sms-sandbox-account-status --region eu-west-2

Expected output:

{"IsInSandbox": true}

6. The same call in Java, Go, .NET and the CLI

Why do we need this?

Teams often mix languages. Once you know the call in Python, PHP and Node.js, the other SDKs are the same API with different syntax.

What is it?

All of them call the Publish API. Use the CLI line to test it quickly from a terminal.

How to do it (step by step)

StackCode
AWS CLIaws sns publish --topic-arn $ARN --message "07:45 late" --message-attributes '{"city":{"DataType":"String","StringValue":"manchester"}}'
Java v2sns.publish(b -> b.topicArn(arn).message("07:45 late"));
Go v2client.Publish(ctx, &sns.PublishInput{TopicArn: aws.String(arn), Message: aws.String("07:45 late")})
.NETawait sns.PublishAsync(new PublishRequest { TopicArn = arn, Message = "07:45 late" });

7. Clean up so nothing keeps costing

Why do we need this?

Lab resources left running cost money and can be a security risk.

What is it?

Delete in reverse order: children first, then parents.

How to do it (step by step)

  1. Delete the topic (its subscriptions go with it).
aws sns delete-topic --topic-arn $ARN --region eu-west-2

Expected output:

(no output means success)

Ravindra Bagale's Tip

Put the filter on the subscription, not in the consumer code; SNS then never sends what is not needed, and you pay less.

8. Interview questions and answers

Q. SNS vs SQS?

SNS pushes to many subscribers; SQS holds messages until one consumer pulls them.

Q. What is fan-out?

One SNS topic delivering to several SQS queues, each processed independently.

Q. Why does an email subscription stay pending?

The recipient must click the confirmation link.

Q. What does RawMessageDelivery do?

Sends only the message body to SQS/HTTP without the SNS JSON envelope.

Q. How do filter policies match?

Against message attributes (or body with FilterPolicyScope MessageBody).

Try at home

  1. Add a Lambda subscriber in Node.js that logs every delay.
  2. Create a second queue for Manchester and show fan-out with one publish.

In short

  1. CreateTopic → TopicArn.
  2. Subscribe email/SQS/Lambda.
  3. Publish with attributes.
  4. FilterPolicy on subscriptions.
  5. SMS via PhoneNumber.

Practice Tasks

About this scenario

Latur Coaching Classes is a coaching business in Latur. Pooja Jadhav looks after its IT and cloud work. They count money in INR and run their AWS resources in the ap-south-1 Region. In the tasks below you do real jobs for them using what this lesson teaches. All names, account IDs, IP addresses and numbers are made up for practice.

0 / 11

Easy Publish to one topic

Why: An alerting app only needs to publish.

What to do: Allow sns:Publish on arn:aws:sns:ap-south-1:123666135775:laturcoaching-alerts only.

How:
  1. Start with { "Version": "2012-10-17", "Statement": [ ... ] }.
  2. In each statement write Effect, Action and Resource.
  3. Give only what the task needs (least privilege).
  4. Use double quotes and commas correctly. Click Check answer.

Easy Publish a message

Why: One publish reaches email, SMS, SQS and Lambda subscribers together.

What to do: Publish the message "Stock low in Latur" with subject "Stock alert" to arn:aws:sns:ap-south-1:123666135775:laturcoaching-alerts.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Easy Create an SNS topic

Why: A topic is a channel: publish once, every subscriber gets it.

What to do: Create topic laturcoaching-alerts.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Easy Create a queue

Why: A queue holds work safely until a worker is ready.

What to do: Create queue laturcoaching-orders.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Send an SMS directly

Why: SNS can send a one-off SMS to a phone number without a topic.

What to do: Send the SMS "Your OTP is 482913" to +919800000001.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Producer may only send

Why: The web app should add jobs but never read or delete them.

What to do: Allow sqs:SendMessage on arn:aws:sqs:ap-south-1:123666135775:laturcoaching-orders only.

How:
  1. Start with { "Version": "2012-10-17", "Statement": [ ... ] }.
  2. In each statement write Effect, Action and Resource.
  3. Give only what the task needs (least privilege).
  4. Use double quotes and commas correctly. Click Check answer.

Medium Subscribe an email

Why: Email subscribers must click the confirm link before they receive messages.

What to do: Subscribe ops@laturcoaching.in by email to arn:aws:sns:ap-south-1:123666135775:laturcoaching-alerts.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Delete a processed message

Why: If you do not delete it, the message comes back after the visibility timeout.

What to do: Delete the message with receipt handle stored in $RH from https://sqs.ap-south-1.amazonaws.com/123666135775/laturcoaching-orders.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Add a subscription filter policy

Why: A filter policy sends a subscriber only the messages it cares about.

What to do: Set the FilterPolicy of subscription arn:aws:sns:ap-south-1:123666135775:laturcoaching-alerts:4b1c-77 to {"type":["refund"]}.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Subscribe a queue to a topic

Why: Fan-out: one SNS message is copied to many SQS queues for different workers.

What to do: Subscribe queue arn:aws:sqs:ap-south-1:123666135775:laturcoaching-billing to arn:aws:sns:ap-south-1:123666135775:laturcoaching-alerts.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Attach a dead-letter queue

Why: After a few failed tries, bad messages move to a DLQ instead of blocking the queue.

What to do: Set the attributes in attrs.json (a RedrivePolicy) on https://sqs.ap-south-1.amazonaws.com/123666135775/laturcoaching-orders.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Revision, comparison and interview cards

Revise this lesson in a few minutes. Save the cards on your phone or download them as PNG files. The QR code on each card opens this lesson.

SNS publish. One publish, many subscribers. Email waits for confirmation. SQS needs a queue policy. SMS: E.164 phone number.
Revision card: SNS publish · Download PNG · Open card page
SNS filters. Publish with MessageAttributes. FilterPolicy on the subscription. String and numeric match. RawMessageDelivery drops the envelope.
Revision card: SNS filters · Download PNG · Open card page
SNS vs SQS. Pushes to many subscribers. / One consumer pulls.
Comparison: SNS vs SQS · Download PNG · Open card page
SNS to SQS not arriving?. Queue policy missing. Allow sns.amazonaws.com SendMessage. Check the filter policy too.
Interview card: SNS to SQS not arriving? · Download PNG · Open card page

More cards: Ravi Sir's Cards.