DynamoDB with Serverless Framework - The Ultimate Guide
Written by Rafal Wilinski
Published on May 8th, 2020
Time to 10x your DynamoDB productivity with Dynobase [learn more]
Why DynamoDB with Serverless Framework?
DynamoDB integrates seamlessly with the Serverless Framework and AWS Lambda. Why? Both DynamoDB and AWS Lambda are serverless services, meaning that they are billed based on your usage, which can lead to cost savings. Moreover, AWS provides a set of integrations between them, including DynamoDB Streams, which can be consumed by Lambda functions to react to data changes in real-time. Both services can be deployed in a multi-region fashion, ensuring high availability and disaster recovery. Additionally, you don't have to worry about managing, patching, or maintaining either of these services, as AWS handles that for you.
If I've convinced you that these services work well together, let's proceed with a tutorial on how to deploy a simple CRUD application using the Serverless Framework with Node.js and JavaScript.
Step 1 - Prerequisites
Make sure you have:
- AWS profile set up
- Node.js installed, preferably version > 10
- Serverless Framework
You should be able to run the following commands without any issues:
Step 2 - Create a new Serverless Framework project
Serverless Framework provides a set of templates for a variety of platforms and languages. For this tutorial, we're going to use the aws-nodejs
template:
It should create the following file structure:
Step 3 - Provision necessary infrastructure
Open the serverless.yml
file. This file defines our cloud-native application. We need to add a DynamoDB Table definition here. You can either use our DynamoDB Table Designer tool or use the following example table definition. Paste this at the end of the serverless.yml
file:
But that's not all. We have our DynamoDB table, but we don't have:
- A reference to that table
- IAM permissions to let Lambda query and mutate this table
The first one is fairly easy. Simply add the following lines to the provider
to supply the table name as an environment variable to all functions, or at the function
level to pass it just to one function.
The second one is a bit more complex. Since we want to follow the principle of least privilege and don't want to give the Lambda permission to manipulate all DynamoDB tables but only this particular one, we need to use a combination of the Fn::GetAtt
intrinsic function and listing applicable IAM actions in the iamRoleStatements
block nested inside provider
.
Step 4 - Application Code
Now, let's get to the actual Lambda functions - our business logic. In this project, our API will have three CRUD functionalities:
- Create Animal
- Get Animals
- Delete Animal
Go ahead and open the handler.js
file, delete everything inside, and include the following require statement at the top:
Don't worry that you don't have aws-sdk
installed locally. AWS-SDK is available in the AWS Lambda environment, so you don't have to bundle it with your deployment artifact.
Create Function
In serverless.yml
, add our createAnimal
function definition. It will be invoked on a POST animals
request. You may also add other properties like memory
or timeout
.
In handler.js
, paste the following lines of code.
It's pretty straightforward. We create a newAnimal
object based on parameters from the body of the POST request, save that to the database, and return the newly created entity with status code 200.
Get Many Function
The function responsible for returning a collection of our animals is pretty similar to the create one:
When it comes to the logic, it's quite simple. We're running a Scan operation against DynamoDB to get the list of our records.
Delete Function
Lastly, the delete function is also similar. The only difference here is that the path
, which includes the :name
variable, uses the DELETE
method.
Once again, the logic is quite simple. We delete an entity with the key name
which equals our path parameter.
If you don't know how to create DynamoDB queries because of its complicated syntax, use our DynamoDB Query Builder.
Step 5 - Deploy & Test
Deploying your project to the cloud is as easy as executing the following command:
It should output the URL of your endpoint. Copy it, and fire a request to check if it works correctly. If it does, then congrats! You've just deployed a production-ready, cloud-native API with Serverless Framework and DynamoDB!
Bonus - Our proven boilerplate
If you want to use something a bit more sophisticated which follows many of the best practices, we've prepared a battle-tested Serverless Framework boilerplate for you.
Additional Considerations
When working with DynamoDB and the Serverless Framework, it's important to consider the scalability and performance of your application. DynamoDB offers both provisioned and on-demand capacity modes, allowing you to choose the best pricing model based on your application's traffic patterns. Additionally, you can use DynamoDB's Global Tables feature to replicate your data across multiple AWS regions, providing low-latency access to your data globally. Monitoring and logging are also crucial; make sure to integrate AWS CloudWatch to track the performance and health of your Lambda functions and DynamoDB tables. Finally, consider implementing error handling and retries in your Lambda functions to make your application more resilient to transient failures.