Go Serverless with NodeJS and AWS Lambda

Make your NodeJS Express API run serverless and deploy it to AWS

Feature Image

Serverless architecture is an alternative to high-maintenance, resource-wasting servers. With serverless deployments, you only have to pay for precisely what you use. And it frees you from having to handle multiple server setups and their configurations.

So, it’s no surprise that developers today flock to go serverless with their applications. With the help of AWS Lambda and Serverless framework, you can quickly deploy applications that scale.

In this tutorial, we are looking at deploying a simple serverless API with Node.js, AWS Lambda, and the Serverless framework.


A bit about these technologies

AWS Lambda is a cloud-based serverless service. Lambda functions are stateless functions that are triggered by events and expired at the end of their execution.

Given the complex nature of AWS Lambda, we use the Serverless framework to simplify the deployment process. In fact, with Serverless, you can deploy your Node application in just a few steps.


Prerequisites

To continue with this tutorial, you need to have the following things set up.

  • An AWS account . If you are only experimenting with AWS, you can join a free tier without having to pay a dime.
  • Create an IAM user in your AWS console. Follow the steps in this post to create the IAM user. Remember to save the access key Id and secret access key before going to the next step.

Install and setup Serverless

You can install Serverless easily with npm. Run the following command to install it globally.

npm install -g serverless

Next, configure installed Serverless with IAM keys using the following command. Use the ID and key saved when creating the IAM user as key and secret, respectively.

sls config credentials --provider aws --key xxx --secret xxx

Create the Node application

I created a simple Hello World application for this tutorial, but you can deploy more complex applications following the same logic.

const express = require("express");
const sls = require("serverless-http");
const app = express();

app.get("/", (req, res) => {
    res.send("Hello World");
});

app.get("/:userName", (req, res) => {
    res.send(`Welcome, ${req.params.userName}`);
})

module.exports.handler = sls(app);

As you can see above, we use the serverless-http npm package to setup the serverless application, so make sure you have the package installed. You can install the library with:

npm install --save express serverless-http

Create the serverless.yml file

We use a file named serverless.yml to pass Serverless configurations. For our simple application, it contains the following properties.

service: node-serverless-app

provider: 
  name: aws 
  runtime: nodejs10.x
  stage: dev 
  region: eu-central-1 

functions: 
  app: 
    handler: app.handler 
    events: 
      - http: 
          path: / 
          method: ANY 
      - http: 
            path: /{proxy+} 
            method: ANY 

Here, the functions property lists all the functions in our application. We pass a single function named app and uses the exported reference to the handler in the app.js file as the function handler.

Then, we need to add the events that would trigger the given function. We pass the HTTP requests as the triggering events. I have set it up in the above configuration to call the app function every time an HTTP request is sent.

The use of /{proxy+} forwards every request allowing the Express application to handle every request by itself instead of handling the requests at the API gateway level.


Deploy the application

Now that we have passed our configuration to the serverless.yml deploying the application is only a single command matter.

sls deploy

And its output will look like this.

SLS Deploy Output Example

SLS Deploy Output Example

Congratulations! You have successfully deployed your first serverless application to AWS.

You can visit the deployed application at the links provided under endpoints. If you visit the root, you will see the message “Hello World”.


Path specific routing

Remember how we proxied all the routes to the Express application? Though there are benefits to this implementation, like limiting cold starts, we miss out on benefitting from some serverless architecture features.

Instead of routing all the paths with one Lambda function, we can introduce path specific routes that are handled by different Lambda functions. It allows us to get a better insight into the application using path-specific metrics.

In that case, update the serverless.yml like this so that a different function handles each path.

functions: 
  helloWorld:
    handler: app.handler
    events:
      -http:
        path: /
        method: get
  welcome:
    handler: app.handler
    events: 
      -http:
        path: /{userName}
        method: get

Adding environment variables

If you want to pass environment variables to the application, you can use the environment property.

For example, if you want to pass a NODE_ENV variable, you can set it up like this.

provider: 
  name: aws 
  runtime: nodejs10.x
  stage: dev 
  region: eu-central-1 
  environment:
   NODE_ENV: production

If you want to pass the environment variables from a .env file, you need to use the serverless-dotenv-plugin.

First, install the plugin as a development dependency.

npm install serverless-dotenv-plugin --save-dev

You can then create a .env file in the root directory and add the environment variables to it.

STAGE=dev
SECRET=**********

Once you have listed the dotenv-plugin under application plugins, you can import the stored environment variables and use them inside the serverless.yml file.

service: node-serverless-app

provider: 
  name: aws 
  runtime: nodejs10.x
  stage: ${env:STAGE}
  region: eu-central-1 
  environment:
   SECRET: ${env:SECRET}

functions: 
  helloWorld:
    handler: app.handler
    events:
      - http:
          path: /
          method: get
  welcome:
    handler: app.handler
    events: 
      - http:
          path: /{userName}
          method: get

plugins:
  - serverless-dotenv-plugin

Use Serverless Offline

Until this point, we had to deploy our application even to carry out the simplest of route tests. You only have to write two-three new routes in your application to realize how annoying this is.

What if there is a way to test your application before deploying it to AWS?

With the use of the serverless-offline plugin, you can do just that. You only have to install a new npm package and add one new line of code to the serverless.yml file to make this work.

First, install the package.

npm install serverless-offline --save-dev

Then, update serverless.yml.

plugins:
  - serverless-offline
  - serverless-dotenv-plugin

Now, you simply have to run the following command to start the application locally.

sls offline start

It will show you a list of all the routes in your application. Also, most importantly, it starts your application running locally on port 3000.

You can now test the application routes by visiting them on your browser with the URL, http://localhost:3000.


Summary

Serverless architecture is still in its early days compared to servers. You can count on it becoming even more powerful and prominent in the coming years. I hope your first experience with Serverless and AWS Lambda tempted you to give this technology a chance next time you are looking for a deployment option.

Thanks for reading!

Join the Free Newsletter

A free, weekly e-mail with the best new articles, courses, and special bonuses.

We won't send you spam. Unsubscribe at any time.