Why an AI agent's browser can kill a small server: Chromium tabs, the OOM killer, and swap
After ten browsing tasks an agent's Chromium held 31 processes on a 2 vCPU, 4 GB server with no swap; the kernel killed a renderer and every later task stalled. What we measured, why a laptop shrugs it off, and the fixes.
Because an agent opens a browser tab for every task and closes almost none, each tab is a Chromium renderer process holding 100 to 300 MB, and a small cloud server usually has no swap to absorb the pile-up. On a 2 vCPU, 4 GB server we watched ten browsing tasks leave 31 Chromium processes running beside the agent’s own 785 MB; the kernel then killed a renderer (“Out of memory: Killed process 27072 (chrome)” in the kernel log), every later task stalled at its timeout, and even SSH slowed to minutes. A laptop absorbs the same session because it has more memory and swaps or compresses quietly. The fix that matched the laptop was a 2 GB swap file: the same ten tasks re-run on the same size of server never triggered the killer.
What we watched
The machine was a 2 vCPU, 4 GB cloud server (3.8 GB usable), with a 40 GB disk, Ubuntu 24.04, and, as with most cloud images, no swap configured. OpenClaw ran in a container with its browser tool driving one managed Chromium on a virtual display. Over about forty minutes the agent worked through ten tasks in fresh sessions: flight searches, an airport board, shopping comparisons on three storefronts, news headlines, a hotel results page. Each task opened one or more tabs. None closed any.
At the tenth task the host looked like this: load average 25, 54 and 56 on two cores; 31 Chromium processes, with renderers timestamped across five different tasks at 100 to 290 MB each; 795 MB free of 3,819 MB; and in dmesg, the kernel’s out-of-memory killer taking a renderer with 291 MB resident. From then on new agent sessions could not get a page: four tasks in a row hit their five-minute timeouts with empty logs, because the browser they were waiting on was thrashing. Recovery was manual: openclaw browser stop and a sweep of stray processes, after which the remaining tasks ran one at a time on a fresh browser.
Two causes
The agent never closes a tab, and the harness never reaps one. That half is not the server’s fault; a laptop’s Chrome would carry the same tabs. It is partly the model (it does not think to tidy up) and partly the harness (nothing expires an idle tab). In a second run the same agent closed tabs between tasks unprompted, which tells you how much of this is model mood rather than design. Worth an upstream report; not something you can configure away today.
The server has 4 GB and no swap. That half is the operator’s. A laptop or a Mac mini has 8 to 16 GB plus swap or memory compression, so the same pile of tabs costs it some speed and nothing else. Cloud images ship without swap because it is a per-workload decision, and most server workloads do not want it. An agent running a browser is not most server workloads: its memory use is spiky, tab by tab, and a cushion that is almost never touched is exactly what stops one bad afternoon from killing the process. In our re-run with a 2 GB swap file, swap use sat at 31 MB for the first six tasks and rose to 179 MB from the seventh; available memory never fell below 1.28 GB; the killer never fired.
The fixes
Add swap. A file is the simplest and survives reboots once it is in fstab:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
free -m # the Swap row should now read 2047Size it at half the RAM or more; 2 GB on a 4 GB box matched the laptop’s behaviour in our test. If you would rather not write swap to an SSD, zram gives you a compressed swap device in memory instead (zram-tools or systemd-zram-generator on Ubuntu). Either one turns a kill into a slowdown, which is the whole point.
Give Chromium shared memory. A container gets 64 MB of /dev/shm by default, and Playwright’s docs warn that without more Chromium “can run out of memory and crash.” OpenClaw’s own browser passes --disable-dev-shm-usage so it does not hit this, but a Chromium the agent launches itself will; shm_size: "1gb" in the compose file is free until used.
Restart the browser between heavy jobs. openclaw browser tabs shows what is open; openclaw browser stop releases everything. A line in the agent’s notes asking it to close tabs when a task ends helps some of the time, which is about how much instructions to a model help.
Size for the job. For one agent that reads and chats, 2 vCPU and 4 GB with swap is comfortable, and the measured requirements still stand. For an agent whose day is mostly browsing heavy pages (results pages on booking sites were the slowest we drove), 8 GB removes the question, and the price difference is a few euros.
How to tell this is what happened
sudo dmesg -T | grep -i "out of memory" # the killer's own line, with the process name
free -m # free memory and the Swap row
ps -C chrome -o pid,rss,etime,args | sort -k2 -n | tail # renderers by size and age
uptime # a load average far above your core countThe tell from the agent’s side is quieter: tasks that time out with nothing in the log, one after another, after a stretch of browsing that worked. If you see that pattern, look at the host before you look at the harness. What the browser tool can do is the companion read; the memory it takes to do it is this page.