16 — Runtimes — Node.js vs Edge
The word "runtime" used to be background noise until I had to pick between two of them. The model that clicked: "runtime" means the set of libraries, APIs, and functionality available during execution — and Next.js offers two: Node.js (the default, full-featured) and Edge (a lightweight subset built on V8 — the JavaScript engine that powers Chrome — optimized for proximity to users) [1][2]. The choice is a capability-vs-proximity trade, and for most code the answer is Node; Edge earns its keep in specific places.
Node.js — the full-featured default
The Node.js runtime has access to all Node.js APIs and is the default for rendering the application [1][3]. It supports every Next.js feature, every npm package (including those that depend on native modules), the filesystem, and the full standard library. Route handlers, Server Components, Server Functions — all run on Node by default.
Node.js itself is a JavaScript runtime that executes JS outside the browser, using an event-driven, non-blocking I/O model suited to scalable network applications [3]. Its dominance on the server is why so much of the npm ecosystem assumes it.
Edge — lightweight and close to users
The Edge runtime is a lightweight JavaScript runtime based on V8, designed to run code closer to the user [1][4]. Code deployed to the edge runs on a globally distributed network of servers, so a request is handled by the nearest instance rather than one origin. The payoff is reduced latency and faster cold starts — the trade is a more limited API surface.
The Edge runtime is a subset of the web platform APIs — it doesn't have the Node.js standard library, can't use most npm packages that depend on Node built-ins, and is intentionally constrained. It's the runtime used by Middleware, which is why middleware is lean and fast [1].
When to pick which
The default is Node, and that's the right answer for the majority of code. Edge earns its keep in specific situations:
- Middleware — always runs on Edge by design.
- Geo/personalization — when a response depends on the user's location, running at the edge avoids a round trip to the origin.
- Latency-critical handlers — a small, fast route that must respond in tens of milliseconds benefits from edge proximity.
The constraint that decides it: if the code needs a Node-only API (filesystem, a native module, a package that assumes Node), it can't run on Edge. The runtime is opt-in per route via a segment config:
// app/api/geo/route.ts
export const runtime = 'edge'; // opt this handler into edge
export function GET(request: Request) {
const country = request.headers.get('x-vercel-ip-country');
return Response.json({ country });
}How I use this
I leave everything on Node by default — Server Components, route handlers, Server Functions. The places I reach for Edge are middleware (mandatory) and any handler that's both latency-sensitive and free of Node-only dependencies — geo detection, lightweight auth gates, A/B test assignment. The discipline is to resist the "edge everything" temptation: the constraint on APIs bites when a route grows, and migrating off Edge later means rewriting against a smaller surface.
References
[1] Vercel, "Edge runtime," Next.js Docs, 2024. [Online]. Available: https://nextjs.org/docs/app/api-reference/edge
[2] "What is Edge Runtime?," edge-runtime.vercel.app, 2024. [Online]. Available: https://edge-runtime.vercel.app/
[3] OpenJS Foundation, "About Node.js," nodejs.org, 2024. [Online]. Available: https://nodejs.org/en/about/
[4] "Visit the dedicated Node.js roadmap," roadmap.sh, 2024. [Online]. Available: https://roadmap.sh/nodejs
Knowledge check · Question 1 of 5
Which runtime is the default for rendering a Next.js application?
Comments
Leave a Comment
You must be signed in to comment
0 Comments
No comments yet. Be the first to comment!