AWS Compute Blog

New for AWS Lambda – SQS FIFO as an event source

AWS Lambda first announced support for Amazon SQS standard queues as an event source in April 2018. This allows builders to develop serverless applications using queues to directly invoke Lambda functions. Today, we have expanded this feature to include SQS FIFO queues. This makes it easier to create serverless applications using queues where the order of messages is important.

Ordered events and operations are critical for some types of event-driven application. For example, in stock market trading applications, the order of events for a trade is essential to determine the time, price, and parties in a transaction. Similarly, in applications managing pricing or inventory, the order of events is key for maintaining the data integrity of the system.

Using SQS FIFO with Lambda is straight-forward, with only minor differences in configuration compared with standard SQS queues. This blog post explains how serverless developers can get started using SQS FIFO queues in their Lambda functions.

How it works

SQS FIFO queues are similar to standard queues but use two additional attributes in the SendMessage API. These attributes are also returned in the event payload to the consuming Lambda function:

  • MessageGroupID: this required field enables multiple message groups within a single queue. If you do not need this functionality, provide the same MessageGroupId value for all messages. Messages within a single group are processed in a FIFO fashion.
  • MessageDeduplicationID: this token is used to deduplicate messages within a 5-minute interval. If two messages with the same MessageDuplicationID are sent, both messages are accepted successfully but only one is delivered. Learn more about the best practices for using this attribute.

You can submit a message into an SQS FIFO queue using the AWS Management Console, AWS CLI, AWS SAM, or AWS SDK. This SDK example uses Node.js to submit a single message:

const AWS = require('aws-sdk')
AWS.config.update({region: 'us-west-2'})
const sqs = new AWS.SQS({apiVersion: '2012-11-05'})

const send = async (groupId, messageId) => {
  return await sqs.sendMessage({
    MessageGroupId: `group-${groupId}`,
    MessageDeduplicationId: `m-${groupId}-${messageId}`,
    MessageBody: `${messageId}`,
    QueueUrl: "https://sqs.us-west-2.amazonaws.com/123456789012/myTestQueue.fifo"
  }).promise()
}

const main = async () => {
  await send ('A', '1')
}
main()

When the Lambda function is triggered by the SQS FIFO queue, these two attributes are delivered as part of the event payload:

SQS FIFO payload

When configured this way, the SQS FIFO queue sends as many messages as possible to the consuming Lambda function, subject to the Batch size configured in the trigger. The Batch size determines the number of items to read from the queue, up to a maximum of 10 items, though a single batch is smaller if the queue has fewer items.

For example, if you submit six messages to a queue with a Batch size of 10 using two separate MessageGroupId values, the consuming Lambda function would receive all six items:

 

SQS FIFO example #1

As all the messages are processed in a single batch, only one Lambda function is invoked. A more complex example shows how the Lambda service uses concurrency to process a busy SQS FIFO queue more efficiently.

SQS FIFO example #2

In this example, there are three message groups, and a Lambda function with an SQS FIFO trigger. The Batch size for the Lambda trigger is 5, and there are 53 messages in total:

  • Message Group A consists of 18 messages, A1-A18
  • Message Group B consists of 12 messages, B1-B12
  • Message Group C consists of 23 messages, C1-C23

There are three rules governing the order of messages leaving a FIFO queue, to help understand the processing behavior:

  1. Return the oldest message where no other message with the same MessageGroupId is in flight.
  2. Return as many messages with the same MessageGroupId as possible.
  3. If a message batch is still not full, go back to the first rule. As a result, it’s possible for a single batch to contain messages from multiple MessageGroupIds.

In this case, the SQS FIFO queue receives these messages, and orders the items within each message group. In processing, the following events occur:

  1. Consumer #1 receives 5 messages in batch #1 (C1-C5).
  2. Consumer #1 receives 5 messages in batch #2 (B1-B5).
  3. As there are messages in flight for group B, and there are items in the queue from other groups ready for processing, Lambda scales up. Consumer #2 now receives 5 messages in batch #2 (C6-C10).
  4. Consumer #3 receives batch #3 (A1-A5).
  5. Each Lambda instance will continue receiving batches of 5 messages until the queue is empty.

Lambda automatically scales out horizontally to consume the messages in the queue. It will try to consume the queue as quickly and efficiently as possible by maximizing concurrency within the bounds of each service. As queue traffic fluctuates, the Lambda service scales the polling operations based on the number of inflight messages.

In SQS FIFO queues, using more than one MessageGroupId enables Lambda to scale up and process more items in the queue using a greater concurrency limit. Total concurrency is equal to or less than the number of unique MessageGroupIds in the SQS FIFO queue. Learn more about AWS Lambda Function Scaling and how it applies to your event source.

Amazon SQS FIFO queues ensure that the order of processing follows the message order within a message group. However, it does not guarantee only once delivery when used as a Lambda trigger. If only once delivery is important in your serverless application, it’s recommended to make your function idempotent. You could achieve this by tracking a unique attribute of the message using a scalable, low-latency control database like Amazon DynamoDB.

Triggering Lambda from SQS

1. Navigate to the SQS console and choose Create New Queue.

2. Names for FIFO queues must end in .fifo. For Queue Name, enter myTestQueue.fifo and select FIFO Queue. Choose Quick-Create Queue.

Create New Queue

3. From the Lambda console, choose Create function.

4. Enter mySQStest for Function name, and leave the Node.js 12.x runtime selected. Open the Choose or create an execution role panel and select Create a new role from AWS policy templates.

5. Enter mySQStest for Role name and select Amazon SQS poller permissions from the Policy templates drop-down. Choose Create function.

Create Lambda function

6. Once the function is created, you can configure the trigger. Choose Add trigger.

Add trigger

7. In the Select a trigger drop-down, choose SQS. In the SQS queue drop-down, select the FIFO queue created earlier. Leave Batch size as the default value, then choose Add.

Add trigger dialog

8. After a few seconds, the SQS trigger is ready.

SQS FIFO trigger ready

The Lambda function is now invoked when new messages are available in the SQS FIFO queue.

Conclusion

Now, you can process messages from Amazon SQS FIFO queues with Lambda, helping bring scalable serverless processing to applications needing first-in, first-out message processing.

You can get started with SQS FIFO queue as a Lambda event source via AWS Management Console, AWS CLI, AWS SAM, AWS CloudFormation, or AWS SDK for Lambda. It is available in all AWS Regions where AWS Lambda is available. You pay only for the SQS API operations performed by the Lambda service on your behalf, and the Lambda requests and duration used to process your messages.

For more information on where AWS Lambda is available, see the AWS Region Table. To learn more, see Using AWS Lambda with Amazon SQS FIFO in the AWS Lambda Developer Guide.