Skip to main content
← Назад к блогу
Next.jsMemory LeakDockerAWS LambdaNode.js

Next.js Memory Leak: Fetch + Standalone Mode — 2 года без фикса

Next.js патчит глобальный fetch и добавляет кеш-слой, который течёт на каждом запросе. В Docker/K8s это приводит к OOM crash каждые несколько часов. Баг существует с Next.js 14 и до сих пор не решён в 16.2.x.

Опубликовано 19 марта 2026 г.10 мин чтения

TL;DR

Next.js патчит глобальный fetch и добавляет кеш-слой, который держит ссылки на response data после того как они должны были быть освобождены. Каждый вызов fetch добавляет память, которая никогда не возвращается GC. В Docker/Kubernetes это приводит к OOM crash каждые несколько часов. Баг существует с Next.js 14 (апрель 2024) и до сих пор не решён в 16.2.x (март 2026). На Vercel проблема не проявляется из-за ephemeral serverless функций.

Как работает нормальный fetch

Request → fetch → got data → response to user → GC cleans up → memory free

Как работает fetch в Next.js

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

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

Тестировали на Node.js 20, 22, 24, 25 — течёт на всех.

Что не работает

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)

Что работает (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

Ограничение workaround с axios

Свои API-запросы можно заменить на axios. Но Next.js внутренне использует пропатченный fetch для:

  • ISR (Incremental Static Regeneration)
  • revalidatePath / revalidateTag
  • Server Components data fetching с дедупликацией
  • use cache (Next.js 16)

То есть даже без единого fetch в своём коде — Next.js всё равно использует его под капотом.

Почему Vercel не фиксит

Бизнес-логика

Vercel — компания, которая зарабатывает на хостинге Next.js. На их платформе проблема не проявляется (serverless = ephemeral). Баг затрагивает только self-hosted (Docker, K8s, VPS) — тех, кто не платит Vercel.

Официальная позиция

Tim Neutkens (мейнтейнер Vercel) провёл анализ и заявил что это проблема undici (Node.js fetch библиотека), а не Next.js. Issue #90433 закрыли. При том что:

  • axios и node-fetch на том же Node.js работают без утечек
  • Утечка появляется только когда fetch проходит через Next.js обёртку
  • Баг открыт 2 года без фикса

Приоритеты

За эти 2 года команда Next.js выпустила:

  • Turbopack (2-5x быстрее билды) — маркетинговое преимущество
  • Cache Components / use cache — уменьшает нагрузку на серверы Vercel
  • proxy.ts вместо middleware — упрощает edge-деплой на Vercel
  • DevTools MCP — AI-хайп

Memory leak в self-hosted? Не в приоритетах.

Решение: AWS Lambda (SST + OpenNext)

Что это

OpenNext — open-source адаптер, который превращает 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 функция обрабатывает запросы и recycled через 5-15 минут неактивности. Память не успевает накопиться.

Деплой

npx sst@latest init
npx sst deploy --stage production

Сравнение

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

  • Cold starts — первый запрос медленнее (~200-500ms)
  • Безопасность — включить OAC (Origin Access Control), иначе Lambda URL публичный
  • OpenNext — community проект, не официальный Vercel. Новые фичи Next.js могут ломаться
  • Wallet attack — при DDoS автоскейлинг Lambda может привести к большому счёту

Почему исправить нереально

1. Архитектурная проблема

Утечка — не случайный баг, а следствие дизайн-решения: Next.js перехватывает глобальный fetch и добавляет кеш/трекинг поверх. Чтобы пофиксить — нужно переделать как App Router взаимодействует с fetch. Это затрагивает ISR, revalidation, data cache, request deduplication — ядро фреймворка.

2. Конфликт интересов

Vercel не мотивирован фиксить то, что не затрагивает их платформу. Self-hosted конкурирует с их бизнесом. Чем больше проблем в self-hosted — тем больше людей мигрируют на Vercel.

3. Blame shifting

Официальная позиция — "это undici, не мы". Пока она не изменится — над фиксом работать не будут.

4. Нет community fix

AGPL-3.0 лицензия Next.js позволяет форки, но кодовая база огромна и тесно связана с инфраструктурой Vercel. Community PR с фиксом fetch обёртки потребовал бы глубокого понимания внутренней архитектуры и одобрения мейнтейнеров — которые уже закрыли issue.

Выводы

  1. Если на Vercel — проблемы нет, ничего делать не нужно
  2. Если self-hosted и нужен serverless — SST + OpenNext на AWS Lambda
  3. Если self-hosted Docker — заменить fetch на axios где возможно, мониторить RAM, настроить автоматический рестарт подов
  4. Если начинаешь новый проект — рассмотреть SvelteKit или Nuxt как альтернативу без этой проблемы

Источники