cswork / libraryOpen practice workspace

Articles

Linux OOM Interview Questions: Memory Pressure, Kill Selection, and Exit Evidence

Practice Linux OOM interview questions with cgroup memory events, kernel logs, kill selection, PSI, and the limits of exit-code evidence in production.

An exit status of 137, a restart, and a graph showing “plenty of free memory” can all be true at once. That combination does not tell you who sent SIGKILL or which memory boundary was crossed. A strong Linux OOM interview answer builds a time-aligned evidence chain: process exit, kernel or cgroup event, memory limit and usage, and the workload's trajectory before the kill.

This article uses Linux cgroup v2 documentation, Linux OOM score manuals, and pressure-stall documentation as primary technical evidence. The incident packet below is an original practice exercise, not a real production event or a reported employer question. Question records are practice prompts, not predictions of an exact interview.

The shortest accurate OOM answer

First ask which scope ran out of memory. A process can hit a cgroup's memory.max while the host has available RAM. A host can suffer global memory exhaustion even when a particular cgroup is below its own limit. A userspace manager or operator can also send SIGKILL, producing a similar process exit without a kernel OOM decision. In cgroup v2, memory.events exposes counters including max, oom, and oom_kill; kernel logs identify actual kill decisions. Compare counter changes and log timestamps with the process exit.

Then ask why this workload consumed that memory. A rising resident anonymous footprint might suggest retained objects or a larger working set; file cache growth alone is not a leak. PSI memory pressure measures time tasks were stalled, not simply bytes allocated. After confirming the event, choose a mitigation that fits the cause: fix a leak, reduce concurrency, adjust a justified limit, or rebalance the node. Raising the limit before understanding the boundary can move the next failure elsewhere.

Original incident packet: one kill, three hypotheses

At 14:02, a batch worker stops. The orchestrator reports exit 137. The node dashboard at 14:05 shows 18 GiB available. The worker belongs to a cgroup with memory.max = 2 GiB. At 14:01, its memory.current approached that limit; memory.events.local later shows max increased by 28, oom by 1, and oom_kill by 1. A host kernel log at 14:02 names a memory-cgroup out-of-memory kill in that service's cgroup. Its application metric shows in-flight task count doubled after a deployment.

The leading explanation is a cgroup-local OOM kill, not host-wide exhaustion. The cgroup limit and timestamped local event align with the exit; the kernel message confirms the kill context. The node's available memory does not refute it because memory.max is a separate boundary. The doubled in-flight task count suggests a mechanism, but it is not yet proof of a memory leak. Memory use could have grown because more valid tasks were resident at the same time.

Now remove one piece of evidence. If the event counters did not change and no OOM message appeared, exit 137 only says the process was killed by signal 9 under the usual shell 128 + signal convention. Investigate a deployment controller, an operator action, a watchdog, or a userspace OOM manager. If the kernel log shows a global OOM instead, the victim may be in this cgroup even though its own memory.max was not the trigger. The important interview move is to rank these explanations with evidence, not recite a single command.

Read cgroup memory files as a set

memory.current is current charged memory for the cgroup. memory.max is the hard limit when set to a value instead of max. memory.high is a throttling and reclaim boundary, not the same as a hard kill threshold. memory.events provides hierarchical event counts; memory.events.local gives counts local to that cgroup. A parent cgroup's hierarchical counter can move because a child had the event. This distinction matters in multi-tenant services where the same parent includes several workloads. The kernel's cgroup v2 reference defines these interfaces.

Read deltas, not just one cumulative value. An oom_kill count of 4 after a crash might include three events from last week. Capture counters before and after the suspected window, or compare against monitoring samples with timestamps. oom and oom_kill are not synonyms: the oom event records an allocation situation where the OOM killer was considered, while oom_kill counts processes killed by any kind of OOM killer that belong to the cgroup. The exact relationship depends on the event path; avoid a one-to-one assumption.

Also inspect memory.stat to understand what was charged: anonymous memory, file-backed cache, kernel memory, and other categories. memory.swap.current and swap limits may matter. Current values taken after a restart can be misleading because the killed process released memory. Historical metrics and kernel messages are often more valuable than free -h run several minutes later. In a container, inspect the correct cgroup path rather than assuming the container's process sees the host's root hierarchy.

Why did the kernel choose that process?

Linux exposes a current /proc/<pid>/oom_score; higher scores make selection more likely in an OOM context. /proc/<pid>/oom_score_adj adjusts the kernel's badness heuristic from -1000 to +1000. The manual page explains that the “allowed memory” underlying selection depends on whether the event concerns the whole system, a cpuset, a memory policy, or a memory limit. Consequently, “the largest PID always dies” is not a complete rule.

oom_score_adj is a policy lever, not a memory fix. Protecting one daemon more strongly can push the kill to another task. Setting -1000 broadly can make an exhausted system less recoverable. In an interview, explain which workload is expendable, which is critical, and how you would validate the effect of any adjustment under controlled conditions. Do not change this value in production merely to make a dashboard look quieter.

For a cgroup OOM, the candidate set is constrained to that cgroup's scope. memory.oom.group can direct group kill behavior when enabled; check the actual configuration before asserting that one process or the whole workload must die. For a host-wide event, the kernel log's victim and context matter more than a present-day oom_score, which may have changed or vanished with the process.

Pressure is an early warning, not a kill receipt

Pressure Stall Information (PSI) reports how much time tasks are unable to make progress because of CPU, memory, or I/O contention. /proc/pressure/memory has some and full time series. some means at least one task was stalled; full means all non-idle tasks were stalled simultaneously. A cgroup can expose its own pressure file when configured. The kernel PSI documentation describes these semantics.

PSI helps answer whether performance degraded before a kill. A rise in memory pressure plus memory.high events may indicate reclaim and throttling before memory.max is reached. But PSI alone cannot say who sent SIGKILL, nor can it prove a leak. Link it to allocations, working-set behavior, limits, and incident timing. If latency spiked but no OOM kill occurred, pressure may still be the core problem; if a process was killed instantly by an operator, memory PSI may remain quiet.

This distinction makes an answer operationally useful. A team could alert on sustained pressure and reclaim before users see 500s, while still keeping separate alerts for oom_kill counter changes and kernel kill messages. No single “memory usage over 90%” rule captures all three phenomena.

Diagnose cause before changing the limit

In the incident packet, concurrency doubled and memory approached 2 GiB. Two plausible repairs compete. If each task legitimately needs 120 MiB and the worker allows 20 simultaneous tasks, the limit and concurrency are mismatched. Bounded concurrency or a measured higher limit may solve it. If a worker retains completed task buffers forever, increasing the limit delays the kill but does not fix the leak. Heap profiles, object counts, memory.stat trends, and controlled load runs distinguish them.

Be careful with cache explanations. Linux uses spare memory for page cache and may reclaim it; a high “used” number on a host does not prove an application leak. Yet cgroups charge memory, including relevant file cache, and workload-specific reclaim may still create pressure at a limit. Compare anonymous and file components, reclaim counters, and the request pattern. A dataset scan can look like a leak in a coarse dashboard while actually being cache churn; a true retained-object leak shows a different post-GC or post-task baseline.

If the remedy is more memory, explain the capacity effect on placement and neighboring services. A 2 GiB-to-4 GiB increase may make the Pod unschedulable on some nodes, or it may worsen host-wide contention if many replicas are changed together. Test with representative peak work, set a justified request and limit, and observe both service outcomes and node pressure. Do not generalize a number from this fictional case to production.

Evidence worksheet to use in the interview

QuestionStrong evidence and What it does not prove alone
Was the process killed?Strong evidence: Exit signal/status plus runtime recordWhat it does not prove alone: Who sent the signal.
Was a cgroup OOM involved?Strong evidence: Timestamped memory.events.local delta and kernel contextWhat it does not prove alone: Why memory grew.
Was the host exhausted?Strong evidence: Global OOM log and host pressure at the event timeWhat it does not prove alone: That this process was leaking.
Was there early pressure?Strong evidence: PSI, reclaim, and latency trendsWhat it does not prove alone: That a kill actually occurred.
Did the fix work?Strong evidence: Representative load, bounded memory, stable latency, no new killsWhat it does not prove alone: Safety at all future scales.

This worksheet is an original diagnostic aid. In a live interview, make the scope and time of each observation explicit. “The host is fine now” is weaker than “At the kill time, the cgroup hit its hard limit; the local OOM counter advanced; the kernel named the same cgroup.”

Final interview takeaway

Do not start with “137 means OOM.” Start with “137 tells me a SIGKILL-style exit; I need a timestamped kernel, cgroup, runtime, and memory-trajectory correlation to identify the cause.” Then choose a targeted mitigation and state how you will know it worked. Use the single-server crash prompt to practice saying the evidence chain in under two minutes before expanding into the cause analysis.

Sources and Further Reading

Research checked September 28, 2026. Kernel version, cgroup hierarchy, runtime, and userspace kill policy affect the evidence available on a real host.