Jonatan Matajonmatum.com
conceptsnotesexperimentsessays
© 2026 Jonatan Mata. All rights reserved.v2.1.1
Concepts

AWS SNS

AWS pub/sub messaging service that distributes messages to multiple subscribers simultaneously, enabling fan-out patterns and notifications at scale.

evergreen#aws#sns#messaging#pub-sub#notifications#serverless

What it is

Amazon SNS (Simple Notification Service) is a fully managed pub/sub messaging service that enables sending messages from publishers to multiple subscribers simultaneously. Unlike traditional queue systems, SNS implements the fan-out pattern where a message is distributed to all endpoints subscribed to the topic.

The service operates with topics as logical communication points. Publishers send messages to a topic, and SNS handles delivering copies of the message to all configured subscribers. This architecture completely decouples producers from consumers, enabling independent scalability and system evolution without affecting other components.

SNS supports both standard and FIFO (First-In-First-Out) topics. Standard topics offer virtually unlimited throughput with at-least-once delivery, while FIFO topics guarantee strict ordering and exactly-once delivery with a limit of 300 messages per second per message group (up to 3,000 msg/s per topic).

Subscriber types and use cases

SNS can deliver messages to multiple endpoint types:

Native AWS services:

  • AWS Lambda: Serverless event processing
  • AWS SQS: Reliable buffering and asynchronous processing
  • Kinesis Data Firehose: Data streaming to analytical stores
  • EventBridge: Complex event routing

External endpoints:

  • HTTP/HTTPS: Webhooks to external systems
  • Email/SMS: Direct user notifications
  • Mobile push: Push notifications to mobile applications
  • Platform endpoints: Integration with third-party services

Message filtering with attribute policies

SNS enables granular message filtering using message attributes and filter policies. Each subscriber can define a JSON policy specifying which messages it should receive:

{
  "event_type": ["order_created", "order_updated"],
  "region": ["us-east-1", "eu-west-1"],
  "amount": [{"numeric": [">", 100]}],
  "customer_tier": ["premium", "enterprise"]
}

This functionality eliminates the need to process and discard irrelevant messages in the consumer, reducing costs and latency. Filters support exact matches, numeric ranges, string prefixes, and allowed value lists.

Complete example: SNS + SQS Fan-out with Terraform

# Main SNS topic
resource "aws_sns_topic" "order_events" {
  name         = "order-events"
  display_name = "Order Processing Events"
  
  # Delivery configuration
  delivery_policy = jsonencode({
    "http" = {
      "defaultHealthyRetryPolicy" = {
        "minDelayTarget"     = 20
        "maxDelayTarget"     = 20
        "numRetries"         = 3
        "numMaxDelayRetries" = 0
        "numMinDelayRetries" = 0
        "numNoDelayRetries"  = 0
        "backoffFunction"    = "linear"
      }
    }
  })
}
 
# SQS for inventory processing
resource "aws_sqs_queue" "inventory_processing" {
  name                       = "inventory-processing"
  visibility_timeout_seconds = 300
  message_retention_seconds  = 1209600
  
  # Dead letter queue for failed messages
  redrive_policy = jsonencode({
    deadLetterTargetArn = aws_sqs_queue.inventory_dlq.arn
    maxReceiveCount     = 3
  })
}
 
resource "aws_sqs_queue" "inventory_dlq" {
  name = "inventory-processing-dlq"
}
 
# SQS for user notifications
resource "aws_sqs_queue" "user_notifications" {
  name                       = "user-notifications"
  visibility_timeout_seconds = 60
  
  redrive_policy = jsonencode({
    deadLetterTargetArn = aws_sqs_queue.notifications_dlq.arn
    maxReceiveCount     = 5
  })
}
 
resource "aws_sqs_queue" "notifications_dlq" {
  name = "user-notifications-dlq"
}
 
# Inventory subscription with filtering
resource "aws_sns_topic_subscription" "inventory_subscription" {
  topic_arn = aws_sns_topic.order_events.arn
  protocol  = "sqs"
  endpoint  = aws_sqs_queue.inventory_processing.arn
  
  # Only order creation and cancellation events
  filter_policy = jsonencode({
    event_type = ["order_created", "order_cancelled"]
    product_category = ["electronics", "books"]
  })
}
 
# Notifications subscription with different filtering
resource "aws_sns_topic_subscription" "notifications_subscription" {
  topic_arn = aws_sns_topic.order_events.arn
  protocol  = "sqs"
  endpoint  = aws_sqs_queue.user_notifications.arn
  
  # Only events requiring user notification
  filter_policy = jsonencode({
    event_type = ["order_created", "order_shipped", "order_delivered"]
    notification_required = ["true"]
  })
}
 
# Permissions for SNS to write to SQS
resource "aws_sqs_queue_policy" "inventory_policy" {
  queue_url = aws_sqs_queue.inventory_processing.id
  
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = {
        Service = "sns.amazonaws.com"
      }
      Action   = "sqs:SendMessage"
      Resource = aws_sqs_queue.inventory_processing.arn
      Condition = {
        ArnEquals = {
          "aws:SourceArn" = aws_sns_topic.order_events.arn
        }
      }
    }]
  })
}
 
resource "aws_sqs_queue_policy" "notifications_policy" {
  queue_url = aws_sqs_queue.user_notifications.id
  
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = {
        Service = "sns.amazonaws.com"
      }
      Action   = "sqs:SendMessage"
      Resource = aws_sqs_queue.user_notifications.arn
      Condition = {
        ArnEquals = {
          "aws:SourceArn" = aws_sns_topic.order_events.arn
        }
      }
    }]
  })
}

FIFO topics and ordering guarantees

SNS FIFO topics guarantee strict ordering and exactly-once delivery using message group IDs and deduplication IDs:

import boto3
import json
from datetime import datetime
 
sns = boto3.client('sns')
 
# Publish FIFO message with grouping
response = sns.publish(
    TopicArn='arn:aws:sns:us-east-1:123456789012:order-events.fifo',
    Message=json.dumps({
        'order_id': 'ord_12345',
        'event_type': 'order_created',
        'timestamp': datetime.utcnow().isoformat(),
        'customer_id': 'cust_67890'
    }),
    MessageGroupId='customer_67890',  # Group by customer
    MessageDeduplicationId='ord_12345_created',  # Prevent duplicates
    MessageAttributes={
        'event_type': {
            'DataType': 'String',
            'StringValue': 'order_created'
        },
        'customer_tier': {
            'DataType': 'String', 
            'StringValue': 'premium'
        }
    }
)

Retry and delivery policies

SNS implements configurable retry policies per endpoint type:

EndpointTotal retriesDurationConfiguration
Lambda/SQS100,015~23 daysAutomatic (exponential backoff)
HTTP/HTTPS3 (default)CustomizableConfigurable delivery policy
Email/SMS/Push50~6 hoursFixed (exponential backoff)

For HTTP endpoints, you can configure a custom delivery policy that defines retry behavior, including minimum and maximum delays, backoff function, and number of attempts. AWS managed endpoints (Lambda, SQS) have aggressive retries with exponential backoff that can extend for weeks.

Cross-account subscriptions

SNS enables subscriptions across different AWS accounts, enabling multi-tenant and organizational architectures:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::ACCOUNT-B:root"
    },
    "Action": "sns:Subscribe",
    "Resource": "arn:aws:sns:us-east-1:ACCOUNT-A:shared-events",
    "Condition": {
      "StringEquals": {
        "sns:Protocol": ["sqs", "lambda"]
      }
    }
  }]
}

Monitoring and observability

SNS integrates natively with CloudWatch for observability:

Key metrics:

  • NumberOfMessagesPublished: Messages published to topic
  • NumberOfNotificationsDelivered: Successful deliveries per endpoint
  • NumberOfNotificationsFailed: Delivery failures
  • PublishSize: Average message size

Suggested alarms (adjust per use case):

  • Failure rate above acceptable thresholds for the service
  • Delivery latency outside expected ranges
  • Message volume with significant deviations

Why it matters

SNS is fundamental in modern event-driven architectures because it solves the coupling problem between services. In distributed systems, direct coupling between components creates fragile dependencies that limit scalability and increase operational complexity.

With SNS, an order service can publish events without knowing which systems consume them. Inventory, billing, notifications, and analytics can subscribe independently. This enables independent service evolution, decoupled deployment, and improved fault tolerance.

The SNS + SQS combination is especially powerful because it combines SNS's immediate distribution with SQS's durability and controlled processing. Teams can process events at their own pace without losing messages, implement backpressure, and handle traffic spikes resiliently.

For system architects, SNS represents the difference between coupled monolithic systems and distributed architectures that scale. It's the infrastructure that enables patterns like Event Sourcing, CQRS, and truly decoupled microservices.

References

  • Amazon SNS Developer Guide — AWS, 2024. Complete official service documentation.
  • SNS Message Filtering — AWS, 2024. Detailed guide for attribute-based filtering.
  • SNS FIFO Topics — AWS, 2024. Implementation of topics with guaranteed ordering.
  • Event-Driven Architecture — AWS, 2024. Architectural guides and best practices.
  • Best Practices for Amazon SNS SMS Messaging — AWS, 2024. SMS messaging recommendations.
  • Serverless Land — AWS Serverless Land, 2024. SNS integration patterns with other services.

Related content

  • Serverless

    Cloud computing model where the provider manages infrastructure automatically, allowing code execution without provisioning or managing servers, paying only for actual usage.

  • AWS SQS

    AWS fully managed message queue service that decouples distributed application components, guaranteeing message delivery with unlimited scalability.

  • Event-Driven Architecture

    Architectural pattern where components communicate through asynchronous events, enabling decoupled, scalable, and reactive systems.

  • AWS Lambda

    AWS serverless compute service that runs code in response to events without provisioning or managing servers, automatically scaling from zero to thousands of concurrent executions.

  • Observability

    Ability to understand a system's internal state from its external outputs: logs, metrics, and traces, enabling problem diagnosis without direct system access.

  • From Prototype to Production: A Serverless Second Brain on AWS

    Architecture design for scaling a personal second brain to a production system with AWS serverless — from the current prototype to specialized use cases in legal, research, and community building.

  • Terraform AWS Serverless Modules

    Collection of 13 Terraform modules published on the Terraform Registry for deploying serverless architectures on AWS, with 12 examples covering basic ECS to full-stack CRUD with DynamoDB and AgentCore with MCP.

  • Serverless Second Brain

    Production-ready serverless backend for a personal knowledge graph — DynamoDB, Lambda, Bedrock, MCP, Step Functions. The implementation of the architecture described in the 'From Prototype to Production' essay.

Concepts