Vercel Compute Runtime Decision Guide: Edge vs Node.js for Dynamic Routes
Choose Edge runtime for low-latency, Web-API handlers; use Node.js for full Node compatibility, larger bundles, or native modules. Validate your choice by deploying, checking the Vercel dashboard's function list, and measuring TTFB from multiple regions.
07 Sept 2026, 09:22 UTC

The Decision: Low Latency or Node Compatibility?
When deploying dynamic routes on Vercel, choose between the Edge runtime for global low-latency responses and Node.js serverless functions for broader API compatibility. This guide compares the two runtimes side-by-side and shows how to validate your choice.
Runtime Comparison at a Glance
| Constraint | Edge Runtime | Node.js Runtime |
|---|---|---|
| Execution Environment | V8 isolates near user edge locations | Serverless containers in Vercel regions |
| Startup Time | ~10-50ms cold starts | ~100-500ms cold starts (varies by bundle) |
| Code Size Limit | ~1-5 MB (plan-dependent) | ~50 MB uncompressed |
| Memory Limit | ~128-256 MB | ~128-1024 MB (configurable) |
| Execution Duration | ~10-60 seconds | ~10-300 seconds (configurable) |
| Node API Support | Limited; no node:fs, node:crypto web streams only |
Full Node.js built-ins and native modules |
| Billing Model | Invocations + CPU time | Duration + Memory + Invocations |
Trade-offs in Practice
Choose Edge when:
- Your handler uses only
fetch,Request,Response, and Web Streams API - You need sub-100ms time-to-first-byte for users across multiple continents
- Your bundle is small (<5 MB) and contains no native Node modules
- Traffic is bursty and you want to minimize duration-based costs
Choose Node.js when:
- Your code imports
node:fs,node:http, or native modules likesharp,bcrypt - You need >256 MB memory or >60 seconds execution
- Your dependency tree is large (e.g., full Express app)
- You rely on in-memory caching between requests (though external stores are preferred)
Implementation Example: Mixed Runtime Route
The following Next.js app directory structure demonstrates routing with different runtimes. Place Edge middleware for auth/gating, then delegate heavy work to a Node.js handler.
my-app/
├── app/
│ ├── middleware.js # Always Edge; auth check
│ ├── api/
│ │ ├── health/
│ │ │ └── route.js # Edge: lightweight health check
│ │ └── reports/
│ │ └── [id]/
│ │ └── route.js # Node.js: heavy PDF generation
│ └── page.js # Edge: render-time data fetch
Edge middleware (middleware.js) – runs at the edge before any route:
export async function middleware(request) {
const auth = request.headers.get('authorization');
if (!auth) return Response.redirect('/login');
return NextResponse.next();
}
export const config = { matcher: '/api/:path*' };
Edge route (api/health/route.js) – minimal bundle, fast response:
export async function GET() {
return Response.json({ ok: true }, { status: 200 });
}
// Ensure no Node built-ins are imported
Node.js route (api/reports/[id]/route.js) – heavier work:
import { PDFDocument } from 'pdf-lib'; // native-ish dependency
export async function GET(request, { params }) {
const { id } = params;
// Simulate heavy work: fetch data, generate PDF, store
const doc = await PDFDocument.create();
// ... processing ...
return new Response(doc.save(), {
headers: { 'Content-Type': 'application/pdf' },
});
}
// Explicitly request Node.js runtime (default, but explicit for clarity)
export const runtime = 'nodejs';
Validation Path: Deploy and Compare
After deploying, verify both routes behave as expected:
- Deploy the application: Run
vercel --prodfrom the project root. Ensure you have project write access. - Check the Vercel dashboard: Navigate to Functions tab. Each route should appear with its runtime label (Edge or Node.js) and region(s).
- Test from multiple regions: Use
curlwith the-wflag to measure TTFB:
# Test Edge route from Europe
curl -w 'TTFB: %{time_starttransfer}s\n' https://your-app.vercel.app/api/health
# Test Node.js route from US East
curl -w 'TTFB: %{time_starttransfer}s\n' https://your-app.vercel.app/api/reports/123
Expected: Edge route TTFB should be consistently lower across regions.
- Inspect logs for errors: Run
vercel logs <deployment-url> --function api/reports/[id]and look forError [ERR_UNKNOWN_BUILTIN_MODULE]or cold-start duration logs. - Verify bundle size: Check the Build Output in the dashboard. Edge functions exceeding the limit fail at build time with a size error.
Cost Considerations
Edge functions are billed per invocation plus CPU time, making them cheaper for high-volume, short-duration requests. Node.js functions bill per second of execution and memory, favoring workloads with longer processing or larger memory needs. Calculate expected costs using Vercel's pricing page and your traffic projections.
Limitations to Verify
- Edge runtime limits (duration, memory, code size) vary by Vercel plan and may change between releases. Check the current limits documentation before setting hard expectations.
- Edge functions cannot use
node:*protocols or native modules requiringffi,node-pty, or similar. - State does not persist between Edge invocations. Use Vercel KV or an external database for shared state.
Key Takeaway
Start with Edge for any route that can work with Web-standard APIs. Fall back to Node.js when you need full Node compatibility, larger memory, or native modules. Use Edge middleware for auth and routing, then let each route use the most appropriate runtime. Validate by deploying, checking the dashboard, and measuring response times from multiple regions.