Next.js Memory Leak: Fetch + Standalone режимі — түзетусіз 2 жыл
Next.js глобалды fetch-ке патч салып, әр сұрауда жад ағызатын кэш қабатын қосады. Docker/K8s-те бұл бірнеше сағат сайын OOM құлауына әкеледі. Қате Next.js 14-тен бері бар және 16.2.x-те әлі шешілмеген.
TL;DR
Next.js жаһандық fetch-ке патч салып, жауап деректеріне босатылуы тиіс болғаннан кейін де сілтемелерді ұстап тұратын кэш қабатын қосады. Әрбір fetch шақыруы GC-ге ешқашан қайтарылмайтын жадты қосады. Docker/Kubernetes-те бұл бірнеше сағат сайын OOM құлауына әкеледі. Бұл қате Next.js 14-тен (2024 жылдың сәуірі) бері бар және 16.2.x-те (2026 жылдың наурызы) әлі шешілмеген. Vercel-де мәселе эфемерлі serverless функцияларының арқасында білінбейді.
Қалыпты fetch қалай жұмыс істейді
Request → fetch → got data → response to user → GC cleans up → memory freeNext.js-те fetch қалай жұмыс істейді
Next.js жаһандық fetch-ті ұстап алып, оны өзінің кэш/трекинг қабатымен орайды:
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Продакшнде не болады
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Зардап шеккен нұсқалар
Next.js — 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
Node.js 20, 22, 24, 25-те сынақтан өтті — барлығында ағады.
Не жұмыс істемейді
| 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) |
Не жұмыс істейді (уақытша шешімдер)
| 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 |
axios уақытша шешімінің шектеуі
Өз API сұрауларыңды axios-пен алмастыруға болады. Бірақ Next.js ішкі түрде патч салынған fetch-ті мыналар үшін пайдаланады:
- ISR (Incremental Static Regeneration)
revalidatePath/revalidateTag- Дедупликациямен Server Components деректерін алу
use cache(Next.js 16)
Яғни кодыңда бірде-бір fetch болмаса да — Next.js оны бәрібір астыртын пайдаланады.
Vercel неге түзетпейді
Бизнес-логика
Vercel — Next.js хостингінен ақша табатын компания. Олардың платформасында мәселе білінбейді (serverless = эфемерлі). Қате тек self-hosted-ке (Docker, K8s, VPS) — яғни Vercel-ге төлемейтіндерге ғана әсер етеді.
Ресми ұстаным
Tim Neutkens (Vercel мейнтейнері) мәселені талдап, бұл Next.js емес, undici-дің (Node.js fetch кітапханасы) мәселесі деп мәлімдеді. Issue #90433 жабылды. Мынаған қарамастан:
- сол Node.js-те axios пен node-fetch ағусыз жұмыс істейді
- Ағу тек fetch Next.js орамасынан өткенде ғана пайда болады
- Қате 2 жыл бойы түзетілмей ашық тұр
Басымдықтар
Осы 2 жылда Next.js командасы мыналарды шығарды:
- Turbopack (2-5x жылдам build) — маркетингтік артықшылық
- Cache Components /
use cache— Vercel серверлеріне жүктемені азайтады - middleware орнына
proxy.ts— Vercel-де edge-деплойды жеңілдетеді - DevTools MCP — AI хайпы
Self-hosted-тегі memory leak? Басымдықта емес.
Шешім: AWS Lambda (SST + OpenNext)
Бұл не
OpenNext — Next.js build-ін AWS Lambda пішіміне түрлендіретін ашық бастапқы кодты адаптер. SST — инфрақұрылымды автоматтандыратын фреймворк.
Архитектура
Next.js build
→ OpenNext
→ AWS Lambda (SSR, API routes)
→ S3 (static, assets)
→ CloudFront (CDN)
→ SQS + DynamoDB (ISR revalidation)Бұл memory leak-ті неге шешеді
Lambda функциялары сұрауларды өңдейді және 5-15 минут белсенсіздіктен кейін қайта пайдаланылады. Жад жиналып үлгермейді.
Деплой
npx sst@latest init
npx sst deploy --stage productionСалыстыру
| 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 нюанстары
- Cold starts — бірінші сұрау баяуырақ (~200-500ms)
- Қауіпсіздік — OAC (Origin Access Control) қос, әйтпесе Lambda URL ашық болады
- OpenNext — қауымдастық жобасы, ресми Vercel емес. Next.js жаңа мүмкіндіктері бұзылуы мүмкін
- Әмиянға шабуыл — DDoS кезінде Lambda авто-масштабтауы үлкен шотқа әкелуі мүмкін
Неге нақты түзету шындыққа жанаспайды
1. Архитектуралық мәселе
Ағу — кездейсоқ қате емес, дизайн шешімінің салдары: Next.js жаһандық fetch-ті ұстап алып, үстіне кэш/трекинг қосады. Оны түзету үшін — App Router-дің fetch-пен қалай әрекеттесетінін қайта жобалау керек. Бұл ISR, revalidation, data cache, request deduplication-ге — фреймворктің өзегіне әсер етеді.
2. Мүдделер қақтығысы
Vercel өз платформасына әсер етпейтін нәрсені түзетуге ынталы емес. Self-hosted олардың бизнесімен бәсекелеседі. Self-hosted-те мәселе неғұрлым көп болса — соғұрлым көп адам Vercel-ге көшеді.
3. Кінәні аудару
Ресми ұстаным — "бұл undici, біз емес". Ол өзгермейінше — олар түзетумен айналыспайды.
4. Қауымдастық түзетуі жоқ
Next.js-тің AGPL-3.0 лицензиясы форктарға рұқсат береді, бірақ код базасы орасан зор әрі Vercel инфрақұрылымымен тығыз байланысқан. fetch орамасын түзететін қауымдастық PR-ы ішкі архитектураны терең түсінуді және мейнтейнерлердің мақұлдауын талап етер еді — ал олар issue-ді әлдеқашан жапты.
Қорытындылар
- Егер Vercel-де болсаң — мәселе жоқ, ештеңе істеудің қажеті жоқ
- Егер self-hosted болсаң әрі serverless керек болса — AWS Lambda-да SST + OpenNext
- Егер self-hosted Docker болса — мүмкін жерде fetch-ті axios-пен алмастыр, RAM-ды бақыла, под-тарды автоматты қайта іске қосуды баптап қой
- Егер жаңа жоба бастасаң — осы мәселесіз балама ретінде SvelteKit не Nuxt-ты қарастыр
Дереккөздер
- 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