Introduction
One of the coolest features that Next.js offers is API Routes.
An API route is similar to a typical route, except instead of serving a statically-built HTML page, it invokes a Node.js function. You can use this for all kinds of stuff:
- Managing user authentication
- Getting and setting application data from a database
- Proxying requests to 3rd-party APIs, while keeping secrets secret
- Anything you'd normally use Node.js for!
Even mostly-static sites like this blog can benefit from being able to mix in a splash of Node. For example, this blog has a hit counter at the bottom of every article. The data for the # of hits needs to be stored in a database.
Gatsby doesn't have first-class support for API routes, but fear not! With a helping hand from Netlify, we can build something which is just as awesome.
This tutorial will show you how to add to your existing Gatsby site. No experience with serverless / backend code is expected. To follow along, you'll need a site currently being deployed on Netlify.
Watch the video NEW
Prefer your lessons in video format? Watch for free on egghead:
Link to this headingWhat are Netlify Functions?
Netlify Functions are essentially AWS Lambda functions, wrapped and integrated into Netlify's platform.
If you've heard the term “serverless”, it's usually a reference to AWS Lambda. Essentially it's a cloud platform that lets you run backend code without thinking about servers. Your code exists simultaneously on many different computers, and it scales up and down automatically as needed. Instead of paying a monthly fee for renting a server, you only pay when your code is executed.
AWS products are notoriously difficult to work with, and AWS Lambda has its share of sharp edges. Netlify Functions sands down some of these edges, by doing stuff like:
- Bundling and deploying your code when you publish changes to your site
- Managing routing
- Offering a local dev environment
In exchange for this convenience, Netlify charges a slight premium. Your first 125,000 requests are free, but anything above that adds a $25/month/site package (and the price scales up more once you exceed 2 million requests per month per site). Learn more on their pricing page.
Link to this headingHello World
Let's look at a straightforward example of a Netlify Function. Create a new root-level directory called functions
, and add a file, hello-world.js
:
js
Breaking this down, our file has a single function, which is exported using CommonJS syntax as handler
. This function can be given parameters, and we'll see them a little later on. For now, we don't need them.
We are expected to return a response object from this function, which should include:
statusCode
, an HTTP status codebody
, the contents of the response. Must be a string (you can useJSON.stringify
for objects)
In order to use this function, you'll need to save this file in a top-level functions
directory. The name of the file will become the path you can use to make the request. For example: /functions/hello-world.js
will be available at https://your-site-com/.netlify/functions/hello-world
.
Link to this headingConfiguring Netlify
I'll warn you now: this part of the tutorial is boring. Fortunately, it's a one-time setup deal. Think of it as the annoying insurance forms you need to fill out before they'll let you go ziplining.
We need to do two things:
- Enable functions for our Netlify project
- Link our local development environment to our Netlify site
Link to this headingEnabling functions
Log into your Netlify dashboard, and select your site. These pictures show the sequence needed to enable functions for your site:




Link to this headingLinking our local development environment
Next, we need to install the Netlify command-line tools. Open a new terminal and run:
bash
cd
into your Gatsby project, so we can link it to our Netlify project:
bash
You'll be prompted to select the correct project. In many cases, it can infer the project from the Git remote. After this has been completed, you should see a happy little message like this:

Link to this headingRunning locally
In order to execute the function we wrote, we need to make a request to this URL:
The URL is derived from our local path to the function (/functions/hello-world.js
), but without the .js
suffix, and with a .netlify
prefix.
Of course, if we start our Gatsby dev environment and try and access localhost:8000/.netlify/functions/hello-world
, we'll get a 404 error; our Gatsby development server doesn't know anything about this!
Instead, we'll need to run Netlify Dev, a service for running the Netlify platform on your development machine. At the time of writing, it was still in Beta, but it works great for running local serverless functions.
From within your Gatsby project, run:
bash
You should get a whole lot of output:

Let's go through this step by step:
- We run
netlify dev
in our project - It correctly identifies that this is a Gatsby project
- It sets up an AWS Lambda server on port 34567
- It starts a Gatsby dev server with
npm run develop
- It launches a wrapper server on port 8888
- It echoes the typical Gatsby output, which shows a Gatsby dev server on port 8000 (the default for Gatsby apps).
That's a lot of servers! In addition to the typical Gatsby dev server at port 8000, it also runs a Lambda server at 34567, and a "wrapper" server at 8888.
The idea with the wrapper server is that it intercepts any requests to /.netlify
. The Gatsby app doesn't have a route for that path, but Netlify does! This allows us to access our function by visiting localhost:8888/.netlify/functions
:

Link to this headingUsing Functions
Our Netlify Functions work like an API endpoint: we can hit it with fetch
whenever we want to execute them. The returned value will be the response.
We're free to use whichever HTTP action we want (GET
, POST
, etc). Here's an example of how we might retrieve the "hello World!" copy:
js
Link to this headingThe “event” Parameter
The function we've seen so far responds identically to all requests. This isn't exactly realistic; our function may depend on query or body params, cookies, the HTTP method, and so on. Fortunately, our function takes an event
parameter, which tells us all about this request.
Here's a quick look:
js
Link to this headingCDNs for the backend
Many people pick Gatsby because they like the idea of a site that can be compiled to plain HTML + CSS + JS, deployed around the world on a simple CDN instead of a monolithic server.
This is really cool, because it means you get a blazing fast site with perfect uptime; since your site is copied across thousands of individual static servers across the world, there's no problem at all if a bunch of them spontaneously explode.
Up until very recently, if we needed a dynamic runtime backend, we'd need to introduce a single point of failure; we'd need to rent a VPS and install a Node/Express app, and hope it doesn't crash if a meteor hits the data center, or our site gets featured on Product Hunt.
Serverless functions are CDNs for the backend. When you deploy a function to AWS Lambda through Netlify Functions, it's dispersed across the cloud, and it automatically scales up or down depending on traffic. We don't lose any resiliency by introducing backend functions!
This tutorial is ending, but your journey with functions is just beginning. Now that you have this tool in your toolbox, a lot of new doors are open to you!
In the near future, I'll be writing about how I use serverless functions and FaunaDB to set up things like a hit counter + a “like” button. Be sure to subscribe and I'll let you know when it's published!
Last Updated
June 10th, 2020