Building a REST API in Node.js with AWS Lambda, API Gateway, DynamoDB, and Serverless Framework
Tags: aws, serverless, node, lambda
Published: 2022-03-14 15:33:06

Originally posted at [Serverless](https://www.serverless.com/blog/node-rest-api-with-serverless-lambda-and-dynamodb)

Serverless means different things depending on the context. It could mean using third party managed services like Firebase, or it could mean an event-driven architecture style. It could mean next generation compute service offered by cloud providers, or it could mean a framework to build Serverless applications.

In this tutorial, you’ll learn how to build a REST API following the Serverless approach using [AWS Lambda](https://serverless.com/aws-lambda/), API Gateway, DynamoDB, and the Serverless Framework. AWS Lambda is the third compute service from Amazon. It’s very different from the existing two compute services EC2 (Elastic Compute Cloud) and ECS (Elastic Container Service). AWS Lambda is an event-driven, serverless computing platform that executes your code in response to events. It manages the underlying infrastructure scaling it up or down to meet the event rate. You’re only charged for the time your code is executed. AWS Lambda currently supports Java, Python, and Node.js language runtimes.
>  *This tutorial is part of my [open-source hands-on guide to build real world Serverless applications](https://github.com/shekhargulati/hands-on-serverless-guide/tree/master/01-aws-lambda-serverless-framework) by Shekhar Gulati, senior technologist at Xebia. You can refer to the [guide for in-depth coverage on building Serverless applications](https://github.com/shekhargulati/hands-on-serverless-guide/tree/master/01-aws-lambda-serverless-framework).*

## Application: Lambda Coding Round Evaluator

In my current organization, one of the interview rounds is a coding round. The candidate is emailed an assignment that he/she has to submit in a week’s time. The assignment is then evaluated by an existing employee who makes the decision on whether the candidate passed or failed the round. I wanted to automate this process so that we can filter out unsuitable candidates without any human intervention. A task that can be automated should be automated. This is how the flow will work:

 1. Recruitment team submits candidate details to the system.

 2. System sends an email with assignment zip to the candidate based on candidate skills and experience. The zip contains the problem as well as a Gradle or Maven project.

 3. Candidate writes the code and submits the assignment using Maven or Gradle task like gradle submitAssignment. The task zips the source code of the candidate and submits it to the system.

 4. On receiving assignment, systems builds the project and run all test cases.

a. If the build fails, then candidate status is updated to failed in the system and recruitment team is notified.

b. If the build succeeds, then we find the test code coverage and if it’s less than a certain threshold we mark the candidate status to failed and recruitment team is notified.

5. If build succeeds and code coverage is above a certain threshold, then we run static analysis on the code to calculate the code quality score. If code quality score is below a specified threshold then candidate is marked failed and notification is sent to the recruitment team. Otherwise, the candidate passes the round and a human interviewer will now evaluate candidate assignment.

In this tutorial, we will only build a REST API to store candidate details. Please refer to the [guide](https://github.com/shekhargulati/hands-on-serverless-guide/tree/master/01-aws-lambda-serverless-framework) to learn how to build the full application from scratch. Also, source code for the application is available on [Github](https://github.com/xebiaww/lambda-coding-round-evaluator).

## Prerequisite

To go through this tutorial you will need following:

 1. AWS account

 2. Node.js

 3. AWS CLI and configure it

## What is the Serverless Framework?

The Serverless Framework makes it easy to build applications using AWS Lambda. It is multi-provider framework, which means you can use it to build Serverless applications using other providers as well. For AWS, Serverless relies on CloudFormation to do the provisioning. It also scaffolds the project structure and takes care of deploying functions.

## Getting Started with the Serverless Framework

To install Serverless on your machine, run the below mentioned npm command.
{% gist https://gist.github.com/richardgrantserverless/195c61d4cb87ad96e742c93b31d70045.js %}
This will install Serverless command-line on your machine. You can use sls alias instead of typing serverless as well.

Now, we will build the application in a step by step manner.

## Step 1: Create a Node.js Serverless Project

Navigate to a convenient location on your filesystem and create a directory coding-round-evaluator.
{% gist https://gist.github.com/richardgrantserverless/8d59d03d70e35bb3f685881b43a8f38f.js %}
Once inside the coding-round-evaluator directory, we'll scaffold our first microservice for working with candidates. This will be responsible for saving candidate details, listing candidates, and fetching a single candidate details.
{% gist https://gist.github.com/richardgrantserverless/d9f2ca1fd5851672135de57ae3fb1266.js %}
This will create a directory candidate-service with the following structure.
{% gist https://gist.github.com/richardgrantserverless/836e017496be68b3505e3ca0b4f71b16.js %}
Let’s look at each of these three files one by one.

 1. **.npmignore**: This file is used to tell npm which files should be kept outside of the package.

 2. **handler.js**: This declares your Lambda function. The created Lambda function returns a body with Go Serverless v1.0! Your function executed successfully! message.

 3. **serverless.yml**: This file declares configuration that Serverless Framework uses to create your service. serverless.yml file has three sections — provider, functions, and resources.

a. provider: This section declares configuration specific to a cloud provider. You can use it to specify name of the cloud provider, region, runtime etc.

b. functions: This section is used to specify all the functions that your service is composed off. A service can be composed of one or more functions.

c. resources: This section declares all the resources that your functions use. Resources are declared using AWS CloudFormation.

## Step 2: Create a REST Resource for Submitting Candidates

Next, we’ll update serverless.yml as shown below.
{% gist https://gist.github.com/richardgrantserverless/726976e2b843ce1ee271bf6b49725927.js %}
Let’s go over the YAML configuration:

 1. We defined name of the service — candidate-service. Service name has to be unique for your account.

 2. Next, we defined framework version range supported by this service.

 3. Next, we defined configuration of the cloud provider. As we are using AWS so we defined AWS corresponding configuration.

 4. Finally, we defined candidateSubmission function. In the configuration shown above, we declared that when the HTTP POST request is made to /candidates then api/candidate.submit handler should be invoked. We also specified memory we want to allocate to the function.

Now, create a new directory api inside the candidate-service directory. Move the handler.js to the api directory. Rename handler.js to candidate.js and rename handle to submit.
{% gist https://gist.github.com/richardgrantserverless/39ecda38263f71a652574d8ac958d333.js %}
To deploy the function, execute serverless deploy command.
{% gist https://gist.github.com/richardgrantserverless/f62fc1da2146b4d4139df38adba58dcf.js %}{% gist https://gist.github.com/richardgrantserverless/9e96e4ab83b2bcc421249fdaf9b1bac4.js %}
Now, POST operation of your service is available. You can use tools like cURL to make a POST request.
{% gist https://gist.github.com/richardgrantserverless/c2426dddb72a362d5dad5a5a1a0f93db.js %}{% gist https://gist.github.com/richardgrantserverless/41d66461c7b823694c3942fb24038709.js %}
## Step 3: Saving Data to DynamoDB

Now that we are able to make HTTP POST request to our API let’s update the code so that data can be saved to DynamoDB. We’ll start by adding iamRoleStatemements to serverless.yml. This defines which actions are permissible.
{% gist https://gist.github.com/richardgrantserverless/1501eaff8d12f0697ef1420474eed96a.js %}
Next, we’ll create a resource that will create DynamoDB table as shown below.
{% gist https://gist.github.com/richardgrantserverless/119f20d3184343b01e7baf67712d03a3.js %}
Now, install a couple of node dependencies. These will be required by our code.
{% gist https://gist.github.com/richardgrantserverless/c0332c9862fe0d9c832165725f03c7ea.js %}
Update the api/candidate.js as shown below.
{% gist https://gist.github.com/richardgrantserverless/84d0d6b885022eb46ae517751ced6c65.js %}
Now, you can deploy the function as shown below.
{% gist https://gist.github.com/richardgrantserverless/31ebb526b05144741ee812994b1beb45.js %}
This will create the DynamoDB table.

To test the API, you can use cURL again.
{% gist https://gist.github.com/richardgrantserverless/da0eaac666690d354109b4be4786d4e8.js %}
The response you’ll receive from the API is shown below.
{% gist https://gist.github.com/richardgrantserverless/64b72c3c9580d32c1c478eed5876f9a4.js %}
## Step 4: Get All Candidates

Define a new function in the serverless.yml as shown below.
{% gist https://gist.github.com/richardgrantserverless/4836797c20baa76a6fe4a9b9936e9d26.js %}
Create new function in the api/candidate.js as shown below.
{% gist https://gist.github.com/richardgrantserverless/020bc4a060389b1152b7b7d486ef2168.js %}
Deploy the function again.
{% gist https://gist.github.com/richardgrantserverless/018f4f48585e550d4681dc9c8ac03c49.js %}
Once deployed you will be able to test the API using cURL.

## Step 5: Get Candidate Details by ID

Define a new function in serverless.yml as shown below.
{% gist https://gist.github.com/richardgrantserverless/05f82c366ecd11340521bce75dc9face.js %}
Define a new function in api/candidate.js
{% gist https://gist.github.com/richardgrantserverless/173024582edbe5866dbc28f7149f433a.js %}
Now, you can test the API using cURL.
{% gist https://gist.github.com/richardgrantserverless/b459bf552514540c03814d80bb8748ed.js %}
## Working with Local DynamoDB

Download the jar and run locally.

## Invoking Functions Locally and Remotely
{% gist https://gist.github.com/richardgrantserverless/0befc54ad4c6f0853ccaa7a2e06a6a58.js %}
## Tailing the Logs
{% gist https://gist.github.com/richardgrantserverless/579781a30842fce305bab1ff6cfa386c.js %}
## Conclusion

In this part, you learned how to create a REST API with the Serverless Framework. To learn more read the [guide](https://github.com/shekhargulati/hands-on-serverless-guide/blob/master/01-aws-lambda-serverless-framework/01-introduction-to-serverless.md).

[![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t49crfzf9thtggyxu34l.png)](https://www.serverless.com/console/docs?utm_campaign=Console%20Signup&utm_source=dev.to&utm_medium=post&utm_content=Building%20a%20REST%20API%20in%20Node.js%20with%20AWS%20Lambda%2C%20API%20Gateway%2C%20DynamoDB%2C%20and%20Serverless%20Framework)