Skip to main content
← Tilbake til bloggen
Next.jsMemory LeakDockerAWS LambdaNode.js

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.

Publisert 19. mars 202610 min lesing

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 free

Hvordan 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 indefinitely

Hva 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 accumulates

Berørte versjoner

Next.js — Alle versjoner med App Router

VersionIssueDate
14.2.x#64212April 2024
14.x-15.x#68578August 2024
14.3.0-canary#79588May 2025
16.0.1#85914November 2025
16.1.0#88603January 2026
16.0.10#90433February 2026
16.2.0-canary.51Confirmed in #90433 commentsMarch 2026

Node.js

Testet på Node.js 20, 22, 24, 25 — lekker på alle.

Hva som ikke fungerer

AttemptResult
cacheMaxMemorySize: 0Doesn't help — leak is not from this cache
Disable image optimizationDoesn't help
--max-old-space-size=6144Just crashes slower
Read response via .json() / .text()Doesn't help
Remove React fetch patching (canary.45)Doesn't help
Upgrade to latest versionDoesn't help (leaks on 16.2.0-canary.51 too)

Hva som fungerer (workarounds)

WorkaroundWhy it helps
Replace fetch with axiosBypasses Next.js wrapper
Replace fetch with node-fetchSame reason
Downgrade Node.js to 20.15.1Older undici has fewer leaks (for some)
Docker image node:20-alpine3.21Helps in some cases
Deploy to Lambda (SST + OpenNext)Ephemeral functions — memory doesn't accumulate
Deploy to VercelSame — 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.ts i 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 production

Sammenligning

VercelAWS Lambda (SST)Docker self-hosted
Memory leakNot feltNot feltCritical
Cold startsYesYes (~200-500ms)No
Price (~medium traffic)$20-150/mo$5-30/mo$5-50/mo
ControlMinimalFullFull
ISR/RevalidationWorksWorks (SQS)Works (with leak)
Vendor lock-inVercelAWSNone

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

  1. Hvis du er på Vercel — ikke noe problem, ingenting å gjøre
  2. Hvis self-hosted og trenger serverless — SST + OpenNext på AWS Lambda
  3. Hvis self-hosted Docker — erstatt fetch med axios der det er mulig, overvåk RAM, konfigurer automatisk pod-omstart
  4. Hvis du starter et nytt prosjekt — vurder SvelteKit eller Nuxt som alternativer uten dette problemet

Kilder