
Building Event-Driven Architectures on AWS with SQS, Lambda, and Terraform
Learn how to build a scalable and reliable event-driven architecture using Amazon SQS, AWS Lambda, and Terraform, with a practical flow from event producers to automated processing.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Building Event-Driven Architectures on AWS with SQS, Lambda, and Terraform
Modern applications need to handle thousands of events without tightly coupling different components.
One effective approach is to use an **event-driven architecture**, where applications communicate through events instead of directly depending on each other.
In this article, we will build a simple event-driven architecture using:
- Amazon SQS
- AWS Lambda
- Terraform
- Amazon CloudWatch
The architecture will follow this flow:
**Producer ā Amazon SQS ā AWS Lambda ā Processing**
## 1. What is Event-Driven Architecture?
In a traditional application, one service may directly call another service.
For example:
```text
Application ā Backend ā DatabaseIf the backend is unavailable, the application may also be affected.
With an event-driven architecture, components can communicate asynchronously.
1
2
3
4
5
6
7
8
9
10
Producer
|
v
Amazon SQS
|
v
AWS Lambda
|
v
ProcessingThe producer sends a message to SQS and does not need to wait for Lambda to process it.
This creates a more loosely coupled and scalable system.
2. Why Use Amazon SQS?
Amazon Simple Queue Service (SQS) provides a reliable message queue between applications.
Instead of sending an event directly to a processing service, the producer places the event into a queue.
For example:
1
2
3
4
5
6
7
8
9
10
11
Order Service
|
| Order Created
v
SQS Queue
|
v
Lambda Function
|
v
Process OrderThis provides several benefits:
- Decoupling
- Asynchronous processing
- Automatic scaling
- Message durability
- Improved fault tolerance
3. Why Use AWS Lambda?
AWS Lambda allows us to run code without managing servers.
Lambda can consume messages from an SQS queue and process them automatically.
For example, when a new order is added to the queue:
1
2
3
4
5
6
7
8
9
10
SQS Message
|
v
Lambda Trigger
|
v
Process Order
|
v
SuccessLambda can process messages without requiring a continuously running EC2 instance.
4. Architecture
Our architecture will look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
+----------------+
| Producer |
| Application |
+-------+--------+
|
| Send Event
v
+----------------+
| Amazon SQS |
| Queue |
+-------+--------+
|
| Trigger
v
+----------------+
| AWS Lambda |
| Processor |
+-------+--------+
|
v
+----------------+
| Business |
| Processing |
+----------------+
|
v
+----------------+
| CloudWatch |
| Logs |
+----------------+Terraform will be used to create and manage the infrastructure.
5. Creating the Infrastructure with Terraform
Instead of manually creating every AWS resource from the console, we can use Terraform.
Terraform allows us to define infrastructure as code.
Our project can have a simple structure:
1
2
3
4
5
6
7
event-driven-architecture/
ā
āāā main.tf
āāā variables.tf
āāā outputs.tf
āāā lambda/
āāā lambda_function.py6. Create an SQS Queue
In
main.tf:1
2
3
4
5
resource "aws_sqs_queue" "event_queue" {
name = "event-processing-queue"
visibility_timeout_seconds = 60
}This creates an SQS queue that will store incoming events.
The visibility timeout gives Lambda enough time to process a message before it becomes visible again.
7. Create the Lambda Function
We can define a Lambda function using Terraform:
1
2
3
4
5
6
7
8
9
10
11
resource "aws_lambda_function" "processor" {
function_name = "event-processor"
filename = "lambda.zip"
source_code_hash = filebase64sha256("lambda.zip")
handler = "lambda_function.lambda_handler"
runtime = "python3.12"
role = aws_iam_role.lambda_role.arn
}Lambda will execute the Python function whenever messages are available for processing.
8. Connect SQS with Lambda
Now we need to connect our SQS queue to Lambda.
1
2
3
4
5
6
resource "aws_lambda_event_source_mapping" "sqs_lambda" {
event_source_arn = aws_sqs_queue.event_queue.arn
function_name = aws_lambda_function.processor.arn
batch_size = 10
}This creates the event source mapping.
The flow becomes:
1
2
3
4
5
6
7
8
9
SQS
|
| Messages available
v
Lambda
|
| Process messages
v
Application LogicLambda polls the SQS queue and receives messages in batches.
9. Lambda Processing Code
A simple Python Lambda function can look like this:
1
import jsondef lambda_handler(event, context): for record in event["Records"]: message = record["body"] print("Received message:") print(message) return { "statusCode": 200, "body": json.dumps("Messages processed successfully") }When Lambda receives messages from SQS, the messages are available inside:
1
event["Records"]We can then process each message.
10. IAM Permissions
Lambda needs permission to interact with SQS.
A simplified IAM policy can provide the required SQS permissions:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
resource "aws_iam_role_policy" "lambda_sqs_policy" {
role = aws_iam_role.lambda_role.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = [
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes"
]
Resource = aws_sqs_queue.event_queue.arn
}]
})
}IAM should always follow the principle of least privilege.
Only the permissions required by the Lambda function should be granted.
11. Deploying with Terraform
After configuring the resources, initialize Terraform:
1
terraform initReview the infrastructure changes:
1
terraform planApply the configuration:
1
terraform applyTerraform will create the AWS infrastructure defined in the configuration.
12. Understanding the Complete Flow
Let's understand what happens when an event enters the system.
Step 1 ā Producer creates an event
For example:
1
2
3
4
{
"order_id": "ORD-1001",
"event": "ORDER_CREATED"
}Step 2 ā Event is sent to SQS
The producer sends the event to the SQS queue.
Step 3 ā SQS stores the message
SQS keeps the message until it is successfully processed.
Step 4 ā Lambda receives the message
Lambda polls the queue through the event source mapping.
Step 5 ā Lambda processes the event
The Lambda function executes the required business logic.
Step 6 ā Message is removed
After successful processing, the message is deleted from the queue.
The complete flow is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Event
|
v
Producer
|
v
SQS Queue
|
v
Lambda
|
v
Processing
|
v
Success13. What Happens When Processing Fails?
Failures are an important part of event-driven systems.
Suppose Lambda cannot process a message.
The message can become visible again after the visibility timeout.
This allows the system to retry processing.
A common architecture is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
+----------------+
| Main Queue |
+-------+--------+
|
v
Lambda
|
+------+------+
| |
Success Failure
| |
v v
Complete Retry
|
v
Dead Letter QueueA Dead Letter Queue can be used to isolate messages that repeatedly fail.
This makes troubleshooting much easier.
14. Monitoring with CloudWatch
AWS Lambda automatically integrates with Amazon CloudWatch.
We can monitor:
- Lambda invocations
- Errors
- Duration
- Throttles
- SQS message count
- Failed processing attempts
CloudWatch logs can help us understand why a message failed.
For production systems, monitoring should be considered part of the architecture rather than an optional feature.
15. Benefits of This Architecture
This architecture provides several advantages.
Scalability
SQS can handle large numbers of messages while Lambda can scale based on incoming workload.
Loose Coupling
The producer does not need to directly communicate with the processing service.
Reliability
Messages remain in the queue until they are successfully processed.
Cost Efficiency
Lambda uses a serverless execution model, so there is no need to maintain an always-running server for the processing workload.
Infrastructure as Code
Terraform makes infrastructure repeatable and easier to manage across environments.
16. Best Practices
When building an SQS and Lambda architecture, consider the following:
- Use appropriate visibility timeout settings.
- Configure a Dead Letter Queue for important workloads.
- Follow the principle of least privilege with IAM.
- Monitor Lambda errors and SQS metrics.
- Choose an appropriate Lambda batch size.
- Make Lambda processing idempotent.
- Use CloudWatch for logging and monitoring.
- Keep infrastructure configuration in version control.
- Use Terraform modules for larger environments.
- Test failure and retry scenarios before production deployment.
17. Conclusion
Event-driven architecture helps applications become more scalable, loosely coupled, and resilient.
By combining:
Amazon SQS + AWS Lambda + Terraform
we can create an architecture where events are queued, processed asynchronously, and managed through Infrastructure as Code.
The key idea is simple:
1
2
3
4
5
6
7
8
9
Producer
ā
SQS
ā
Lambda
ā
Processing
ā
CloudWatchTerraform then allows us to create and manage the infrastructure consistently.
This pattern can be extended to many real-world workloads such as order processing, notifications, background jobs, data processing, and asynchronous application workflows.
Build for failure, automate your infrastructure, and design your systems to scale.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
### š·ļø Recommended Tags
Choose these **5 tags**:
- `AWS`
- `Amazon SQS`
- `AWS Lambda`
- `Terraform`
- `Serverless`
### š¼ļø Cover image
For the cover, I recommend a clean **1200 Ć 675** architecture graphic showing:
**Producer ā SQS ā Lambda ā Processing ā CloudWatch**
with **Terraform** represented underneath as the Infrastructure-as-Code layer.
If you want, I can also **create the AWS Builder cover image in the recommended 1200Ć675 format** for this article.Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article