·
3 min read

Analyze Memory Leaks in Your Nuxt App

Analyze Memory Leaks in Your Nuxt App Image

In one of my client projects, we recently had to analyze and fix a memory leak in our Nuxt 3+ application. In this article, I will share my experience and our steps to identify and fix the memory leak.

What is a Memory Leak?

A memory leak occurs when a program allocates memory but doesn't release it when it's no longer needed. Over time, this can lead to the exhaustion of system resources and the application crashing.

In our case, the memory leak caused our Kubernetes pods to restart frequently, forcing us to increase the resources allocated to the pods. However, this was only a temporary solution, and we had to find and fix the root cause of the memory leak.

Finding the Memory Leak

The first step in fixing a memory leak is identifying the root cause. Here are the steps we took to find the memory leak in our Nuxt application.

First, it's important to note that we use Hybrid Rendering in our application, which means that the server-side rendering (SSR) and client-side rendering (CSR) are combined. Technically, a Node.js server is deployed, so we had to monitor the memory usage of the Node.js process.

Step 1: Monitor Memory Usage

The first step is to monitor your application's memory usage. In our case, this only happened in production, so we had to monitor the memory usage of our application's production build.

To debug a production build of your Nuxt app in Visual Studio Code, you have to define a launch configuration in your .vscode/launch.json file. Here is an example configuration:

json.vscode/launch.json
{ "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Debug Prod Build", "cwd": "${workspaceFolder}", "outputCapture": "std", "runtimeExecutable": "pnpm", "runtimeArgs": ["build:preview"] }, ] }

In this configuration, we use the pnpm build:preview command to build the production version of our Nuxt app. You can replace this command with the command you use to build your production app.

In this example, the command is configured like this:

jsonpackage.json
{ "scripts": { "build": "nuxt build", "preview": "nuxt preview", "build:preview": "nuxt build && nuxt preview", } }

After configuring the launch configuration, you can start the debugger in Visual Studio Code and monitor the memory usage of the Node.js process.

I recommend using the Flame Chart Visualizer for JavaScript Profiles extension, which enables you to profile the heap and CPU usage of your Node.js process in real-time.

The following picture shows the Flame Chart Visualizer in action:

Flame Chart Visualizer

Info

For a more detailed analysis, you can record a heap profile and analyze it in VS Code or with the Chrome DevTools.

To simulate traffic, we used oha, a tiny program that sends some load to a web application.

An exemplary command to simulate traffic with oha is:

bash
oha -c 2 -n 250 --disable-keepalive http://localhost:3000/route-that-should-be-tested

-c specifies the number of concurrent requests, -n the number of total requests, and --disable-keepalive prevents the re-use of TCP connections between different HTTP requests.

Step 2: Analyze the Memory Usage

In our scenario, we saw that the memory usage of the Node.js process increased over time and with each request, which indicated that there was a memory leak.

Step 3: Find the Root Cause

One approach to finding the root cause of a memory leak is to use git bisect to identify the commit that introduced the memory leak. This approach can be time-consuming, but it can help you narrow down the code that caused the memory leak.

In our project, we identified that we defined some watchers after an await in a Nuxt page component which caused the memory leak. Because we only needed those watchers on the client, we wrapped them in the onMounted lifecycle hook which fixed the memory leak.

Conclusion

Memory leaks can be challenging to identify and fix, but with the right tools and approach, you can find and fix them. In our case, monitoring the memory usage of the Node.js process and analyzing the memory usage helped us identify the root cause of the memory leak.

If you liked this article, follow me on X to get notified about my new blog posts and more content.

Alternatively (or additionally), you can subscribe to my weekly Vue & Nuxt newsletter:

I will never share any of your personal data. You can unsubscribe at any time.

If you found this article helpful.You will love these ones as well.
How I Replaced Revue With a Custom-Built Newsletter Service Using Nuxt 3, Supabase, Serverless, and Amazon SES Image

How I Replaced Revue With a Custom-Built Newsletter Service Using Nuxt 3, Supabase, Serverless, and Amazon SES

When to Use useState in Nuxt Image

When to Use useState in Nuxt

Rendering Dynamic Markdown in Nuxt 3+ Image

Rendering Dynamic Markdown in Nuxt 3+

Self-Host Your Nuxt App With Coolify Image

Self-Host Your Nuxt App With Coolify