DEV Community

Cover image for 12.Integrate SNS with SQS for Messaging Using Terraform
Thu Kha Kyawe
Thu Kha Kyawe

Posted on

12.Integrate SNS with SQS for Messaging Using Terraform

Lab Information

The Nautilus DevOps team is implementing a messaging system in AWS. They want to create an SNS topic and an SQS queue. The team needs to subscribe the SQS queue to the SNS topic so that any messages sent to the SNS topic will be delivered to the SQS queue.

Create an SNS topic named devops-sns-topic.

Create an SQS queue named devops-sqs-queue.

Subscribe the SQS queue to the SNS topic.

Use the main.tf file (do not create a separate .tf file) to provision the SNS topic and SQS queue.

Create the outputs.tf file, and use the following:

    The ARN of the SNS topic using the output variable kke_sns_topic_arn.

    The URL of the SQS queue using the output variable kke_sqs_queue_url.
Enter fullscreen mode Exit fullscreen mode

Lab Solutions

1️⃣ main.tf

# SNS Topic
resource "aws_sns_topic" "devops_sns_topic" {
  name = "devops-sns-topic"
}

# SQS Queue
resource "aws_sqs_queue" "devops_sqs_queue" {
  name = "devops-sqs-queue"
}

# Allow SNS to send messages to SQS
resource "aws_sqs_queue_policy" "sqs_policy" {
  queue_url = aws_sqs_queue.devops_sqs_queue.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = "*"
      Action = "sqs:SendMessage"
      Resource = aws_sqs_queue.devops_sqs_queue.arn
      Condition = {
        ArnEquals = {
          "aws:SourceArn" = aws_sns_topic.devops_sns_topic.arn
        }
      }
    }]
  })
}

# SNS Subscription (SNS → SQS)
resource "aws_sns_topic_subscription" "sns_to_sqs" {
  topic_arn = aws_sns_topic.devops_sns_topic.arn
  protocol  = "sqs"
  endpoint  = aws_sqs_queue.devops_sqs_queue.arn
}
Enter fullscreen mode Exit fullscreen mode

⚠️ Important:
Without the aws_sqs_queue_policy, SNS cannot deliver messages to SQS.

2️⃣ outputs.tf

output "kke_sns_topic_arn" {
  value = aws_sns_topic.devops_sns_topic.arn
}

output "kke_sqs_queue_url" {
  value = aws_sqs_queue.devops_sqs_queue.url
}
Enter fullscreen mode Exit fullscreen mode

3️⃣ Terraform Commands (Run in Order)
terraform init
terraform validate
terraform apply

Type:

yes

✅ Expected Output

bob@iac-server ~/terraform via 💠 default ➜  terraform apply

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_sns_topic.devops_sns_topic will be created
  + resource "aws_sns_topic" "devops_sns_topic" {
      + arn                         = (known after apply)
      + beginning_archive_time      = (known after apply)
      + content_based_deduplication = false
      + fifo_topic                  = false
      + id                          = (known after apply)
      + name                        = "devops-sns-topic"
      + name_prefix                 = (known after apply)
      + owner                       = (known after apply)
      + policy                      = (known after apply)
      + signature_version           = (known after apply)
      + tags_all                    = (known after apply)
      + tracing_config              = (known after apply)
    }

  # aws_sns_topic_subscription.sns_to_sqs will be created
  + resource "aws_sns_topic_subscription" "sns_to_sqs" {
      + arn                             = (known after apply)
      + confirmation_timeout_in_minutes = 1
      + confirmation_was_authenticated  = (known after apply)
      + endpoint                        = (known after apply)
      + endpoint_auto_confirms          = false
      + filter_policy_scope             = (known after apply)
      + id                              = (known after apply)
      + owner_id                        = (known after apply)
      + pending_confirmation            = (known after apply)
      + protocol                        = "sqs"
      + raw_message_delivery            = false
      + topic_arn                       = (known after apply)
    }

  # aws_sqs_queue.devops_sqs_queue will be created
  + resource "aws_sqs_queue" "devops_sqs_queue" {
      + arn                               = (known after apply)
      + content_based_deduplication       = false
      + deduplication_scope               = (known after apply)
      + delay_seconds                     = 0
      + fifo_queue                        = false
      + fifo_throughput_limit             = (known after apply)
      + id                                = (known after apply)
      + kms_data_key_reuse_period_seconds = (known after apply)
      + max_message_size                  = 262144
      + message_retention_seconds         = 345600
      + name                              = "devops-sqs-queue"
      + name_prefix                       = (known after apply)
      + policy                            = (known after apply)
      + receive_wait_time_seconds         = 0
      + redrive_allow_policy              = (known after apply)
      + redrive_policy                    = (known after apply)
      + sqs_managed_sse_enabled           = (known after apply)
      + tags_all                          = (known after apply)
      + url                               = (known after apply)
      + visibility_timeout_seconds        = 30
    }

  # aws_sqs_queue_policy.sqs_policy will be created
  + resource "aws_sqs_queue_policy" "sqs_policy" {
      + id        = (known after apply)
      + policy    = (known after apply)
      + queue_url = (known after apply)
    }

Plan: 4 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + kke_sns_topic_arn = (known after apply)
  + kke_sqs_queue_url = (known after apply)

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_sqs_queue.devops_sqs_queue: Creating...
aws_sns_topic.devops_sns_topic: Creating...
aws_sns_topic.devops_sns_topic: Creation complete after 1s [id=arn:aws:sns:us-east-1:000000000000:devops-sns-topic]
aws_sqs_queue.devops_sqs_queue: Still creating... [10s elapsed]
aws_sqs_queue.devops_sqs_queue: Still creating... [20s elapsed]
aws_sqs_queue.devops_sqs_queue: Creation complete after 26s [id=http://sqs.us-east-1.localhost.localstack.cloud:4566/000000000000/devops-sqs-queue]
aws_sqs_queue_policy.sqs_policy: Creating...
aws_sns_topic_subscription.sns_to_sqs: Creating...
aws_sns_topic_subscription.sns_to_sqs: Creation complete after 0s [id=arn:aws:sns:us-east-1:000000000000:devops-sns-topic:748fb525-7f72-49e8-96be-4547f1d65500]
aws_sqs_queue_policy.sqs_policy: Still creating... [10s elapsed]
aws_sqs_queue_policy.sqs_policy: Still creating... [20s elapsed]
aws_sqs_queue_policy.sqs_policy: Creation complete after 25s [id=http://sqs.us-east-1.localhost.localstack.cloud:4566/000000000000/devops-sqs-queue]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Outputs:

kke_sns_topic_arn = "arn:aws:sns:us-east-1:000000000000:devops-sns-topic"
kke_sqs_queue_url = "http://sqs.us-east-1.localhost.localstack.cloud:4566/000000000000/devops-sqs-queue"
Enter fullscreen mode Exit fullscreen mode

🧠 Step-by-Step Explanation (Simple & Clear)

Let’s explain this in plain English.

🔹 What problem is this lab solving?

The team wants:

One system to publish messages

Another system to process messages

Loose coupling (systems don’t talk directly)

SNS + SQS is perfect for this.

🔹 Roles in this setup

Think of it like this:

SNS Topic = 📣 broadcaster

SQS Queue = 📬 mailbox

Subscription = 🔌 connection

When SNS gets a message → it forwards it to SQS.

🔹 Step 1: Create SNS Topic
aws_sns_topic

This is where messages are published.

Example:

aws sns publish --topic-arn ... --message "Hello"

🔹 Step 2: Create SQS Queue
aws_sqs_queue

This stores messages until a consumer reads them.

Reliable, durable, retry-friendly.

🔹 Step 3: Why do we need a Queue Policy?

By default:
❌ SNS is not allowed to send messages to SQS.

So we explicitly say:

“SNS topic X is allowed to send messages to this queue.”

That’s what this does:

aws_sqs_queue_policy

Security + least privilege.

🔹 Step 4: Subscribe SQS to SNS
aws_sns_topic_subscription

This creates the actual connection:

Protocol = sqs

Endpoint = SQS queue ARN

Now the pipeline is live 🔥

🔹 What happens during terraform apply?

1️⃣ SNS topic is created
2️⃣ SQS queue is created
3️⃣ Queue policy allows SNS
4️⃣ SNS subscription is created
5️⃣ Terraform outputs ARN & URL

From now on:

Publish to SNS

Message appears in SQS

Consumer processes it

🧠 Easy Memory Model

SNS = 📣 push

SQS = 📥 pull

Subscription = 🔁 bridge

Policy = 🔐 permission

🚨 Common Mistakes

❌ Forgetting SQS policy
❌ Using queue URL instead of ARN in subscription
❌ Wrong protocol (email instead of sqs)
❌ Outputting wrong attributes


Resources & Next Steps
📦 Full Code Repository: KodeKloud Learning Labs
📖 More Deep Dives: Whispering Cloud Insights - Read other technical articles
💬 Join Discussion: DEV Community - Share your thoughts and questions
💼 Let's Connect: LinkedIn - I'd love to connect with you

Credits
• All labs are from: KodeKloud
• I sincerely appreciate your provision of these valuable resources.

Top comments (0)