Edge runtime cheatsheet.
What is edge
V8-based runtime, deployed globally close to users. Much faster cold starts than Node.js Lambdas. Limited APIs.
Trade-offs:
- ✅ Cold start ~5ms.
- ✅ Geographic distribution.
- ✅ Smaller bundle = faster.
- ❌ No
fs,child_process,net, native modules. - ❌ Limited memory (~128MB on Vercel).
- ❌ Different fetch/
Buffersemantics.
Opting into edge
Per route:
// app/api/foo/route.ts
export const runtime = "edge";
export async function GET() {
return Response.json({ hello: "edge" });
}
Per page:
// app/page.tsx
export const runtime = "edge";
Middleware is always edge (default).
What works on edge
fetchRequest,Response,URL,Headers,FormData- Web Crypto (
crypto.subtle) TextEncoder/TextDecodersetTimeout,setIntervalconsole,Math,Date,JSON- Standard JS
What doesn’t work:
fs(no filesystem)net,dgram,child_process- Native node modules (sharp, etc)
require()of CommonJS (use ESM)- Most ORMs that use TCP — Prisma needs Data Proxy / Accelerate
Auth on edge
import { jwtVerify } from "jose";
const secret = new TextEncoder().encode(process.env.AUTH_SECRET);
export const runtime = "edge";
export async function GET(req: Request) {
const token = req.headers.get("authorization")?.replace("Bearer ", "");
if (!token) return new Response("401", { status: 401 });
try {
const { payload } = await jwtVerify(token, secret);
return Response.json({ user: payload });
} catch {
return new Response("401", { status: 401 });
}
}
jose works on edge. jsonwebtoken does not (uses Node crypto).
Database from edge
Native TCP doesn’t work. Options:
HTTP-based databases:
- Neon (Postgres serverless driver)
- PlanetScale (HTTP API)
- Upstash Redis (REST)
- Turso (libSQL HTTP)
import { neon } from "@neondatabase/serverless";
export const runtime = "edge";
const sql = neon(process.env.DATABASE_URL!);
export async function GET() {
const rows = await sql`SELECT * FROM users LIMIT 10`;
return Response.json(rows);
}
Prisma + Accelerate:
import { PrismaClient } from "@prisma/client";
import { withAccelerate } from "@prisma/extension-accelerate";
const db = new PrismaClient().$extends(withAccelerate());
Geolocation
// Vercel
export const runtime = "edge";
export async function GET(req: NextRequest) {
const country = req.headers.get("x-vercel-ip-country");
const city = req.headers.get("x-vercel-ip-city");
return Response.json({ country, city });
}
Or use geolocation(req):
import { geolocation } from "@vercel/functions";
const { country, city, region } = geolocation(req);
Streaming responses
export const runtime = "edge";
export async function GET() {
const encoder = new TextEncoder();
const stream = new ReadableStream({
async start(controller) {
for (let i = 0; i < 10; i++) {
controller.enqueue(encoder.encode(`event: ${i}\n\n`));
await new Promise((r) => setTimeout(r, 200));
}
controller.close();
},
});
return new Response(stream, {
headers: { "Content-Type": "text/event-stream" },
});
}
Edge is great for streaming (low latency).
OG images on edge
// app/posts/[id]/opengraph-image.tsx
import { ImageResponse } from "next/og";
export const runtime = "edge";
export const size = { width: 1200, height: 630 };
export default async function OG({ params }) {
return new ImageResponse(<div>...</div>, { ...size });
}
Fast generation at edge, cached at CDN.
LLM streaming
export const runtime = "edge";
import { OpenAI } from "openai";
export async function POST(req: Request) {
const { messages } = await req.json();
const openai = new OpenAI();
const stream = await openai.chat.completions.create({
model: "gpt-4",
messages,
stream: true,
});
const encoder = new TextEncoder();
return new Response(
new ReadableStream({
async start(controller) {
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content ?? "";
controller.enqueue(encoder.encode(text));
}
controller.close();
},
}),
{ headers: { "Content-Type": "text/plain" } },
);
}
Edge config (Vercel)
Read-only fast KV for feature flags, redirects, etc:
import { get } from "@vercel/edge-config";
export const runtime = "edge";
export async function GET() {
const flag = await get("featureX");
return Response.json({ flag });
}
Reads in ~1ms.
When NOT to use edge
- Heavy CPU work — limited memory and timeout.
- Native node deps (sharp, ffmpeg, etc).
- TCP-based databases without HTTP wrappers.
- Long-running requests (limits apply).
Common mistakes
- Importing a Node-only library → build fails.
- Buffer use → undefined on edge.
process.envnot set in edge — verify available vars.- TCP DB without HTTP proxy → connection error.
- Forgetting
runtime = "edge"declaration.
Read this next
If you want my edge + LLM streaming patterns, they’re at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .