n4nAI

Edge vs Node.js runtime for Vercel AI SDK streaming

A head-to-head comparison of Edge and Node.js runtimes for Vercel AI SDK streaming, covering capabilities, costs, latency, ergonomics, and limits with a clear verdict by use case.

n4n Team5 min read1,190 words

Audio narration

Coming soon — every post will get a voice note here.

The vercel ai sdk edge vs node.js runtime decision shapes everything from cold-start latency to which libraries you can import. Both runtimes support streaming responses via streamText and streamObject, but they diverge sharply on execution model, ecosystem access, and cost profile. This comparison breaks down the trade-offs so you can pick the right runtime for your workload without guessing.

Execution model and cold starts

Edge runs on V8 isolates — not full Node.js processes. Isolates start in single-digit milliseconds, but they share a global isolate pool across invocations. That means no process global, no fs module, and no native addons. Node.js on Vercel runs in a traditional serverless container: cold starts around 100–300 ms for a minimal function, but you get the complete Node.js API surface.

For AI streaming, the cold-start difference matters most at low traffic. An Edge function serving a chat endpoint stays warm more aggressively because isolates are cheaper to keep alive. Node.js functions scale to zero more aggressively on the Hobby and Pro plans, so the first request after idle pays the container startup tax.

// Edge runtime — app/api/chat/route.ts
export const runtime = 'edge'

import { streamText } from 'ai'
import { openai } from '@ai-sdk/openai'

export async function POST(req: Request) {
  const { messages } = await req.json()
  const result = await streamText({
    model: openai('gpt-4o-mini'),
    messages,
  })
  return result.toDataStreamResponse()
}
// Node.js runtime — app/api/chat/route.ts
export const runtime = 'nodejs'

import { streamText } from 'ai'
import { openai } from '@ai-sdk/openai'
// Node-only imports work here
import { readFileSync } from 'fs'
import { resolve } from 'path'

export async function POST(req: Request) {
  const { messages } = await req.json()
  const result = await streamText({
    model: openai('gpt-4o-mini'),
    messages,
  })
  return result.toDataStreamResponse()
}

Streaming behavior and backpressure

Both runtimes implement the same ReadableStream contract from the AI SDK. The difference shows up under load. Edge isolates have a hard 128 MB memory limit and a 30-second max execution time (Pro plan: 60 s). Node.js functions get 1 GB (Hobby) or 3 GB (Pro) and up to 800 seconds max duration.

When streaming large model responses — think 8k+ output tokens — Edge can hit the memory ceiling if you buffer chunks server-side. The AI SDK’s toDataStreamResponse() streams directly to the client without buffering, so this rarely bites in practice. But if you transform the stream (e.g., inject citations, run a moderation pass per chunk), Node.js gives you more headroom.

// Transforming a stream — safe on both, but Node.js has more margin
import { streamText, smoothStream } from 'ai'

const result = await streamText({
  model: openai('gpt-4o'),
  messages,
  experimental_transform: smoothStream({ chunking: 'word' }),
})

Tool calling and structured outputs

Tool calling works identically on both runtimes — the AI SDK handles the loop. Where Node.js wins: you can call into heavy libraries inside tools. PDF parsing, image processing, database drivers with native bindings, sharp, pdf-parse, playwright — all require Node.js. Edge supports a growing subset of npm packages (ESM-only, no native deps), but anything touching crypto, fs, or native modules fails at deploy time.

// Node.js only — tool that uses a native dependency
import { streamText, tool } from 'ai'
import { z } from 'zod'
import pdf from 'pdf-parse' // native dep, Node.js only

const extractPdfText = tool({
  parameters: z.object({ buffer: z.instanceof(Buffer) }),
  execute: async ({ buffer }) => {
    const data = await pdf(buffer)
    return data.text
  },
})

Local development parity

vercel dev emulates both runtimes locally, but Edge emulation uses workerd (the Cloudflare Workers runtime) while Node.js runs actual Node.js. This creates subtle mismatches: crypto.subtle behaves differently, Request/Response implementations diverge, and some Web APIs polyfill incompletely in workerd.

Node.js local dev is higher fidelity. If your CI runs integration tests against a real Vercel preview deployment, the gap narrows — but you still catch Edge-specific failures later in the pipeline.

Ecosystem and middleware

Edge middleware runs on every request before your route handler. It’s useful for auth checks, bot detection, or rewriting — but it shares the same isolate limits. You cannot import Node.js-only packages in middleware. Node.js has no equivalent middleware layer; you handle cross-cutting concerns in route handlers or a custom server (which defeats serverless benefits).

For AI workloads, the practical impact is small. Most auth lives in a separate Edge middleware anyway, and the AI route itself picks its runtime independently.

Cost model

Vercel bills Edge and Node.js differently:

Dimension Edge Node.js
Invocation cost $0.50 / million invocations (after free tier) Included in function duration
Duration billing GB-hours × $0.000016 GB-hours × $0.000024
Free tier 1M invocations + 100 GB-hours/mo 100 GB-hours/mo
Max memory 128 MB 1 GB (Hobby) / 3 GB (Pro)
Max duration 30 s (Hobby) / 60 s (Pro) 60 s (Hobby) / 800 s (Pro)

For high-frequency, low-latency chat (many short invocations), Edge wins on invocation pricing. For long-running streams or heavy tool use, Node.js duration billing is cheaper per GB-hour but you pay for more memory. A 512 MB Node.js function running 10 seconds costs the same GB-hours as a 128 MB Edge function running 40 seconds — but the Node.js function can actually complete the work.

Bundle size and deployment

Edge enforces a 1 MB compressed bundle limit (3 MB uncompressed). The AI SDK core is ~200 KB gzipped; adding @ai-sdk/openai, zod, and a few utilities pushes you to ~400–600 KB. You have headroom, but large dependencies (e.g., langchain, heavy ORMs) will break the build.

Node.js has a 50 MB limit. You can bundle Prisma, full ORMs, or ML libraries without webpack gymnastics. The trade-off: larger bundles increase cold-start time because the container must download and extract them.

# Check your Edge bundle size locally
npx @vercel/nft --output bundle.json app/api/chat/route.ts
# Look at "size" in the output — must be < 1,048,576 bytes gzipped

Limits summary

Limit Edge Node.js (Pro)
Memory 128 MB 3 GB
Max duration 60 s 800 s
Bundle size (gzipped) 1 MB 50 MB
Concurrent invocations 1000 (soft) 1000 (soft)
Request body size 1 MB 5 MB
Response streaming Yes Yes
WebSocket support No No (use Pusher/Ably)
Native addons No Yes
fs, crypto, child_process No Yes

Debugging and observability

Edge logs appear in Vercel’s dashboard with the same UI as Node.js, but stack traces can be less complete because workerd strips some frames. console.log works, but you lose async_hooks-based context propagation (e.g., cls-rtracer for request IDs). Node.js gives you full Node inspector support — you can attach node --inspect locally and debug with Chrome DevTools.

For production debugging, both runtimes integrate with Vercel’s Log Drains (Datadog, Logtail, Axiom). The AI SDK’s onFinish callback works identically on both, so you can emit custom telemetry per completion.

// Works on both runtimes
const result = await streamText({
  model: openai('gpt-4o'),
  messages,
  onFinish: async ({ usage, finishReason }) => {
    await analytics.track('ai_completion', {
      tokens: usage.totalTokens,
      finishReason,
      runtime: process.env.NEXT_RUNTIME, // 'edge' or 'nodejs'
    })
  },
})

When to choose Edge

  • High-frequency, low-latency chat — many short requests, sub-100ms cold starts matter
  • Global distribution priority — Edge runs in 35+ regions; Node.js runs in fewer primary regions
  • Simple request/response — no heavy tooling, no native deps, no large bundle
  • Middleware-heavy auth — you’re already running Edge middleware, keep the stack uniform
  • Cost optimization at scale — millions of invocations where $0.50/M beats duration billing

When to choose Node.js

  • Tool calling with native deps — PDF, images, audio, video, sharp, canvas, playwright
  • Long-running streams — 60+ second model responses, multi-step agent loops
  • Heavy libraries — Prisma, Drizzle with full relations, LangChain, vector DB clients
  • Local dev fidelity — you need crypto, fs, child_process to behave identically in CI
  • Higher memory ceiling — buffering, transformation, or large context windows
  • Team familiarity — your engineers know Node.js debugging tools, not workerd quirks

Run your chat endpoint on Edge for fast cold starts and global latency. Offload heavy tools to a separate Node.js route (or a background job via Inngest/Trigger.dev/QStash) that the Edge route calls via HTTP. This keeps the hot path fast while giving you Node.js power where you need it.

// Edge route — fast path, calls Node.js tool endpoint
export const runtime = 'edge'

import { streamText, tool } from 'ai'
import { openai } from '@ai-sdk/openai'

const analyzeDocument = tool({
  parameters: z.object({ url: z.string().url() }),
  execute: async ({ url }) => {
    const res = await fetch(`${process.env.NODEJS_API_URL}/analyze`, {
      method: 'POST',
      body: JSON.stringify({ url }),
    })
    return res.json()
  },
})

export async function POST(req: Request) {
  const { messages } = await req.json()
  const result = await streamText({
    model: openai('gpt-4o'),
    messages,
    tools: { analyzeDocument },
  })
  return result.toDataStreamResponse()
}

Verdict

Default to Edge for new AI streaming endpoints. The cold-start advantage, global footprint, and lower invocation cost align with typical chat workloads. You’ll hit the limits (bundle size, native deps, 60 s max) only when you add complexity — and that’s the right time to migrate that specific route to Node.js.

Choose Node.js first if you already know you need native dependencies, long durations, or heavy libraries. Don’t preemptively optimize for Edge if your toolchain fights you.

Use the hybrid pattern when a single feature needs both: keep the streaming UX on Edge, push the heavy lifting to Node.js. The AI SDK’s tool calling makes this clean — the model doesn’t care where the tool executes.

Tagsvercel-ai-sdkedge-runtimenode-jsstreaming

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All vercel ai sdk on edge & serverless runtimes posts →