Build your Backend with Netlify Functions in 20 Minutes
Tags: javascript, webdev, netlify
Published: 2020-12-08 16:38:16

---
title: Build your Backend with Netlify Functions in 20 Minutes
published: true
description: Netlify makes deploying your front end quick and easy, and Netlify functions makes running a serverless backend just as easy.  In this guide we'll get setup on how to use Netlify functions, cover the new (premium) background functions
canonical_url: https://labs.thisdot.co/blog/build-your-backend-with-netlify-functions-in-20-minutes
tags: javascript, webdev, netlify
cover_image: https://images.ctfassets.net/zojzzdop0fzx/61c5Lu7Xr2qPf5dr2X23k9/645b96b6a8f0478b6fd8347488584822/Build_your_Backend_with_Netlify_Functions_in_20_Minutes.png
---


<!-- 
# Build your Backend with Netlify Functions in 20 minutes
-->

Netlify makes deploying your front end quick and easy, and Netlify functions makes running a serverless backend just as easy.

In this guide, we'll get setup on how to use Netlify functions.  As an indie developer, you should embrace serverless offerings because of their low barrier to entry and generous free tiers.  And as an enterprise shop, you should seriously consider them for an extremely cheap, fast, and scalable way to build out your backend infrastructure.

## Use Cases - What can you build?

Modern JavaScript frameworks allow us to build large and complex applications on the client, but they can occasionally run into limitations.  For everything else, there's the "backend" which excels at handling some of these use cases:

* Protecting Secrets & Credentials
* Server Side Rendering
* Sending Emails
* Handling File IO
* Running centralized logic
* Executing tasks off the main thread
* Bypassing CORS issues for locked down APIs
* Providing Progressive Enhancement / NoScript Fallback

## Composition of a Function

[Netlify Functions](https://www.netlify.com/products/functions/) provides a wrapper around [AWS Lambdas](https://aws.amazon.com/lambda/).  While the Netlify documentation should be sufficient, it's good to know that there's an escape hatch if you ever want to run on your own AWS subscription.  However, Netlify handles some of the deployment magic for you, so let's start there.

Here's the bare bones of a Netlify function in JavaScript:

```js
exports.handler = async function(event, context) {
    return {
        statusCode: 200,
        body: JSON.stringify({message: "Hello World"})
    };
}
```

If you're familiar with running JavaScript on Node, this should look somewhat familiar.  Each function should live in its own file, and will execute whatever is assigned to `exports.handler`. We have access to `event` and `context`.  We can run whatever code we need on Node, and return whatever response type we'd like.

To set this up, lets create an empty repository on GitHub.  We need to add functions to a folder.  While we can use any name, a common pattern is to create a folder name `functions`. Let's add a file in there called `hello.js`

```js
//functions/hello.js
exports.handler = async (event, context) => {
  const { name = "Anonymous" } = event.queryStringParameters;
  return {
    statusCode: 200,
    body: `Hello, ${name}`
  };
};
```

In our function, we can grab information from the query string parameters passed in.  We'll destructure those ([with a default value](https://wesbos.com/destructuring-default-values)) and look for a `name` param.

To actually wire up our functions folder, we'll need to add a [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/#functions) config file at the root of our project.

```ini
# netlify.toml
[build]
  functions = "functions/"
```

## Walk Before You Run (Locally)

Our "repo" should look like this at this point:

```bash
my-app
├── functions
│   └── hello.js
└── netlify.toml
```

The best way to run your Netlify site locally, with all the bells and whistles attached, is to use [Netlify Dev](https://www.netlify.com/products/dev/) which you can install via npm:

```bash
npm install netlify-cli -g
```

And then kick off your dev server like this:

```bash
netlify dev
```

![Netlify Dev](https://images.ctfassets.net/zojzzdop0fzx/3TH4jBOh9rpMHtaMbggESp/015afef380a9d9e8bd7f6bf8468eb3ac/netlify-dev.png)

Your "site" should now be live at `http://localhost:8888`. By default, Netlify hosts functions under the subpath `/.netlify/functions/<fn-name>` so you can invoke your function here:

http://localhost:8888/.netlify/functions/hello?name=Beth

Now, let's make our function's address a little cleaner by also taking advantage of another free Netlify feature using [redirects](https://docs.netlify.com/configure-builds/file-based-configuration/#redirects).  This allows us to expose the same functions at a terser url by replacing `/.netlify/functions` with `/api`.

**FROM**: `<site>/.netlify/functions/hello`
**TO**: `<site>/api/hello`

To do so, append the following info to your `netlify.toml` config, and restart Netlify dev:

```ini
[[redirects]]
  from = '/api/*'
  to = '/.netlify/functions/:splat'
  status = 200
```

This will route all traffic at `/api/*` internally to the appropriate functions directory, and the wildcard will capture all additional path info, and move to `:splat`.  By setting the [HTTP Status Code = `200`](https://docs.netlify.com/routing/redirects/redirect-options/#http-status-codes), Netlify will preform a "rewrite" (as opposed to a "redirect") which will change the server response without changing the URL in the browser address bar.

So let's try again with our new url:

http://localhost:8888/api/hello?name=Beth

![hello world](https://images.ctfassets.net/zojzzdop0fzx/LgezyZNZ9J2IJ6xqHLiUH/6636d093beff3dd4381c2f0f59ad64a6/hello-world.png)

👏 Awesome, you just created a function! (you're following along live, right?)

## Getting the CRUD Out & Submitting Data

Now that we can build functions, let's create our own API with some basic CRUD functions (Create, Read, Update, & Delete) for a simple todos app.

One of the central tenants of serverless computing is that it's also stateless.  If you need to store any state across function invocations, it should be persisted to another, layer like a database.  For this article, let's use the free tier of DynamoDb, but feel free to BYODB (Bring Your Own DB), especially if it has a Node SDK.

In the next steps, we'll:

1. Setup a table on DynamoDB in AWS
2. Install npm packages into our project
3. Setup secret keys in AWS, and add to our environment variables
4. Initialize the aws-sdk package for NodeJs
5. And then finally add a Netlify function route to create a record on our database

### AWS - Amazon Web Services

This guide will assume some degree of familiarity with AWS & DynamoDB, but if you're new to DynamoDB, you can start with this guide on [Getting Started with Node.js and DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.NodeJs.html).

On AWS, [create a table](https://console.aws.amazon.com/dynamodb/home?region=us-east-1#create-table) with the name `NetlifyTodos`, and string partition key called `key`.

### NPM - Node Package Manager

Now, let's setup npm and install [`aws-sdk`](https://www.npmjs.com/package/aws-sdk), [`nanoid`](https://www.npmjs.com/package/nanoid), & [`dotenv`](https://www.npmjs.com/package/dotenv).

In a terminal at the root of your project, run the following commands:

```bash
npm init -y
npm install aws-sdk nanoid dotenv --save
```

### ENV - Environment Variables

You'll  need to provision an [access key / secret for an IAM user](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-iam-create-creds.html) that we'll use to authenticate our API calls.  One of the benefits of running these calls on the server is you're able to protect your application secret through environment variables, instead of having to ship them to the client, which is not recommended.

There are quite a few ways to log into AWS on your local machine, but just to keep everything inside of our project, let's create a `.env` file at the root of our project, and fill in the following keys with your own values:

```ini
# .env
MY_AWS_ACCESS_KEY_ID=***
MY_AWS_SECRET_ACCESS_KEY=***
MY_AWS_REGION=us-east-1
```

**NOTE**: One little gotcha here is that the more common `AWS_ACCESS_KEY_ID` is a reserved environment keyword used by the Netlify process.  So if we want to pass around env variables, we'll have to use our own key, in this case prefixed with `MY_`.

Once they're added to the process, we can destructure them and use in setting up our AWS SDK.  We'll need to setup AWS for every CRUD function, so let's assemble all this logic in a separate file called `dyno-client.js`.

```js
// dyno-client.js
require('dotenv').config()
const { MY_AWS_ACCESS_KEY_ID, MY_AWS_SECRET_ACCESS_KEY, MY_AWS_REGION } = process.env
```

The following is required.

### SDK - Software Developer Kit

Using the aws-sdk makes our life a lot easier for connecting to DynamoDB from our codebase.  We can create an instance of the Dynamo client that we'll use for the remaining examples:

```js
// dyno-client.js
const AWS = require("aws-sdk");

AWS.config.update({
    credentials: {
        accessKeyId: MY_AWS_ACCESS_KEY_ID,
        secretAccessKey: MY_AWS_SECRET_ACCESS_KEY
    },
    region: MY_AWS_REGION,
});

const dynamoDb = new AWS.DynamoDB.DocumentClient();
```

To make this available to all our functions, add the DynamoDB instance to your exports, and we'll grab it when we need it:

```js
module.exports = { dynamoDb, TABLE_NAME }
```

### Create Todo (Due by EOD 😂)

⚡ We're finally ready to create our API function!

In the following example, we'll post back form data containing the `text` for our todo item.  We can parse the form data into JSON, and transform it into an item to insert into our table.  If it succeeds, we'll return the result with a status code of `200`, and if it fails, we'll return the the error message along with the status code from the error itself.

```js
// functions/create.js
const { nanoid } = require("nanoid");
const { dynamoDb } = require("../dyno-client")

exports.handler = async(event, context) => {
    try {
        // parse form data
        const body = JSON.parse(event.body);

        // create item to insert
        const params = {
            TableName: TABLE_NAME,
            Item: {
                key: nanoid(7),
                text: body.text,
                createDate: new Date().toISOString(),
            },
        };

        let result = await dynamoDb.put(params).promise();

        // return success
        return {
            statusCode: 200,
            body: JSON.stringify({
                success: true,
                data: result,
            }),
        };

    } catch (error) {
        return {
            statusCode: error.statusCode || 500,
            body: JSON.stringify(error),
        };
    }

};
```

This should give you the gist of how to expose your API routes and logic to perform various operations.  I'll hold off on more examples because most of the code here is actually just specific to DynamoDB, and we'll save that for a separate article.  But the takeaway is that we're able to return something meaningful with very minimal plumbing.  And that's the whole point!

> **With Functions, you *only* have to write your own business logic!**

## Debugging - For Frictionless Feedback Loops

There are two critical debugging tools in Visual Studio Code I like to use when working with node and API routes.

1. Script Debugger &
2. Rest Client Plugin

✨ **Did you know**, instead of configuring a custom [`launch.json`](https://code.visualstudio.com/docs/editor/debugging#_launchjson-attributes) file, you can run and attach debuggers directly onto npm scripts in the `package.json` file:

![npm debug](https://images.ctfassets.net/zojzzdop0fzx/4VpMPC1mLnzbEgmKIXkJSG/d7329a551088f26c647b7bfec9c1b8c0/npm-debug.png)

And while tools like [Postman](https://www.postman.com/) are a valuable part of comprehensive test suite, you can add the [REST Client Extension](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) to invoke API commands directly within VS Code.  We can easily use the browser to mock GET endpoints, but this makes it really easy to invoke other HTTP verbs, and post back form data.

Just add a file like `test.http` to your project.  *REST Client* supports expansion of variable environment, and custom variables.  If you stub out multiple calls, you can separate multiple different calls by delimiting with `###`.

Add the following to your sample file:

```js
@baseUrl = http://localhost:8888

// create todo item
POST {{baseUrl}}/api/create
content-type: application/json

{
    "text": "Feed the cats",
}
```

![send request](https://images.ctfassets.net/zojzzdop0fzx/5gpNvzYCy2gAEulbefRLyq/0f2c65a170ca23ddf7d51a1fca799aeb/send-request.png)

We can now run the above by clicking "Send Request".  This should hit our Netlify dev server, and allow us to step through our function logic locally!

![debugger breakpoint](https://images.ctfassets.net/zojzzdop0fzx/rObvoyuZYuGpmk4FCQTWW/ca72b014f162dcc726f40918898295dd/breakpoint.png)

## Publishing

Publishing to Netlify is easy as well.  Make sure your project is committed, and pushed up to a git repository on GitHub, GitLab or BitBucket.

Login to [Netlify](https://www.netlify.com/), and click the option to Create "New Site From Git" and select your repo.

Netlify will prompt for a **Build command**, and a **Publish directory**.  Believe it or not, we don't actually have either of those things yet, and it's probably a project for another day to set up our front end.  Those commands refer to the static site build part of the deployment.  Everything we need to build serverless functions is inside our functions directory and our `netlify.toml` config.

Once we deploy the site, the last thing we'll need to do is add our environment variables to Netlify under Build > Environment

![netlify environment variables](https://images.ctfassets.net/zojzzdop0fzx/3CDrDHUXxfDZP5fonYdwlj/51ac23dc7614b96476c1c959a0454327/netlify-environment-variables.png)

## Next Steps - This is only the beginning

Hopefully some ideas are spinning as to how you can use these technologies on your own sites and projects.  The focus of this article is on building and debugging Netlify functions, but an important exercise left to the reader is to take advantage of that on your front end.

**TIP**: If you want to add Create React App to your current directory (without creating a new folder), add a `.` when scaffolding out a new app like this:

```bash
create-react-app .
```

Try it out - build a front end, and let me know how it goes at [KyleMitBTV](https://twitter.com/KyleMitBTV)!

For more context, you can browse the full source code for the article on GitHub at [KyleMit/**netlify-functions-demo**](https://github.com/KyleMit/netlify-functions-demo).

For even more practical examples with actual code, checkout the following resources as well!

* [David Wells - Netlify Serverless Functions Workshop](https://github.com/DavidWells/netlify-functions-workshop)
* [netlify/functions - Community Functions Examples](https://github.com/netlify/functions#community-function-examples)

Good luck, and go build things!

----

*This Dot Labs is a modern web consultancy focused on helping companies realize their digital transformation efforts. For expert architectural guidance, training, or consulting in React, Angular, Vue, Web Components, GraphQL, Node, Bazel, or Polymer, visit [thisdotlabs.com](https://www.thisdotlabs.com).*

*This Dot Media is focused on creating an inclusive and educational web for all.  We keep you up to date with advancements in the modern web through events, podcasts, and free content. To learn, visit [thisdot.co](https://www.thisdot.co).*