NextJS Memory Leak
Answered
Northeast Congo Lion posted this in #help-forum
Northeast Congo LionOP
Hello!
I have a NextJS Project that uses websockets. I have deployed to Railway successfully, but am concerned about the memory usages of the server. For those who are not aware railway deploys code and you rent a server for the whole month rather than vercel architecture where you pay for the time that you use on your server. Since I am using websockets and need the connections to persist for a long time, I chose to go this route.
The problem is this. After deploying a change to the website the server load is around 200mb. Then when a user connects to the website the server load suddenly jumps up to around 400-500mbs. Even though this is quite a significant load, I am not worried about this spike.
The issue that I am worried about is that this spike seems to persist even if that user ceases to use the website. So that 400mbs-500mbs will stay with the server until after another deployment. It is constantly using resources and I am not quite sure why.
I have stress tested my website with multiple clients open all sending messages and the server spiked to 1.5GB of memory usage which would not fall down even after all clients disconnected.
Here is a list of the things that I have tried to fix this issue:
1) Used export const dynamic = 'force-dynamic' in order to stop caching of data inside of the server in case this was a problem.
Reasoning: I thought that the server would cache the html from the website into the server and serve it to the client, in order to prevent this i disabled caching in the routes with the most html.
2) Disabled Polling Inside Of My Website
Reasoning: My project Uses Websockets, and when a socket is not connected it reverts to polling. I figured that this setup could be persistently calling the server and putting on a load.
3) Checked logs To See if Sockets are disconnecting correctly (They Are)
4) https://github.com/vercel/next.js/issues/49929
I have also checked this github issues post. However most of the comments seem to suggest that the issue is with the appdir. I am using the app directory structure in my application, and cannot turn off the appdir like some in this thread are saying to do as a solution.
I believe that there is some sort of memory leak happening, since the memory usage is constantly slowly creeping upwards. If there are tools that anyone knows about that check for memory leaks, or if there are common patterns that I should look out for. Please let me know!
I am also willing to completly start over with this project if that is needed. This is my first nextjs project and I would like to understand what I need to do to prevent memory leaks. I have started the process of finding the leak by having every route returning null so that none of my code is being run. However I am slightly worried since the memory usage on the server is still slowly creeping up from 350mb to 400mb without any usage in the course of a day.
I have a NextJS Project that uses websockets. I have deployed to Railway successfully, but am concerned about the memory usages of the server. For those who are not aware railway deploys code and you rent a server for the whole month rather than vercel architecture where you pay for the time that you use on your server. Since I am using websockets and need the connections to persist for a long time, I chose to go this route.
The problem is this. After deploying a change to the website the server load is around 200mb. Then when a user connects to the website the server load suddenly jumps up to around 400-500mbs. Even though this is quite a significant load, I am not worried about this spike.
The issue that I am worried about is that this spike seems to persist even if that user ceases to use the website. So that 400mbs-500mbs will stay with the server until after another deployment. It is constantly using resources and I am not quite sure why.
I have stress tested my website with multiple clients open all sending messages and the server spiked to 1.5GB of memory usage which would not fall down even after all clients disconnected.
Here is a list of the things that I have tried to fix this issue:
1) Used export const dynamic = 'force-dynamic' in order to stop caching of data inside of the server in case this was a problem.
Reasoning: I thought that the server would cache the html from the website into the server and serve it to the client, in order to prevent this i disabled caching in the routes with the most html.
2) Disabled Polling Inside Of My Website
Reasoning: My project Uses Websockets, and when a socket is not connected it reverts to polling. I figured that this setup could be persistently calling the server and putting on a load.
3) Checked logs To See if Sockets are disconnecting correctly (They Are)
4) https://github.com/vercel/next.js/issues/49929
I have also checked this github issues post. However most of the comments seem to suggest that the issue is with the appdir. I am using the app directory structure in my application, and cannot turn off the appdir like some in this thread are saying to do as a solution.
I believe that there is some sort of memory leak happening, since the memory usage is constantly slowly creeping upwards. If there are tools that anyone knows about that check for memory leaks, or if there are common patterns that I should look out for. Please let me know!
I am also willing to completly start over with this project if that is needed. This is my first nextjs project and I would like to understand what I need to do to prevent memory leaks. I have started the process of finding the leak by having every route returning null so that none of my code is being run. However I am slightly worried since the memory usage on the server is still slowly creeping up from 350mb to 400mb without any usage in the course of a day.
Answered by Northeast Congo Lion
I think that I may have solved the problem? The client component that I was using StudentSearch was using FilteredStudentList which didint declare "use client" on the top. So I think it was a server component that the server never collected. So all of those people in the website were being cached and rendered on the server and never collected leading to massive memory build up.
Does this reasoning make sense? Just trying to understand NextJS a little more, on the bright side memory usage is being cleaned up again so yay!
Does this reasoning make sense? Just trying to understand NextJS a little more, on the bright side memory usage is being cleaned up again so yay!
35 Replies
Northeast Congo LionOP
I realize that nextjs is a serverless architecture, and that sockets require a server to be constantly running. So this may not be the best combination, however I believe that services such as chatgpt use websockets and were using nextjs as well. Are these memory leaks just a fundamental incompatibility between the two services? If so, is there another commonly reccomended framework that has the server action functionality that nextjs has that I could use?
Northeast Congo LionOP
Update:
I have tried having the routes like start/example layout.tsx fetch the data that I need. Then return null as its component/html instead of the components that I have rendered before that used my data. Now opening 50 tabs of the website will spike the usage by 50mb, then when I close the tabs the server memory will decrease again to baseline. This is exactly the behavior that I want, before when I was rendering client components instead of null. The usage of the server will spike and then never go back down when I close the tabs. I hope this extra context helps!
I have tried having the routes like start/example layout.tsx fetch the data that I need. Then return null as its component/html instead of the components that I have rendered before that used my data. Now opening 50 tabs of the website will spike the usage by 50mb, then when I close the tabs the server memory will decrease again to baseline. This is exactly the behavior that I want, before when I was rendering client components instead of null. The usage of the server will spike and then never go back down when I close the tabs. I hope this extra context helps!
websockets with nextjs is not a good idea
you should move that to a external node server
Northeast Congo LionOP
Yes it is starting to look that way with this memory usage error. However I just have one quick question about how data is passed from server to client in nextjs
import { ReactNode } from 'react';
import fetchCoursesAndServers from '../../server_actions/fetchCoursesAndServers';
import StudentSearch from '../../(site)/components/StudentSearch';
import fetchAllProfiles from '../../server_actions/fetchAllProfiles';
import fetchHighSchoolNames from '../../server_actions/fetchHighSchoolNames';
export const dynamic = 'force-dynamic';
export default async function Layout({children}:{children:ReactNode}) {
const courses = await fetchCoursesAndServers();
const students = await fetchAllProfiles();
const highSchools = await fetchHighSchoolNames();
const courseNames = courses.map((course) => course.abbreviation + " " + course.course_number);
return null;
return (
<div
style={{
width: '100%',
height: '100%',
backgroundColor: 'var(--color-background)',
display: "flex",
justifyContent:'space-between',
borderRadius: '5px',
}}
>
<StudentSearch highSchools={highSchools} courses={courseNames} students={students}/>
{children}
</div>
);
}I have been testing this route, and it seems that when I return null instead of this studentSearch client component, that the memory usage errors stop. The garbage collection will take all unused data and then clean up after itself. However, the memory usage will never clean up after I use a client component and instead of return null return studentSearch.
Is this data fetching on server and giving to a client component that uses "use client" wrong?
no
but that has nothing to do with nextjs, u should check your functions and your StudentSearch component
memory usage where btw?
on the server or client
Northeast Congo LionOP
server
yeah check your rsc functions
Northeast Congo LionOP
quick question what is an rsc?
react server component
everything without "use client"
Northeast Congo LionOP
ahh makes sense
but should a client component affect the server memory and cause that memory build up?
I am thinking that the inital rendering of the client component happens on server and sends to cleint, but in the server the unused data is never being picked up by garbage collection. However I am not using many server components, my pattern is mostly using things like layout.tsx to fetch data and then feeding it to a client component.
I checked my server actions and simply using them does not keep the memory usage high on the server. It is only when I render a client component that uses that data from the server actions
I checked my server actions and simply using them does not keep the memory usage high on the server. It is only when I render a client component that uses that data from the server actions
@Northeast Congo Lion I am thinking that the inital rendering of the client component happens on server and sends to cleint, but in the server the unused data is never being picked up by garbage collection. However I am not using many server components, my pattern is mostly using things like layout.tsx to fetch data and then feeding it to a client component.
I checked my server actions and simply using them does not keep the memory usage high on the server. It is only when I render a client component that uses that data from the server actions
so basically when u remove StudentSearch the memory usage drops?
Northeast Congo LionOP
yes. the memory usage will spike when the tabs are opened since its fetching the data, then it drops to normal after cleaned up. But rendering the StudentSearch will stop this behavior
its basically a filtering program. Takes in a group of people and filtres them based on certain attributes that you fill in the form
I am using Virtuoso in the FilteredStudentList component. Testing commenting out that part to test for any memory leaks in that library
Northeast Congo LionOP
I think that I may have solved the problem? The client component that I was using StudentSearch was using FilteredStudentList which didint declare "use client" on the top. So I think it was a server component that the server never collected. So all of those people in the website were being cached and rendered on the server and never collected leading to massive memory build up.
Does this reasoning make sense? Just trying to understand NextJS a little more, on the bright side memory usage is being cleaned up again so yay!
Does this reasoning make sense? Just trying to understand NextJS a little more, on the bright side memory usage is being cleaned up again so yay!
Answer
Northeast Congo LionOP
Thanks for your time! You reminding me of server components and looking into it reminded me that you cant put server components inside of client components!
@Northeast Congo Lion Thanks for your time! You reminding me of server components and looking into it reminded me that you cant put server components inside of client components!
u can btw pass your server component to the client component as a prop
and basically render your server component from the client
the initial render will be still on the server tho
Northeast Congo LionOP
but the initial render will be garbage collected after the client component renders the server component inside of it and stop taking up memory on server right?
Northeast Congo LionOP
cool, Ill try this pattern out and see how it goes! Thanks for the info!