
"Add a swap file" is the standard advice for a small server, and "swap makes everything slow" is the standard reply. Both are true, in different situations, so we ran the situations. We booted real 512 MB and 1 GB Ubuntu 24.04 virtual machines 84 times under controlled memory pressure, with no swap, with a swap file at two swappiness settings, and with zram, and counted OOM kills, failed requests and latency.
Short version: swap saves you from spikes and idle memory. In our spike test, no swap meant the app was killed by the kernel and 470 to 1,100 requests failed in 60 seconds; with swap, none failed. It slows you down when the data you actively use doesn't fit: top speed fell from about 565 to 693 requests a second to 87 to 107, and on a slow disk the server served only 18 to 29% of a modest load. Swappiness barely changed anything. zram beat a swap file in one test on 1 GB and lost to it on 512 MB.
How we tested
Each run was a fresh KVM virtual machine from the Ubuntu 24.04.5 cloud image (kernel 6.8), with 1 vCPU and 512 MB or 1 GB, disk capped at 3,000 IOPS and 150 MB/s, so the results don't depend on our test machine's fast disk. After boot, the image left about 312 MB available of the 512 MB and 692 MB of the 1 GB. That's the first useful number here: a stock cloud image starts with roughly 40% of a 512 MB server already gone.
The app is a small Python web server holding text-like data in memory, split into "hot" (each request reads 20 random 64 KB chunks of it) and "cold" (filled at start and never touched again, like the idle parts of most long-running apps). systemd restarted it if it died. We loaded it from outside with hey at a steady 40 requests a second for 60 seconds, with a 10 second timeout. We set the app's memory as a share of what was available at boot:
| Scenario | Memory the app uses | Stands in for |
|---|---|---|
| Fits | 65% (25% hot, 40% cold) | A server with room to spare |
| Spike | 65%, plus a separate job taking 50% more for 15 seconds, started 15 seconds in | A backup, a build, a report, |
| Cold overflow | 120% (25% hot, 95% cold) | More services than fit, most of them idle |
| Hot overflow | 140%, all hot | Your working data really is bigger than RAM |
Four swap setups: none; a 1 GB swap file at swappiness 60 (the default) and at 10; and zram with zstd, sized equal to RAM, at swappiness 100. Each combination ran twice, so 64 runs, plus 20 more without the rate limit or on a slow disk (below). Every table shows both results as a range. We ran three VMs at a time on a 6-core Windows machine under WSL2, so they shared a host: p99s jumped in some runs even with no memory pressure, including no-swap ones, so we don't report p99 and small differences in p95 mean nothing.
Does it save you? Failures
| Server | Test | No swap: requests served | No swap: failed | Swap file: served | Swap file: failed | zram: served | zram: failed |
|---|---|---|---|---|---|---|---|
| 512 MB | Spike | 608 to 1,370 | 577 to 1,100 | 2,360 to 2,400 | 0 | 2,243 to 2,362 | 0 |
| 1 GB | Spike | 1,146 to 1,322 | 470 to 707 | 2,045 to 2,214 | 0 | 2,232 to 2,278 | 0 |
| 512 MB | Cold overflow | 0 | 1,468 to 1,473 | 2,154 to 2,400 | 0 | 2,307 to 2,398 | 0 |
| 1 GB | Cold overflow | 0 | 1,461 to 1,467 | 2,313 to 2,400 | 0 | 2,245 to 2,247 | 0 |
| 512 MB | Hot overflow | 0 | 1,461 to 1,462 | 2,348 to 2,400 | 0 | 2,128 to 2,192 | 0 |
| 1 GB | Hot overflow | 0 | 1,479 to 1,487 | 2,372 to 2,384 | 0 | 2,156 to 2,400 | 0 |
A perfect run serves 2,400 requests. The swap file line is swappiness 60; 10 looked the same. Swap setups lost no request in any run; counts below 2,400 there are the load tool sending fewer because the app answered slowly, and even runs with no pressure at all dipped to about 2,170 in this lab.
The kernel kills your app, not the job that caused the trouble. In 7 out of 8 OOM kills during the spike tests, the victim was the web app, because it was the biggest process, and in 3 of 4 no-swap spike runs the job itself finished happily while the app went down twice. That is the classic small-server failure: a nightly backup takes your site offline, and the backup log says everything went fine.
Over 100% with no swap is not a slow server but a dead one. The app never finished starting in any of the 8 no-swap overflow runs: it was killed, restarted by systemd, and killed again, 3 or 4 times in the runs where we could read the counter. In 5 of those 8 runs SSH couldn't even complete our final read at the end, and in one it gave no answer for the full 2 minutes we waited. With swap, the same 120% load started in 3 to 11 seconds and served normally.
Does it slow you down? Latency at a steady 40 requests a second
p95 response time for the requests that succeeded:
| Server | Scenario | No swap | File, swappiness 60 | File, swappiness 10 | zram |
|---|---|---|---|---|---|
| 512 MB | Fits (65%) | 12 to 13 ms | 12 to 14 ms | 12 to 15 ms | 13 to 21 ms |
| 512 MB | Spike | 11 to 12 ms | 15 to 22 ms | 14 to 29 ms | 92 to 149 ms |
| 512 MB | Cold overflow (120%) | never served | 17 to 24 ms | 18 to 24 ms | 25 to 29 ms |
| 512 MB | Hot overflow (140%) | never served | 60 to 65 ms | 53 to 58 ms | 86 to 125 ms |
| 1 GB | Fits (65%) | 19 ms | 18 to 31 ms | 12 to 16 ms | 17 to 87 ms |
| 1 GB | Spike | 12 to 156 ms | 24 to 72 ms | 27 to 100 ms | 43 to 50 ms |
| 1 GB | Cold overflow (120%) | never served | 22 to 37 ms | 22 to 24 ms | 32 to 55 ms |
| 1 GB | Hot overflow (140%) | never served | 47 to 55 ms | 51 to 54 ms | 35 to 43 ms |
Under real pressure, swap costs surprisingly little if most of the swapped memory is idle. The cold overflow case, with 20% more memory in use than the server has available, had a p95 of 17 to 37 ms on a swap file against 12 to 19 ms with room to spare. The kernel pushes out what nobody is reading and leaves the hot data alone. That's what swap is for. Hot overflow is visibly slower at 47 to 65 ms but still working, at this modest load, on this disk. The two tests below are where it stops being fine.
Where it stops being fine
Top speed falls by 85%
We removed the rate limit and let 4 connections go as fast as they could, for 60 seconds:
| Server | Fits in RAM, no swap | Hot overflow, swap file | Hot overflow, zram |
|---|---|---|---|
| 512 MB | 565 to 693 req/s | 106 to 107 req/s | 48 to 62 req/s |
| 1 GB | 658 to 674 req/s | 87 to 89 req/s | 61 to 71 req/s |
This is the real price of hot swapping. It looked fine at 40 requests a second only because that was well under the limit, which sat at about 90 to 105 on the swap file and 50 to 70 on zram. An app at 40 requests a second that gets a burst to 200 has no headroom left at all, whereas with enough RAM it had more than 10x to spare.
A slow disk changes the answer
Next, the same swap file on a disk capped at 300 IOPS, a tenth of the speed above, again offering 40 requests a second:
| Scenario | 3,000 IOPS: p95 | 300 IOPS: p95 | 300 IOPS: requests served of 2,400 |
|---|---|---|---|
| 512 MB, spike | 15 to 22 ms | 57 to 196 ms | 1,898 to 2,218 |
| 512 MB, cold overflow | 17 to 24 ms | 38 to 107 ms | 1,897 to 2,064 |
| 512 MB, hot overflow | 60 to 65 ms | 984 to 1074 ms | 436 to 490 |
| 1 GB, hot overflow | 47 to 55 ms | 638 to 652 ms | 683 to 695 |
Spikes and idle memory still survive a slow disk with a p95 around 40 to 200 ms. Hot overflow doesn't: p95 hits about 1 second on 512 MB and the server keeps up with 18 to 29% of what is asked. No request timed out and nothing was killed, which is the trap: the server looks up, and the site is just slow. A VPS that's stuck there is worse to diagnose than one that crashed.
Swappiness: leave it alone
Setting vm.swappiness=10 is the most repeated tip on the subject. In our runs it made no difference you could measure: under the same pressure, swap use and p95 overlapped at 60 and 10. On the 512 MB spike, 60 swapped 144 to 192 MB and 10 swapped 165 to 203 MB. Where there's no pressure it just changes how much idle memory drifts out: 1,450 pages (about 6 MB) during a 512 MB fits run at 60, about 190 to 330 pages at 10, and nothing at all on 1 GB in either case. The kernel documentation describes it as the relative IO cost of swapping against dropping file cache, and our workload didn't lean on file cache. A database that relies on its file cache may see a difference, so test on yours, but don't expect the setting to rescue a server that's short of memory.
zram: not free memory
zram keeps swapped pages compressed in RAM, with no disk involved. Our text-like data compressed at about 1.9 to 1 with zstd, measured as original data over the memory zram really used (for example, 371 MB stored in 192 MB). The kernel's zram guide expects about 2 to 1 as well. Real apps with binary or already-compressed data will do worse.
It trades disk writes for CPU, on the same vCPU your app needs. On our 1 vCPU servers that was a bad deal at 512 MB: p95 in the spike was 92 to 149 ms against 15 to 22 ms on a swap file, and in hot overflow 86 to 125 ms against 60 to 65 ms. On 1 GB it was closer, and at steady load better in hot overflow (35 to 43 ms against 47 to 55 ms), though its top speed was still lower. We did not run zram on the 300 IOPS disk. It doesn't write swapped pages to disk, so it should dodge most of that penalty, but that is reasoning rather than a measurement. Our advice: try it when the disk is your bottleneck, and don't make it the default on one small vCPU.
What to do on your server
| What you see | What it means | Do this |
|---|---|---|
shows little available, swap off | One spike from an OOM kill | Add a swap file (below). It costs nothing until it's used. |
Swap in use, in near zero most of the time | Idle memory parked on disk. Healthy | Nothing. Don't tune swappiness. |
and both active all the time, app slow | Hot data doesn't fit | More RAM or less work: fewer workers, smaller caches. Swap can't fix this. |
shows | No room left at all | Add swap now, then find out why. Set on what must stay up. |
For scale, our healthy cold overflow runs swapped in about 320 pages a second (si about 1,300 KB/s in vmstat), and the hot overflow about 4,000 pages a second at the same load (si about 16,000 KB/s), which is where capacity had already fallen by 85%. Your disk's numbers will differ, so watch the trend on your own server.
A swap file, as we ran it
zram, as we ran it
Two things caught us out. On Ubuntu cloud images the module is in a separate package, and right after modprobe the device can be busy for a moment: zramctl failed with "failed to reset: Device or resource busy" in our first runs, and those silently ran with no swap at all until we looked at the output. Always check swapon --show.
These commands don't survive a reboot; we ran them on each boot of each test, so we haven't tested a permanent setup. page-cluster=0 turns off swap readahead (kernel documentation), which a RAM-backed device doesn't need.
Where this lands on tport.cloud
One honest note, because it decides whether the steps above apply to you: our servers under $20 a month and our shared accounts have a hard memory limit and no swap, so swapon won't work there and the "no swap" columns are your columns. That includes the $1 server (0.5 vCPU, 512 MB, free for 30 days), which is fine for a small service that fits, and not for one that spikes.
The way out is what this test keeps pointing to: memory is cheaper than the problem. Our standard server is $7.50 a month for 4 vCPU and 8 GB, 8 times the memory of the bigger server in this test, and you can resize up from the console. To see what your stack needs first, we've measured 10 common stacks, and here's how those prices compare with Droplets.
Sources
Our own measurements, 2 November 2026: 84 runs on Ubuntu 24.04.5 cloud images, kernel 6.8.0-147, under QEMU/KVM with 1 vCPU, nested under WSL2; load from hey. Settings: Linux kernel sysctl vm documentation (swappiness range 0 to 200, default 60; page-cluster) and zram documentation. tport.cloud prices from tport.cloud/pricing, Germany, 2 November 2026.
Skip the swap tuning: 8 GB for $7.50 a month, or the $1 server free for 30 days. Traffic included, prepaid, no surprise bills.
See all servers

