visit
Ever since AWS made a serverless option of , I’ve been on the edge of my seat, eagerly anticipating all the various possibilities. It would mean a breakthrough in building serverless architectures. No more managing connection pools with SQL. No more worrying about capping out available connections. This would make it viable to use serverless for database intensive operations.
I wrote an article a while back explaining how to build a serverless API with MongoDB. But, I saw a pattern emerge. Higher throughput in a system, even though a database instance could take the load, would cause connections to drop because of a limited set of available connections.
I’ll assume you already have a basic understanding of . I would also hope you have an AWS account set up. If you don’t, please check this out.
$ sls create -t aws-nodejs -p web-api && cd web-api
Running this command, you’ll get a nice boilerplate to begin developing your functions. It’ll set up the basic functions and event triggers. You also see we’re entering the web-api
directory right away. We jumped into this directory to set up the required dependencies.
In total, we only need three dependencies. The MySQL ORM called Sequelize to handle connections and map relations, and serverless-offline
for local development.
Make sure you’re in the web-api directory. First, install serverless-offline
, then mysql2
and sequelize
.
$ npm init -y $ npm i --save-dev serverless-offline $ npm i --save mysql2 sequelize
That’s it, let’s take a break from the terminal and jump over to AWS to create a database cluster.
Click the orange Create Database button and follow along.
First, you’ll choose the engine you want to use. Choose Amazon Aurora and click next.
Once you’ve specified the engine, configure Aurora to be Serverless, add a name to your cluster and configure the master username and password.
Only one more set of advanced settings to configure, and you should be set.
Here you’ll set up the capacity and network. Because Aurora Serverless lives inside a VPC you’ll have to configure the access. Here you’re choosing the default VPC.
With the additional configuration, you can set up backups of you so please. Once you’re happy with it all, press the orange Create database button.
Finally, it’ll start provisioning the cluster. You’ll get redirected and see some output looking like this.But, what’s interesting to us is the details section.
Here you have access to security groups and subnets. You’ll need to add them to the functions in order for them to be able to communicate with the database. More about that in the next section.
Note: If you want to access the AWS Aurora Serverless cluster follow to learn how to do it with the CLI, or to connect through . You will need to connect to the cluster and create a database manually because Sequelize can’t create them for you.
The engineers over at have shown me how awesome can be with the huge amounts of data they’re processing. Rumors are they’re in the works of creating a completely called . I’m eager to start using it myself. Hopefully, Aurora Serverless can be of help.Configuring database resources on AWS is always a handful, especially the new serverless database offering. Luckily, the configuration part is over. Now we need to write the configuration for our serverless resources in the serverless.yml file and add the actual CRUD methods to the handler.js.
Open the serverless.yml file first and take a breather. Here you’ll see a bunch of comments with sample configurations. I like clean code, so let’s delete it all, and paste in this snippet instead.
Let’s break it down piece by piece. The provider
section contains all the basic info about the cloud provider. But also data about the runtime, function timeouts, environment variables, and VPC configuration. The VPC setup is needed here because AWS Aurora Serverless can only run behind a VPC, so you need to put your in order to access the database.
Moving on, there’s a custom
section at the top where we load environment variables and then pass them to the environment
section.
Finally, let’s talk about the functions section. We added a total of 6 functions: healthCheck, create, getOne, getAll, update, and destroy. They all point to identically named exported functions in the handler.js file. Their event triggers are hooked up to HTTP events which are handled by . Meaning, an HTTP request to a specified path will trigger the referenced function.
That’s pretty much it, the last thing is to add a plugins section and serverless-offline. We installed this module above and we’ll use it for testing the service out before deploying to AWS.
You saw in the serverless.yml that we referenced a secrets file. Before moving on we need to create it and make sure it’s loading our secrets correctly.
In the root of the project create a secrets.json
and paste this snippet in.
That’s everything regarding the YAML. Let’s play with the handler.js next. Finally, some real code!
Switch over to the handler.js file. You’ll see the default boilerplate. Guess what? Delete it all and add the code below.
I can understand you think this is a bit of a huge snippet. Don’t worry. These are only 6 basic async
functions. The connectToDatabase()
function resolves to an object containing all the database models. We'll only implement the Note
model in this tutorial. The logic behind the function will connect to the SQL database, cache the connection and make sure to never retry connecting if an existing connection is alive.
Create a new file in the root directory of the service, right alongside the handler.js. Give it a pretty logical name of db.js, and add the code below.
At the top, we’re requiring Sequelize
and the NoteModel
.
Note: We’re yet to create the model, but hold on, we’ll get to that right after this part.
We then initialize sequelize
, pass in the connection variables and establish a connection. Calling NoteModel
will initialize the model, which we then pass to a Models
constant. The arbitrary connections
object is there just to use as a cache for the connection. Making sure not to sync the database if it's not necessary. The second reason for await
ing the .sync()
and .authenticate()
methods are to make sure the database connection is established during the initial function call, before handling any business logic.
With the db.js file created, let’s require it in the handler.js. Just add this snippet to the top of the handler.
Jump back to the handler.js. You can see we’re calling const { Note } = await connectToDatabase()
in the functions to retrieve data, but there’s no Note model defined. Well, now is as good a time as any.
Create a new folder in the service root directory and name it models. In it create another file and name it Note.js. This will be just a simple model definition.
That’s it. Time to try it out.
Note: Make sure to add your _secrets.json_
to your _.gitignore_
file.
We’re ready to test the API. To be sure, let’s start by running it all locally. One tiny thing to take into account is that there’s a flag we need to add while running serverless-offline
.
$ sls offline start --skipCacheInvalidation
Note: Serverless Offline invalidates the Node require cache on every run by default, we add this flag to disable it. In Node.js when you _require()_
a module, it stores a cached version of the module, so that all subsequent calls to _require()_
do not have to reload the module from the file system.
All our routes are up and running. Using , I’ve created a POST request to //localhost:3000/notes
with a JSON body.
Checking the terminal you can see => using new database connection
get logged, meaning the initial database connection has been established. Send another POST request and you’ll see => using existing database connection
get logged instead.
Awesome, adding a new note works. Let’s retrieve all the notes we just added using the getAll method.
Try out the other endpoints yourself. Come back here once you’re done playing.
Now comes the tricky part. Make sure to write down all the database parameters you’ll get in the AWS Aurora Serverless console, and of course the security group ID and subnet IDs as well. Usually, you’ll have one security group and three subnets. But, it can vary, so don’t worry. After you have the values, add them to your secrets.json
. That's it! You're ready to deploy.
Note: You can repeat the testing process from above with the endpoints provided. But, be patient with the cold-start times. AWS Aurora Serverless can take a decent 10 seconds to start. A similar issue happens with AWS Lambda in a VPC.
That’s all there is to the deployment process. Easy right? This is why I love the Serverless framework so much.I had an absolute playing with AWS Aurora Serverless. Hope you guys and girls enjoyed reading it as much as I enjoyed writing it. If you liked it, slap that tiny unicorn so more people here on dev.to will see this article. Don’t forget to give the peeps at Cube.js some love if you need a ! Until next time, be curious and have fun.
Originally published at .