Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New serverless pattern - sqs-lambda-ddb-cdk-ts #2032

Merged

Conversation

astan54321
Copy link

Issue #, if available:
#2031

Description of changes:
The purpose of this pattern is to address write throttling issues of Provisioned Capacity DynamoDB Tables by offloading the requests to SQS to handle writes asynchronously. This pattern is deployed through an AWS Cloud Development Kit (CDK) app which provisions DynamoDB tables, SQS queues and DLQs, Lambda functions, and Cloudwatch alarms. Test scripts have been provided for testing.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@bfreiberg
Copy link
Contributor

bfreiberg commented Jan 17, 2024

Hi, it looks like you have a subfolder sqs-lambda-dynamodb-cloudwatch-cdk-ts with another pattern? Is that intentional?

@bfreiberg
Copy link
Contributor

I'm not sure I understand the use-case that this pattern addresses. Could you please elaborate what the benefit is?

@astan54321
Copy link
Author

astan54321 commented Jan 17, 2024

Hi, it looks like you have a subfolder sqs-lambda-dynamodb-cloudwatch-cdk-ts with another pattern? Is that intentional?

Hi Ben, addressed the outdated pattern folder (this was from a previous submission where the pattern also included a cloudwatch alarm)

@astan54321
Copy link
Author

astan54321 commented Jan 17, 2024

I'm not sure I understand the use-case that this pattern addresses. Could you please elaborate what the benefit is?

The pattern is meant to show how to offload dynamodb writes using sqs + lambda per table pipelines to avoid ddb table throttling. This is done in collaboration with gulid@ and their pattern for the same architecture but using SAM instead (under the sqs-lambda-ddb-sam-ts subfolder


The purpose of this pattern is to address write throttling issues of Provisioned Capacity DynamoDB Tables by offloading the requests to SQS to handle writes asynchronously. This pattern is deployed through an AWS Cloud Development Kit (CDK) app which provisions DynamoDB tables, SQS queues and DLQs, and Lambda functions. Test scripts have been provided for testing.

Learn more about this pattern at Serverless Land Patterns: [INSERT SERVERLESS LAND LINK HERE]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Learn more about this pattern at Serverless Land Patterns: [INSERT SERVERLESS LAND LINK HERE]
Learn more about this pattern at Serverless Land Patterns: [https://serverlessland.com/patterns/sqs-lambda-ddb-cdk-ts](https://serverlessland.com/patterns/sqs-lambda-ddb-cdk-ts)


A new Amazon SQS queue will be created and configured to invoke an AWS Lambda function that will write the received messages into an Amazon DynamoDB table. The SQS queue redrive policy will be configured to send undeliverable messages to an Amazon SQS Dead-Letter Queue. Undeliverable messages are the ones that couldn't be written to the DynamoDB table with a maximum of `maxReceiveCount` number of attempts.

Lambda function will stop writing messages into the DynamoDB table as soon as it catches an exception and will report the remaining messages to Amazon SQS service as failed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Lambda function will stop writing messages into the DynamoDB table as soon as it catches an exception and will report the remaining messages to Amazon SQS service as failed.
The Lambda function will stop writing messages into the DynamoDB table as soon as it catches an exception and will report the remaining messages to Amazon SQS service as failed.


Lambda function will stop writing messages into the DynamoDB table as soon as it catches an exception and will report the remaining messages to Amazon SQS service as failed.

Amazon DynamoDB table will have a minimal `ProvisionedThroughput` configuration for demo purposes, so that the users can observe message write retries when testing this stack. Real production throughput must be configured in accordance with the actual business requirements and message sizes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Amazon DynamoDB table will have a minimal `ProvisionedThroughput` configuration for demo purposes, so that the users can observe message write retries when testing this stack. Real production throughput must be configured in accordance with the actual business requirements and message sizes.
The Amazon DynamoDB table will have a minimal `ProvisionedThroughput` configuration for demo purposes, so that the users can observe retries on message writes when testing this stack. Real production throughput must be configured in accordance with the actual business requirements and message sizes.


## Considerations

* For simplicity and demo purposes, the DynamoDB Table deployed in this stack does not have Point-In-Time Recovery enabled. This pattern serves as a customizable template for a solution. It is recommended enable this feature as in a production environment.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* For simplicity and demo purposes, the DynamoDB Table deployed in this stack does not have Point-In-Time Recovery enabled. This pattern serves as a customizable template for a solution. It is recommended enable this feature as in a production environment.
* For simplicity and demo purposes, the DynamoDB Table deployed in this stack does not have Point-In-Time Recovery enabled. This pattern serves as a customizable template for a solution. It is recommended to enable this feature as in a production environment.

## Considerations

* For simplicity and demo purposes, the DynamoDB Table deployed in this stack does not have Point-In-Time Recovery enabled. This pattern serves as a customizable template for a solution. It is recommended enable this feature as in a production environment.
* For simplicity, this project uses a [config](./lib/config/tables.config.ts) file to configure the scaling limits of DynamoDB and Lambda. Customers may wish to automate this process to run in a closed loop based off desired WCUs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* For simplicity, this project uses a [config](./lib/config/tables.config.ts) file to configure the scaling limits of DynamoDB and Lambda. Customers may wish to automate this process to run in a closed loop based off desired WCUs.
* For simplicity, this project uses a [config](./lib/config/tables.config.ts) file to configure the scaling limits of DynamoDB and Lambda. Customers may wish to automate this process to run in a closed loop based off desired write capacity units (WCUs).

\
**NOTE:** If there are no data points loading on the graph, wait a couple of minutes as CloudWatch takes some time to aggregate metrics.

9. Terminate the script
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please highlight this because it will continue to incur costs if the script is not stopped



----
Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.




6. Once you have confirmed that DynamoDB is throttling write requests, go back to the [config](./lib/config/tables.config.ts) file in repo and lower the `lambdaReservedConcurrency` property to a value less than or equal to the current writeCapacity value of the table (1 is a sufficient value for this demo). Increase the `retryAttempts` property value to a high value (20 should be sufficient for this demo) to give Lambda time to keep up with any subsequent throttling events.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The writeCapacity of the table is already at 1, how should the lambdaReservedConcurrency be reduced even more?

]
},
"deploy": {
"text": ["<code>cdk deploy</code>"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"text": ["<code>cdk deploy</code>"]
"text": ["cdk deploy"]

"text": ["See the GitHub repo for detailed testing instructions."]
},
"cleanup": {
"text": ["Delete the stack: <code>cdk destroy</code>."]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"text": ["Delete the stack: <code>cdk destroy</code>."]
"text": ["<code>cdk destroy</code>"]

@bfreiberg
Copy link
Contributor

I'm not sure I understand the use-case that this pattern addresses. Could you please elaborate what the benefit is?

The pattern is meant to show how to offload dynamodb writes using sqs + lambda per table pipelines to avoid ddb table throttling. This is done in collaboration with gulid@ and their pattern for the same architecture but using SAM instead (under the sqs-lambda-ddb-sam-ts subfolder

Hi, why would a customer not use Application Auto Scaling to adjust the amount of Provisioned Concurrency instead? https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html#managing-provisioned-concurency

@astan54321
Copy link
Author

astan54321 commented Jan 30, 2024

I'm not sure I understand the use-case that this pattern addresses. Could you please elaborate what the benefit is?

The pattern is meant to show how to offload dynamodb writes using sqs + lambda per table pipelines to avoid ddb table throttling. This is done in collaboration with gulid@ and their pattern for the same architecture but using SAM instead (under the sqs-lambda-ddb-sam-ts subfolder

Hi, why would a customer not use Application Auto Scaling to adjust the amount of Provisioned Concurrency instead? https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html#managing-provisioned-concurency

The Provisioned Concurrency value would only affect the number of available execution environments for the Lambda handler, not limit the maximum amount. With this pattern, we are trying to offload the DynamoDB writes to lambda to allow the supposed application side to write as frequently as possible, rather than having to time requests in line with the DynamoDB WCUs on the application side. For this purpose, the Reserved Concurrency value is more useful since it represents the max number of concurrent requests allowed, which limits how fast the Lambda handler is allowed to handle the requests to keep the table from throttling as much as possible and avoid redriving requests.

@bfreiberg
Copy link
Contributor

Hi @astan54321 , thanks for your reply. I understand the use-case better now. In this case, I think it would be best to integrate maximum concurrency on the SQS side as well: https://aws.amazon.com/blogs/compute/introducing-maximum-concurrency-of-aws-lambda-functions-when-using-amazon-sqs-as-an-event-source/

@astan54321
Copy link
Author

Hi @astan54321 , thanks for your reply. I understand the use-case better now. In this case, I think it would be best to integrate maximum concurrency on the SQS side as well: https://aws.amazon.com/blogs/compute/introducing-maximum-concurrency-of-aws-lambda-functions-when-using-amazon-sqs-as-an-event-source/

Tanks for sharing this @bfreiberg! This helps a lot. Will go ahead and integrate this and update the PR.

@bfreiberg
Copy link
Contributor

Hi @astan54321, did you have a chance to work on this?

@astan54321
Copy link
Author

Hi Ben, yes, we are still working on making edits to the README and making sure the testing stop makes sense. Should have an updated commit early next week.

@singledigit
Copy link
Contributor

Any updates on this?

@astan54321
Copy link
Author

Hi Ben and Eric, yes just pushed updates with updated functionality to use SQS max concurrency instead of Lambda's reserved concurrency, which fits the goal of the pattern better. Changes were required to the README by another team member and I during the past few weeks which is what took so long with this (along with changing schedules). Let me now if anhy final changes need to be made if this is to be merged into the base ServerLess land repo. Thanks.

Copy link
Contributor

@bfreiberg bfreiberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just two minor comments

8. For a visual representation, you can also look at CloudWatch metrics for **Write throttled requests(count)** in the monitoring tab of the DynamoDB Console. You should see a spike of write throttled requests and then it should decrease around the time you made the config change. It should look similar to the picture below.
\
\
![alt text](./images/write_throttling_metrics.png)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make the alt text a bit more relevant for users with accessibility issues

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added alt text description

"text": [
"This code demonstrates how an Amazon SQS queue can be used to buffer records for an Amazon DynamoDB table and mitigate the risk for a client of being throttled.",
"The CDK code deploys Ingress and Dead-Letter SQS queues, AWS Lambda functions, destination DynamoDB tables and CloudWatch alarms.",
"AWS Lambda function uses NodeJS 18 runtime."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to use Node v20 as it is the latest supported runtime?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated node version in example.json and in CDK template. updated AWS SDK imports for testing script

@bfreiberg
Copy link
Contributor

Looks good, thanks for your contribution. A Developer Advocate will merge the PR and publish the changes to serverlessland.com.

@julianwood julianwood merged commit 6b42a1f into aws-samples:main Apr 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants