Vercel Edge: Edge runtime, ISR, on-demand revalidation
2 min de leitura
Voce fez deploy no Cloudflare Workers. Vercel tem a outra abordagem pra edge: integracao nativa com Next.js, ISR (revalidacao incremental), e on-demand revalidation. Esse no cobre Vercel Edge: o runtime, como configurar ISR, on-demand revalidation, e quando Vercel e' melhor escolha que Cloudflare.
Vercel e' mais usado pra Next.js: Git push → build automatico → deploy. ISR e' o diferencial: SSG + revalidacao on-demand = conteudo estatico rapido + updates sem rebuild.
Voce sai de "Workers e' edge" pra "Vercel tem edge + ISR + Next.js integrado".
O essencial 🟢
Vercel: o que e' e quando usar.
Vercel e' plataforma de deploy com integracao nativa em Next.js: git push → build → URL em segundos. Edge runtime = V8 isolate (mesmo modelo do Cloudflare Workers), mas integrado com Next.js, Vercel Functions (Node runtime), Vercel KV/Postgres/Blob (storage).
Use Vercel quando: Next.js, integracao Git, preview por PR, ISR nativo. Use Cloudflare quando: mais controle, V8 isolate puro, custo baixo, R2/KV/D1.
Next.js com ISR - o "SSG com update".
// app/products/[id]/page.tsx
export const revalidate = 3600; // 1h
// ou revalidate = false (static, sem update)
// ou revalidate = 0 (dynamic, sempre renderiza)
export default async function ProductPage({ params }: { params: { id: string } }) {
const product = await fetch(`https://api.example.com/products/${params.id}`)
.then((r) => r.json());
return <div>{product.name}</div>;
}
revalidate = tempo (segundos)
ate a pagina ser revalidada no
proximo request. SSG-like
performance + ISR-like updates.
Default em Next.js 14+ e' 0
(dynamic), use revalidate pra
ISR.
On-demand revalidation - "atualiza agora, sem esperar 1h".
// app/api/revalidate/route.ts
import { revalidatePath, revalidateTag } from "next/cache";
import { NextResponse } from "next/server";
export async function POST(request: Request) {
const { path, tag, secret } = await request.json();
if (secret !== process.env.REVALIDATE_SECRET) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
if (path) revalidatePath(path);
if (tag) revalidateTag(tag);
return NextResponse.json({ revalidated: true });
}
Use: CMS publica novo conteudo →
POST /api/revalidate?path=/blog/novo-post
→ pagina atualiza imediatamente.
revalidateTag - revalidacao
granular.
// app/products/[id]/page.tsx
export default async function ProductPage({ params }: { params: { id: string } }) {
const product = await fetch(`https://api.example.com/products/${params.id}`, {
next: { tags: [`product-${params.id}`] },
}).then((r) => r.json());
return <div>{product.name}</div>;
}
// app/api/revalidate/route.ts
revalidateTag(`product-${params.id}`); // revalida so essa pagina
Use tags pra revalidar grupo
de paginas (ex: todas paginas de
produto de uma categoria).
Vercel Edge Functions - codigo em edge.
// middleware.ts (roda em edge)
import { NextResponse } from "next/server";
export const config = {
matcher: ["/api/:path*", "/((?!_next|.*\\..*).*)"],
};
export default async function middleware(request: Request) {
const country = request.headers.get("x-vercel-ip-country") || "US";
const url = new URL(request.url);
// Geo-redirect
if (country === "BR" && !url.pathname.startsWith("/br")) {
return NextResponse.redirect(new URL(`/br${url.pathname}`, request.url));
}
// Auth check
const token = request.cookies.get("session");
if (!token && url.pathname.startsWith("/dashboard")) {
return NextResponse.redirect(new URL("/login", request.url));
}
return NextResponse.next();
}
middleware.ts roda em toda
request antes de chegar na rota.
Edge runtime = < 5ms cold start.
Use pra: auth, geo-redirect, A/B
test, rate limit.
Vercel Functions (Node runtime).
// app/api/checkout/route.ts
import { NextResponse } from "next/server";
export async function POST(request: Request) {
// Roda em Node.js (NAO edge)
// CPU/memoria completos, sem limitacao
const { cartId, payment } = await request.json();
// ... logica pesada (payment, DB queries) ...
return NextResponse.json({ success: true });
}
Use Node runtime pra: payment, heavy computation, Node APIs (fs, crypto). Edge runtime pra: auth check, A/B test, geo, light logic.
Config de runtime.
// Edge (default em middleware)
export const runtime = "edge"; // V8 isolate
// Node
export const runtime = "nodejs"; // Node.js (Vercel serverless)
Vercel KV (Redis-like).
import { kv } from "@vercel/kv";
// SET
await kv.set("user:123", { name: "Ana" });
await kv.set("user:123", value, { ex: 3600 }); // 1h TTL
// GET
const user = await kv.get("user:123");
// INCR (atomic counter)
await kv.incr("counter:page-views");
Use Vercel KV pra: session, rate limit, feature flag, cache.
Vercel Postgres.
import { sql } from "@vercel/postgres";
const { rows } = await sql`SELECT * FROM users WHERE id = ${userId}`;
Postgres serverless, 1 connection por request, scale automatica.
Vercel Blob (object storage).
import { put } from "@vercel/blob";
const { url } = await put("uploads/image.png", imageBuffer, {
access: "public",
});
Use pra uploads, imagens, files.
Edge runtime vs Node runtime - quando usar cada.
| Caso | Runtime |
|---|---|
| Auth check | Edge |
| Geo-redirect | Edge |
| A/B test | Edge |
| Rate limit | Edge |
| Light API (read, transform) | Edge |
| Payment | Node |
| ML inference | Node |
| WebSocket longo | Node |
| File upload grande | Node |
| Node APIs (fs, child_process) | Node |
Edge = latencia + scale global. Node = CPU/memoria completo.
Preview deploys por PR.
# Vercel detecta PR, faz build, gera URL
# https://feat-novo-checkout-meuapp.vercel.app
# Cada PR tem URL unica
PM/tester/QA revisa visual sem checkout local. Vercel faz isso por default. Integra com GitHub PR comments: bot posta URL no PR.
Configurando ISR com Next.js 14+.
// app/blog/page.tsx
export const revalidate = 60; // revalidar a cada 60s
// ou on-demand via API
// app/api/revalidate/route.ts
import { revalidatePath } from "next/cache";
export async function POST(req: Request) {
const { secret, path } = await req.json();
if (secret !== process.env.REVALIDATE_SECRET) {
return new Response("Unauthorized", { status: 401 });
}
revalidatePath(path);
return Response.json({ revalidated: true });
}
On-demand revalidation = CMS publica → POST revalida → conteudo novo no edge.
Custo de Vercel.
- Hobby: free, 100GB bandwidth.
- Pro: $20/seat, 1TB bandwidth.
- Enterprise: custom.
- Edge Functions: 500K invocations free, $2/M depois.
- ISR: incluido.
- KV: 30K req/dia free.
- Postgres: 256MB free, 60h compute.
Em 2026, Vercel e' caro pra alto volume. Use Cloudflare pra $ e Vercel pra DX (Next.js).
Aprofundamento 🟡
Vercel Analytics - RUM built-in.
// app/layout.tsx
import { Analytics } from "@vercel/analytics/react";
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Analytics />
</body>
</html>
);
}
Vercel Analytics mede Web Vitals reais de users em prod. Free ate 100K page views/dia.
Vercel Speed Insights - similar, mais focado em performance.
Edge Config - feature flags em edge com < 1ms latency.
import { get } from "@vercel/edge-config";
const flag = await get("newCheckout");
// 0-1ms (cached at edge)
Use pra: feature flags, A/B tests, geo-targeting. < 1ms vs 50ms (KV).
ISR e revalidatePath vs
revalidateTag. revalidatePath
= revalida 1 path especifico.
revalidateTag = revalida
todas paginas com aquela tag.
Use tags pra granularidade
(categoria, autor, etc).
Streaming SSR com Suspense.
// app/product/[id]/page.tsx
import { Suspense } from "react";
export default function ProductPage({ params }: { params: { id: string } }) {
return (
<div>
<h1>Product</h1>
<Suspense fallback={<Skeleton />}>
<ProductDetails id={params.id} /> {/* server component async */}
</Suspense>
</div>
);
}
async function ProductDetails({ id }: { id: string }) {
const product = await fetch(`https://api.example.com/products/${id}`).then((r) => r.json());
return <div>{product.name}</div>;
}
Streaming SSR = HTML streamed em chunks (TTFB rapido) + Suspense pula partes lentas. App e' interativo enquanto dados chegam.
Server Actions (Next.js 14+).
// app/products/actions.ts
"use server";
export async function addToCart(productId: string) {
// Server-side mutation
await db.cart.add(userId, productId);
revalidatePath("/cart");
}
Server Actions = mutations sem API route. Rodam em server, NAO em edge.
next/image automatic optimization.
import Image from "next/image";
<Image src="/hero.jpg" alt="Hero" width={1200} height={600} priority />
Next.js automaticamente: gera
WebP/AVIF, lazy loads, gera
srcset responsivo. Cobre
image-optimization no proximo no.
Differential serving.
// next.config.js
module.exports = {
experimental: {
workerThreads: false,
cpus: 1,
},
};
Build gera diferentes bundles para Edge (minimo) e Node (full). Edge bundle = < 1MB (rapido), Node bundle = full.
Leitura recomendada:
- Vercel - Edge Functions - edge runtime, middleware, limits.
- Next.js - ISR - revalidate, on-demand, tags.
- Vercel - Functions API - edge + node runtime, deploy.
Dica: o erro mais comum em Vercel e' misturar edge e Node runtime sem pensar. Edge = rapido mas limitado, Node = completo mas lento. Use edge pra auth, geo, A/B test (latencia < 50ms). Use Node pra payment, ML, file upload (CPU/memoria).
middleware.tse' edge by default; route handlers sao Node by default. Configureexport const runtime = "edge"explicitamente. Mix inteligente = melhor DX + melhor performance.
No proximo no, vamos image optimization: Next/Image, Cloudflare Images, formato moderno (WebP, AVIF), e lazy loading pra LCP rapido.
// Quiz
O que e' ISR (Incremental Static Regeneration) e como ele combina o melhor de SSG e SSR?