Loading...
Loading...
Weekly AI insights —
Real strategies, no fluff. Unsubscribe anytime.
Written by Gareth Simono, Founder and CEO of Agentik {OS}. Full-stack developer and AI architect with years of experience shipping production applications across SaaS, mobile, and enterprise platforms. Gareth orchestrates 267 specialized AI agents to deliver production software 10x faster than traditional development teams.
Founder & CEO, Agentik {OS}
Preview deployments, edge functions, environment management, and production protection. Vercel has capabilities most teams never use. Here's what matters.

Most teams use Vercel for one thing: automatic deployment when they push to main. That is 5% of what Vercel offers.
The teams getting the most out of Vercel use preview deployments for every PR, edge functions for sub-20ms response times on AI-heavy endpoints, environment variable management that prevents secrets from leaking, and production protection rules that make deploying at midnight safer.
This guide covers the Vercel setup that makes a real difference. Not the basics you already know.
Every pull request gets its own deployment URL. Not a shared staging environment. A completely isolated, production-like environment with the exact code from that PR.
This changes how teams review code.
Instead of "it looks good in staging" (which might be contaminated by other work), reviewers can say "I tested this at the PR URL, the form validation works correctly, and the edge case we discussed is handled." Concrete verification instead of assumption.
Setting up automatic preview comments:
// vercel.json
{
"framework": "nextjs",
"buildCommand": "npm run build",
"devCommand": "npm run dev",
"outputDirectory": ".next",
"github": {
"enabled": true,
"autoAlias": true
}
}Vercel automatically comments on every PR with the preview URL, build status, and deployment time. No configuration needed.
Preview environment variables:
Previews should use preview-specific secrets, not production secrets. A misconfigured preview environment should not be able to write to your production database.
# Set environment variables by environment in Vercel dashboard
# Or use the CLI:
vercel env add DATABASE_URL production
vercel env add DATABASE_URL preview
vercel env add DATABASE_URL development
# Each environment gets its own value
# Production: postgresql://prod-db.example.com/app
# Preview: postgresql://preview-db.example.com/app
# Development: postgresql://localhost:5432/appProtecting preview deployments:
By default, preview deployments are publicly accessible. For confidential work, enable Vercel Authentication to require login:
// vercel.json - require authentication for previews
{
"github": {
"enabled": true
},
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "X-Robots-Tag",
"value": "noindex"
}
]
}
]
}Edge functions run in Vercel's global network, close to users. The difference from serverless functions is latency: 50-200ms for a regional serverless function versus 5-20ms for an edge function running in the nearest edge node.
For AI applications, this matters significantly. Not for the AI inference itself (that happens on external APIs), but for the routing, middleware, authentication, and response transformation that wraps every AI request.
When to use Edge Functions:
// middleware.ts - Runs at the edge, before every request
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Authentication check at the edge
// Sub-5ms overhead for auth verification
const token = request.cookies.get("auth-token")?.value;
if (pathname.startsWith("/dashboard") && !token) {
return NextResponse.redirect(new URL("/login", request.url));
}
// A/B testing at the edge
// No round-trip to origin needed
if (pathname === "/") {
const bucket = Math.random() < 0.5 ? "control" : "variant";
const response = NextResponse.next();
response.cookies.set("ab-bucket", bucket, { maxAge: 60 * 60 * 24 * 30 });
response.headers.set("x-ab-bucket", bucket);
return response;
}
// Rate limiting at the edge
const ip = request.ip ?? "unknown";
const rateLimitResult = checkRateLimit(ip);
if (!rateLimitResult.allowed) {
return new NextResponse("Rate limit exceeded", {
status: 429,
headers: {
"Retry-After": rateLimitResult.resetIn.toString(),
"X-RateLimit-Limit": "100",
"X-RateLimit-Remaining": "0",
},
});
}
return NextResponse.next();
}
export const config = {
matcher: ["/dashboard/:path*", "/api/:path*", "/"],
};Edge-compatible AI streaming:
// app/api/ai/route.ts - Edge runtime for streaming AI responses
export const runtime = "edge";
import Anthropic from "@anthropic-ai/sdk";
export async function POST(request: Request) {
const { messages } = await request.json();
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
// Edge functions support streaming natively
const stream = client.messages.stream({
model: "claude-sonnet-4-20250514",
max_tokens: 2048,
messages,
});
const readableStream = new ReadableStream({
async start(controller) {
const encoder = new TextEncoder();
for await (const chunk of stream) {
if (
chunk.type === "content_block_delta" &&
chunk.delta.type === "text_delta"
) {
controller.enqueue(
encoder.encode(`data: ${JSON.stringify({ text: chunk.delta.text })}\n\n`)
);
}
}
controller.enqueue(encoder.encode("data: [DONE]\n\n"));
controller.close();
},
});
return new Response(readableStream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
});
}Edge functions are not always the right choice. They have limitations: no Node.js APIs, limited memory, no file system access. Use them for routing, authentication, and streaming. Use serverless for compute-heavy tasks.
Environment variable mismanagement causes security incidents. Production credentials leaked to preview environments. Development credentials accidentally used in production. Secrets committed to git.
Vercel's environment management, used correctly, prevents all of these.
The three-environment model:
// lib/config.ts - Central configuration with validation
import { z } from "zod";
const envSchema = z.object({
// Required in all environments
NEXT_PUBLIC_APP_URL: z.string().url(),
// Required only in production and preview
DATABASE_URL: z.string(),
ANTHROPIC_API_KEY: z.string(),
// Optional with defaults
RATE_LIMIT_MAX: z.string().transform(Number).default("100"),
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("info"),
// Vercel-injected variables (always available)
VERCEL_ENV: z
.enum(["production", "preview", "development"])
.default("development"),
VERCEL_URL: z.string().optional(),
});
export const config = envSchema.parse(process.env);
export const isProduction = config.VERCEL_ENV === "production";
export const isPreview = config.VERCEL_ENV === "preview";
export const isDevelopment = config.VERCEL_ENV === "development";
// The canonical app URL across all environments
export const appUrl = isProduction
? config.NEXT_PUBLIC_APP_URL
: config.VERCEL_URL
? `https://${config.VERCEL_URL}`
: "http://localhost:3000";Secrets rotation without downtime:
Rotating API keys in production without downtime requires keeping both old and new keys valid simultaneously during the transition:
// lib/anthropic.ts - Supports key rotation without deployment
import Anthropic from "@anthropic-ai/sdk";
// Vercel supports multiple values per env variable
// Format: "key1,key2" allows rotation
function getAnthropicKey(): string {
const keys = process.env.ANTHROPIC_API_KEY?.split(",") ?? [];
if (keys.length === 0) throw new Error("ANTHROPIC_API_KEY not configured");
// Use the first (newest) key
return keys[0].trim();
}
export const anthropic = new Anthropic({ apiKey: getAnthropicKey() });To rotate: add the new key as NEW_KEY,OLD_KEY, verify it works, then update to NEW_KEY alone. Zero-downtime rotation.
Production deployments should require proof that the code works. Vercel's deployment protection rules enforce this.
Required checks configuration:
// vercel.json
{
"github": {
"enabled": true,
"deploymentProtection": {
"enabled": true,
"requiredChecks": [
"ci/typecheck",
"ci/tests",
"ci/build"
]
}
}
}GitHub Actions that gate deployment:
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
typecheck:
name: ci/typecheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: "20" }
- run: npm ci
- run: npm run type-check
tests:
name: ci/tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: "20" }
- run: npm ci
- run: npm test -- --coverage
- uses: codecov/codecov-action@v3
build:
name: ci/build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: "20" }
- run: npm ci
- run: npm run build
env:
# Use preview env vars for build check
DATABASE_URL: ${{ secrets.PREVIEW_DATABASE_URL }}
ANTHROPIC_API_KEY: ${{ secrets.PREVIEW_ANTHROPIC_API_KEY }}With these checks required, Vercel will not deploy to production until all three pass. A broken build literally cannot reach production.
AI-generated content creates a caching challenge: the content is expensive to generate, but it should update periodically. ISR handles this perfectly.
// app/blog/[slug]/page.tsx - ISR with on-demand revalidation
import { notFound } from "next/navigation";
export const revalidate = 3600; // Revalidate every hour
// For AI-generated content, you might want longer TTLs
// since regeneration is expensive
export async function generateStaticParams() {
const posts = await getBlogPosts();
return posts.map((post) => ({ slug: post.slug }));
}
export default async function BlogPost({ params }: { params: { slug: string } }) {
const post = await getPost(params.slug);
if (!post) notFound();
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}
// app/api/revalidate/route.ts - On-demand revalidation webhook
export async function POST(request: Request) {
const { searchParams } = new URL(request.url);
const secret = searchParams.get("secret");
if (secret !== process.env.REVALIDATION_SECRET) {
return Response.json({ error: "Invalid secret" }, { status: 401 });
}
const body = await request.json();
const { path, tag } = body;
if (path) {
revalidatePath(path);
}
if (tag) {
revalidateTag(tag);
}
return Response.json({ revalidated: true, timestamp: Date.now() });
}Vercel Analytics and Speed Insights give you the data you need without setting up a separate monitoring stack.
// app/layout.tsx - Enable Vercel analytics
import { Analytics } from "@vercel/analytics/react";
import { SpeedInsights } from "@vercel/speed-insights/next";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<Analytics />
<SpeedInsights />
</body>
</html>
);
}
// Track AI-specific events
import { track } from "@vercel/analytics";
export function trackAIUsage(action: string, metadata: Record<string, string | number>) {
track(action, metadata);
}
// Usage in components
trackAIUsage("ai_generation_complete", {
model: "claude-sonnet-4",
tokens: 1245,
duration_ms: 2340,
success: 1,
});Custom alerts for AI application metrics:
Vercel does not currently provide custom alerting on custom events, but you can use Vercel Log Drains to forward logs to your monitoring service:
// Structured logging for monitoring
export function logAIEvent(
event: "start" | "complete" | "error",
metadata: {
model: string;
prompt_tokens?: number;
completion_tokens?: number;
duration_ms?: number;
error?: string;
}
) {
console.log(
JSON.stringify({
type: "ai_event",
event,
timestamp: new Date().toISOString(),
...metadata,
})
);
}Log Drains send these structured logs to Datadog, New Relic, Axiom, or any log aggregation service in real time.
Large teams need more structure around what gets deployed to production and when.
Branch protection with required reviewers:
// vercel.json - Different behavior per branch
{
"github": {
"enabled": true,
"autoJobCancelation": true
},
"rewrites": [
{ "source": "/health", "destination": "/api/health" }
]
}Rollback strategy:
Vercel keeps the last 50 deployments accessible. Rollback is instant:
# List recent deployments
vercel ls --token $VERCEL_TOKEN
# Promote a previous deployment to production
vercel promote <deployment-url> --token $VERCEL_TOKEN
# Or alias to production domain
vercel alias <deployment-url> yourdomain.com --token $VERCEL_TOKENThe instant rollback capability is the safety net that makes confident deployment culture possible. When you know you can roll back in 30 seconds, you deploy more often.
The teams that deploy most frequently have the fastest rollback mechanisms. Deployment frequency and rollback capability are directly correlated. Invest in rollback infrastructure and deployment frequency increases naturally.
Q: What are the best Vercel deployment strategies?
Key strategies include preview deployments for every PR (automatic testing environments), production deployment from main branch (zero-downtime), branch-based staging environments, feature flags for gradual rollouts, and edge functions for global performance. Vercel's git integration automates the entire deployment pipeline.
Q: How do you deploy AI applications on Vercel?
Deploy AI apps on Vercel using Edge Functions for low-latency AI API routes, streaming responses with the Vercel AI SDK, environment variables for API keys, and preview deployments for testing AI features before production. Vercel's infrastructure handles scaling and edge caching automatically.
Q: What is the difference between Vercel preview and production deployments?
Preview deployments are created for every git push and PR, each with a unique URL for testing. Production deployments serve your live domain and are triggered by merging to main. Preview deployments let AI agents and reviewers test changes in a production-like environment before going live.
Full-stack developer and AI architect with years of experience shipping production applications across SaaS, mobile, and enterprise. Gareth built Agentik {OS} to prove that one person with the right AI system can outperform an entire traditional development team. He has personally architected and shipped 7+ production applications using AI-first workflows.

Next.js 16 + AI: Build Intelligent Apps Fast
Next.js 16 solves AI's hardest problems: secret exposure, blocking UIs, and scaling costs. Here's the architecture that actually works in production.

Deployment Automation: AI Agents Handle DevOps
Thousands of production deployments, zero 2am wake-up calls. AI agents automate Vercel config, env management, and progressive rollouts that actually work.

Automated Testing: The Stack That Won't Slow You
Testing setups that make developers slow are abandoned. Here's the fast, modern testing stack for Next.js apps that actually gets used and maintained.
Stop reading about AI and start building with it. Book a free discovery call and see how AI agents can accelerate your business.