I have several virtual machines. They are quite cheap, with only 1–2 GB of RAM. High performance isn’t a priority for me because I only use them to host a few websites and online services. However, as I deployed more services, some of these VMs started running out of memory. Upgrading the RAM is the worst option because it costs extra money. If we can expand the RAM without paying a penny, that would be the perfect solution.
The easiest way is to add a traditional swap file or partition. Generally speaking, if you don’t need a huge amount of memory all at once, swapping out inactive pages is highly worthwhile. Some memory pages just sit there, occupying space while rarely being accessed. If a server runs long enough, you’ll notice that the swap space almost always holds a few hundred megabytes of data—things that are completely idle.
Since these are budget VMs, their hard disks usually have very strictly restricted bandwidth and IOPS (after all, you get what you pay for). If your system runs low on memory and needs to swap frequently, a sluggish disk will make the entire OS painfully laggy.
This is where ZRAM comes to the rescue. Simply put, it’s compressed RAM. It acts as a block device that can be formatted as a swap partition. When the system runs out of memory, it compresses idle pages and keeps them right inside the RAM. Compared to disk-based swap, the benefit is blazing speed and much lower latency. Although it consumes a tiny bit of CPU for compression and decompression, it’s still significantly faster than disk swap in practice, making the user experience much smoother. This method has been around for years—even your routers and smartphones utilise ZRAM. I usually enable this on all my servers. For example, on a 2GB RAM server, I’ll configure a 2GB ZRAM swap alongside a 1GB disk swap, giving ZRAM a higher priority. The system will prefer ZRAM first and only resort to the disk swap when ZRAM is full.
Based on my server benchmarks, using ZRAM with the zstd compression algorithm yields an average compression ratio of around 2.3:1. This means a 2.3GB ZRAM swap actually occupies only about 1GB of physical memory. If you have 2GB of physical RAM and a 2GB ZRAM swap, it’s roughly equivalent to having 3GB of total RAM (the 2GB ZRAM compresses down to ~1GB of memory usage, leaving 1GB of free physical memory; 1GB free + 2GB swap = 3GB).
However, a bottleneck occurs when you use ZRAM alongside disk swap. Once ZRAM fills up and the system starts hitting the disk swap, everything grinds to a halt. Furthermore, ZRAM might still hold a lot of totally redundant rubbish, which continues to waste physical memory. So, is there a way to flush these long-term inactive pages out to the disk instead of letting them sit in RAM?
Back in 2017, Linux 4.14 introduced a feature called writeback for ZRAM. It allows ZRAM to write its compressed pages back to a physical disk. With this feature, I can completely ditch traditional disk swap. It perfectly scratches my itch: it moves stagnant memory pages to the disk while maintaining excellent everyday swap performance. Taking the previous scenario, if a 2GB RAM server uses a 2GB ZRAM swap with writeback enabled, it can ideally act like a 4GB RAM machine because ZRAM can offload its pages to the disk and free up the memory it occupied.
To set up writeback, you need to configure a backing device and manually trigger the writeback process. You can first run echo all > /sys/block/zram0/idle to mark all current pages as idle. After some time, running echo idle > /sys/block/zram0/writeback will write the pages that remained untouched during that period into the backing storage. In other words, writeback doesn’t happen automatically just by attaching a backing device—it requires manual triggers. This gives you the flexibility to decide exactly when to write back, preventing disk I/O from slowing down your system during peak traffic hours.
For detailed configurations, check out the Linux Kernel Documentation: zram: Compressed RAM-based block devices.
I recently rolled this feature out to several of my servers, and it feels fantastic. My servers run Debian, and I installed zram-config to handle the boot configuration automatically (it’s essentially just a helper script; you can do it manually, but apt is just way more convenient). Once installed, you need to tweak the config script at /usr/bin/init-zram-swapping:
| |
Even though this particular machine only has 2GB of RAM, thanks to writeback, I boldly allocated a 4GB ZRAM disk size. Additionally, you need to create the /zram_backend.img file:
| |
Next, set up a crontab to mark pages as idle every 10 minutes and perform the writeback 9 minutes later. (This part is flexible; I chose this schedule because I have another cron job running every 10 minutes, so I wanted to wrap up the marking and writeback right before the next cycle hits):
| |
Finally, reboot the server and you’re good to go. (Alternatively, you can just apply the configurations manually without a reboot).
I also had an AI help me write a quick status script called zram_stat.sh to monitor things:
| |
The final output looks something like this:
| |
It works beautifully. The available memory on my services has opened up completely.
Honestly, I’m pretty sure the hyped-up “Extended RAM” marketing gimmicks we see from smartphone manufacturers lately are just ZRAM under the hood. Android phones have been doing this for absolute ages, and it’s enabled by default on most devices. It’s just that nobody used to put it in a brochure. I have no idea who started this trend of rebranding a years-old core feature as a “shiny new breakthrough” just because the general public hadn’t heard of it before. Truly speechless.