• Guide Content

Integrating AWS SQS with Lambda: Pros, Cons & Quick Tutorial

What Is AWS SQS?

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.

Benefits of Integrating AWS SQS with AWS Lambda 

Lambda functions can be used to process SQS messages. This setup provides several advantages:

Decoupling Components

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.

Scalability

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.

Simplified Error Handling

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.

Asynchronous Processing

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.

Potential Pitfalls of Using AWS SQS with AWS Lambda 

Avoid the following common pitfalls when using AWS Lambda to consume messages from the SQS queue.

Message Processing Duplicates

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.

Polling Management

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.

Batch Size Configuration

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 Start Issues

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.

Tutorial: Using Lambda with Amazon SQS 

Here’s an overview of creating a Lambda function to process messages from SQS.

Step 1: Create an Execution Role

To create an execution role for AWS Lambda that allows it to interact with Amazon SQS, follow these steps:

  1. Navigate to the IAM console’s Roles page.
  2. Select Create role and specify AWS service as the Trusted entity type.

       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.

Step 2: Create a Lambda Function

To set up the Lambda function in Node.js:

  1. Create a directory and navigate to it using:

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:

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.

Step 3: Test Your Function

To test the Lambda function:

  1. Create a sample event JSON file and call it input.json. This will simulate an SQS message:

{
    "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:

Step 4: Set Up an SQS Queue

To create an Amazon SQS queue:

  1. Go to the Amazon SQS console and select Create queue.
  2. Enter a name for your queue and keep the default settings.

         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.

Step 5: Configure an Event Source

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:

Step 6: Send Messages

You can send a test message to your SQS queue to make sure it works:

  1. Navigate to the SQS console and select your queue.
  2. Go to Send and receive messages.
  3. In the Message body, type “I am a test message”.

      4. Click Send message.

The message is sent to the queue and should trigger the Lambda function.

Step 7: Check Your CloudWatch Logs

To verify that the new Lambda function has processed the message:

  1. Go to the Lambda console and select your function.
  2. Click on Monitor and then View CloudWatch logs.
  3. In the CloudWatch console, select the log stream.

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:

  • Solve cold starts easily obtain cold start-related metrics for your Lambda functions, including cold start % and average cold duration, and enable provisioned concurrency. Generate real-time alerts on cold starts, so you’ll know instantly when a function is under-provisioned and can adjust provisioned concurrency.
  • Find and fix issues in seconds with visual debugging – Lumigo builds a virtual stack trace of all services participating in the transaction. Everything is displayed in a visual map that can be searched and filtered.
  • Automatic distributed tracing – with one click and no manual code changes, Lumigo visualizes your entire environment, including your Lambdas, other AWS services, and every API call and external SaaS service.
  • Identify and remove performance bottlenecks – see the end-to-end execution duration of each service and which services run sequentially and in parallel. Lumigo automatically identifies your worst latency offenders, including AWS Lambda cold starts.
  • Serverless-specific smart alerts – using machine learning, Lumigo’s predictive analytics identifies issues before they impact application performance or costs, including alerts about AWS Lambda cold starts.

Get a free account with Lumigo to resolve Lambda issues in seconds.