TerraformPilot

Terraform

AWS SNS Topics and Subscriptions with Terraform

Create AWS SNS topics and subscriptions with Terraform. Email, SQS, Lambda, and HTTP endpoints with encryption and access policies.

LLuca Berton1 min read

Quick Answer

#
resource "aws_sns_topic" "alerts" {
  name = "app-alerts"
}
 
resource "aws_sns_topic_subscription" "email" {
  topic_arn = aws_sns_topic.alerts.arn
  protocol  = "email"
  endpoint  = "ops@example.com"
}

SNS Topic with Encryption

#
resource "aws_sns_topic" "orders" {
  name              = "${var.project}-${var.environment}-orders"
  kms_master_key_id = "alias/aws/sns"
 
  tags = {
    Environment = var.environment
    Project     = var.project
  }
}

Subscription Types

#
# Email
resource "aws_sns_topic_subscription" "email" {
  topic_arn = aws_sns_topic.alerts.arn
  protocol  = "email"
  endpoint  = "team@example.com"
}
 
# SQS Queue
resource "aws_sns_topic_subscription" "sqs" {
  topic_arn = aws_sns_topic.orders.arn
  protocol  = "sqs"
  endpoint  = aws_sqs_queue.processor.arn
  raw_message_delivery = true
}
 
# Lambda
resource "aws_sns_topic_subscription" "lambda" {
  topic_arn = aws_sns_topic.orders.arn
  protocol  = "lambda"
  endpoint  = aws_lambda_function.processor.arn
}
 
resource "aws_lambda_permission" "sns" {
  statement_id  = "AllowSNS"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.processor.function_name
  principal     = "sns.amazonaws.com"
  source_arn    = aws_sns_topic.orders.arn
}
 
# HTTPS Webhook
resource "aws_sns_topic_subscription" "webhook" {
  topic_arn = aws_sns_topic.events.arn
  protocol  = "https"
  endpoint  = "https://api.example.com/webhooks/sns"
}

Message Filtering

#
resource "aws_sns_topic_subscription" "high_priority" {
  topic_arn = aws_sns_topic.orders.arn
  protocol  = "sqs"
  endpoint  = aws_sqs_queue.priority.arn
 
  filter_policy = jsonencode({
    priority = ["high", "critical"]
    event    = ["order.created", "order.failed"]
  })
}

SNS + SQS Fan-Out Pattern

#
resource "aws_sns_topic" "orders" {
  name = "orders"
}
 
# Queue 1: Order processing
resource "aws_sqs_queue" "process" {
  name = "order-process"
}
 
# Queue 2: Analytics
resource "aws_sqs_queue" "analytics" {
  name = "order-analytics"
}
 
# Subscribe both queues
resource "aws_sns_topic_subscription" "process" {
  topic_arn            = aws_sns_topic.orders.arn
  protocol             = "sqs"
  endpoint             = aws_sqs_queue.process.arn
  raw_message_delivery = true
}
 
resource "aws_sns_topic_subscription" "analytics" {
  topic_arn            = aws_sns_topic.orders.arn
  protocol             = "sqs"
  endpoint             = aws_sqs_queue.analytics.arn
  raw_message_delivery = true
}
 
# SQS policy to allow SNS
resource "aws_sqs_queue_policy" "process" {
  queue_url = aws_sqs_queue.process.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "sns.amazonaws.com" }
      Action    = "sqs:SendMessage"
      Resource  = aws_sqs_queue.process.arn
      Condition = {
        ArnEquals = { "aws:SourceArn" = aws_sns_topic.orders.arn }
      }
    }]
  })
}

Subscription Protocols

#
ProtocolEndpointUse Case
emailEmail addressAlerts, notifications
sqsSQS queue ARNAsync processing
lambdaLambda ARNEvent-driven compute
httpsHTTPS URLWebhooks
smsPhone numberCritical alerts
firehoseFirehose ARNData streaming
#

Conclusion

#

SNS is the backbone of event-driven AWS architectures. Use fan-out patterns with SQS for reliable processing, message filtering for routing, and KMS encryption for sensitive data. Always set raw_message_delivery = true for SQS subscriptions to avoid double-encoding.

#Terraform#AWS#SNS#Messaging#Infrastructure as Code

Share this article