Memory limits and parking idle tabs
The v-code.service unit runs inside a cgroup with a hard memory ceiling. Near the
ceiling the server refuses to open another tab, and under real pressure it stops
idle claude processes so the kernel does not have to.
Why you would use it
Every agent and its children run inside this one unit's cgroup. A test run with 27 workers inside a tab can take the whole desktop down. The cap is what keeps the kill inside VCode.
How to use it
- Check what is set:
systemctl --user show v-code -p MemoryHigh -p MemoryMax -p MemorySwapMax - Raise it persistently on a machine with room:
systemctl --user set-property v-code MemoryHigh=16G MemoryMax=18G - These apply immediately. No restart, and the server re-reads the cgroup per request, so a new cap takes effect on the next tab you open.
Never set MemoryHigh above MemoryMax: the hard cap would fire first.
What you see
The journal logs one line per parked tab: parked <thread-id> after 4 min idle,
and parked idle claude process from the runner. The 503 a user meets when the
cap is close, and what a parked tab feels like from the phone, are in
memory-headroom-and-idle-parking.
Options and settings
| Option | Default | What it changes |
|---|---|---|
MemoryHigh |
8G |
Where cgroup reclaim and throttling begin |
MemoryMax |
12G |
The hard ceiling. The OOM kill lands inside this cgroup |
MemorySwapMax |
2G |
How much swap the unit may use |
OOMPolicy |
continue |
An agent child killed by the OOM killer does not take VCode with it |
The guard's own thresholds — new-tab headroom, parking headroom, idle time,
reaper interval, CPU mark — are constants in lib/memory-guard.js and are listed
in
memory-headroom-and-idle-parking.
Limits and known gaps
- Neither guard stops one tab from allocating the whole cap.
MemoryMaxon the unit is what stops that: the kill lands on the biggest process inside the cgroup, which is the runaway, instead of on the desktop. Keep the cap set. - Which tabs are eligible to park, and why a tab is left alone, are in memory-headroom-and-idle-parking.
- Outside a cgroup with a cap — a bare
node server.js— both guards are off.readCgroupMemory()returnsnulland nothing is refused or parked. - A unit that masks
/sys/fs/cgroupalso getsnull, which fails open rather than 500-ing every new tab.
Related
- install-as-systemd-units — where the caps are set
- logs-and-troubleshooting — reading the park lines
- thread-state-on-disk — the disk side of the same question
- memory-headroom-and-idle-parking — the 503 and the parked tab, from the user's seat