How Linux Handles Memory, OOM Killer, and Swappiness

By Raman Kumar

Updated on Oct 07, 2025

In this tutorial, we'll learn how to do swap and memory tuning. How Linux handles memory, OOM killer, and swappiness.

Concise, practical, and aimed at sysadmins and DevOps teams. We cover how Linux manages RAM and swap, how the OOM Killer chooses a victim, what swappiness does, and concrete tuning steps for Ubuntu 24.04 / recent kernels.

1) Brief primer — how Linux thinks about memory

Linux exposes a single virtual address space per process. Physical RAM, the page cache (file-backed pages), and swap together form the system’s usable memory: the kernel keeps hot data in RAM and moves inactive anonymous pages out to swap when needed. Several kernel knobs control behavior (swappiness, overcommit, vfs cache pressure).

Useful quick checks:

free -h                 # summary (Mem / Swap)
cat /proc/meminfo       # detailed counters (CommitLimit, Committed_AS ...)
swapon --show           # active swap devices/files
vmstat 1 5              # see si/so (swap in/out) activity
ps aux --sort=-rss | head -n 10   # top memory processes

2) What swap is and how it works

Swap is disk/flash space used to hold pages that are not currently needed in RAM. It’s slower than RAM and should be a safety valve, not a primary performance tool. Modern Ubuntu uses swap files by default (swapfile), which are easier to resize than partitions. Adding swap keeps the system alive under peak loads and affects the kernel’s overcommit accounting and OOM behavior.

Create a swap file (Ubuntu 24.04 — safe, step-by-step)

# Create (choose size)
sudo fallocate -l 8G /swapfile || sudo dd if=/dev/zero of=/swapfile bs=1M count=8192

# Secure and format
sudo chmod 600 /swapfile
sudo mkswap /swapfile

# Enable now
sudo swapon /swapfile
sudo swapon --show
free -h

# Persist across reboot
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

If fallocate fails (filesystems that don’t support it), use dd. Verify with swapon --show and free -h.

3) Swappiness — what it is and how to tune it

vm.swappiness is a kernel parameter (0–100) that controls how aggressively Linux moves anonymous memory to swap versus reclaiming filecache. Higher numbers → more swapping; lower numbers → prefer keeping processes resident (less swap). The usual default is 60.

Check current:

cat /proc/sys/vm/swappiness
sysctl vm.swappiness

Set temporarily (immediate effect until reboot):

sudo sysctl vm.swappiness=10

Make persistent (recommended):

echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf
sudo sysctl --system

Practical guidance (rules of thumb)

Database / latency-sensitive servers (Postgres, Redis, real-time apps): swappiness=1 to 10. We strongly prefer RAM for process memory to avoid I/O-induced latencies.

General-purpose servers: swappiness=10–30 is common for servers where latency matters but some swap is acceptable.

File servers / cache-heavy workloads: keep default (60) or tune higher only if tests show benefit — aggressive swapping can free RAM for pagecache and improve throughput on read-heavy workloads, at the expense of latency.

Do not pick a value blindly. Run load tests and measure. Swappiness affects behavior at the kernel reclaim level; the right value depends on workload and I/O performance.

4) OOM Killer — how the kernel picks a process

When the kernel determines the system is out of memory, it runs the OOM Killer. It computes a “badness” / oom_score per process (higher = more likely to be killed) based primarily on memory usage but adjusted by other factors and by oom_score_adj. You can view a process’s score with /proc/<pid>/oom_score and influence it with /proc/<pid>/oom_score_adj.

Key facts:

oom_score is driven by memory footprint and other heuristics; oom_score_adj / OOMScoreAdjust is additive and can make a process effectively immune (-1000) or very likely (+1000) to be chosen.

There are kernel-level OOM decisions and userspace helpers (e.g., systemd-oomd) that can act earlier using PSI and cgroups. Ubuntu 24.04 systems commonly include systemd-oomd to take preventive action.

Inspect OOM events/logs:

# Kernel OOM logs
journalctl -k | grep -i -E 'out of memory|oom'
dmesg | grep -i oom

# systemd-oomd activity
journalctl -u systemd-oomd

Protecting critical services

If a process must not be chosen by the OOM killer, prefer systemd unit settings (for systemd-managed services) rather than fiddling with proc files manually.

Example systemd drop-in (protect Postgres or another daemon):

sudo systemctl edit postgresql.service
# add:
[Service]
OOMScoreAdjust=-1000

Then sudo systemctl daemon-reload && sudo systemctl restart postgresql. Use with care: protected processes can force the kernel to kill other important services or block recovery.

5) Overcommit and related knobs (safety / behavior)

Overcommit controls whether the kernel allows allocations that exceed physical memory + swap:

vm.overcommit_memory=0 (default heuristic),

=1 (always allow — allocations succeed until actual OOM),

=2 (strict; refuse allocations beyond swap + RAM * overcommit_ratio / 100).

If we want deterministic behavior in memory-constrained production, consider =2 with an appropriate vm.overcommit_ratio, but test carefully — some apps expect overcommit. Check CommitLimit / Committed_AS in /proc/meminfo to debug allocation accounting.

Set example:

# Conservative policy (test first)
echo 'vm.overcommit_memory=2' | sudo tee /etc/sysctl.d/99-overcommit.conf
echo 'vm.overcommit_ratio=50' | sudo tee -a /etc/sysctl.d/99-overcommit.conf
sudo sysctl --system

6) Swap performance improvements and modern features

zswap: compressed in-RAM cache of pages destined for swap — trades CPU for less I/O; useful on systems where swap I/O is slow or SSD wear is a concern. Kernel docs describe zswap and when it helps. Enable via kernel cmdline or sysfs parameters; Ubuntu 24.04 supports it.

zram: compressed block-device in RAM that can be used as swap; good for very low-RAM systems.

On SSDs, swap I/O is faster, but frequent swapping still harms latency and can shorten device life.

Enable zswap (example kernel parameter; persistent via GRUB):

# /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash zswap.enabled=1 zswap.compressor=lz4 zswap.max_pool_percent=20"
sudo update-grub

Test and measure before rolling to production.

7) Practical, ordered tuning checklist (apply with staging + telemetry)

Measure baseline
free -h; vmstat 1 10; iostat -x 1 10; top -o %MEM — identify whether swapping already happens and whether it harms performance.

Add modest swap (if none)
Create an 8–16GB swapfile (as above). Verify with swapon --show.

Set swappiness
Start conservative: vm.swappiness=10. Persist via /etc/sysctl.d/99-swappiness.conf. Load test and observe si/so (vmstat). If underutilizing cache, increase and retest.

Consider zswap on disk-backed swap
Enable and test; zswap often reduces swap I/O and improves responsiveness.

Protect critical services
Add OOMScoreAdjust=-1000 to systemd units for the most critical daemons we cannot afford to kill. Use sparingly.

Overcommit policy
If deterministic failure semantics are needed (embedded, strong guarantees), test vm.overcommit_memory=2 with a matching overcommit_ratio. Otherwise keep default.

Monitor continuously
Track si/so (vmstat), oom messages (journalctl/dmesg), iowait, and application latency during synthetic load. Re-tune based on measured latency, not intuition.

8) Monitoring commands and what to watch

  • vmstat 1 — watch si/so (swap in/out) and wa (I/O wait).
  • iostat -x 1 (install sysstat) — check device utilization and wait times for swap device.
  • journalctl -k | grep -i oom and journalctl -u systemd-oomd — OOM events and userspace actions.
  • /proc/<pid>/oom_score and /proc/<pid>/oom_score_adj to inspect targets.
  • sar -B (if sysstat installed) for historical paging activity.

Interpretation: sustained so/si activity with rising wa and higher request latency = swapping causing performance problems.

9) Short, practical rules

  • Swap is a safety net, not a substitute for RAM. Use swap to avoid crashes; rely on RAM for performance.
  • For DB and latency-sensitive services, reduce swappiness (1–10) and prefer adding RAM.
  • Protect critical daemons via OOMScoreAdjust, but do it cautiously — protecting everything defeats the OOM killer.
  • Use zswap/zram on I/O-poor systems to reduce swap I/O if testing shows benefit.
  • Always test tunings under representative load and monitor metrics before and after.

Check out robust instant dedicated serversInstant KVM VPS, premium shared hosting and data center services in New Zealand