Your 12-year-old laptop doesn't need replacing. Linux needs tuning.

Linux ships with memory management defaults designed for systems with plenty of RAM. Give it a machine with 3.3 GB and a few modern apps competing for that space, and those defaults are too conservative to prevent freezes.

This is my 2013 MacBook Air – Intel Core i5 Haswell at 1.4 GHz, 3.3 GB RAM, new SSD, new battery, running Ubuntu 26.04. It was locking up about once a session. I was close to buying a replacement. Instead I spent an afternoon on three config changes.

The machine now runs without incident. This is what I changed.


The actual problem

When Chrome, Obsidian, and Ollama compete for 3.3 GB of RAM, the system eventually starts using swap. The kernel's OOM (out-of-memory) killer is supposed to clean this up, but it's a last resort. By the time it activates, the system has already been thrashing swap hard enough that the UI is frozen. The machine is freezing because the kernel lets memory pressure get catastrophic before intervening.

There are three levers to change this.


Lever 1: Know what's happening

Before you can fix a problem, you need to be able to see it.

By default, systemd-journald logs to /run/log/journal – a tmpfs partition in RAM that disappears on reboot. Every crash wipes its own evidence. The fix is one command:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

journald defaults to Storage=auto, which uses /var/log/journal when the directory exists. Creating the directory is all it takes. Logs now survive reboots. After any incident, journalctl --boot=-1 shows what happened.


Lever 2: Intervene earlier

systemd-oomd is a userspace OOM manager. It monitors memory pressure and kills processes before the kernel's OOM killer has to. Userspace kill is surgical: one process dies, the machine stays responsive. Kernel kill is blunt and arrives too late.

The problem: oomd's default thresholds are conservative. Two drop-in configs tune it for a memory-constrained machine.

System-wide: /etc/systemd/oomd.conf.d/99-aggressive.conf

[OOM]
SwapUsedLimitPercent=60%
DefaultMemoryPressureLimit=90%
DefaultMemoryPressureDurationSec=20s

oomd ignores memory pressure below the SwapUsedLimitPercent floor and only acts when sustained pressure exceeds DefaultMemoryPressureLimit for the duration specified. Below 60% swap usage, it stays out of the way entirely.

User session: /etc/systemd/system/user@1000.service.d/99-oomd.conf

[Service]
ManagedOOMMemoryPressure=kill
ManagedOOMMemoryPressureLimit=80%
ManagedOOMPreference=avoid

ManagedOOMMemoryPressure=kill is the important one – without this line, oomd only observes. With it, oomd kills. The 80% threshold for user apps is lower than the system 90%, so Chrome dies before anything critical does. ManagedOOMPreference=avoid protects system services.

sudo systemctl restart systemd-oomd

In practice: memory pressure spikes, oomd kills a Chrome process or renderer, the machine keeps running.


Lever 3: Give the system more room

The machine had a 3.8 GB swapfile. With 3.3 GB RAM and oomd's 60% threshold, that left ~2.3 GB of swap before oomd activates – not much runway. Expanding to 8 GB raises that to ~4.8 GB.

sudo swapoff /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1G count=8
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Run this shortly after boot or after closing Chrome. swapoff moves swap contents back to RAM – if you're already 2+ GB into swap, this will itself trigger an OOM kill.


Bonus: Keep Chrome from eating everything in the first place

Auto Tab Discard suspends idle Chrome tabs automatically. Configure it to discard after 10–20 minutes of inactivity. On a 3.3 GB machine with 30+ tabs, this cuts RAM usage by 500 MB to 1 GB before memory pressure ever becomes an issue.


What I tried that didn't work: zram

zram compresses swap data in RAM – faster than disk swap, roughly 3:1 compression ratio. It would be the ideal solution for this machine. But the kernel (6.17-generic on Haswell-ULT) doesn't have the zram module compiled in. Getting it requires a custom kernel. That's a project for another day.


Results

Metric Before After
Swap 3.8 GB 8 GB
OOM kills Kernel (machine freezes) Userspace (process dies, machine survives)
Crash logs Gone on reboot Persistent in /var/log/journal
Daily reboots 1–3 0 (so far)

The hardware was never the problem. A 2013 MacBook Air with a new SSD and a new battery runs Linux fine – it just needs the OS configured for the memory it actually has.

Kernel OOM defaults assume you have room to breathe. Tune oomd to intervene early, give the system enough swap runway, and make sure failures leave evidence. That's it.


May 2026 – 2013 MacBook Air (MacBookAir6,2), Ubuntu 26.04, kernel 6.17