SNS is the Kafka of the AWS world, but it’s not a message queue.

Let’s watch SNS fan out events to multiple services with a simple example.

Imagine you have a new user signup event. You want to trigger multiple downstream actions: send a welcome email, update a user profile in a database, and push a notification to a mobile app. SNS is perfect for this.

First, we create an SNS topic. This is the central hub where our signup event will be published.

aws sns create-topic --name user-signup-events

This returns a TopicArn. Let’s say it’s arn:aws:sns:us-east-1:123456789012:user-signup-events.

Next, we need subscribers to this topic. Each subscriber will represent one of our downstream services. For demonstration, we’ll use Lambda functions, but these could also be SQS queues, HTTP/S endpoints, or even other SNS topics.

Let’s create three Lambda functions: send-welcome-email, update-user-profile, and push-mobile-notification.

Now, we subscribe these Lambda functions to our SNS topic.

aws sns subscribe \
    --topic-arn arn:aws:sns:us-east-1:123456789012:user-signup-events \
    --protocol lambda \
    --notification-endpoint arn:aws:lambda:us-east-1:123456789012:function:send-welcome-email

aws sns subscribe \
    --topic-arn arn:aws:sns:us-east-1:123456789012:user-signup-events \
    --protocol lambda \
    --notification-endpoint arn:aws:lambda:us-east-1:123456789012:function:update-user-profile

aws sns subscribe \
    --topic-arn arn:aws:sns:us-east-1:123456789012:user-signup-events \
    --protocol lambda \
    --notification-endpoint arn:aws:lambda:us-east-1:123456789012:function:push-mobile-notification

You’ll get back SubscriptionArns for each. Crucially, you also need to grant SNS permission to invoke your Lambda functions. This is done by adding a resource-based policy to each Lambda function.

For send-welcome-email:

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "allow-sns-to-invoke-lambda",
      "Effect": "Allow",
      "Principal": {
        "Service": "sns.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:send-welcome-email",
      "Condition": {
        "ArnLike": {
          "aws:SourceArn": "arn:aws:sns:us-east-1:123456789012:user-signup-events"
        }
      }
    }
  ]
}

Repeat this policy for update-user-profile and push-mobile-notification, adjusting the Resource ARN accordingly.

Now, when a new user signs up, your application publishes a message to the user-signup-events topic.

aws sns publish \
    --topic-arn arn:aws:sns:us-east-1:123456789012:user-signup-events \
    --message '{"userId": "user-123", "email": "test@example.com", "timestamp": "2023-10-27T10:00:00Z"}' \
    --subject "New User Signup"

SNS takes this single message and, like a watering can, distributes an identical copy to each subscribed Lambda function. Each Lambda function then executes independently with the same message payload.

This is the core of the fan-out pattern. One event, multiple independent consumers. The beauty is that you can add or remove subscribers without affecting the publisher or other subscribers. If you later decide to add a new service to log all signups, you just create a new Lambda and subscribe it to the topic.

The MessageAttributes feature is key to enabling intelligent routing or filtering at the subscriber level. For example, you could add an attribute like "eventType": "signup" to the published message. Then, in the Lambda subscription filter policy, you could specify that this Lambda only processes messages where eventType is signup. This allows a single topic to carry many different types of events, with each subscriber only reacting to the ones it cares about. Without filter policies, every subscriber receives every message published to the topic, regardless of its content.

The next step in managing event-driven architectures often involves ensuring reliable delivery and handling of these fan-out events, which leads to exploring dead-letter queues for SNS subscriptions.

Want structured learning?

Take the full Aws course →