Migrating your Node.js REST API to Serverless
Tags: javascript, serverless, node, aws
Published: 2018-01-17 10:27:30

---
title: "Migrating your Node.js REST API to Serverless"
published: true
tags: javascript,serverless,node,aws
canonical_url: https://hackernoon.com/migrating-your-node-js-rest-api-to-serverless-d2a170e0856c
cover_image: https://cdn-images-1.medium.com/max/1024/1*5UL0AphTuLNdlLnVsd-7Nw.jpeg
series: Serverless Crash Courses
---

I’ve dabbled a fair share in the dark arts of Serverless. Digging into the various pros and cons of not having dedicated servers, or instances you can call your own. Even if they technically are not. They’re just in some undisclosed server farm somewhere floating in the&nbsp;_cloud_.

Many of the use cases make sense to let the cloud provider handle the server management, scaling and up time. You’re a developer, why should you need to get your hands dirty with the horror of the command line. Ew, the terminal! How do you exit Vim again? _\*shivers\*_

Learning new things is not easy, believe me. I’m not in any way an above average developer. Learning is hard, even if you’re a dev, and used to learning new things. Shifting your mindset to using Serverless Architecture is not a small feat. Here’s my take on starting slow. I’ll show you how to use the code you’re already used to, and apply it to a Serverless environment.

If you have an app in production, you can cut costs drastically. With the auto-scaling properties of using Serverless Architecture, you can rest assured it will always serve all the users hitting your API. So, if you ever make it big and get featured on Tech Crunch, the influx of users won’t break all your servers and leave your users hanging. Pun intended.

### From server to Serverless

The goal will be to take an existing Express API and edit it slightly to be deployed to AWS through the Serverless framework. I’ll expect you already have an AWS account and an installation of the Serverless framework set up and working on your machine. If not, please check [this](https://dev.to/adnanrahic/a-crash-course-on-serverless-with-nodejs-5jp) out and follow along the steps to set up an installation of the Serverless framework. Otherwise, if you more prefer screen casts, [here’s](https://www.packtpub.com/web-development/serverless-javascript-example-video) a course where I explained it through&nbsp;video.

#### Let’s set up an old-school server

I’ve taken the liberty of creating a small repo with an Express REST API. It’s from one of my [previous articles](https://hackernoon.com/restful-api-design-with-node-js-26ccf66eab09) you may have read. My point for taking an existing Express API is to show how easy it is to migrate it to using Serverless.

First, let’s clone the repo to our machine. We’re grabbing the dev branch where I’ve set up all the necessary modules and configurations.

```shell
$ git clone -b dev https://github.com/adnanrahic/nodejs-restful-api.git
```

This will clone the repo into a directory named nodejs-restful-api. Open it up in a code editor of choice. We have some work to&nbsp;do.

First thing’s first. Installing node&nbsp;modules.

```shell
$ npm install
```

Running npm install will install all modules from the **package.json** file. That shouldn’t take longer than a few&nbsp;seconds.

Once that’s done we need to configure the database connection. We keep this in the **db.js** file. Opening it up you see **mongoose** is connecting to a database connection URL which we keep in an environment variable.

```js
// db.js

var mongoose = require('mongoose');
mongoose.connect(process.env.DB, { useMongoClient: true });
```

We set this environment variable in an&nbsp; **.env** file. A sample file is present, named **sample.variables.env**. Let’s open it up and rename it to **variables.env**.

```
// variables.env

DB=mongodb://localhost:27017/test
```

The default connection is set up as the local instance of MongoDB. You can use any connection URL you want. [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) or [mLab](https://mlab.com/) are both&nbsp;fine.

**_Note_** _: If you want to follow along coding in this tutorial please create a MongoDB Atlas database cluster. This will be used once we deploy the application to AWS. You can follow along the tutorial_ [_here_](https://dev.to/adnanrahic/building-a-serverless-rest-api-with-nodejs-and-mongodb-43db) _to learn how to create an Atlas cluster or_ [_this_](https://hackernoon.com/restful-api-design-with-node-js-26ccf66eab09) _tutorial to create an mLab instance._

What’s left to do is just run the server. Jump back to the terminal.

```shell
$ node server.js
```

If you added a valid database connection URL it should log back Express server listening on port 3000 to the command&nbsp;line.

Using Insomnia, I’ll just quickly add a new user to the database.

![](https://cdn-images-1.medium.com/max/1024/1*kyp_64_iPwvgAY33FIIpSA.png)

Don’t forget to pick **“Form URL Encoded”** as the content type. Change the method to GET and remove the request body. Now check if the user was added correctly.

![](https://cdn-images-1.medium.com/max/1024/1*Sitbvbc4R5Lpoj-PKrfOsw.png)

Seems right. John is alive and&nbsp;well.

Using this traditional approach with a server and a running Express API is great for various use cases. But, you have to pay for it even if you don’t have any real user throughput. But what’s dangerous is that if you would suddenly get a large influx of users, you’d have to scale it manually. That’s no fun. Serverless does that for you, automagically!

#### Migrate to Serverless

Guess what, you can use the code above and deploy it to AWS using the Serverless framework with just a couple of minor changes. Actually, you’re just replacing a couple of lines in the **server.js** file and installing one more module. Lastly, you add a Serverless configuration file named **serverless.yml**. That’s&nbsp;it!

```js
// server.js

// before

require('dotenv').config({ path: './variables.env' });
var app = require('./app');

var port = process.env.PORT || 3000;
var server = app.listen(port, function() {
  console.log('Express server listening on port ' + port);
});

// after

require('dotenv').config({ path: './variables.env' });
var app = require('./app');

var serverless = require('serverless-http');
module.exports.handler = serverless(app);
```

We’re replacing the server with the [serverless-http](https://github.com/dougmoscrop/serverless-http) module. This module is then given the whole Express app object and exported with a handler. We’ll configure this handler in the **serverless.yml** file. But first, install the&nbsp;module.

```shell
$ npm install --save serverless-http
```

There we go. Create the new **serverless.yml** file in the root of the project directory, and paste this code in. It’s very important to keep the indents correct, hence why I’ve added it as a&nbsp;gist.

{% gist https://gist.github.com/adnanrahic/8972c6b23f46e7fb63400a5e992d7442 %}

What’s happening here is that you’re hooking the handler function from the **server.js** file to the / endpoint. On AWS it will mean the whole app object will be created as a single Lambda function with one main API Gateway route. How cool is&nbsp;this!?

#### Test and&nbsp;deploy

You may have noticed the plugins section in the **serverless.yml** file. It states one plugin named serverless-offline. We need this to run a local emulation of [Lambda](https://dashbird.io/lambda-cost-calculator/) and [API&nbsp;Gateway](https://dashbird.io/api-gateway-cost-calculator/).

```shell
$ npm install --save-dev serverless-offline
```

There we have it. Now just spin up the emulation.

```shell
$ sls offline start --skipCacheInvalidation
```

Test out the same endpoints as we did above and you should see they work exactly the same. Now comes the fun part. Deploying all of this is a breeze. One command and that’s&nbsp;it.

```shell
$ sls deploy
```

The deploy command will return back to you an endpoint. This is your deployed API’s root&nbsp;path.

![](https://cdn-images-1.medium.com/max/798/1*1Lrc-m4M79zTM2fGRVAJhg.png)

Would you believe me that this is all that’s required? Well, it is. Feel free to try this endpoint out. It’ll behave just as the local instance did. What’s even cooler is that this is all packaged into a single function. Let me show&nbsp;you.

### Do you even log&nbsp;bro?

What does it mean that it’s all just one Lambda function? Most importantly for us is that we’ll only have one cold start. Meaning it’s a lot more manageable to keep the Lambda warm. Whichever request method it gets, it’ll hit the same function. For a small project, this is fine but not that great for larger things. But here’s the kicker. You can build this on a microservice level. The /users route can have one dedicated Lambda while other features can have their own. And all of this is doable with the same code and modules you’re already used&nbsp;to!

Check this out. I’ve been using [Dashbird](https://www.dashbird.io/) for some time now to monitor my Lambdas and I could not be any happier. I’d never be able to see all of this through CloudWatch alone.

![](https://cdn-images-1.medium.com/max/1024/1*MYHPMN0UzndjYIGOBPLXIQ.png)

All of the requests are made to the same function even if the methods are different. Some of them are POSTs, others are GETs. But they all fire the same Lambda. I can’t be the only one here hyped about the fact you can write all the code you’re used to already, but deploy it to Lambda&nbsp;instead.

### Wrapping up

Today we’ve seen that learning Serverless isn’t that big of a deal. It’s rather easy to migrate an existing app. I mean why wouldn’t you? If you don’t want to pay for your server all the time, and only pay for what you use, it makes perfect sense. I mean, it’s literally almost free to run a small to average sized REST API with Serverless Architecture. Only that makes it viable, not to mention the autoscaling. Maybe it’s time for you to re-think the tech stack for your next project. I hope I’ve made you a believer.

If you want to take a look at all the code we wrote above, [here’s the repository](https://github.com/adnanrahic/nodejs-restful-api/tree/sls-express-app). Or if you want to read my latest articles, head over [here](https://dev.to/adnanrahic).

If I’ve intrigued you to learn more about Serverless, feel free to take a peek at a [course](https://www.packtpub.com/web-development/serverless-javascript-example-video) I authored on the&nbsp;subject.

_Hope you guys and girls enjoyed reading this as much as I enjoyed writing it._   
_Do you think this tutorial will be of help to someone? Do not hesitate to share. If you liked it, smash the_ **_unicorn_** _below so other people will see this here on&nbsp;DEV.to._

***

*Disclaimer: <a href="https://tracetest.io?utm_source=devto&utm_medium=blog&utm_campaign=adnans_blog" target="_blank">Tracetest</a> is sponsoring this blogpost. Use observability to reduce time and effort in test creation + troubleshooting by 80%.*

***