A game server with a memory leak has a memory floor that rises day after day and never comes back down until the process restarts. That pattern is the only reliable sign. Memory that climbs for a few hours and then levels off is a cache or a heap filling to its configured size, and memory that rises with the explored world is growth, not a leak. Once you know you have a real leak, find it by measuring inside the runtime - a heap summary in Java, collectgarbage("count") in Lua, resource monitors in FiveM, handle dumps in SourceMod - and by disabling halves of your plugins until the slope disappears. Until it is fixed, a scheduled restart and some headroom keep it from becoming a crash at peak time.
Leak, growth or cache: three graphs that look alike#
The panel's memory graph shows the same rising line for three very different situations. Telling them apart is the whole first step.
| Pattern | What you see | What it is | Action |
|---|---|---|---|
| Fill and plateau | Rises for hours after a restart, then flat | A heap or cache reaching its size | Nothing; size the plan for the plateau |
| Step growth | Rises when players explore or build, flat otherwise | The world getting bigger | Expected; world limits or more memory |
| Rising floor | Lowest point higher every day, regardless of activity | A leak | Find it; restart until you do |
The test is to read the graph over days, not minutes, and look at the troughs - the quiet hours when nobody is online. A real leak keeps climbing even overnight, or at least never gives back what it took. Growth tracks player activity: a night with nobody on is a flat night. A full heap rises once and stops. Reading a server load graph goes through the other shapes on the same chart.
Two systems make the first pattern look like a leak to people who have not met it before.
- Java does not give memory back. A Minecraft or Project Zomboid server started with
-Xmx6Gwill, sooner or later, use close to 6 GB plus some overhead, and stay there. The garbage collector frees memory inside the heap; it rarely returns it to the operating system. That is normal, and it is why the Minecraft RAM guide warns against giving Java everything. - Unity and Unreal servers grow their heaps in steps and reuse them. A Valheim or Palworld server's memory after a busy evening is higher than after a quiet one and may not fall back, without leaking anything.
Why a leak becomes a crash#
A leak is a slow problem with a sudden ending. Each day the floor is higher, the peak is higher, and at some point a busy evening's peak meets the plan's memory limit.
On a container host there are two possible endings. Upstream Pterodactyl can let a server swap, which keeps it alive while making it painfully slow. On RE:NODE the kernel stops the container at the limit and it restarts clean instead of swapping - quick to recover, but an unsaved stop from the game's point of view, so everything since the last autosave is lost. The crash watcher also notices: it polls every two minutes for servers whose uptime went backwards, ignores restarts you asked for, and after three unrequested restarts in an hour posts a warning on the server page and opens a ticket automatically. A leaking server usually never reaches that rate, because a leak takes days to refill, but a leaking server that crash-loops at its ceiling will. The detail is in why your game server keeps restarting, and the kernel side in Linux swap and the OOM killer.
Measuring properly#
Before blaming anything, take numbers.
- Restart the server and note memory after it has finished loading and settled - five or ten minutes.
- Record the floor daily for three to five days: the lowest figure in the quiet hours.
- Note what changed in those days: players, new builds, new plugins, events.
- Compute the slope. 150 MB a day on a 6 GB plan gives you a month; 800 MB a day gives you a week.
If you have a shell on the machine, the process's resident memory is in /proc:
$ grep VmRSS /proc/$(pgrep -f valheim_server)/statusVmRSS: 3145728 kBOne caution about container figures. Memory accounting for a container can include file cache - pages of game files the kernel has kept in memory because they were read recently. That cache is reclaimable and is not a leak, though it may show up in raw cgroup numbers. The process's own resident memory, or the runtime's own report, is the better measure.
Finding it in Java servers#
Minecraft and Project Zomboid run on the JVM, and Java has the best tooling of any game runtime.
The question in Java is not "is the process using a lot" - it will use its heap - but "is the live data after garbage collection growing". On Paper, spark answers that from inside the game:
/spark heapsummary/spark gcheapsummary lists the classes holding the most memory, by instance count and size. Take one shortly after a restart and another a day later. A class whose count has grown from thousands to millions, with a plugin's package name in it, is your suspect. /spark gc shows garbage-collection behaviour; a heap that is nearly full straight after every collection means the live set has grown. The spark profiler guide covers reading the output.
Outside the game, the JDK's own tools do the same job:
$ jcmd $(pgrep -f paper.jar) GC.class_histogram | head -25$ jstat -gcutil $(pgrep -f paper.jar) 10sThe histogram is the same information as heapsummary. jstat -gcutil prints how full each heap generation is every ten seconds; watch the old generation column right after full collections. If it creeps upward over hours, live data is growing. A full heap dump (jcmd <pid> GC.heap_dump /tmp/heap.hprof) can be opened in Eclipse MAT to see what is holding the objects, but it pauses the server and writes a file the size of the heap - take it at a quiet time.
The usual Java culprits are plugins that keep references to players, worlds or chunks after they unload: per-player maps never cleared on quit, a listener that stores every event, a cache with no size limit. Chunk-loading plugins and some world-map renderers keep chunks in memory that the server would otherwise unload. Those show up as world or chunk objects growing in the histogram.
Finding it in Lua: Garry's Mod, FiveM, Don't Starve Together#
Lua tells you its own heap size. In Garry's Mod, from the server console:
lua_run print(collectgarbage("count"))The number is kilobytes in use by the server's Lua state. Note it after a restart, after a few hours, and after a day. If it grows steadily, an addon is storing tables it never releases - commonly per-player tables keyed by the player entity, timers created on every spawn and never removed, or hooks added repeatedly. Removing addons in halves and watching this number for a few hours narrows it down far faster than watching overall process memory.
FiveM shows memory per resource. In the client's F8 console, resmon 1 opens the resource monitor with CPU time and memory for each running resource as that client sees it, and the server's own profiler command records server-side resource cost. A resource whose memory column climbs steadily while others hold still is the leak. FiveM server performance and resmon covers reading it.
Don't Starve Together and other Lua-modded games follow the same principle: Lua memory belongs to mods, so a leak is almost always a mod storing state per player, per entity or per day without ever clearing it.
Finding it in Unity, Unreal and Source servers#
Unity games
Valheim, Rust, 7 Days to Die and Unturned run on Unity, usually with the Mono runtime for mods. Their managed heap grows and rarely shrinks, so a high but flat number is normal. Leaks here come mostly from mods: a BepInEx plugin in Valheim, an Oxide or Carbon plugin in Rust, a Harmony mod in 7 Days to Die. Rust gives you some tools in its console - gc.collect forces a collection, and plugin frameworks report per-plugin hook times that point at misbehaving plugins - but per-plugin memory accounting is limited. Bisection is the reliable method.
Some Unity games also have world-driven growth that looks like a leak: Rust entity counts climb across a wipe as players build, and 7 Days to Die memory rises with the number of loaded regions. Compare against entity or region counts before blaming a mod.
Unreal Engine games
Palworld, ARK and other Unreal servers manage native memory. Leaks here are usually in the game itself rather than in mods, and the only real fixes are developer patches. Palworld's early releases were a well-known example, with memory growing over uptime until a restart. If your Unreal server shows a rising floor with no mods installed, check the developer's patch notes and community reports before spending time on bisection, and contain it with restarts. Palworld server memory covers that game specifically.
Source and SourceMod
SourceMod tracks handles - references plugins hold to timers, files, database queries and data structures. A plugin that opens handles and never closes them leaks, and SourceMod notices at a threshold, writing MEMORY LEAK DETECTED IN PLUGIN with the plugin's file name to its error log before unloading the plugin. You can also inspect handle counts directly:
sm_dump_handles handles.txtThe dump lists handles by owning plugin. Take one after a restart and another a day later; the plugin whose count keeps rising is the leak. Team Fortress 2 SourceMod plugins covers plugin management.
Bisection, when the tools do not point anywhere#
When the runtime cannot attribute memory to a component, divide and measure:
- Take a backup of the server, configs and plugin data.
- Disable half the plugins or mods that are safe to remove without breaking saves. Keep content mods that the world depends on; test those last, on a copy.
- Run a full day and record the floor at the same quiet hour.
- If the slope is gone, the leak is in the half you removed; restore that half and remove the other. If it remains, it is in the half still running.
- Repeat until one plugin is left. Twenty plugins take about five rounds - a working week, because each test needs a day.
That is slow, so do it on a copy if you can. Running a test server beside production covers keeping one, and what to do when a mod update breaks has the same halving method applied to crashes. Once you have the culprit, check for an update, report it to the author with your before-and-after numbers, or replace it.
Containing it until it is fixed#
Most leaks are not fixed by you; they are fixed by a plugin author or a game developer, eventually. In the meantime:
- Schedule a restart before the floor reaches danger. If the floor rises 500 MB a day and you have 2 GB of headroom over your normal peak, a restart every two days is enough - you do not need one nightly. Restart schedules that help explains choosing the cadence from the graph rather than habit.
- Save before every restart. Put the game's save command a minute ahead of the restart in the same schedule. A restart that saves first costs nobody anything.
- Shorten the autosave interval while the leak exists, so an unplanned stop at the ceiling loses minutes. Game server autosave intervals has the settings for each game.
- Keep headroom. A server whose normal peak is within a few hundred megabytes of its limit has no margin for a leak. Moving up a tier on RE:NODE changes the limit on the server you already have, without a rebuild.
On RE:NODE, the Schedules tab runs ordered tasks with delays - a console command, then a power action - on a cron expression, so "save, wait a minute, restart" every second night at 05:00 is one schedule.
FAQ#
Is it normal for my server's RAM to keep going up?
For a few hours after a restart, yes - heaps and caches fill. Past that, memory should track player activity and world size. A floor that rises every day, even when nobody plays, is a leak.
Why does my Minecraft server use all the RAM I gave it?
Because Java fills its heap up to -Xmx and rarely returns memory to the operating system. That is not a leak. Check whether the heap's live data after garbage collection is growing, with spark's heapsummary or jstat, before worrying.
Will a daily restart fix a memory leak?
It contains one, it does not fix it. The leak resets with the process and starts again. Use a restart to keep the server away from its limit while you find and remove the cause.
Can more RAM solve a memory leak?
It buys time in proportion to the extra memory divided by the daily growth. That can be the right short-term answer, but the leak still reaches the new limit eventually unless something restarts the server first.
How do I find which plugin is leaking memory?
Use the runtime's own tools first - spark or jcmd for Java, collectgarbage("count") for Lua, resmon for FiveM, sm_dump_handles for SourceMod. If they do not point at one plugin, disable plugins in halves and measure the memory floor for a day each time.




Comments
Completely anonymous: no account, no email, no cookie. We store the name you type, the text and the time - nothing else. Links are limited and markup is not rendered.