Getting started with a Practical Serverless Setup on AWS — using Lambda, API Gateway and RDS

Image for post
Image for post

Creating a serverless project on AWS using Lambda, API Gateway and RDS can be simple at first but as your project progresses, management of code, libraries, deployment and testing can become tedious.

For example, say you have multiple lambda functions each sharing libraries and helper code. How could we manage all this without maintaining seperate code bases for each function and uploading these functions to Lambda in a .zip file every time we went to update or test it?

Let’s base the tutorial off a simple project, an API that can list and create different types of ice cream having it’s data stored in a relational database (MySQL) which will be hosted on RDS. We will be using the Node 8 runtime environment complete with ES6 capabilities including the usage of Async Await.

The local environment assumed in this tutorial is macOS 10.12 with the AWS SDK, Node 8 and NPM installed. All code can be found on my GitHub.

Please make sure to follow this guide with the repository I have created on GitHub

Setup and Project Explanation

For this project we are using Apex (http://apex.run), a command line based serverless management tool. Apex is by far the best serverless management tool for AWS Lambda I have seen to date. Apex will assist you in building, deploying and testing Lambda functions with ease. It will allow you to remove the use of the Lambda GUI from your project completely allowing you entirely to focus on your code and less on it’s deployment.

Our directory setup will be roughly as follows (the functions folder and the project.json file is needed for Apex to work).

project.json 
package.json
common/functions
├── CreateIceCream
│ └── index.js
│ └── function.json
└── GetIceCream
└── index.js
└── function.js

project.json

This is the main JSON file apex will reference for your Lambda’s configuration when working with your individual Lambda functions.

{
"name": "PracticalServerlessAWS",
"description": "Practical Serverless AWS",
"nameTemplate": "ice{{.Function.Name}}",
"runtime": "nodejs6.10",
"memory": 128,
"timeout": 6,
"role": "arn:aws:iam::123456789:role/LambdaExecution",
"profile": "jamesmarino",
"handler": "main.handler",
"hooks": {
"build": "../../node_modules/.bin/webpack --config ../../config/webpack.config.js --bail",
"clean": "rm -f main.js"
},
"environment": {
"mysql_host": "my-instance.rds.amazonaws.com",
"mysql_user": "root",
"mysql_password": "password",
"mysql_database": "MyDatabase"
}
}

Besides the self explanatory parameters, heres an explanation of the rest:

  • “role” — The role for your functions can be found or created in your IAM console. It is also created automatically when adding a new function in the Lambda web based interface
  • “profile” — Found in your AWS credentials file in “~/.aws/credentials” . Make sure to set the region of this profile in “~/.aws/config” as well
  • “hooks” — The life cycles of the Lambda deployment. Here we are using build, to build the lambda code and clean, to remove the built file after it’s deployed
  • “hooks.build” — WebPack is used to transpile your code to ES5 (A standard of JavaScript lambda can currently run) and place it and all your libraries into a single main.js file. Please see “config/webpack.config.js” for further details
  • “environment” — Lambda environment variables. This will contain all environment variables that will be accessible to all lambda functions within your project. Please keep in mind to not commit passwords to your repository

package.json

Your normal Node.Js package file

functions/myFunctionName

This is where your lambda code will live. Both index.js and test.js will live in here along with other helper classes. The index.js file will be the entry point to your function. The test.js will allow us to test the function locally.

functions/myFunctionName/function.json

This file will allow us to overwrite the common project.json specifications and have custom properties on a per function basis. For example, below we have specified a function specific description and timeout.

{
"description": "Get Ice Cream",
"timeout": 3,
"memory": 128
}

common/

Although not necessary for Apex to work, we can place common files here such as a database helper class. We can then symbolically link to them in each function. For example in the directory of the function, you would link to the common file using the unix symlink command

$ ln -s ../../common.js common.js

Let’s create a schema for our RDS instance, (the schema used in the repository’s example Lambda functions)

CREATE TABLE `DatabaseName`.`IceCream` (
`idIceCream` INT NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(45) NULL,
`Flavour` VARCHAR(45) NULL,
`Rating` INT NULL,
`Colour` VARCHAR(45) NULL,
`NextOrderDate` DATETIME NULL,
PRIMARY KEY (`idIceCream`));

Be sure to note your host, user name, password and database name of your RDS instance for the environment variables as specified in the project.json file.

Deployment and Testing

Next is the testing and deployment of our functions. For this you will need to have Apex installed and the project.json file edited accordingly. Please see the Apex site for the latest install instructions. Make sure your working directory is the root of the project.

$ cd path/to/project/

To List all the functions and their deployment status.

$ apex list
Image for post
Image for post
List of all functions

To deploy to Lambda

$ apex deploy

or if you want to deploy a single function

$ apex deploy myFunction
Image for post
Image for post
Deployment Log for all functions

If you check the lambda console, these function will now appear in their transpiled form.

Image for post
Image for post
Lambda Console with our functions

Testing Locally

$ DEVELOPMENT=true node functions/GetIceCream/test.js
Image for post
Image for post
Our lambda function running our local machine

Invoking the function remotely

$ apex invoke GetIceCreaResults
Image for post
Image for post
Results are shown as if the function was run through the Lambda console

API Gateway

Although this is not an API Gateway management guide, I have used the stock standard API Gateway web based interface to manage my API’s as this is always a one off process. Once I have created my API’s I export the API’s into a swagger file for backup purposes.

Summing Up

As you can see, once all setup this is a fairly easy process to now test and deploy your lambda functions in a project of any scale.

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store