CLI tool
rfjakob/earlyoom avatar
rfjakob/earlyoom

earlyoom: the userspace OOM daemon that kills at 10 percent, not at zero

earlyoom - Early OOM Daemon for Linux

4,317 stars212 forksCMIT

At a glance

What is it?
earlyoom is a dependency-free C daemon that watches MemAvailable and free swap and sends SIGTERM before the kernel oom-killer has to. It suits servers and desktops that freeze instead of recovering, and it is the wrong tool if you already run systemd-oomd or PSI-based oomd.
Who is it for?
Adopt earlyoom on Linux boxes where a memory spike locks the machine before the kernel oom-killer acts: servers without systemd-oomd, desktops, and containers built from the provided scratch Dockerfile. Skip it if you already run systemd-oomd or oomd on PSI, or if you need per-cgroup policy, because earlyoom kills one global victim chosen by /proc/*/oom_score.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The freeze earlyoom exists to prevent

The README opens with the complaint that gives the project its reason to exist: the kernel oom-killer has a bad reputation, so Linux invokes it only when it has no other choice, swapping out the desktop environment, dropping page cache and emptying buffers before it kills anything. The author says he has never been patient enough to sit in front of an unresponsive system and wait. The question people asked on reddit and Stack Exchange was whether the in-kernel killer could be configured to step in earlier. The README answers that directly: no, at least not through the in-kernel oom-killer. In userspace, it says, we can do whatever we want.

That is the whole pitch. earlyoom is a userspace daemon that decides when memory pressure has gone far enough and picks a victim itself. It is aimed at anyone who has watched a Linux box thrash instead of recovering: desktop users, small server operators, and people running workloads that occasionally balloon. It is not a general memory manager and it does not tune the kernel. It watches two numbers and sends signals.

How earlyoom decides: MemAvailable, swap, and oom_score

earlyoom checks available memory and free swap up to 10 times a second, and less often when there is a lot of free memory. The README is explicit that it reads available memory rather than free memory, because on a healthy Linux system free memory is supposed to be near zero: the kernel caches disk access in whatever is left over, and those caches can be dropped when something else needs the pages. The available figure sums memory that is unused or can be freed immediately. Seeing the available column requires a recent free and Linux kernel 3.14 or newer; with an older free, the same value comes from grep MemAvailable /proc/meminfo.

The default trigger is a pair of conditions: both available memory and free swap below 10 percent of total memory available to userspace processes, which the README defines as total minus shared. When that holds, earlyoom sends SIGTERM to the process the kernel itself considers the largest, read from /proc/*/oom_score. A second, lower threshold sends SIGKILL: the startup banner in the README shows SIGTERM at 10 percent and SIGKILL at 5 percent for both memory and swap. Processes are killed until the values rise above the minimum again, and every action is logged to stderr.

The design is deliberately blunt. There is one global decision, not a per-cgroup or per-service policy, and the victim is whoever the kernel already ranks highest. That is why the README can claim the tool is simple and solid and written in pure C with no dependencies. The trade-off is that earlyoom has no notion of which process matters to you. A large but important process and a large and disposable one look the same if their oom_score is similar.

Installing earlyoom and watching it kill a test process

The README gives two paths. Building from source is a clone, a cd and make, followed optionally by make test for the Go-based unit and integration suite. Installing as a service is a separate step: sudo make install for systemd, or sudo make install-initscript on non-systemd systems. The Makefile places the binary under /usr/local/bin by default, writes the systemd unit to /etc/systemd/system, and runs systemctl enable earlyoom; the note in the README says chcon warnings about failing to set a context can be ignored on systems with SELinux disabled, such as Ubuntu 19.04 or Debian 9.

bash
git clone https://github.com/rfjakob/earlyoom.git
cd earlyoom
make
sudo make install

Distribution packages exist too. Debian 10 and newer and Ubuntu 18.04 and newer have an earlyoom package, Fedora and RHEL 8 with EPEL have one, and Arch Linux carries it in extra. On the packaged route the service is enabled in the same command that installs it.

bash
sudo apt install earlyoom
bash
sudo dnf install earlyoom
sudo systemctl enable --now earlyoom
bash
sudo pacman -S earlyoom
sudo systemctl enable --now earlyoom

Running the binary directly prints a banner with memory and swap totals, the SIGTERM and SIGKILL thresholds, and a running line of available memory and free swap figures. To see it act, the README suggests creating a memory leak with tail /dev/zero. If you want to react to a kill, parse the journal: sudo journalctl -u earlyoom | grep sending. The README notes that systemctl status earlyoom shows the last 10 lines when earlyoom runs as a systemd service.

Why earlyoom does not just poke the kernel oom-killer

There is a --kernel-oom flag that makes earlyoom write f to /proc/sysrq-trigger instead of choosing a victim itself. The README warns against assuming this works. On some kernel versions, tested on v4.0.5, triggering the kernel oom killer manually does not work at all: it may free only graphics memory, which is allocated again immediately, and kill no process. The README links a gist showing the behaviour on a machine with Intel integrated graphics. The problem was fixed in Linux v5.17, by commit f530243a in the mainline tree.

That history explains the default. earlyoom finds its victim the way the kernel would, by reading /proc/*/oom_score, but it does the signalling in userspace where it controls the timing. If you are on a kernel older than 5.17 and were considering --kernel-oom as a way to get the kernel's own selection logic, the README's own testing says the flag may do nothing useful on that machine. The userspace path is the one the project actually stands behind.

Memory footprint, logging, and the limits of a global victim

earlyoom reports about 2 MiB of VmRSS, of which only 220 kiB is private RssAnon; the rest is the libc library shared with other processes. All of it is locked with mlockall() so the daemon does not slow down when memory is short. That is a sensible choice for a process that must stay responsive at exactly the moment the system is under pressure, and it is one of the few places where the implementation detail matters more than the feature list.

The limitation is the selection policy. earlyoom kills the largest process by oom_score, globally. On a machine running several services, the largest process is not necessarily the one you would choose, and there is no configuration in the README for protecting a specific process or scoping the decision to a cgroup. If your problem is one container or one user session eating the box, a tool with per-cgroup accounting is a better fit. earlyoom also has no rollback: it sends signals, and the process is gone. The README does not document any way to undo a kill or to mark a process as exempt beyond the kernel's own oom_score_adj, which earlyoom does not manage for you.

The logging story is similarly minimal. Actions go to stderr, which under systemd means the journal. The README's suggested post-kill hook is to grep the journal for sending, which is fine for alerting but not a policy engine. If you need different behaviour per workload, you are writing that yourself around the log.

earlyoom versus nohang, systemd-oomd and oomd

The README names two alternatives. nohang is described as a similar project written in Python with additional features and configuration options. That is the real difference: earlyoom is pure C with no dependencies and a deliberately small surface, while nohang trades the dependency-free build for more knobs. If the defaults are close to what you want, earlyoom's lack of configuration is a feature. If you need per-process rules, nohang is where the README points you.

The second alternative is Facebook's pressure stall information patches and the accompanying oomd userspace helper, with the patches merged in Linux 4.20. That is a different mechanism entirely: PSI measures how much time tasks spend stalled on memory, CPU or IO, and oomd acts on that signal rather than on a percentage of available memory and swap. For a modern kernel and a cgroup-based workload, PSI-based oomd is the more precise instrument. earlyoom's percentage thresholds are simpler to reason about and work on kernels back to 3.14, which is why it remains useful on older or non-systemd systems. The related searches comparing earlyoom with systemd-oomd and oomd are asking exactly this question, and the honest answer is that the newer tools see pressure the older one cannot.

Licence, packaging and the cost of keeping it current

earlyoom is MIT licensed, which is permissive and imposes no copyleft obligation on the surrounding system; the repository carries the LICENSE file the badge points to. The practical licence question is not the daemon but the packaging: distributions ship their own builds, and the version you get from apt, dnf or pacman is whatever that distribution has packaged, not necessarily the latest release. The releases listed in the repository are v1.9.0 from 2025-09-16, and v1.8.2 and v1.8.1, both from 2024-05-13. The last push to the repository was on 2026-09-21.

Upgrade cost is low but not zero. Building from source needs a C compiler and, for the manpage, pandoc; the Makefile skips manpage generation with a message when pandoc is absent. The test suite is written in Go and pulls golang.org/x/sys and goprocinfo, so running make test needs a Go toolchain even though the daemon itself has no runtime dependencies. The Dockerfile builds with gcc, sets CFLAGS to -static, and copies the resulting binary into a scratch image, which is a clean way to ship it into a container without a package manager. That is the path to take if you want a specific version rather than the distribution's.

Editorial conclusion

Adopt earlyoom on Linux boxes where a memory spike locks the machine before the kernel oom-killer acts: servers without systemd-oomd, desktops, and containers built from the provided scratch Dockerfile. Skip it if you already run systemd-oomd or oomd on PSI, or if you need per-cgroup policy, because earlyoom kills one global victim chosen by /proc/*/oom_score. Before rollout, check which release your distribution ships, confirm MemAvailable is present in /proc/meminfo on kernels 3.14 and newer, and decide whether the default 10 percent SIGTERM and 5 percent SIGKILL thresholds are right for the machine.

Frequently asked questions

What does earlyoom do?

It checks available memory and free swap up to 10 times a second and, by default, sends SIGTERM to the largest process by oom_score when both fall below 10 percent, then SIGKILL below 5 percent. It runs in userspace and is written in pure C with no dependencies.

How to install earlyoom?

Clone the repository and run make, then sudo make install for systemd or sudo make install-initscript otherwise. Debian 10+, Ubuntu 18.04+, Fedora and RHEL 8 with EPEL, and Arch Linux also have packages, installed with apt, dnf or pacman respectively.

What are the differences between systemd-oomd and earlyoom?

earlyoom acts on percentage thresholds for available memory and free swap and kills one global victim chosen by /proc/*/oom_score. systemd-oomd is built on pressure stall information, which measures time tasks spend stalled on memory, and the PSI patches were merged in Linux 4.20.

Is earlyoom safe?

It sends SIGTERM first and only escalates to SIGKILL below the lower threshold, and it locks its roughly 2 MiB of memory with mlockall() so it stays responsive under pressure. There is no documented way to undo a kill or to exempt a specific process beyond the kernel's own oom_score_adj.

What is an earlyoom alternative?

The README points to nohang, a similar Python project with additional features and configuration options, and to Facebook's PSI patches with the oomd userspace helper, merged in Linux 4.20. The difference is that nohang offers more configuration and oomd acts on pressure stall information rather than percentage thresholds.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. rfjakob/earlyoom on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rfjakob-earlyoom.svg)](https://hysenlabs.com/projects/rfjakob-earlyoom)