AWS SNS (Simple Notification Service) - Complete Guide
Overview
Amazon Simple Notification Service (SNS) is a fully managed pub/sub messaging service that enables you to decouple microservices, distributed systems, and serverless applications. SNS provides topics for high-throughput, push-based, many-to-many messaging.
Table of Contents
- Core Concepts
- Key Features
- Architecture
- Use Cases
- Implementation Examples
- Best Practices
- Security
- Monitoring and Logging
- Cost Optimization
- Common Interview Questions
- Integration Patterns
- Troubleshooting
Core Concepts
Topics
- Publishers: Send messages to topics
- Subscribers: Receive messages from topics
- Topics: Logical access points for communication
- Messages: Data sent between publishers and subscribers
Message Types
- Standard Topics: Best-effort delivery, at-least-once delivery
- FIFO Topics: Exactly-once processing, ordered delivery
Subscription Types
- HTTP/HTTPS: Webhook endpoints
- Lambda: Serverless functions
- SQS: Queue integration
- Email/Email-JSON: Email notifications
- SMS: Mobile text messages
- Application: Mobile push notifications
Key Features
1. High Availability
- 99.9% availability SLA
- Multi-AZ deployment
- Automatic failover
2. Scalability
- No message ordering limits
- Automatic scaling
- Global deployment
3. Security
- IAM integration
- VPC endpoints
- Server-side encryption (SSE)
- Cross-account access
4. Message Filtering
- JSON path filtering
- Attribute-based filtering
- Message deduplication
Architecture
Basic Architecture
Publisher → Topic → Subscribers
↓ ↓ ↓
Lambda SNS Topic Lambda
EC2 SQS Queue
API Gateway HTTP/HTTPS
Advanced Architecture
Application → SNS Topic → Multiple Subscribers
↓ ↓ ↓
Event Message Filtering Lambda
Source Dead Letter Queue SQS
Monitoring CloudWatch HTTP
Use Cases
1. Event-Driven Architecture
import boto3
import json
# Publisher
sns = boto3.client('sns')
def publish_order_event(order_data):
topic_arn = 'arn:aws:sns:us-east-1:123456789012:order-events'
message = {
'order_id': order_data['id'],
'customer_id': order_data['customer_id'],
'total': order_data['total'],
'timestamp': order_data['timestamp']
}
response = sns.publish(
TopicArn=topic_arn,
Message=json.dumps(message),
MessageAttributes={
'event_type': {
'DataType': 'String',
'StringValue': 'order_created'
},
'priority': {
'DataType': 'String',
'StringValue': 'high'
}
}
)
return response['MessageId']
2. Microservices Communication
# Order Service
def create_order(order_data):
# Process order
order = process_order(order_data)
# Publish event
publish_order_event({
'order_id': order.id,
'status': 'created',
'items': order.items,
'total': order.total
})
return order
# Inventory Service (Subscriber)
def handle_order_created(event, context):
order_data = json.loads(event['Records'][0]['Sns']['Message'])
# Update inventory
for item in order_data['items']:
update_inventory(item['product_id'], item['quantity'])
# Publish inventory updated event
publish_inventory_event(order_data['order_id'])
3. Fan-out Pattern
# Single publisher, multiple subscribers
def publish_user_registration(user_data):
topic_arn = 'arn:aws:sns:us-east-1:123456789012:user-events'
message = {
'user_id': user_data['id'],
'email': user_data['email'],
'name': user_data['name'],
'timestamp': datetime.utcnow().isoformat()
}
# All subscribers receive this message
response = sns.publish(
TopicArn=topic_arn,
Message=json.dumps(message),
MessageAttributes={
'event_type': {
'DataType': 'String',
'StringValue': 'user_registered'
}
}
)
return response['MessageId']
# Subscribers:
# - Email Service: Send welcome email
# - Analytics Service: Track user registration
# - Notification Service: Send push notification
# - Database Service: Update user statistics
Implementation Examples
1. Creating Topics and Subscriptions
import boto3
from botocore.exceptions import ClientError
class SNSService:
def __init__(self):
self.sns = boto3.client('sns')
def create_topic(self, topic_name, tags=None):
"""Create an SNS topic"""
try:
response = self.sns.create_topic(
Name=topic_name,
Tags=tags or []
)
return response['TopicArn']
except ClientError as e:
print(f"Error creating topic: {e}")
return None
def create_subscription(self, topic_arn, protocol, endpoint, attributes=None):
"""Create a subscription"""
try:
response = self.sns.subscribe(
TopicArn=topic_arn,
Protocol=protocol,
Endpoint=endpoint,
Attributes=attributes or {}
)
return response['SubscriptionArn']
except ClientError as e:
print(f"Error creating subscription: {e}")
return None
def publish_message(self, topic_arn, message, subject=None, attributes=None):
"""Publish a message to a topic"""
try:
response = self.sns.publish(
TopicArn=topic_arn,
Message=message,
Subject=subject,
MessageAttributes=attributes or {}
)
return response['MessageId']
except ClientError as e:
print(f"Error publishing message: {e}")
return None
# Usage
sns_service = SNSService()
# Create topic
topic_arn = sns_service.create_topic('order-events')
# Create subscriptions
lambda_subscription = sns_service.create_subscription(
topic_arn, 'lambda', 'arn:aws:lambda:us-east-1:123456789012:function:process-order'
)
sqs_subscription = sns_service.create_subscription(
topic_arn, 'sqs', 'arn:aws:sqs:us-east-1:123456789012:order-queue'
)
# Publish message
message_id = sns_service.publish_message(
topic_arn,
'{"order_id": "123", "status": "created"}',
'Order Created',
{
'event_type': {
'DataType': 'String',
'StringValue': 'order_created'
}
}
)
2. Message Filtering
# Create subscription with filter policy
def create_filtered_subscription(topic_arn, protocol, endpoint, filter_policy):
"""Create subscription with message filtering"""
try:
response = sns.subscribe(
TopicArn=topic_arn,
Protocol=protocol,
Endpoint=endpoint,
Attributes={
'FilterPolicy': json.dumps(filter_policy)
}
)
return response['SubscriptionArn']
except ClientError as e:
print(f"Error creating filtered subscription: {e}")
return None
# Filter policy examples
high_priority_filter = {
"priority": ["high", "critical"]
}
order_filter = {
"event_type": ["order_created", "order_updated"],
"amount": [{"numeric": [">", 100]}]
}
# Create filtered subscriptions
high_priority_subscription = create_filtered_subscription(
topic_arn,
'lambda',
'arn:aws:lambda:us-east-1:123456789012:function:high-priority-handler',
high_priority_filter
)
order_subscription = create_filtered_subscription(
topic_arn,
'sqs',
'arn:aws:sqs:us-east-1:123456789012:order-queue',
order_filter
)
3. Dead Letter Queue Integration
def create_subscription_with_dlq(topic_arn, protocol, endpoint, dlq_arn):
"""Create subscription with dead letter queue"""
try:
response = sns.subscribe(
TopicArn=topic_arn,
Protocol=protocol,
Endpoint=endpoint,
Attributes={
'RedrivePolicy': json.dumps({
'deadLetterTargetArn': dlq_arn
})
}
)
return response['SubscriptionArn']
except ClientError as e:
print(f"Error creating subscription with DLQ: {e}")
return None
# Create SQS queue for dead letters
sqs = boto3.client('sqs')
dlq_response = sqs.create_queue(
QueueName='sns-dlq',
Attributes={
'MessageRetentionPeriod': '1209600' # 14 days
}
)
dlq_arn = dlq_response['QueueArn']
# Create subscription with DLQ
subscription_arn = create_subscription_with_dlq(
topic_arn,
'lambda',
'arn:aws:lambda:us-east-1:123456789012:function:process-message',
dlq_arn
)
4. FIFO Topics
def create_fifo_topic(topic_name, content_based_deduplication=True):
"""Create FIFO topic with content-based deduplication"""
try:
response = sns.create_topic(
Name=f"{topic_name}.fifo",
Attributes={
'FifoTopic': 'true',
'ContentBasedDeduplication': str(content_based_deduplication).lower()
}
)
return response['TopicArn']
except ClientError as e:
print(f"Error creating FIFO topic: {e}")
return None
def publish_fifo_message(topic_arn, message, group_id, deduplication_id=None):
"""Publish message to FIFO topic"""
try:
publish_kwargs = {
'TopicArn': topic_arn,
'Message': message,
'MessageGroupId': group_id
}
if deduplication_id:
publish_kwargs['MessageDeduplicationId'] = deduplication_id
response = sns.publish(**publish_kwargs)
return response['MessageId']
except ClientError as e:
print(f"Error publishing FIFO message: {e}")
return None
# Usage
fifo_topic_arn = create_fifo_topic('order-events')
# Publish messages with same group ID for ordering
for i in range(5):
message_id = publish_fifo_message(
fifo_topic_arn,
f'{{"order_id": "123", "step": {i}}}',
'order-123' # Same group ID ensures ordering
)
Best Practices
1. Message Design
# Good: Structured message with metadata
def publish_well_structured_message(topic_arn, event_data):
message = {
'metadata': {
'event_id': str(uuid.uuid4()),
'timestamp': datetime.utcnow().isoformat(),
'version': '1.0',
'source': 'order-service'
},
'data': event_data,
'correlation_id': get_correlation_id()
}
attributes = {
'event_type': {
'DataType': 'String',
'StringValue': event_data['type']
},
'priority': {
'DataType': 'String',
'StringValue': event_data.get('priority', 'normal')
}
}
return sns.publish(
TopicArn=topic_arn,
Message=json.dumps(message),
MessageAttributes=attributes
)
# Bad: Simple string message
def publish_simple_message(topic_arn, message):
return sns.publish(
TopicArn=topic_arn,
Message=message # No structure, no metadata
)
2. Error Handling
def publish_with_retry(topic_arn, message, max_retries=3):
"""Publish message with exponential backoff retry"""
for attempt in range(max_retries):
try:
response = sns.publish(
TopicArn=topic_arn,
Message=message
)
return response['MessageId']
except ClientError as e:
if e.response['Error']['Code'] == 'ThrottlingException':
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # Exponential backoff
continue
raise e
return None
3. Monitoring and Alerting
import boto3
from datetime import datetime, timedelta
def monitor_sns_metrics(topic_arn, hours=24):
"""Monitor SNS metrics for a topic"""
cloudwatch = boto3.client('cloudwatch')
end_time = datetime.utcnow()
start_time = end_time - timedelta(hours=hours)
# Get delivery success rate
success_metric = cloudwatch.get_metric_statistics(
Namespace='AWS/SNS',
MetricName='NumberOfNotificationsDelivered',
Dimensions=[
{
'Name': 'TopicName',
'Value': topic_arn.split(':')[-1]
}
],
StartTime=start_time,
EndTime=end_time,
Period=3600, # 1 hour
Statistics=['Sum']
)
# Get failure rate
failure_metric = cloudwatch.get_metric_statistics(
Namespace='AWS/SNS',
MetricName='NumberOfNotificationsFailed',
Dimensions=[
{
'Name': 'TopicName',
'Value': topic_arn.split(':')[-1]
}
],
StartTime=start_time,
EndTime=end_time,
Period=3600,
Statistics=['Sum']
)
return {
'success_count': sum(point['Sum'] for point in success_metric['Datapoints']),
'failure_count': sum(point['Sum'] for point in failure_metric['Datapoints'])
}
Security
1. IAM Policies
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:Publish",
"sns:GetTopicAttributes"
],
"Resource": "arn:aws:sns:us-east-1:123456789012:order-events"
},
{
"Effect": "Allow",
"Action": [
"sns:Subscribe",
"sns:Receive"
],
"Resource": "arn:aws:sns:us-east-1:123456789012:order-events"
}
]
}
2. VPC Endpoints
import boto3
# Configure SNS client with VPC endpoint
sns = boto3.client(
'sns',
endpoint_url='https://sns.us-east-1.amazonaws.com',
region_name='us-east-1'
)
3. Server-Side Encryption
def create_encrypted_topic(topic_name, kms_key_id):
"""Create topic with server-side encryption"""
try:
response = sns.create_topic(
Name=topic_name,
Attributes={
'KmsMasterKeyId': kms_key_id
}
)
return response['TopicArn']
except ClientError as e:
print(f"Error creating encrypted topic: {e}")
return None
Monitoring and Logging
1. CloudWatch Metrics
def get_sns_metrics(topic_arn):
"""Get key SNS metrics"""
cloudwatch = boto3.client('cloudwatch')
metrics = {
'delivery_success': 'NumberOfNotificationsDelivered',
'delivery_failure': 'NumberOfNotificationsFailed',
'publish_success': 'NumberOfMessagesPublished',
'publish_failure': 'NumberOfNotificationsFailed'
}
results = {}
for metric_name, cloudwatch_metric in metrics.items():
response = cloudwatch.get_metric_statistics(
Namespace='AWS/SNS',
MetricName=cloudwatch_metric,
Dimensions=[
{
'Name': 'TopicName',
'Value': topic_arn.split(':')[-1]
}
],
StartTime=datetime.utcnow() - timedelta(hours=1),
EndTime=datetime.utcnow(),
Period=300,
Statistics=['Sum']
)
results[metric_name] = response['Datapoints']
return results
2. CloudTrail Logging
def enable_cloudtrail_logging(trail_name, s3_bucket):
"""Enable CloudTrail logging for SNS"""
cloudtrail = boto3.client('cloudtrail')
try:
response = cloudtrail.create_trail(
Name=trail_name,
S3BucketName=s3_bucket,
IncludeGlobalServiceEvents=True,
IsMultiRegionTrail=True
)
# Start logging
cloudtrail.start_logging(Name=trail_name)
return response['TrailARN']
except ClientError as e:
print(f"Error creating CloudTrail: {e}")
return None
Cost Optimization
1. Message Batching
def batch_publish_messages(topic_arn, messages, batch_size=10):
"""Publish messages in batches to reduce API calls"""
message_ids = []
for i in range(0, len(messages), batch_size):
batch = messages[i:i + batch_size]
# Publish batch
for message in batch:
response = sns.publish(
TopicArn=topic_arn,
Message=json.dumps(message)
)
message_ids.append(response['MessageId'])
return message_ids
2. Subscription Management
def cleanup_unused_subscriptions():
"""Remove unused subscriptions to reduce costs"""
sns = boto3.client('sns')
# List all subscriptions
paginator = sns.get_paginator('list_subscriptions')
for page in paginator.paginate():
for subscription in page['Subscriptions']:
# Check if subscription is confirmed and active
if (subscription['SubscriptionArn'] != 'PendingConfirmation' and
subscription['Protocol'] in ['http', 'https']):
# Check if endpoint is responding
if not is_endpoint_healthy(subscription['Endpoint']):
print(f"Removing unhealthy subscription: {subscription['SubscriptionArn']}")
sns.unsubscribe(SubscriptionArn=subscription['SubscriptionArn'])
Common Interview Questions
1. Basic Questions
Q: What is the difference between SNS and SQS?
- SNS: Pub/sub messaging, one-to-many, push-based
- SQS: Queue messaging, one-to-one, pull-based
- SNS: No message persistence, immediate delivery
- SQS: Message persistence, consumer pulls messages
Q: What are the delivery guarantees of SNS?
- Standard Topics: At-least-once delivery, best-effort ordering
- FIFO Topics: Exactly-once delivery, strict ordering
- HTTP/HTTPS: At-least-once delivery with retries
- Lambda: At-least-once delivery with automatic retries
Q: How does message filtering work in SNS?
# Filter policy example
filter_policy = {
"event_type": ["order_created", "order_updated"],
"priority": ["high", "critical"],
"amount": [{"numeric": [">", 100]}]
}
# Only messages matching ALL conditions are delivered
2. Advanced Questions
Q: How would you implement idempotency with SNS?
def publish_idempotent_message(topic_arn, message, deduplication_id):
"""Publish message with deduplication"""
try:
response = sns.publish(
TopicArn=topic_arn,
Message=json.dumps(message),
MessageAttributes={
'deduplication_id': {
'DataType': 'String',
'StringValue': deduplication_id
}
}
)
return response['MessageId']
except ClientError as e:
if e.response['Error']['Code'] == 'DuplicateMessage':
# Message already published
return None
raise e
Q: How do you handle message ordering in SNS?
# Use FIFO topics for strict ordering
def create_fifo_topic_with_ordering(topic_name):
"""Create FIFO topic with message ordering"""
response = sns.create_topic(
Name=f"{topic_name}.fifo",
Attributes={
'FifoTopic': 'true',
'ContentBasedDeduplication': 'true'
}
)
return response['TopicArn']
def publish_ordered_message(topic_arn, message, group_id):
"""Publish message with ordering"""
return sns.publish(
TopicArn=topic_arn,
Message=json.dumps(message),
MessageGroupId=group_id # Messages with same group ID are ordered
)
Q: How would you implement a dead letter queue for SNS?
def create_subscription_with_dlq(topic_arn, protocol, endpoint):
"""Create subscription with dead letter queue"""
# Create SQS queue for dead letters
sqs = boto3.client('sqs')
dlq_response = sqs.create_queue(QueueName='sns-dlq')
dlq_arn = dlq_response['QueueArn']
# Create subscription with DLQ
response = sns.subscribe(
TopicArn=topic_arn,
Protocol=protocol,
Endpoint=endpoint,
Attributes={
'RedrivePolicy': json.dumps({
'deadLetterTargetArn': dlq_arn,
'maxReceiveCount': '3'
})
}
)
return response['SubscriptionArn']
3. Architecture Questions
Q: How would you design a notification system using SNS?
class NotificationSystem:
def __init__(self):
self.sns = boto3.client('sns')
self.topics = {
'user_events': 'arn:aws:sns:us-east-1:123456789012:user-events',
'order_events': 'arn:aws:sns:us-east-1:123456789012:order-events',
'system_alerts': 'arn:aws:sns:us-east-1:123456789012:system-alerts'
}
def send_user_notification(self, user_id, message, notification_type):
"""Send user notification via multiple channels"""
event_data = {
'user_id': user_id,
'message': message,
'type': notification_type,
'timestamp': datetime.utcnow().isoformat()
}
# Publish to user events topic
# Subscribers: Email service, SMS service, Push notification service
return self.sns.publish(
TopicArn=self.topics['user_events'],
Message=json.dumps(event_data),
MessageAttributes={
'notification_type': {
'DataType': 'String',
'StringValue': notification_type
}
}
)
def send_system_alert(self, alert_level, message, service):
"""Send system alert"""
alert_data = {
'level': alert_level,
'message': message,
'service': service,
'timestamp': datetime.utcnow().isoformat()
}
return self.sns.publish(
TopicArn=self.topics['system_alerts'],
Message=json.dumps(alert_data),
MessageAttributes={
'alert_level': {
'DataType': 'String',
'StringValue': alert_level
}
}
)
Integration Patterns
1. SNS + Lambda Pattern
# Lambda function triggered by SNS
def lambda_handler(event, context):
"""Process SNS messages in Lambda"""
for record in event['Records']:
sns_message = record['Sns']
message_body = json.loads(sns_message['Message'])
# Process message based on type
if message_body.get('type') == 'order_created':
process_order_created(message_body)
elif message_body.get('type') == 'user_registered':
process_user_registration(message_body)
else:
print(f"Unknown message type: {message_body.get('type')}")
def process_order_created(order_data):
"""Process order created event"""
# Update inventory
# Send confirmation email
# Update analytics
pass
def process_user_registration(user_data):
"""Process user registration event"""
# Send welcome email
# Create user profile
# Update metrics
pass
2. SNS + SQS Pattern
# SNS publishes to SQS queue
def setup_sns_sqs_integration(topic_arn, queue_arn):
"""Set up SNS to SQS integration"""
# Create subscription
response = sns.subscribe(
TopicArn=topic_arn,
Protocol='sqs',
Endpoint=queue_arn
)
# Configure SQS queue policy to allow SNS
sqs_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "sns.amazonaws.com"
},
"Action": "sqs:SendMessage",
"Resource": queue_arn,
"Condition": {
"ArnEquals": {
"aws:SourceArn": topic_arn
}
}
}
]
}
sqs = boto3.client('sqs')
sqs.set_queue_attributes(
QueueUrl=queue_arn.replace(':sqs:', ':sqs:').replace('arn:aws:sqs:', ''),
Attributes={
'Policy': json.dumps(sqs_policy)
}
)
return response['SubscriptionArn']
3. Fan-out Pattern
# Single publisher, multiple subscribers
def implement_fan_out_pattern():
"""Implement fan-out pattern with SNS"""
topic_arn = 'arn:aws:sns:us-east-1:123456789012:user-events'
# Multiple subscribers
subscribers = [
{
'protocol': 'lambda',
'endpoint': 'arn:aws:lambda:us-east-1:123456789012:function:email-service'
},
{
'protocol': 'lambda',
'endpoint': 'arn:aws:lambda:us-east-1:123456789012:function:analytics-service'
},
{
'protocol': 'sqs',
'endpoint': 'arn:aws:sqs:us-east-1:123456789012:notification-queue'
},
{
'protocol': 'http',
'endpoint': 'https://api.example.com/webhooks/user-events'
}
]
# Create subscriptions
for subscriber in subscribers:
sns.subscribe(
TopicArn=topic_arn,
Protocol=subscriber['protocol'],
Endpoint=subscriber['endpoint']
)
# Publish message (all subscribers receive it)
return sns.publish(
TopicArn=topic_arn,
Message=json.dumps({
'user_id': '123',
'event': 'user_registered',
'timestamp': datetime.utcnow().isoformat()
})
)
Troubleshooting
1. Common Issues
def troubleshoot_sns_issues():
"""Common SNS troubleshooting steps"""
# 1. Check topic permissions
def check_topic_permissions(topic_arn):
try:
response = sns.get_topic_attributes(TopicArn=topic_arn)
return response['Attributes']
except ClientError as e:
print(f"Permission error: {e}")
return None
# 2. Check subscription status
def check_subscription_status(subscription_arn):
try:
response = sns.get_subscription_attributes(
SubscriptionArn=subscription_arn
)
return response['Attributes']
except ClientError as e:
print(f"Subscription error: {e}")
return None
# 3. Test message delivery
def test_message_delivery(topic_arn):
try:
response = sns.publish(
TopicArn=topic_arn,
Message='Test message',
Subject='Test'
)
print(f"Test message sent: {response['MessageId']}")
return response['MessageId']
except ClientError as e:
print(f"Publish error: {e}")
return None
# 4. Check CloudWatch metrics
def check_delivery_metrics(topic_arn):
cloudwatch = boto3.client('cloudwatch')
response = cloudwatch.get_metric_statistics(
Namespace='AWS/SNS',
MetricName='NumberOfNotificationsFailed',
Dimensions=[
{
'Name': 'TopicName',
'Value': topic_arn.split(':')[-1]
}
],
StartTime=datetime.utcnow() - timedelta(hours=1),
EndTime=datetime.utcnow(),
Period=300,
Statistics=['Sum']
)
return response['Datapoints']
2. Debugging Tools
def enable_sns_logging(topic_arn):
"""Enable detailed logging for SNS topic"""
try:
response = sns.set_topic_attributes(
TopicArn=topic_arn,
AttributeName='DeliveryPolicy',
AttributeValue=json.dumps({
'healthyRetryPolicy': {
'numRetries': 3,
'minDelayTarget': 20,
'maxDelayTarget': 20,
'numMaxDelayRetries': 0,
'numNoDelayRetries': 0,
'backoffFunction': 'linear'
},
'sicklyRetryPolicy': {
'numRetries': 3,
'minDelayTarget': 20,
'maxDelayTarget': 20,
'numMaxDelayRetries': 0,
'numNoDelayRetries': 0,
'backoffFunction': 'linear'
},
'throttlePolicy': {
'maxReceivesPerSecond': 10
}
})
)
return response
except ClientError as e:
print(f"Error enabling logging: {e}")
return None
Summary
AWS SNS is a powerful messaging service that enables:
- Decoupled Communication: Publishers and subscribers are independent
- Scalable Architecture: Automatic scaling with no message limits
- Multiple Protocols: Support for HTTP, Lambda, SQS, Email, SMS
- Message Filtering: Attribute-based filtering for selective delivery
- High Availability: 99.9% SLA with multi-AZ deployment
- Security: IAM integration, VPC endpoints, encryption
Key use cases include:
- Event-driven architectures
- Microservices communication
- Notification systems
- Fan-out patterns
- System monitoring and alerting
Best practices include:
- Proper message structure and metadata
- Error handling and retry logic
- Monitoring and alerting
- Security configuration
- Cost optimization through batching
Interview angle
- “SNS or SQS?” - SNS is push, one-to-many, fan-out: every subscriber gets a copy, and there is no retention if nobody is listening. SQS is pull, one consumer per message, with durable retention. The standard answer to “both” is the fan-out pattern: SNS topic with SQS queues subscribed to it, so each consumer gets its own durable buffer.
- “Why put a queue between SNS and a consumer?” - retries and backpressure. A direct SNS-to-Lambda or SNS-to-HTTP subscription retries on a fixed schedule and then drops; an SQS queue holds the message until the consumer is healthy and gives you a dead-letter queue.
- “FIFO or standard?” - standard for almost everything: higher throughput, at-least-once delivery, no ordering guarantee. FIFO when strict ordering within a group genuinely matters, at much lower throughput. Both mean you still design consumers to be idempotent.
- “How do you filter?” - subscription filter policies on message attributes, so a subscriber only receives what it cares about. Filtering at the topic is cheaper than delivering everything and discarding in the consumer.