Next.js Memory Leak: Fetch + Standalone-tilstand — 2 år uden fix
Next.js patcher den globale fetch og tilføjer et cache-lag, der lækker hukommelse ved hver anmodning. I Docker/K8s fører dette til OOM-nedbrud hver par timer. Buggen har eksisteret siden Next.js 14 og er stadig uløst i 16.2.x.
TL;DR
Next.js patcher den globale fetch og tilføjer et cache-lag, der holder referencer til responsdata, efter de burde have været frigivet. Hvert fetch-kald tilføjer hukommelse, der aldrig returneres til GC. I Docker/Kubernetes fører dette til OOM-nedbrud hver par timer. Buggen har eksisteret siden Next.js 14 (april 2024) og er stadig uløst i 16.2.x (marts 2026). På Vercel viser problemet sig ikke takket være efemere serverless-funktioner.
Hvordan normal fetch fungerer
Request → fetch → got data → response to user → GC cleans up → memory freeHvordan fetch fungerer i Next.js
Next.js opfanger den globale fetch og pakker den ind med sit eget cache-/tracking-lag:
Request → Next.js fetch wrapper → creates:
- Performance entry (speed tracking) ← not cleaned
- Request metadata object ← not cleaned
- Internal promise wrapper ← not cleaned
- Cache lookup entry ← not cleaned
- Response body (for unique URL) ← not cleaned
→ Response to user
→ GC sees objects are still referenced → doesn't touch them
→ Memory grows indefinitelyHvad der sker i produktion
Self-hosted (Docker/K8s):
Request 1: fetch → +100KB → RAM: 100KB
Request 2: fetch → +100KB → RAM: 200KB
Request 1000: fetch → +100KB → RAM: 100MB
Request 50,000: fetch → +100KB → RAM: 5GB → OOM Kill 💀
→ Kubernetes restarts the pod → cycle repeats
Vercel (Serverless):
Request 1: [start] → fetch → +100KB → [process dies] → 0 KB ✅
Request 2: [start] → fetch → +100KB → [process dies] → 0 KB ✅
→ Memory never accumulatesBerørte versioner
Next.js — Alle versioner med App Router
| Version | Issue | Date |
|---|---|---|
| 14.2.x | #64212 | April 2024 |
| 14.x-15.x | #68578 | August 2024 |
| 14.3.0-canary | #79588 | May 2025 |
| 16.0.1 | #85914 | November 2025 |
| 16.1.0 | #88603 | January 2026 |
| 16.0.10 | #90433 | February 2026 |
| 16.2.0-canary.51 | Confirmed in #90433 comments | March 2026 |
Node.js
Testet på Node.js 20, 22, 24, 25 — lækker på alle.
Hvad der ikke virker
| Attempt | Result |
|---|---|
cacheMaxMemorySize: 0 | Doesn't help — leak is not from this cache |
| Disable image optimization | Doesn't help |
--max-old-space-size=6144 | Just crashes slower |
Read response via .json() / .text() | Doesn't help |
| Remove React fetch patching (canary.45) | Doesn't help |
| Upgrade to latest version | Doesn't help (leaks on 16.2.0-canary.51 too) |
Hvad der virker (workarounds)
| Workaround | Why it helps |
|---|---|
Replace fetch with axios | Bypasses Next.js wrapper |
Replace fetch with node-fetch | Same reason |
| Downgrade Node.js to 20.15.1 | Older undici has fewer leaks (for some) |
Docker image node:20-alpine3.21 | Helps in some cases |
| Deploy to Lambda (SST + OpenNext) | Ephemeral functions — memory doesn't accumulate |
| Deploy to Vercel | Same — serverless |
Begrænsning med axios-workaround
Dine egne API-kald kan erstattes med axios. Men Next.js bruger internt den patchede fetch til:
- ISR (Incremental Static Regeneration)
revalidatePath/revalidateTag- Server Components data fetching med deduplikering
use cache(Next.js 16)
Selv uden en eneste fetch i din kode — bruger Next.js den stadig internt.
Hvorfor Vercel ikke fikser det
Forretningslogik
Vercel er en virksomhed, der tjener penge på at hoste Next.js. På deres platform viser problemet sig ikke (serverless = efemert). Buggen påvirker kun self-hosted (Docker, K8s, VPS) — dem, der ikke betaler Vercel.
Officiel position
Tim Neutkens (Vercel-maintainer) analyserede problemet og erklærede det for et undici-problem (Node.js fetch-bibliotek), ikke Next.js. Issue #90433 blev lukket. På trods af at:
- axios og node-fetch på samme Node.js fungerer uden lækager
- Lækagen kun opstår, når fetch går gennem Next.js-wrapperen
- Buggen har været åben i 2 år uden en fix
Prioriteringer
I løbet af disse 2 år har Next.js-teamet udgivet:
- Turbopack (2-5x hurtigere builds) — markedsføringsfordel
- Cache Components /
use cache— reducerer belastningen på Vercel-servere proxy.tsi stedet for middleware — forenkler edge-deployment på Vercel- DevTools MCP — AI-hype
Memory leak i self-hosted? Ikke en prioritet.
Løsning: AWS Lambda (SST + OpenNext)
Hvad er det
OpenNext er en open-source-adapter, der konverterer et Next.js-build til et format til AWS Lambda. SST er et framework, der automatiserer infrastrukturen.
Arkitektur
Next.js build
→ OpenNext
→ AWS Lambda (SSR, API routes)
→ S3 (static, assets)
→ CloudFront (CDN)
→ SQS + DynamoDB (ISR revalidation)Hvorfor dette løser hukommelseslækagen
Lambda-funktioner behandler anmodninger og genbruges efter 5-15 minutters inaktivitet. Hukommelsen når ikke at akkumulere.
Deployment
npx sst@latest init
npx sst deploy --stage productionSammenligning
| Vercel | AWS Lambda (SST) | Docker self-hosted | |
|---|---|---|---|
| Memory leak | Not felt | Not felt | Critical |
| Cold starts | Yes | Yes (~200-500ms) | No |
| Price (~medium traffic) | $20-150/mo | $5-30/mo | $5-50/mo |
| Control | Minimal | Full | Full |
| ISR/Revalidation | Works | Works (SQS) | Works (with leak) |
| Vendor lock-in | Vercel | AWS | None |
Lambda-nuancer
- Cold starts — første anmodning er langsommere (~200-500ms)
- Sikkerhed — aktiver OAC (Origin Access Control), ellers er Lambda-URL'en offentlig
- OpenNext — community-projekt, ikke officielt fra Vercel. Nye Next.js-funktioner kan gå i stykker
- Tegnebogsangreb — ved DDoS kan Lambda auto-scaling føre til en stor regning
Hvorfor en rigtig fix er urealistisk
1. Arkitekturproblem
Lækagen er ikke en tilfældig bug, men en konsekvens af en designbeslutning: Next.js opfanger den globale fetch og tilføjer cache/tracking ovenpå. For at fixe det skal måden, App Router interagerer med fetch, redesignes. Dette påvirker ISR, revalidation, data cache, request deduplication — frameworkets kerne.
2. Interessekonflikt
Vercel er ikke motiveret til at fixe det, der ikke påvirker deres platform. Self-hosted konkurrerer med deres forretning. Jo flere problemer i self-hosted — jo flere migrerer til Vercel.
3. Skyldforskydning
Den officielle position er "det er undici, ikke os". Indtil det ændrer sig — vil de ikke arbejde på en fix.
4. Ingen community-fix
Next.js AGPL-3.0-licens tillader forks, men kodebasen er enorm og tæt koblet til Vercel-infrastrukturen. En community-PR til at fixe fetch-wrapperen ville kræve dyb forståelse af den interne arkitektur og godkendelse fra maintainers — som allerede har lukket issuen.
Konklusioner
- Hvis du er på Vercel — intet problem, intet at gøre
- Hvis self-hosted og behov for serverless — SST + OpenNext på AWS Lambda
- Hvis self-hosted Docker — erstat fetch med axios hvor muligt, overvåg RAM, konfigurer automatisk pod-genstart
- Hvis du starter et nyt projekt — overvej SvelteKit eller Nuxt som alternativer uden dette problem
Kilder
- Issue #64212 — Memory Leak with global fetch (April 2024)
- Issue #68578 — Possible memory leak in Fetch API (August 2024)
- Issue #85914 — Memory Leak with fetch + standalone (November 2025)
- Issue #90433 — OOM in 16.0.10 (February 2026)
- Discussion #88603 — OOM in Docker/K8s (January 2026)
- Discussion #88078 — cacheMaxMemorySize behavior
- OpenNext
- SST — Next.js on AWS
- Secret knowledge to self-host Next.js
- Next.js Memory Usage Guide