A pattern to show how to use Lambda SnapStart with relational databases.
Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/apigw-lambda-rds-snapstart
Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the AWS Pricing page for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.
- Create an AWS account if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
- AWS CLI installed and configured
- Git Installed
- AWS CDK (AWS CDK) installed
- jq
- Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
git clone https://github.com/aws-samples/serverless-patterns
- Change directory to the pattern directory:
cd apigw-lambda-rds-snapstart
- Build the database setup and unicorn functions
./mvnw clean package -f infrastructure/db-setup/pom.xml ./mvnw clean package -f software/unicorn-store/pom.xml
- Deploy the infrastructure
cd infrastructure/cdk cdk bootstrap cdk deploy UnicornStoreInfrastructure --require-approval never --outputs-file target/output.json
- Execute the DB setup function to create the table
aws lambda invoke --function-name $(cat target/output.json | jq -r '.UnicornStoreInfrastructure.DbSetupArn') /dev/stdout | cat;
- Deploy the unicorn store
cdk deploy UnicornStoreApp --outputs-file target/output.json --require-approval never
Create a new unicorn
curl --location --request POST $(cat target/output.json | jq -r '.UnicornStoreApp.ApiEndpoint')'/unicorns' \
--header 'Content-Type: application/json' \
--data-raw '{
"id": "123",
"name": "Something",
"age": "Older",
"type": "Animal",
"size": "Very big"
}' | jq
Get a unicorn with the Id.
curl --location --request GET $(cat target/output.json | jq -r '.UnicornStoreApp.ApiEndpoint')'/unicorns/123'
CDK creates all the infrastructure we need for the pattern, include the VPC, subnets, security groups,secrets and the DB.
The DB setup Lambda function is executed once to create the database table with a given structure.
This REST API is implemented with the Micronaut framework. Credentials for the DB are passed as environment variables to the application.
The Micronaut Data component implements it's database connectivity using the Hikari data source library. When a Lambda function is initialised it automatically creates and opens a connection to the database, in this case to Postgres.
This is advantageous if you are not using SnapStart, if you are then the application state is recorded with the knowledge of an active db connection. This means that the first time a snapshot is resumed it has a stale db connection and the database library has to repair this by making a new connection.
It is best practice to use Runtime hooks to suspend the data source and close any open connections before the snapshot is taken. You can then resume the data source after the snapshot has been resumed.
The Micronaut framework has created additional support to help with this scenario. To enable it include the Micronaut CRaC module in you project.
<dependency>
<groupId>io.micronaut.crac</groupId>
<artifactId>micronaut-crac</artifactId>
<scope>compile</scope>
</dependency>
When this is added the
Hikari data source hooks in HikariDataSourceResource.java
are activated.
Test | Restore Duration | Duration | Total Duration |
---|---|---|---|
without runtime hooks | 527ms | 333ms | 860ms |
with runtime hooks | 280ms | 438ms | 718ms (-16%) |
cd infrastructure/cdk
cdk destroy --all
Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0