SurviveTh3Dead

Arma 2 DayZ mod, survival servers, and the people who ran them

VPS Hosting for Project Zomboid: Its Shipped 8 GB Java Heap Filled My 8 GB Box at Zero Players

CT 161 gamelab is an unprivileged LXC container on my Proxmox host: Debian 12.15, four cores of an Intel Core i7-4790K at 4.00 GHz, 8,192 MB RAM, 2,048 MB swap. I installed the Project Zomboid dedicated server there on 2026-10-18 using LinuxGSM v26.4.0. ./pzserver auto-install logged Success! App '380870' fully installed, and the server version was 42.21.0.

The box is LAN only. Nobody has ever joined this server. A minute after ./pzserver start, the ProjectZomboid64 process was holding 7,873 MB. When the run ended, free -m showed 128 MB free and 1,400 MB in swap. The process jumped from 2,202 MB to 7,873 MB between 31 and 61 seconds, before ready at 92 seconds.

Where the 8 GB cap comes from

serverfiles/ProjectZomboid64.json ships with this block:

	"vmArgs": [
		"-Djava.awt.headless=true",
		"-Xmx8g",
		"-Dzomboid.steam=1",
		"-Dzomboid.znetlog=1",
		"-Djava.library.path=linux64/",
		"-Djava.security.egd=file:/dev/urandom",
		"-XX:+UseZGC",
		"-XX:-OmitStackTraceInFastThrow"
	]

-Xmx8g is the maximum Java heap. -XX:+UseZGC selects the ZGC garbage collector. I changed only the -Xmx value for the second run. Everything else stayed as shipped.

The measurement setup

I measured both starts with gmeasure.py on the container. It cold-starts ./pzserver start, polls /proc/<pid>/status every second, and marks ready when the console log prints *** SERVER STARTED ****. RSS and process swap come from VmRSS and VmSwap. CPU was sampled from /proc/<pid>/stat over a 60-second window after the ten minutes of RSS sampling; the window measured 3.7% of one core at -Xmx8g and 3.9% at -Xmx4g. Zero players joined either run.

The shipped heap did this

Run 1 kept -Xmx8g. Start time was 16:44:57. At 31 seconds the process RSS was 2,202 MB and swap was 0 MB. At 61 seconds it was 7,873 MB with 97 MB of process swap. Peak RSS came in at 7,891 MB. Final RSS after ten minutes was 7,617 MB, with a process tree at 7,621 MB.

free -m at the end showed 7,861 MB used, 128 MB free, 330 MB available, and 1,400 MB in container swap.

Project Zomboid build 42 server with the shipped -Xmx8g: resident memory jumps to 7.9 GB within a minute, swap in use, ready at 92 seconds
As shipped. 7.9 GB a minute in, before the server even said it had started, and the box in swap.

What the counters reported

An earlier start at 16:44:00 with the same settings left free -m at 7,937 MB used, 67 MB free, and 1,529 MB swap. The ProjectZomboid64 process reported RSS 7,968,480 kB, VmSwap 200,468 kB, RssAnon 908,524 kB, RssFile 33,776 kB, and RssShmem 7,026,180 kB.

Of the roughly 7.6 GB resident, 7.0 GB was counted as shared memory and 0.9 GB as anonymous memory. The container’s swap use was 1,400–1,529 MB, far above the process’s own VmSwap of 156–200 MB. Those are the numbers the captures show. They do not line up, and I left it there.

The heap setting in ProjectZomboid64.json and the memory counters: 7.0 GB of the process counted as shared memory, the container 1.5 GB into swap
The one line that decides it, and where the counters put the memory.

One line changed

At 16:56:12 I changed only -Xmx8g to -Xmx4g in ProjectZomboid64.json and started again. At 31 seconds RSS was 2,089 MB with no swap. At 61 seconds it was 4,864 MB, still no swap. Ready came at 69 seconds. The server settled at 5,176 MB by the end, with peak RSS 5,190 MB and final RSS 5,142 MB.

The container’s free -m after the run showed 5,144 MB used, 2,118 MB free, 3,047 MB available, and 9 MB in swap. At a 4 GB heap cap, the process still used 5,142–5,190 MB, roughly 1.1 GB above the cap. Each configuration was run once. I did not repeat them.

The same server with -Xmx4g: resident memory flat at 5.1 GB, no swap, ready at 69 seconds
One line changed. 5.1 GB, no swap, 23 seconds sooner.

Side by side

heap capreadyrss peakrss finalcontainer swap
-Xmx8g92 s7,891 MB7,617 MB1,400 MB
-Xmx4g69 s5,190 MB5,142 MB9 MB

The VPS arithmetic

Both runs are rows in the server requirements table, and the number that actually decided the plan was in the JSON file.

The measured 5.1 GB at a 4 GB cap does not fit a 4 GB plan. It fits an 8 GB plan. The shipped 8 GB cap filled an 8 GB box into swap at zero players, so leaving it alone means either a 16 GB plan or a config edit before first start.

plans.py reads the same price file as the hosting cost calculator. These are list prices from each provider’s public pricing page, checked 2026-10-18.

ProviderPlanRAMvCPUPrice
HetznerCPX328 GB4 vCPUEUR 35.99/mo
VultrCloud Compute Regular 8 GB8 GB4 vCPUUSD 40.00/mo
DigitalOceanBasic Regular 8 GiB8 GB4 vCPUUSD 48.00/mo
ProviderPlanRAMvCPUPrice
HetznerCPX4216 GB8 vCPUEUR 69.99/mo
VultrCloud Compute Regular 16 GB16 GB6 vCPUUSD 80.00/mo
DigitalOceanBasic Regular 16 GiB16 GB8 vCPUUSD 96.00/mo

Hetzner shows a “from” price in EUR. At the time of writing, those are the figures.

The cheapest 8 GB VPS plan at Hetzner, Vultr and DigitalOcean, prices checked 2026-10-18
What fits the 4 GB-heap measurement, at the time of writing.

The update catch

ProjectZomboid64.json lives in serverfiles/, the directory SteamCMD installs and updates. I have not run a SteamCMD update since editing it, so whether an update restores -Xmx8g is not observed. It is worth checking after every update before you start the server.

Same box, other games

Same container, zero players, one game at a time. Valheim used 1,432 MB. Vanilla DayZ used 4,842 MB. Project Zomboid used more than either at both heap caps.

Before you rent a VPS for a Project Zomboid server, open serverfiles/ProjectZomboid64.json and set the heap cap to fit the plan you are about to pay for. On an 8 GB plan, the run here says -Xmx4g: 5.1 GB used, 9 MB in swap, and the server came up 23 seconds sooner.