Skip to content
Deployment
Skill

/netlify-server

Build and deploy a long-lived Node.js backend on Netlify Server (Early Access) from netlify/server/index.ts. Use this skill whenever someone wants to run an Express, Fastify, Hono or Koa app on Netlify as it is, add a backend or REST/GraphQL API that keeps database pools and

From plugin
netlify-skills
5216 skills1 MCP

Claude Code

$ npx -y skills add netlify/context-and-tools --skill netlify-server --agent claude-code

SKILL.md

netlify-server.SKILL.md
name: netlify-server
description: Build and deploy a long-lived Node.js backend on Netlify Server (Early Access) from netlify/server/index.ts. Use this skill whenever someone wants to run an Express, Fastify, Hono or Koa app on Netlify as it is, add a backend or REST/GraphQL API that keeps database pools and caches warm, build real-time features such as chat, live dashboards or multiplayer with WebSockets or Server-Sent Events, or stream AI responses and run agent loops. It also covers background work after responding with waitUntil, startup and graceful shutdown hooks, load-aware health checks, edge caching of server responses, region/size/scale settings, local testing with netlify dev, reading server logs with netlify logs or log drains, and debugging a server that gets no requests, fails to start, drops database connections after a minute, or returns 429/500/501/502.

Netlify Server

Early Access, so APIs may change. It is available on credit-based plans and on Enterprise plans with credits enabled. It requires **Node.js 24+** for both build and local dev, and **Netlify CLI 27.17.0+** for both local dev and deploys.

It is free during Early Access and intended for evaluation, experimentation, and low-volume production use. At GA it will bill credits for reserved memory (GB-hours) and active CPU (vCPU-hours). **Every request the server handles already counts toward the web requests meter.**

Reach for this / avoid this

// ✅ netlify/server/index.ts — handler (same signature as Netlify Functions)
import type { Context, Config } from "@netlify/server";
export default async (req: Request, context: Context) =>
  new Response(`Hello from ${context.geo.city ?? "somewhere"}`);
export const config: Config = { path: "/api/*" };
// ✅ Fetchable app (Hono etc.): export as is
export default app;
// ✅ Node request listener: wrap it, do NOT call listen(). WebSockets work.
export default createServer(handleRequest);
// ✅ Framework that starts itself (Express/Fastify): listen on PORT within 10 s
app.listen(process.env.PORT);
// ❌ export default (req, res) => {...}   // two params = treated as a fetch handler, breaks
// ❌ export default expressApp            // works, but WebSocket upgrades get 501
// ❌ server.close(() => process.exit(0))  // cuts off shutdown hooks and background work
// ❌ setInterval / fire-and-forget promise // invisible to Netlify; the instance can stop mid-work

You don't configure ports, add health endpoints, or install adapters. Install the package with `npm install @netlify/server`.

Entry file and detection

  • Use **one** server per project: `netlify/server/index.ts`, `.mts`, `.js`, or `.mjs`. **The build fails if more than one exists.**
  • Startup runs once per instance:

1. `PORT` is set. 2. The entry file is imported, running top-level code (top-level `await` is awaited). 3. `onStart` hooks run in order. 4. The default export is inspected.

  • No traffic arrives until all steps finish. Any throw fails the start.

Netlify uses the **first matching row** for the default export:

| Default export | Run as | WebSockets | |---|---|---| | `http.Server` without `listen()` | Requests sent to it | `upgrade` event (`ws`, Socket.IO) | | Object with `fetch` (Fetchable, e.g. Hono) | `fetch(request, context)` | `upgradeWebSocket` | | Express/Connect app, or a function with ≥3 params | Wrapped in its own HTTP server | **501** | | Any other function | `(request, context) => Response` | `upgradeWebSocket` | | Anything else / nothing | Waits for your code to listen | `upgrade` event |

> ⚠️ **Self-started servers must listen within 10 s after start hooks finish.** > - If your code starts several servers, the one on `process.env.PORT` wins. If none listens on it, the start fails. > - Reserved ports are `53` and `15000–15099`. > - Only Node.js HTTP servers are supported, not raw TCP.

Create shared resources such as a DB pool at top level so they are reused across requests.

> ⚠️ **Outbound connections are closed after 60 s without data in either direction.** TCP keepalives don't count. > - Set your pool's idle timeout **below 60 s** (e.g. `idleTimeoutMillis: 30_000`), or it hands out dead connections. > - Quiet connections such as Postgres `LISTEN` need traffic at least every 60 s (e.g. `SELECT 1`), or must reconnect on close. The symptom is `Connection terminated unexpectedly`.

Examples

// netlify/server/index.mjs — Express, self-started
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);
// Fastify
const app = Fastify();
app.get("/api/hello", async () => ({ message: `Hello from ${getContext().geo.city ?? "somewhere"}` }));
await app.listen({ port: Number(process.env.PORT) || 3000 });

Background work after responding

export default async (req: Request, context: Context) => {
  const order = await saveOrder(await req.json());
  context.waitUntil(sendConfirmationEmail(order)); // keeps the instance alive until settled
  return Response.json(order, { status: 201 });
};
// In frameworks: const { waitUntil } = getContext();

How `waitUntil` behaves:

  • It is not bound by the request duration limit.
  • Rejections are logged.
  • On replacement, background work gets up to 90 s. Persist critical work to Netlify Database or Netlify Blobs.

WebSockets (handler/Fetchable)

import { upgradeWebSocket } from "@netlify/server";
export default async (req: Request) => {
  if (req.headers.get("upgrade") === "websocket") {
    const { socket, response } = upgradeWebSocket(req, { idleTimeout: 30 }); // pings off unless set
    socket.onmessage = (e) => socket.send(`Echo: ${e.data}`);
    return response; // return as is
  }
  return new Response("Connect with a WebSocket client");
};

###

Read more
@netlify
Ships withnetlify-skills

Public Netlify skills for AI coding agents. Each skill is a focused, factual reference for a Netlify platform primitive — designed to help agents build correctly on Netlify without needing to search docs.

5216 skills1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
52
Star history of netlify/context-and-tools on GitHub, a chart by star-history.com

Other skills on netlify-skills.

netlify-blobs

netlify-blobs

Store and retrieve unstructured objects, files, and cache-like state on Netlify with the @netlify/blobs module. Use when…

netlify-caching

netlify-caching

Cache dynamic and static responses on Netlify's CDN from Functions, Edge Functions, and proxies. Use when you add caching or…

netlify-config

netlify-config

Configure Netlify builds and routing via netlify.toml, _redirects, and _headers. Use when setting a build command or publish…

More skills from other plugins.

configuring-horizon

configuring-horizon

Use this skill whenever the user mentions Horizon by name in a Laravel context. Covers the full Horizon lifecycle: installing…

coolify13d66k
@coollabsio@coollabsioInstall Skill
vercel-cli

vercel-cli

Guides deployment, configuration, and troubleshooting with the Vercel CLI. Use when operating Vercel projects or resources…

vercel2w16k
@vercel@vercelInstall Skill
skypilot

skypilot

Use when launching cloud VMs, Kubernetes pods, or Slurm jobs for GPU/TPU/CPU workloads, training or fine-tuning models on cloud…

@skypilot-org@skypilot-orgInstall Skill
pinme

pinme

Use this skill when the user mentions "pinme", or needs to upload files, store to IPFS, create/publish/deploy websites or…

pinme2mo3.8k
@glitternetwork@glitternetworkInstall Skill

Questions about netlify-server.

Which coding agents can use netlify-server?
netlify-server installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.