AWS Simple Queue Service (SQS) is a fully managed message queuing service that enables you to decouple and scale microservices, distributed systems, and serverless applications. It eliminates the complexity and overhead associated with managing and operating message-oriented middleware.
Using AWS SQS, you can send, store, and receive messages between software components at any volume without losing messages or requiring other services to be available. This enables the smooth operation of applications by ensuring that any component can fail and restart without losing its functionality or data.
In this article
Lambda functions can be used to process SQS messages. This setup provides several advantages:
Integrating AWS SQS with AWS Lambda allows for greater decoupling between components of a serverless architecture. This means the Lambda function only processes messages when they are available in the queue, without needing direct interaction or knowledge of other services.
Implementing this decoupling also adds an extra layer of reliability and flexibility. If a source service fails to operate correctly, the messages it sends are safely stored until the service recovers, preventing a system-wide failure.
AWS Lambda functions can automatically scale according to the number of messages in SQS, ensuring that the workload is handled efficiently. As the volume of messages increases, Lambda functions can increase instances to process more messages concurrently.
This automatic scaling optimizes resource utilization and helps manage the cost effectively, as you pay only for what you use. The demand-driven scalability ensures that performance remains consistent regardless of workload spikes.
In standard architectures without SQS, a failure in processing could lead to data loss or a need for complex transaction management. With SQS, messages that fail processing can simply be returned to the queue to be retried or handled according to configured rules.
This is particularly useful for maintaining data integrity and operational reliability across distributed systems. It allows developers to focus more on core business logic than error management.
AWS SQS and Lambda can be integrated to enable asynchronous processing. With SQS handling message queueing, Lambda functions can operate independently, processing batches of messages as they become available. This model optimizes processing time and resource utilization.
Additionally, asynchronicity ensures the system is resilient to bursts of traffic or load increases, providing stable and consistent backend performance without manual intervention in scaling the infrastructure.
Avoid the following common pitfalls when using AWS Lambda to consume messages from the SQS queue.
When using AWS Lambda to process messages from an SQS queue, a common challenge is the occurrence of duplicate messages. Due to the distributed nature of queueing systems, AWS SQS sometimes delivers a message more than once, especially in high-throughput scenarios. If the processing of a message is not idempotent, this can lead to issues such as inconsistent data.
To address this issue, it’s crucial to design your Lambda functions to be idempotent, meaning they should handle duplicate messages gracefully without affecting the outcome. One effective method is to use a unique identifier within each message, such as a transaction ID, to check against a datastore to determine if the message has already been processed. Additionally, leveraging SQS message deduplication features, where available, can prevent the queue from delivering duplicates during the 5-minute deduplication interval.
Another challenge involves effectively managing the polling of SQS messages to optimize cost and performance. AWS Lambda regularly polls your SQS queue to check for new messages. However, excessive polling can lead to higher costs, while insufficient polling can increase message processing latency.
To solve this, configure the Lambda function’s event source mapping settings to adjust the polling frequency and the number of messages fetched per batch. For instance, setting a larger batch size and a higher polling frequency can improve throughput and reduce latency but may increase costs. Find a balance that fits your application’s requirements and budget. Utilizing features like the SQS long polling reduces empty responses by waiting until a message is available in the queue before sending a response, reducing unnecessary polling.
Configuring the batch size for message processing in AWS Lambda is important for optimizing performance and cost. The batch size determines how many messages Lambda pulls from SQS simultaneously. A small batch size may lead to underutilization of the Lambda function, while a very large batch size could overwhelm the function if each message requires significant processing time.
To address this, carefully select a batch size based on the complexity of the message processing and the expected message volume. Test different batch sizes to determine the optimal configuration that maximizes processing efficiency while keeping costs in check. AWS provides the flexibility to adjust batch sizes from 1 to 10,000 messages per batch, and tuning this parameter according to your workload can significantly improve processing times and resource utilization.
Cold starts in AWS Lambda—when an instance of a function is invoked for the first time or after being idle—can introduce latency in processing SQS messages, which might be critical for time-sensitive applications. This latency occurs because AWS needs to load the function code and initialize the runtime and handler before it can start processing messages.
To mitigate cold start issues, keep your Lambda functions warm by using a scheduled event that triggers the function at regular intervals, such as every 5 to 10 minutes. This approach ensures the function remains ready, reducing the likelihood of cold starts. Another strategy is to optimize the function’s code and dependencies, ensuring they are as lightweight as possible, which can also help reduce the initialization time—additionally, considering the use of provisioned concurrency, which keeps a specified number of instances pre-warmed.
Here’s an overview of creating a Lambda function to process messages from SQS.
To create an execution role for AWS Lambda that allows it to interact with Amazon SQS, follow these steps:
3. Specify Lambda as the use case.
4. On the Permissions page, search for and select the AWSLambdaSQSQueueExecutionRole policy.
5. Provide a role name, e.g., lambda-sqs-execution-role, and select Create role.
This role grants the Lambda function necessary permissions to access SQS services. Save the ARN code for use in the next step.
To set up the Lambda function in Node.js:
mkdir sqs-tutorial
cd sqs-tutorial
2. Save the following JavaScript code in a file called index.js:
exports.handler = async (event) => {
event.Records.forEach(record => {
console.log('Processed message:', record.body);
});
};
3. Zip the code to prepare for deployment:
zip function.zip index.js
4. Deploy the function with the AWS CLI:
aws lambda create-function --function-name ProcessSQSRecord \
--zip-file fileb://function.zip --handler index.handler --runtime nodejs18.x \
--role <arn-code>
Replace <arn-code> with the ARN you copied in the previous step.
This Lambda function will now log each received SQS message to CloudWatch Logs.
To test the Lambda function:
{
"Records": [
{
"messageId": "1",
"body": "test",
}
]
}
2. Invoke the Lambda function with this event using the AWS CLI:
aws lambda invoke --function-name ProcessSQSRecord --payload file://input.json out --log-type Tail \
--query 'LogResult' --output text | base64 --decode
This will trigger the Lambda function, and you can verify the processed message in the output logs as follows:
To create an Amazon SQS queue:
3. Click on Create queue and note the ARN of the newly created queue.
This queue will be used to send messages to the Lambda function.
Connect your SQS queue to the Lambda function by creating an event source mapping:
aws lambda create-event-source-mapping --function-name
ProcessSQSRecord --batch-size 20 \
--maximum-batching-window-in-seconds 60 \
--event-source-arn arn:aws:sqs:us-east-1:111122223333:my-queue
This sets up the Lambda function to be triggered whenever new messages are available in the SQS queue. The output should look like this:
You can send a test message to your SQS queue to make sure it works:
4. Click Send message.
The message is sent to the queue and should trigger the Lambda function.
To verify that the new Lambda function has processed the message:
You should see log entries indicating the message was processed, such as “Processed message: I am a test message”.
Related content: Read our guide to SQS monitoring
AWS Lambda Observability, Debugging, and Performance Made Easy with Lumigo
Lumigo is a serverless monitoring platform that lets developers effortlessly find Lambda cold starts, understand their impact, and fix them.
Lumigo can help you:
Get a free account with Lumigo to resolve Lambda issues in seconds.