Serverless functions in Next.js

Serverless functions in Next.js

In this tutorial, Next.js developers will learn another feature of Next.js — serverless functions. Throughout the article, we’ll discuss Next.js page routes and dynamic routes and later build on the knowledge to learn about Next.js SPA and dynamic API routes.

Next.js is a popular JavaScript framework for building server-rendered, single-page applications (SPAs) and static sites. It is built on top of React, a popular library for building user interfaces. It provides tools and features that make it easy to build fast, scalable, and reliable web applications.

One of its key features is server-side rendering (SSR), which allows you to render your React components on the server and send the resulting HTML to the client. This has several benefits, including improved performance, better SEO, and the ability to render content on the server for users with JavaScript disabled.

Next.js also includes a variety of other features, such as automatic code splitting, optimized production builds, and support for serverless functions. It is also fully compatible with the latest JavaScript features and has a thriving community of developers and plugins. One of the unique features of Next.js is its support for serverless functions, also known as Lambda functions. These functions allow developers to build scalable and performant applications by offloading specific tasks to the cloud.

In this article, we will explore how Next.js Lambda functions work and how they can be used in building Single Page Applications (SPAs). We will also cover some prerequisites for using Next.js Lambda functions in your projects.

Using Next.js Lambda Functions in Development

Next.js provides a simple and powerful way to set up page routing in your SPA. With page routing, you can define specific paths that map to different components or pages in your application. This allows you to create a seamless and intuitive user experience by organizing your content into logical sections.

To set up page routing in Next.js, you will need to create a Next.js project using the yarn create-next-app command:

yarn create-next-app example

Inside the pages directory at the root of your project, create files in this directory to correspond to routes in your application. For example, a file called “about.js” in the pages directory will be accessible at the "/about" route.

// pages/about.js

function About() {
  return <h1>About Page</h1>;

export default About;

You can also create dynamic routes in Next.js by using the [id] parametric pattern in your route. Dynamic routes are an essential feature in Next.js that allow you to create complex, flexible routes for your application. With dynamic routes, you can define a route pattern with a parameter, such as [id].js or [param].js, which can match any route that follows that pattern, like${param}.

For example, you can create a dynamic route in Next.js by creating a page component named [param].js. This component can be accessed via its dynamic route, such as pages/users/[param].js. In this example, [param] could be the page’s id, slug, or pretty URLs. This means that this dynamic route could match any route like /users/1 or /users/xyz.

Next.js will send the matched path parameter as a query parameter to the page; if there are other query parameters, it will link the matched path parameter with them. For example, if the dynamic route is pages/users/[param].js, and the matched route is /users/xyz, the query object would be {"param": "xyz"}. If there are additional query parameters, such as ?token=abcdef, the query object would be {"token": "abcdef", "param": "xyz"}.

To illustrate how to use dynamic routes in Next.js, let’s look at an example. Imagine you have a details component that displays the details of an inventory item to the user whenever they click on an item’s details. To create this component, you would create an inventory folder and, inside it, create a component named [id].js. You can then import the useRouter hook from next/router and use it to access the router object, which contains the query object with the matched path parameter. Here is an example of how you could use this in your component:

// pages/inventory/[id].js
import { useRouter } from "next/router";

const Details = async () => {
  const router = useRouter();
  const itemId = router.query["id"];

  // Retrieve item details by id
  const resp = await fetch(`${itemId}`);
  const itemDetails = resp.json();

  return (
      <h1> {itemDetails.title} </h1>
      <p> {itemDetails.price}</p>
export default Details;

With this code, when a user visits the route /inventory/23456, the dynamic route pages/inventory/[id].js will be matched, and the query object {"id": "23456"} will be passed to the component. The component will then display the details of the inventory item with an id equal to 23456 to the user.

With the above sample program, we can see that in addition to creating and serving pages with dynamic routes, Next.js can also create APIs with dynamic routes. This allows you to create flexible, dynamic APIs that handle a wide range of requests and responses.

Session Replay for Developers

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — an open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

Implementing API Routes with Next.js Lambda Functions

API routing with Next.js Serverless Functions allows you to build full-stack applications with backend endpoints using the Next.js framework. This feature, introduced in Next.js v9, enables you to develop full-stack applications that scale effortlessly, as both the frontend and backend are fully implemented with Next.js.

To create an API route in Next.js, you must place the endpoint files inside the /pages/api folder. Next.js will map these files to the /api/* endpoint. This allows you to create APIs that can be accessed from the frontend of your application.

To create a Next.js API route, you must export a request handler function as the default export. This function takes two parameters, req and res, which are instances of http.IncomingMessage and http.ServerResponse, respectively. You can use these objects to handle HTTP requests, such as GET, POST, PUT, and DELETE.

Say you have JSON data that you want to return on one of the endpoints:

// data/items.js
const items = [
    "id": 23456,
    "Title": "Item 23456",
    "Description": "XYZ description",
    "price": "$999.99"
    "id": 23457,
    "Title": "Item 23457",
    "Description": "XYZ description",
    "price": "$499.99"
    "id": 23458,
    "Title": "Item 23458",
    "Description": "XYZ description",
    "price": "$1499.99"

export default items;

To set up the endpoint, create an inventory.js file inside the /pages/api folder and update it with the following code:

// pages/api/inventory.js
import items from "../../data/items.js";

const handler = (req, res) => {
  switch (req.method) {
    case 'GET':
      try {
        // mock a GET request
      } catch(err) {
        res.status(404).json({"message": `error fetching data: ${err}`});
    case 'POST':
      try {
        // mock a POST request
        res.status(200).json({"message": "successful data write"});        
      } catch(err) {
        res.status(404).json({"message": `error writing data: ${err}`});
      // Respond to unrecognized request
export default handler;

Next.js API routes also support dynamic routes, which follow the same naming conventions as dynamic page routes. This means you can create dynamic APIs by using brackets in the filename, such as [param].js, which can match any route that follows that pattern.

// pages/api/inventory/[id].js
import items from "../../../data/items.js";

const handler = (req, res) => {
    if (req.method) {
      try {
        const { id } = req.query;
        const item = items.find((item => === parseInt(id)));
      } catch(err) {
        res.status(404).json({"message": `error fetching item details: ${err}`})

export default handler;

With the above snippet, paths like inventory/23456 will automatically be matched to the dynamic route pages/api/inventory/[id].js. The request handler function will extract the item id using the req.query object. Using this id variable, you will search the items array to find the item with the id, and send it to the client.

In addition to creating APIs with Next.js, you can also use the framework to create serverless functions. These functions are standalone pieces of code that can be executed on demand without needing a dedicated server. They are useful for handling webhooks, running background jobs, and integrating with external APIs.


In this article, we have explored how Next.js Lambda functions can be used to build scalable and performant applications. We have seen how to set up page routing and API routes in a Next.js SPA and how to use Next.js Lambda functions to handle dynamic routes and fetch data from APIs.

By using Next.js Lambda functions, you can offload specific tasks to the cloud and focus on building a high-quality user experience for your users. Whether you are building a simple SPA or a complex full-stack application, Next.js Lambda functions can help you achieve your goals.

In addition to creating APIs and serverless functions with Next.js, you can also use the framework to build webhooks and integrations with external APIs. This can be done by creating a serverless function that listens for requests from external sources and triggers certain actions within your application. Overall, Next.js API routing and serverless functions provide a powerful and flexible way to build backend application endpoints and serverless functions within the Next.js framework.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs and track user frustrations. Get complete visibility into your frontend with OpenReplay, the most advanced open-source session replay tool for developers.