The Three Layers You Are Probably Getting Wrong
Most Next.js applications that underperform at scale have the same three problems. First: rendering strategy mismatch — using SSR for content that should be statically generated, or using SSG for content that requires per-request data. Second: database query placement — running database queries inside components that are rendered at the edge, where the database is not. A 40ms query that runs well in your region becomes a 380ms query when the edge function is in Frankfurt and the database is in Mumbai. Third: image pipeline neglect — shipping unoptimised images through next/image without configuring the loader, sizes, or priority attributes correctly. Each of these is fixable independently. All three together are compounding.
Rendering Strategy — The Decision Tree
The correct rendering strategy for any given page or component is determined by two questions: does this content change per request, and does this content change per user? If neither: static generation (generateStaticParams, full CDN cache). If content changes but not per user: ISR with a revalidation window matched to your content update frequency. If content changes per user: server components for the data-fetching layer, client components only for interactivity. The mistake CipherBitz sees most often in production codebases: entire page trees marked as client components because one leaf node needed useState. The leaf node should be a client component. The tree should not be.
Rule of thumb for App Router: if you are adding 'use client' to a component that does not use useState, useEffect, or a browser-only API, you are probably making a rendering strategy error. Server components are the default for a reason — the reason is performance.
Edge Deployment — What to Put Where
Cloudflare Workers / Vercel Edge Functions are excellent for: routing logic, authentication token validation, A/B testing splits, geolocation-based redirects, and response header manipulation. They are poor choices for: database queries (latency to your database origin will negate the edge benefit unless you are using a distributed database like Turso or PlanetScale with a nearby replica), large file processing, and any operation with significant memory requirements. The pattern that works: edge for routing and lightweight middleware, regional serverless for data-fetching routes, static CDN for everything that can be pre-rendered.
The Image Problem Nobody Talks About
next/image solves the easy image optimisation problems automatically. It does not solve the architecture problem: where are your images stored, and how far are they from your edge nodes? Images stored in an S3 bucket in us-east-1 will have high latency for users in Asia regardless of how well-configured your next/image setup is. The fix is a multi-region CDN with image delivery — Cloudflare Images or a properly configured CloudFront distribution with origin in the region closest to your primary user base. For the India-first products CipherBitz operates, this single change reduced image delivery latency by 60–70% compared to US-region S3 origin.