🚀 Executive Summary

TL;DR: Next.js containers becoming unhealthy after approximately 25 hours with high swap memory usage is a critical symptom of a memory leak, not normal behavior. The definitive solution involves deep debugging using heap snapshots and the V8 inspector to identify and resolve the root cause of unreleased memory.

🎯 Key Takeaways

  • Always set memory limits on containers to contain the blast radius of misbehaving pods and prevent them from taking down entire worker nodes.
  • The most effective way to fix Next.js memory leaks is by capturing and analyzing heap snapshots from the running Node.js process using tools like Chrome DevTools for Node.
  • Increasing container memory limits is a dangerous and lazy approach that only delays crashes and incurs higher costs without addressing the underlying memory leak.

Is it normal for Next.js container to become unhealthy after 25 hours with 80% swap memory usage?

A Next.js container using 80% swap memory and failing health checks after a day isn’t just a glitch; it’s a classic symptom of a memory leak. Here’s how a senior engineer debugs and permanently fixes this all-too-common production nightmare.

That ‘Unhealthy’ Next.js Container? It’s Not Normal, and Here’s How We Fix It.

It was 3:17 AM. My on-call pager went off with an alert that sounded like a dying starship. The P1 incident channel on Slack exploded: our main customer-facing dashboard, the one the C-suite checks every morning, was down. The Kubernetes pod for `dashboard-prod-app-7d5f…` was flapping—failing health checks, getting killed, restarting, and then dying all over again. The logs were clean. Metrics showed a slow, creeping memory usage that peaked right before each crash. I’ve seen this movie before, and it always ends with a memory leak as the villain. Seeing a Reddit thread about a Next.js container becoming unhealthy after 25 hours with 80% swap usage brought me right back to that night. So, let’s talk about it.

Why Your ‘Stable’ Next.js App is Secretly Bleeding Memory

First, let’s get one thing straight: this is not normal. A healthy, stateless web application shouldn’t see its memory usage grow indefinitely. When your container starts chewing through swap space, it’s a scream for help. The underlying issue is almost always a memory leak within the Node.js process that Next.js runs on.

In a Server-Side Rendering (SSR) world, it’s easy to accidentally create these leaks. Maybe it’s a global event listener that’s never removed, a cache that grows without bounds, or an unclosed database connection in a `getServerSideProps` function. On every request, a tiny object gets created and never released. For the first few hours, it’s unnoticeable. But after 24 hours and thousands of requests, those tiny leaks have flooded the ship, forcing the OS to use slow disk-based swap memory. Eventually, the process becomes so sluggish it can’t even respond to a health check, and your orchestrator (like Kubernetes or Docker Swarm) rightly takes it out back and shoots it.

Pro Tip: Always, and I mean always, set memory limits on your containers. An unconstrained container can take down an entire worker node (`k8s-prod-us-east-1-worker-03` doesn’t deserve that). A limit ensures the blast radius is contained to just that one misbehaving pod.

The DevOps Playbook: From Quick Hacks to Permanent Cures

When you’re in a firefight, you need options. Here’s my go-to playbook, ranging from the immediate band-aid to the real, long-term fix.

Solution 1: The ‘Get Me Through The Night’ Restart

Let’s be honest. Sometimes you just need the bleeding to stop so you can get some sleep and investigate properly in the morning. The quickest, dirtiest fix is to force a regular restart of your container before the memory leak becomes critical.

If you’re on Kubernetes, you can tweak your `livenessProbe` to be more aggressive, or if you’re feeling really hacky, you can set up a CronJob to kill the pod every 12 hours. It’s ugly, it papers over the real problem, and it can cause brief downtime for users during the restart, but it works.

# A more aggressive livenessProbe in your deployment.yaml
# This will restart the pod if it doesn't respond in 5 seconds after an initial delay.
livenessProbe:
  httpGet:
    path: /api/health
    port: 3000
  initialDelaySeconds: 60
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3

This is a temporary measure. Do not let this become permanent tech debt. I’ve seen teams leave these “temporary” fixes in for years.

Solution 2: The ‘Put On Your Detective Hat’ Deep Dive

This is the real fix. You have to find the leak. The best way to do this is by getting a heap snapshot from the running Node.js process and analyzing it. A heap snapshot is a JSON file that shows you every object in memory and what’s holding a reference to it.

You can enable the V8 inspector in your Next.js app and use tools like Chrome DevTools for Node to connect to your running container and capture these snapshots. You’ll take one snapshot when the app is fresh, another a few hours later after it’s handled traffic, and then compare them. The objects that have grown massively in number are your suspects.

To enable the inspector, modify your `Dockerfile`’s start command:

# In your Dockerfile
# Expose port 9229 for the inspector
EXPOSE 9229

# Start the node process with --inspect
CMD ["node", "--inspect=0.0.0.0:9229", "server.js"]

This takes time and effort, but it’s the only way to truly solve the problem and become a better engineer. You’ll learn a ton about how Node.js and your own code manage memory.

Solution 3: The ‘More RAM, More Problems?’ Resource Bump

The “nuclear” option. If you can’t find the leak and the restarts are too disruptive, you can just throw more memory at the problem. Go into your container definition and crank the memory limit from `1Gi` to `4Gi`.

This is a terrible idea for several reasons. First, it’s expensive. Cloud memory isn’t free. Second, it doesn’t fix the leak; it just makes the container take longer to die. Instead of crashing every 25 hours, maybe it crashes every 4 days. The problem is still there, lurking. This approach often leads to a false sense of security until the app finally crashes at an even more inconvenient time, like during a Black Friday sales event.

Warning: I only recommend this as a last-ditch effort to keep a critical system alive while you are actively working on Solution 2. It’s a crutch, not a solution.

Comparing the Approaches

To put it all in perspective, here’s how I see these three options:

Solution Effort Effectiveness My Take
Periodic Restarts Low Low (Mitigates symptom) A necessary evil for immediate stability. Your get-out-of-jail-free card at 3 AM.
Heap Analysis High High (Fixes root cause) This is the job. This is what separates a senior from a junior. Do the hard work.
Increase Memory Very Low Very Low (Hides symptom) Dangerous and lazy. Avoid unless it’s a strategic, temporary stopgap.

At the end of the day, a container consistently becoming unhealthy is a signal, not just noise. It’s your system telling you that something is fundamentally wrong. Don’t just silence the alarm by restarting it or giving it more resources. Listen to what it’s telling you, dive in, and fix the root cause. Your future self (and your company’s balance sheet) will thank you.

Darian Vance - Lead Cloud Architect

Darian Vance

Lead Cloud Architect & DevOps Strategist

With over 12 years in system architecture and automation, Darian specializes in simplifying complex cloud infrastructures. An advocate for open-source solutions, he founded TechResolve to provide engineers with actionable, battle-tested troubleshooting guides and robust software alternatives.


🤖 Frequently Asked Questions

âť“ Is it normal for a Next.js container to become unhealthy after 25 hours with high swap memory usage?

No, it is not normal. This behavior is a classic symptom of a memory leak within the Node.js process, often caused by unreleased objects, global event listeners, or unbounded caches in Server-Side Rendering (SSR) applications.

âť“ How do periodic restarts, heap analysis, and increasing memory compare as solutions for Next.js memory leaks?

Periodic restarts are a low-effort, low-effectiveness temporary fix. Heap analysis is a high-effort, high-effectiveness method that fixes the root cause. Increasing memory is a very low-effort, very low-effectiveness approach that only hides the symptom and is considered dangerous.

âť“ What is a common implementation pitfall when dealing with Next.js memory leaks?

A common pitfall is relying on increasing container memory limits or implementing periodic restarts as permanent solutions. These only mask the underlying memory leak, leading to higher costs, delayed crashes, and unaddressed technical debt. The solution is to perform a deep dive using heap analysis.

Leave a Reply

Discover more from TechResolve - SaaS Troubleshooting & Software Alternatives

Subscribe now to keep reading and get access to the full archive.

Continue reading