Module A-2·11 min read

DNS → CDN → edge → origin → streaming response anatomy, cold start cost breakdown, ISR revalidation internals, instrumentation.ts register() lifecycle, and instrumentation-client.js for browser SDK boot.

Written by Jatin Jain Saraf · Architect of SupraScan

A-2 — The Full Request Lifecycle and Edge Infrastructure

Who this is for: Architects who need to understand every hop a request takes from the user's browser to your database and back — and what happens at each layer. This is the module that explains why a page can have a 5ms TTFB or a 800ms TTFB depending on where in the infrastructure the request gets handled.


The Complete Request Path

A request to a Next.js application in production touches up to five distinct layers. Understanding each one tells you where your latency comes from and where to intervene.

Browser
  → DNS resolution (cached after first request)
  → CDN edge node (geographically nearest to user)
      → Cache HIT: return immediately (0-5ms TTFB)
      → Cache MISS: forward to origin
          → Next.js edge middleware (V8 isolate, ~1ms)
          → Next.js server (Node.js)
              → Full Route Cache HIT: return pre-rendered HTML
              → Full Route Cache MISS: render
                  → Data Cache / React.cache() / use cache
                  → Database / external APIs
                  ← Streaming response (chunked transfer encoding)
          ← Response with cache headers
      ← Forward to browser
  ← Progressive HTML rendering

A static page (○) served from CDN cache has a TTFB of 5-30ms globally. A dynamic page (λ) that hits the database has a TTFB of 100-500ms depending on database location, query complexity, and connection pool state. The difference between those two numbers is the entire caching architecture.


What the CDN Layer Does

The CDN sits in front of your Next.js server. For static routes, the CDN stores the pre-rendered HTML and RSC payloads — every request for that route gets served directly from the CDN node nearest the user. The Next.js server is not involved at all.

Next.js communicates with the CDN through HTTP cache headers it generates automatically:

Cache-Control: public, max-age=31536000, immutable
# ↑ Static assets (JS, CSS, fonts) — cache forever, version via hash in filename
 
Cache-Control: s-maxage=31536000, stale-while-revalidate
# ↑ Static HTML pages — cache on CDN, revalidate in background when stale
 
Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate
# ↑ Dynamic pages — CDN does not cache, every request hits origin

On Vercel, this happens automatically — Vercel's CDN understands Next.js's cache model. On self-hosted deployments behind Nginx or Cloudflare, you need to either pass these headers through to the CDN or configure CDN caching rules explicitly.


Cold Start Anatomy

In serverless environments (Vercel Functions, AWS Lambda), your Node.js process doesn't exist until someone requests it. The cold start is the time it takes to create the process, load your application code, and handle the first request.

Cold start breakdown:

1. Container provisioning         ~50-200ms  (platform overhead — not your code)
2. Node.js runtime init           ~20-50ms
3. Module loading (require/import) ~50-300ms  ← your biggest lever
4. Prisma client initialisation   ~20-100ms
5. First request handling         your actual code

Module loading is where your application has the most control. The more code you import at the top level, the longer the cold start.

Strategies to reduce cold start:

// ❌ Importing everything at the top level
import Stripe from 'stripe';
import { Resend } from 'resend';
import { S3Client } from '@aws-sdk/client-s3';
 
// ✅ Dynamic imports for infrequently used heavy modules
export async function handleStripeWebhook(event: StripeEvent) {
  const { default: Stripe } = await import('stripe');
  // Stripe only loads when this function actually runs
}
// ❌ Prisma client created fresh each cold start
export async function GET() {
  const prisma = new PrismaClient();
  const data = await prisma.posts.findMany();
  return Response.json(data);
}
 
// ✅ Singleton — initialised once, reused across warm invocations
import { db } from '@/lib/db'; // the globalThis singleton from P-5

On Vercel, you can see cold start frequency in the Functions tab. A rate of >5% cold starts on production traffic warrants optimisation. For critical paths (login, checkout), consider warming strategies: scheduled pings every 5 minutes, or Vercel's Fluid compute (always-warm instances).

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.