Minecraft server out of memory: what actually causes it
"Out of memory" is three unrelated failures wearing the same words, and the fix for one makes the others worse. Before you buy a bigger tier, work out which one you actually have.
The three failures, and how to tell them apart
1. java.lang.OutOfMemoryError: Java heap space in the log. The JVM asked for heap it was not allowed to have. The world, entities and plugin state genuinely did not fit in -Xmx. This is the one where more memory is the right answer.
2. The container exits with code 137, and the log just stops. No Java stack trace, no OutOfMemoryError — the last line is often mid-chunk-load. The kernel killed the process because the cgroup went over its memory limit. Java never got the chance to complain. This is the common one, and buying a bigger tier often does not fix it, because the same misconfiguration scales up with you.
3. Long freezes, then recovery. Not out of memory at all — that is garbage collection, or CPU contention. If TPS sags every evening and recovers overnight, read why your Minecraft server lags at 8pm instead; RAM is not your problem.
Why exit 137 happens when the heap "fits"
Here is the part most guides miss. Your server's memory tier is the limit on the whole container, not on the Java heap. The same cgroup is also charged for everything Java allocates outside the heap:
- JVM non-heap: metaspace, thread stacks, JIT code cache, and G1's own bookkeeping (remembered sets, card table)
- direct and Netty byte buffers, which Minecraft's networking uses heavily
- the OS page cache for memory-mapped region files, plus socket buffers
Set -Xmx equal to the container limit and there is, by definition, nothing left for any of that. The server looks fine at idle. Then someone flies with a high render distance, chunk I/O spikes the page cache, the cgroup tips over its limit, and the kernel kills the process. The heap was never full — which is exactly why the log contains no OutOfMemoryError.
We know this precisely because we shipped it. Our own configuration once set the heap equal to the container limit, and a 16 GB server was OOM-killed by the kernel (CONSTRAINT_MEMCG) with a working set well under the heap size. The fix was not more memory — it was a smaller heap.
How much headroom to leave
The rule we settled on (recorded as ADR-0040 and enforced in internal/provision/heap.go) reserves a fifth of the tier, with a floor of 1 GB because the overhead is roughly fixed at small sizes, then rounds the heap down to a clean boundary:
| Memory tier | JVM heap (-Xmx) |
Reserved for non-heap |
|---|---|---|
| 2 GB | 1024 MB | 1024 MB |
| 4 GB | 3072 MB | 1024 MB |
| 8 GB | 6144 MB | 2048 MB |
| 16 GB | 12800 MB | 3584 MB |
Servers here are started this way already, so this specific failure is configured out rather than left as an exercise. If you self-host or run somewhere else, the number to check is the gap between your -Xmx and whatever memory ceiling the container or machine actually enforces.
Two things worth knowing while you tune it. A bigger heap is not free: G1 has more to scan, and pause times grow with it, so oversizing trades a crash for stutter. And the memory figure your panel shows may be heap usage rather than the container's total footprint — those differ by exactly the headroom above, and confusing them makes a healthy server look near its limit.
When it really is not enough memory
If the log genuinely ends in java.lang.OutOfMemoryError, resize — but check the cause first, because a leak scales with you:
- A plugin or mod holding references it never releases. Restarting fixes it for a few hours, which is the tell.
- Very high view or simulation distance, which multiplies loaded chunks and every entity in them.
- Large numbers of persistent entities — item frames, armour stands, mob farms — all of which live in the heap for as long as their chunks are loaded.
Modded servers start at 4 GB here for this reason, and heavy kitchen-sink packs are usually happier at 8-16 GB. There is no single correct number for every world, which is why the tick is the thing to watch rather than a recommendation from a pricing page — and why you can resize from the panel yourself instead of opening a ticket.
Skip the setup: spin up a server with guaranteed CPU and live TPS — see pricing.