Skip to main content
All guides
How the edge works

Vercel Edge Functions explained: what they are, when to use them

Edge Functions run on Vercel's global edge network in V8 isolates. Here's exactly what that means for latency, cold starts, and the code you can ship.

Last updated July 18, 2026

What an Edge Function actually is

A Vercel Edge Function is a piece of JavaScript that runs inside a V8 isolate on Vercel's edge network — the same POPs that serve your static assets. It is not Node.js. The global APIs are Web platform APIs: fetch, Request, Response, URL, Headers, crypto.subtle, TextEncoder, ReadableStream. There is no fs module, no child_process, no native addons, and no Buffer unless you import it explicitly. Code executes in a sandbox that starts in tens of milliseconds and shuts down as soon as your response is flushed, so it behaves less like a long-lived server and more like a request-scoped worker. That constraint is what makes the runtime cheap and fast; it is also what surprises teams migrating a Node app to the edge for the first time.

Why isolates instead of containers

V8 isolates share a single host process, so they cold-start in roughly 50ms compared with 500ms–2s for a full Lambda container. Multiple functions can share memory pages, JIT caches, and TCP connections, which is why edge providers can afford to deploy your code to dozens of regions without going bankrupt. The trade-off is isolation depth: an isolate is a per-request sandbox, not a full OS process, so anything that expects a filesystem, environment inspection, or long-running background work will not fit. Think of it as a very fast function that must finish quickly and cleanly.

The 1-second init budget

Vercel enforces a 1 second CPU budget for the initial module evaluation. That includes every import you resolve at module scope. Import a heavyweight ORM, a 500KB markdown parser, or a big validation schema at the top of the file and you can trip the limit before your handler ever runs. The fix is boring but reliable: keep the top of the file to type imports and small pure utilities, and lazy-import anything expensive inside the handler with a dynamic import(). The isolate caches modules across warm invocations, so the second request pays almost nothing.

When to pick Edge over Serverless

  • Auth checks and header rewrites — low latency, no DB round trip in the hot path.
  • Personalization based on geo/IP — the edge already knows the visitor's region.
  • A/B testing and feature flags — millisecond decisions, no cold-start tax.
  • Streaming AI responses — Edge Functions natively support ReadableStream and Server-Sent Events.
  • Cheap fan-out — one request that calls several downstream APIs concurrently.

When Serverless is still the right call

  • Long-running work (>30s) — Edge tops out at 30s, Serverless goes to 60s+ on Pro and 900s on Enterprise.
  • Large dependency graphs — no 1s init budget on Lambda, so heavy ORMs and PDF libs work fine.
  • Node-only libraries — sharp, puppeteer, playwright, native database drivers, anything with a .node addon.
  • Heavy CPU work — image transforms, PDF generation, big parsing jobs.
  • Tight VPC access — Lambda can attach to a private network; Edge cannot.

A minimal example

Export a default function that takes a Request and returns a Response, and add `export const runtime = 'edge'` to opt in. The Web Streams API is your friend for streaming — return a Response wrapping a ReadableStream and clients start receiving bytes before the handler finishes. Add cache headers (Cache-Control, s-maxage, stale-while-revalidate) to let the edge cache the response next to the user; this is how a dynamic route can behave almost like a static asset for repeat visitors.

Common pitfalls

  • Assuming process.env is populated at build time — Edge reads env at request time; check for undefined.
  • Reaching for Buffer or Node streams — use Uint8Array and Web Streams instead.
  • Making a Postgres TCP connection — most Postgres drivers use raw TCP, which Edge cannot open; use HTTP-based drivers (Neon, Supabase, PlanetScale).
  • Blocking on a slow upstream — the 30s ceiling is real; add AbortController with a timeout.
  • Logging huge objects — Edge logs are truncated aggressively; log IDs and pull details from a store.

How Edge affects your architecture

Once you commit to Edge for the hot path, you tend to push more work into it: session decoding, feature flag lookups, personalization, geo routing, even lightweight rendering. That is fine, but be careful about state. Because isolates are short-lived and horizontally distributed, in-memory caches survive only a few requests before being evicted. For anything shared across users or regions, put the cache in an external store (KV, Redis, Data Cache) rather than the isolate's heap. The winning shape is usually: Edge for read, Serverless or a real service for expensive writes.

FAQ

Is Vercel's Edge runtime the same as Cloudflare Workers?
They share a shape — V8 isolates, Web APIs, no Node — and Vercel Edge runs on Cloudflare's Workers infrastructure in many regions. But the developer surface, cold-start behavior, quotas, and pricing are Vercel's. You cannot deploy a Workers script directly to Vercel Edge; you write against the Vercel abstraction and Vercel decides where it runs. Practically that means most Workers-compatible libraries work on Vercel Edge, but Workers-specific bindings (Durable Objects, R2 bindings) do not.
Can I use Prisma in an Edge Function?
Only Prisma's edge-compatible variants — Prisma Accelerate or the Data Proxy — because the standard Prisma client depends on Node APIs and Rust engines that will not run in a V8 isolate. If you must use Prisma from the edge, wrap it in Accelerate. Otherwise consider switching to Drizzle over an HTTP driver (Neon, PlanetScale, Turso), or push the DB call into a Serverless Function and call it from Edge.
Do Edge Functions cost more than Serverless?
Per invocation, Edge is cheaper because the isolate model is more efficient. But Edge is billed on CPU time consumed, so an expensive handler that spends a full second parsing JSON is not obviously cheaper than a Lambda that spends the same time. For very rare, very heavy invocations, Serverless can win on total spend. The rule of thumb: high-volume light work belongs on Edge, low-volume heavy work belongs on Serverless.
What is the timeout on a Vercel Edge Function?
Edge Functions have a 30 second wall-clock ceiling and a smaller CPU-time ceiling per request. Streaming responses reset the wall clock as long as bytes keep flowing, which is why Edge is the right pick for streaming LLM completions — you can hold a connection open for minutes as long as you keep flushing tokens. Blocking work with no streaming activity will be terminated at 30 seconds regardless of your plan tier.
Can Edge Functions read files bundled with my project?
Only via import — the bundler inlines the file into your module graph and you consume it as a string, JSON, or Uint8Array. There is no filesystem to open at runtime. This is why static assets like MDX content or small JSON blobs are typically imported directly. Anything bigger belongs in object storage or a KV, fetched over HTTP at request time.
How do I share state between Edge invocations?
Do not rely on module-level variables — isolates recycle unpredictably and requests fan out across regions. Use an external store: Vercel KV for hot data, Vercel Data Cache for fetch-level caching with tags, or a third-party edge KV. For per-user state, put it in a signed cookie or a JWT so the client carries it, and treat every request as stateless on the server.
Does Edge support WebSockets?
Not directly on Vercel today. Edge Functions handle standard HTTP and streaming responses, but full-duplex WebSocket upgrades are not a first-class primitive. Teams that need real-time typically front their app with a dedicated service (Ably, Pusher, Supabase Realtime, or a custom Cloudflare Durable Object) and use Edge only for the initial handshake or auth token minting.
Can I call an Edge Function from another Edge Function?
Yes, and you should — but do it over fetch(), not a shared import, so both functions can be deployed and scaled independently. Because Edge invocations run in the same region as the caller when possible, the inter-function hop is fast (usually under 20ms). Just remember: every internal fetch counts as a billable invocation, so avoid deep chains that fan out from a single request.

Related on this site

Keep reading