AWS SQS with Lambda Terraform Template

A complete Terraform configuration to deploy an SQS queue with a Lambda function trigger

About This Template

This Terraform template creates an AWS SQS queue and configures a Lambda function to be triggered by messages in the queue. The template includes all necessary IAM permissions and resource configurations.

SQS Queue

Standard queue with configurable visibility timeout and message retention

Lambda Function

Node.js function with SQS trigger and proper IAM permissions

IAM Roles

Least privilege permissions for Lambda to consume SQS messages

main.tf
# Terraform configuration for AWS SQS with Lambda trigger

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

provider "aws" {
  region = "us-east-1" # Change to your preferred region
}

# Create SQS queue
resource "aws_sqs_queue" "example_queue" {
  name                      = "example-queue"
  delay_seconds             = 0
  max_message_size          = 262144 # 256 KiB
  message_retention_seconds = 345600 # 4 days
  receive_wait_time_seconds = 10     # Long polling wait time
  visibility_timeout_seconds = 30    # Should be >= Lambda timeout

  tags = {
    Environment = "production"
  }
}

# IAM role for Lambda execution
resource "aws_iam_role" "lambda_exec_role" {
  name = "lambda_exec_role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "lambda.amazonaws.com"
        }
      }
    ]
  })
}

# IAM policy for Lambda to access SQS
resource "aws_iam_policy" "lambda_sqs_policy" {
  name        = "lambda_sqs_policy"
  description = "Policy for Lambda to read from SQS"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "sqs:ReceiveMessage",
          "sqs:DeleteMessage",
          "sqs:GetQueueAttributes"
        ]
        Resource = aws_sqs_queue.example_queue.arn
      },
      {
        Effect = "Allow"
        Action = [
          "logs:CreateLogGroup",
          "logs:CreateLogStream",
          "logs:PutLogEvents"
        ]
        Resource = "arn:aws:logs:*:*:*"
      }
    ]
  })
}

# Attach policy to Lambda role
resource "aws_iam_role_policy_attachment" "lambda_sqs_attachment" {
  role       = aws_iam_role.lambda_exec_role.name
  policy_arn = aws_iam_policy.lambda_sqs_policy.arn
}

# Lambda function
resource "aws_lambda_function" "sqs_processor" {
  filename      = "lambda_function.zip" # Replace with your Lambda package
  function_name = "sqs_processor"
  role          = aws_iam_role.lambda_exec_role.arn
  handler       = "index.handler"
  runtime       = "nodejs14.x" # Change to your preferred runtime

  source_code_hash = filebase64sha256("lambda_function.zip")

  environment {
    variables = {
      QUEUE_URL = aws_sqs_queue.example_queue.url
    }
  }
}

# Lambda event source mapping
resource "aws_lambda_event_source_mapping" "sqs_trigger" {
  event_source_arn = aws_sqs_queue.example_queue.arn
  function_name    = aws_lambda_function.sqs_processor.arn
  batch_size       = 10 # Number of messages to process at once
}
index.js
// Example Lambda function to process SQS messages
exports.handler = async (event) => {
    console.log('Received event:', JSON.stringify(event, null, 2));
    
    for (const record of event.Records) {
        try {
            const message = JSON.parse(record.body);
            console.log('Processing message:', message);
            
            // Your message processing logic here
            // Example: Send to another service, transform data, etc.
            
            console.log('Successfully processed message ID:', record.messageId);
        } catch (error) {
            console.error('Error processing message:', error);
            // You might want to implement dead-letter queue handling here
            throw error; // This will make Lambda retry the batch
        }
    }
    
    return {
        statusCode: 200,
        body: JSON.stringify('Messages processed successfully')
    };
};

Deployment Instructions

  1. Save the Terraform code to a file named main.tf
  2. Save the Lambda code to a file named index.js
  3. Zip the Lambda file: zip lambda_function.zip index.js
  4. Initialize Terraform: terraform init
  5. Review the execution plan: terraform plan
  6. Apply the configuration: terraform apply
  7. To destroy resources when done: terraform destroy

Important Notes

  • Make sure your AWS credentials are properly configured
  • The Lambda timeout should be less than the SQS visibility timeout
  • Consider adding a dead-letter queue for failed messages
  • Monitor your Lambda concurrency to avoid throttling