Skip to content
For the complete Netlify documentation index, see llms.txt. Markdown versions of any documentation page are available by appending .md to its URL.

Get started with Netlify Server

A server is a single file in your project. Create it, run it locally, and deploy it like the rest of your project.

Write your server whichever way you like, with a Node.js web framework such as Express, Hono, or Fastify, with a plain Node.js HTTP server, or as a handler with the same signature as Netlify Functions. Servers run on Node.js, so you write them in JavaScript or TypeScript. For full-stack frameworks such as Next.js, refer to Full-stack frameworks.

There are no ports to configure, no health-check endpoints to add, and no adapters to install. Netlify works out how to run your server, and handles the rest.

Netlify looks for your server at netlify/server/index.ts in your project. You can also use index.mts, index.js, or index.mjs. A project can have one server, so the build fails if this directory contains more than one of these files.

Each example below answers /api/hello with the visitor's city. If your framework isn't listed, go to Other frameworks to learn how to bring it over.

  1. Install the @netlify/server package for its types:

    Terminal window
    npm install @netlify/server
  2. Create the entry file and export a handler, with the same signature as a Netlify function:

    netlify/server/index.ts
    import type { Context } from "@netlify/server";
    // Runs once per instance, before it receives any traffic.
    const startedAt = new Date();
    export default async (req: Request, context: Context) => {
    const { pathname } = new URL(req.url);
    if (pathname === "/api/hello") {
    return Response.json({
    message: `Hello from ${context.geo.city ?? "somewhere"}`,
    instanceStartedAt: startedAt,
    });
    }
    return new Response("Not found", { status: 404 });
    };

Any Node.js web framework can run on Netlify Server. What to put in the entry file depends on what your framework's app is.

An app with a fetch method that takes a Request and returns a Response, as defined by the Fetchable specification, can be exported as it is:

netlify/server/index.mjs
import { app } from "./app.js";
export default app;

If your framework gives you a function that takes a Request and returns a Response, rather than an object, export the function instead. Netlify calls it as a handler.

A Node.js request listener is a function that takes Node.js request and response objects, (req, res). Wrap it in http.createServer() and export the server, without calling listen(). This works whatever the listener's signature, and supports WebSockets:

netlify/server/index.mjs
import { createServer } from "node:http";
import { handleRequest } from "./app.js";
export default createServer(handleRequest);

Express and Connect apps are request listeners too. You can export one as it is, but Netlify then answers WebSocket requests with a 501, so wrap it in a server as above if you need WebSockets.

Start the server as the framework's documentation shows, listening on process.env.PORT:

netlify/server/index.mjs
import { app } from "./app.js";
app.listen(process.env.PORT);

Netlify waits up to 10 seconds after your start hooks finish for the server to start listening, and then sends requests to it.

Start the Netlify dev server from the root of your project, using version 27.17.0 or later of the Netlify CLI:

Terminal window
netlify dev

The CLI runs your server alongside your frontend, functions, and edge functions, and restarts it whenever you change a file under netlify/server/. Refer to Local development for more details.

Deploy your project the way you normally do, for example by pushing to your Git repository or running netlify deploy, with version 27.17.0 or later of the Netlify CLI. Netlify detects netlify/server/ during the build, bundles your server, and deploys it together with the rest of your project. Your server runs on the same Node.js version as your build, which must be 24 or later.

Every deploy gets its own server, including deploy previews, so you can validate backend changes before they reach production.

  • Connect to a database with Netlify Database, and create the connection pool once at the top level of your entry file so every request reuses it.
  • Hold connections open with WebSockets and Server-Sent Events.
  • Close connections and flush buffers before an instance stops with onShutdown.
  • Respond right away and finish work afterwards with waitUntil.
  • Find what your server logs in its logs.
  • Tell Netlify how busy resources such as a connection pool are with onHealthCheck, so it sends requests to the instances with the most room.
  • Choose where your server runs and how big its instances are with region and size.