fix: cap V8 heap and enable effective garbage collection for nextjs

Add --max-old-space-size=1024 to the node process running the Next.js
server. This caps V8's old-generation heap at 1024MB, forcing the
garbage collector to run more aggressively as memory usage approaches
the limit.

Previously, users saw Next.js RSS grow to 4GB+. This was caused by a
reference chain that prevented GC from freeing memory:

  AfterContext (vercel/next.js#89091) retained ServerResponse objects
  after client disconnect, which held zlib Transform streams (from
  compress: true), which allocated native C++ buffers outside V8's
  heap entirely — invisible to GC and uncapped by --max-old-space-size.

Combined with the prior commit's fixes (compress: false moves gzip to
nginx, httpBatchLink closes connections faster, socket-cleanup.cjs
destroys zombie CLOSE_WAIT sockets every 60s), GC can now actually
reclaim memory because:

- zlib native buffers no longer exist (compress: false)
- The AfterContext → ServerResponse reference chain is broken by
  socket cleanup destroying the underlying sockets
- The JS heap is capped at 1024MB so V8 GCs more frequently for
  the memory it does control

Also fixes the Dockerfile to copy socket-cleanup.cjs from the builder
stage instead of the host context.

Ref: https://github.com/homarr-labs/homarr/issues/3759
This commit is contained in:
KimP0ssible-no committed 2026-04-15 12:49:48 +02:00
1 parent c5e69c3e40
commit b6f6701eda
3 files changed
+2 -3

No files matched your search

+1 -1
View File
@@ -52,7 +52,7 @@ COPY --from=builder /app/packages/db/migrations ./db/migrations
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder /app/apps/nextjs/.next/standalone ./
COPY apps/nextjs/socket-cleanup.cjs ./apps/nextjs/socket-cleanup.cjs
COPY --from=builder /app/apps/nextjs/socket-cleanup.cjs ./apps/nextjs/socket-cleanup.cjs
COPY --from=builder /app/apps/nextjs/.next/static ./apps/nextjs/.next/static
COPY --from=builder /app/apps/nextjs/public ./apps/nextjs/public
COPY scripts/run.sh ./run.sh
-1
View File
@@ -3,7 +3,6 @@
// after client disconnect, leaving sockets in CLOSE-WAIT indefinitely.
//
// Usage: node --require ./socket-cleanup.cjs server.js
// or: NODE_OPTIONS="--require /app/socket-cleanup.cjs" node server.js
const INTERVAL_MS = 60_000; // Check every 60 seconds
+1 -1
View File
@@ -51,7 +51,7 @@ TASKS_PID=$!
node apps/websocket/wssServer.cjs &
WSS_PID=$!
node --require apps/nextjs/socket-cleanup.cjs apps/nextjs/server.js &
node --max-old-space-size=1024 --require apps/nextjs/socket-cleanup.cjs apps/nextjs/server.js &
NEXTJS_PID=$!
# Function to handle SIGTERM and shut down services