For the complete Netlify documentation index, see llms.txt. Markdown versions of any documentation page are available by appending .md to its URL. A server is a single file in your project. Create it, run it locally, and deploy it like the rest of your project.
Create a server
Section titled “Create a server”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.
-
Install the
@netlify/serverpackage for its types:Terminal window npm install @netlify/server -
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 });};
-
Install Express and
@netlify/server:Terminal window npm install express @netlify/server -
Create the entry file with your app, started the way Express's documentation shows:
netlify/server/index.mjs import express from "express";import { getContext } from "@netlify/server";const app = express();app.get("/api/hello", (req, res) => {const { geo } = getContext();res.json({ message: `Hello from ${geo.city ?? "somewhere"}` });});app.listen(process.env.PORT || 3000);
-
Install Hono and
@netlify/server:Terminal window npm install hono @netlify/server -
Create the entry file and export your app:
netlify/server/index.ts import { Hono } from "hono";import { getContext } from "@netlify/server";const app = new Hono();app.get("/api/hello", (c) => {const { geo } = getContext();return c.json({ message: `Hello from ${geo.city ?? "somewhere"}` });});export default app;
-
Install Fastify and
@netlify/server:Terminal window npm install fastify @netlify/server -
Create the entry file with your app, started the way Fastify's documentation shows:
netlify/server/index.mjs import Fastify from "fastify";import { getContext } from "@netlify/server";const app = Fastify();app.get("/api/hello", async () => {const { geo } = getContext();return { message: `Hello from ${geo.city ?? "somewhere"}` };});await app.listen({ port: Number(process.env.PORT) || 3000 });
Other frameworks
Section titled “Other frameworks”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.
Your app has a fetch method
Section titled “Your app has a fetch method”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:
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.
Your app is a request listener
Section titled “Your app is a request listener”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:
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.
Your framework starts its own server
Section titled “Your framework starts its own server”Start the server as the framework's documentation shows, listening on process.env.PORT:
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.
Run locally
Section titled “Run locally”Start the Netlify dev server from the root of your project, using version 27.17.0 or later of the Netlify CLI:
netlify devThe 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
Section titled “Deploy”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.
Next steps
Section titled “Next steps”- 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
regionandsize.
Did you find this doc useful?
Your feedback helps us improve our docs.