
The Next.js Proxy Pattern: Solving SEO and Security for Decoupled Express Backends
I Didn't Want to Choose Between Next.js and Express — So I Didn't
In the development world, the "easy" way is often a trap.
If we choose a pure full-stack framework like Next.js, we get amazing SEO, speed, caching, rendering options, and simple routing — but we're locked in. If we build a decoupled Express API to serve multiple clients (Web, Mobile, Desktop), our web SEO usually takes a massive hit.
I didn't want to choose. I wanted the union of both worlds: the SEO, caching, and rendering power of Next.js with the flexibility of a singleton Express backend.
The Problem: The "Empty HTML" Penalty
Standard React apps (CSR) send an empty <div id="root"></div> to the browser.
If a Google crawler hits your site and your API is slow, it sees nothing — and
indexes an empty page.
Google essentially punishes your hard work by burying your website in the rankings.
This is why CSR is often a poor choice for public-facing sites, whereas SSR (Server-Side Rendering) and ISR (Incremental Static Regeneration) — the bread and butter of Next.js — are the gold standard.
The Solution: The Next.js Proxy Pattern
A proxy sits in the middle. It catches, alters, and forwards requests. By using Next.js as a proxy for my Express backend, the request flow looks like this:
Browser → Next.js Server (SSR / Proxy) → Express API
Instead of the browser talking to Express directly, every request goes through Next.js first. This single architectural decision unlocks three massive wins.
Why This Wins
1. SEO & Core Web Vitals
By using SSR, the crawler receives a fully formed HTML document. This lowers LCP (Largest Contentful Paint) and eliminates CLS (Cumulative Layout Shift) because the data is already present when the page paints.
It feels instant — because it is ready.
2. Security
If you use environment variables in the browser, they're attached to requests that anyone can inspect in the Network Tab. By routing through a Next.js proxy, sensitive API keys stay on the server. They never touch the browser, keeping your backend architecture completely invisible to the public.
3. Automatic Request Memoization
Next.js extends the native fetch API. If three different components on one page
need the same data from Express, Next.js is smart enough to hit the Express backend
only once and share the result across all of them.