Next.js Memory Leak: Fetch + Standalone-modus — 2 år uten fiks
Next.js patcher den globale fetch og legger til et cache-lag som lekker minne ved hver forespørsel. I Docker/K8s fører dette til OOM-krasj hver par timer. Buggen har eksistert siden Next.js 14 og er fortsatt uløst i 16.2.x.
TL;DR
Next.js patcher den globale fetch og legger til et cache-lag som holder referanser til responsdata etter at de burde ha blitt frigjort. Hvert fetch-kall legger til minne som aldri returneres til GC. I Docker/Kubernetes fører dette til OOM-krasj hver par timer. Buggen har eksistert siden Next.js 14 (april 2024) og er fortsatt uløst i 16.2.x (mars 2026). På Vercel viser ikke problemet seg takket være efemere serverless-funksjoner.
Hvordan normal fetch fungerer
Request → fetch → got data → response to user → GC cleans up → memory freeHvordan fetch fungerer i Next.js
Next.js fanger opp den globale fetch og pakker den inn med sitt 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 indefinitelyHva som skjer i produksjon
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 versjoner
Next.js — Alle versjoner 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 — lekker på alle.
Hva som ikke fungerer
| 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) |
Hva som fungerer (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 |
Begrensning med axios-workaround
Dine egne API-kall kan erstattes med axios. Men Next.js bruker internt den patchede fetch for:
- ISR (Incremental Static Regeneration)
revalidatePath/revalidateTag- Server Components data fetching med deduplisering
use cache(Next.js 16)
Selv uten en eneste fetch i koden din — bruker Next.js den fortsatt internt.
Hvorfor Vercel ikke fikser det
Forretningslogikk
Vercel er et selskap som tjener penger på å hoste Next.js. På deres plattform viser ikke problemet seg (serverless = efemert). Buggen påvirker bare self-hosted (Docker, K8s, VPS) — de som ikke betaler Vercel.
Offisiell posisjon
Tim Neutkens (Vercel-maintainer) analyserte problemet og erklærte at det er et undici-problem (Node.js fetch-bibliotek), ikke Next.js. Issue #90433 ble stengt. Til tross for at:
- axios og node-fetch på samme Node.js fungerer uten lekkasjer
- Lekkasjen bare oppstår når fetch går gjennom Next.js-wrapperen
- Buggen har vært åpen i 2 år uten fiks
Prioriteringer
I løpet av disse 2 årene har Next.js-teamet sluppet:
- Turbopack (2-5x raskere builds) — markedsføringsfordel
- Cache Components /
use cache— reduserer 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)
Hva er det
OpenNext er en open-source-adapter som konverterer en Next.js-build til et format for AWS Lambda. SST er et rammeverk som 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 minneslekkasjen
Lambda-funksjoner behandler forespørsler og resirkuleres etter 5-15 minutters inaktivitet. Minnet rekker ikke å akkumuleres.
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-nyanser
- Cold starts — første forespørsel er tregere (~200-500ms)
- Sikkerhet — aktiver OAC (Origin Access Control), ellers er Lambda-URL-en offentlig
- OpenNext — community-prosjekt, ikke offisielt fra Vercel. Nye Next.js-funksjoner kan gå i stykker
- Lommebokattack — ved DDoS kan Lambda auto-scaling føre til en stor regning
Hvorfor en ekte fiks er urealistisk
1. Arkitekturproblem
Lekkasjen er ikke en tilfeldig bug, men en konsekvens av en designbeslutning: Next.js fanger opp den globale fetch og legger til cache/tracking oppå. For å fikse det må måten App Router interagerer med fetch redesignes. Dette påvirker ISR, revalidation, data cache, request deduplication — kjernen i rammeverket.
2. Interessekonflikt
Vercel er ikke motivert til å fikse det som ikke påvirker deres plattform. Self-hosted konkurrerer med deres forretning. Jo flere problemer i self-hosted — jo flere migrerer til Vercel.
3. Skyldforskyvning
Den offisielle posisjonen er "det er undici, ikke oss". Inntil det endrer seg — vil de ikke jobbe med en fiks.
4. Ingen community-fiks
Next.js AGPL-3.0-lisens tillater forks, men kodebasen er enorm og tett koblet til Vercel-infrastrukturen. En community-PR for å fikse fetch-wrapperen ville kreve dyp forståelse av den interne arkitekturen og godkjenning fra maintainers — som allerede har stengt issuen.
Konklusjoner
- Hvis du er på Vercel — ikke noe problem, ingenting å gjøre
- Hvis self-hosted og trenger serverless — SST + OpenNext på AWS Lambda
- Hvis self-hosted Docker — erstatt fetch med axios der det er mulig, overvåk RAM, konfigurer automatisk pod-omstart
- Hvis du starter et nytt prosjekt — vurder SvelteKit eller Nuxt som alternativer uten dette problemet
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