Your Server Has Free RAM. Why Did Linux Kill the App?

Installed rack-mounted server framed by an open perforated rack door, with a technician in the background. Operations

Your application disappears, its supervisor restarts it, and the server dashboard shows available RAM. Before blaming the Linux OOM killer or ordering a larger dedicated server, establish which component ended the process and which memory boundary applied at that moment.

A host-level graph can describe the wrong scope or the wrong time. A service may have a memory limit far below the server’s installed capacity. A graph captured after termination may show the memory that the failed process has just released.

This playbook helps operators of rented Linux dedicated servers separate host memory pressure, workload limits, and userspace termination policies. The practical result is a recovery decision supported by logs and configuration, rather than a hardware upgrade based on a single dashboard.

The commands assume an authorized host shell on a system using systemd. They inspect state without changing configuration. Journal queries may require administrative privileges; the cgroup file inspection below specifically assumes cgroup v2.

Confirm the Linux OOM killer was involved

Record the failure time, affected service or container, user-visible impact, and recent workload changes. Preserve evidence outside the affected workload before repeated restarts or container replacement make it harder to reconstruct the event.

A forced termination alone does not identify its cause. Operators, deployment tools, service managers, and memory-management components can all terminate processes. An application allocation error is also a different observation from a kernel-recorded OOM kill.

On a systemd host, begin with current-boot kernel messages:

sudo journalctl -k -b --no-pager

Match relevant OOM messages to the incident time and process identity. Keep the surrounding context, not only the final line naming a victim. The journalctl documentation explains boot and kernel filtering. Access and retained history depend on the host’s logging configuration.

If the machine rebooted after the incident, the current boot may not contain the event. Check available history before selecting the appropriate previous boot:

journalctl --list-boots

Missing logs leave the cause unconfirmed. They do not establish that an OOM event did or did not occur.

Separate the three investigations

Use evidence to choose the next investigation
Possible mechanism Evidence to seek Next question
Kernel OOM under host memory pressure Kernel incident context and memory history across the host. Which workloads consumed the available operating margin?
Kernel OOM within a constrained workload Cgroup context, applicable limits, and incident-aligned memory events. Did a service, container, or parent group impose the relevant boundary?
Userspace memory-pressure policy Policy-manager logs identifying its action and target. Which policy acted, and what conditions triggered it?
No matching memory evidence Application errors, deployment events, supervisor records, and other termination sources. Is memory actually the cause?

The kernel’s memory-management overview describes OOM killing when memory exhaustion cannot be resolved through reclaim. The service that is killed is not, by itself, a complete diagnosis of what created the pressure.

A Linux OOM killer alert should lead to diagnosis of the affected workload and its constraints before a rental upgrade.

Read the host graph at the incident time

Inspect the period before the failure, not just the recovered state. Compare available memory, swap activity, workload concurrency, and application demand. Check whether the monitoring interval could have missed a short peak.

cat /proc/meminfo

The kernel’s proc filesystem documentation distinguishes MemFree from MemAvailable. The latter estimates memory available for starting applications without swapping; it is not a service-specific allocation allowance.

This command shows current host information. Save it as current context, not as a reconstruction of an earlier failure. Ask which measurements were actually collected before the process exited.

For a dedicated server running databases, web workers, backup jobs, and containers together, compare overlapping work. A nightly export and a backup may be individually acceptable but leave too little room when their peaks coincide. Treat that as a hypothesis to verify against timestamps and workload measurements.

Find the workload’s effective memory boundary

Dedicated hardware does not prevent software from restricting individual workloads. Identify the affected service’s cgroup and its parent hierarchy. Perform this inspection on the host where possible; a container’s view may omit relevant ancestors.

For an illustrative systemd service named api.service, the following read-only query exposes useful properties. Use the actual affected unit on your server:

systemctl show api.service \
  --property=ControlGroup,MemoryCurrent,MemoryHigh,MemoryMax,EffectiveMemoryMax,Result

The systemctl manual documents property inspection. Property availability varies by systemd version; missing output is not proof that a limit does not exist.

The systemd resource-control documentation describes MemoryMax= as a limit for the unit and EffectiveMemoryMax= as accounting for tighter parent-slice limits. Inspect parents before concluding that the service has unrestricted memory.

On cgroup v2, inspect these files in the resolved workload cgroup and relevant ancestors:

  • memory.current: current accounted usage.
  • memory.max: the hard boundary; max means no limit at that particular level.
  • memory.high: a boundary that applies throttling and reclaim pressure, rather than directly invoking the OOM killer.
  • memory.events and memory.events.local: event counters with hierarchical and local scope, respectively.

The kernel cgroup v2 documentation defines these interfaces. If usage reaches memory.max and cannot be reduced, the kernel can invoke OOM killing within the group.

A rise in oom_kill supports investigation of kernel OOM kills involving the group, but does not alone prove its own limit was responsible. Correlate counters with logs and timestamps. An old nonzero count is not a timestamped record, and recreating the cgroup can remove its previous counters.

These filenames apply to cgroup v2. If the host uses cgroup v1 or a mixed arrangement, use the documentation for the actual hierarchy instead of treating missing v2 files as a healthy result.

Check userspace policy and container configuration

If systemd-oomd is installed and active, inspect its records separately:

sudo journalctl -u systemd-oomd.service -b --no-pager

The systemd-oomd documentation describes a userspace service that uses cgroup v2 and pressure information to act before kernel OOM. Its decisions require their own evidence; a search limited to kernel OOM messages can miss this path.

For Docker workloads, inspect the deployed memory and swap configuration through the runtime. Docker’s resource-constraint documentation explains that container limits are configurable and that swap settings interact with the memory allowance.

Compare the deployed configuration with the intended one. A copied deployment definition can retain an old absolute limit after migration to a larger rented machine. Changing the host’s RAM does not automatically raise that fixed limit.

Recover at the boundary the evidence identifies

Choose an intervention that fits the confirmed cause:

  • Legitimate demand exceeds a fixed workload limit: consider a bounded increase only after checking capacity reserved for the operating system and other services.
  • Peak concurrency creates the failure: reduce parallel work, queue requests, or separate overlapping batch jobs through application-supported controls.
  • Memory grows unexpectedly: investigate the release, request pattern, cache, or leak before adopting a larger allowance as the permanent solution.
  • Host-wide pressure persists: evaluate workload separation or additional RAM after measuring demand across representative operating periods.
  • A userspace policy acted: review its configured scope and pressure evidence before deciding whether policy tuning or workload changes are appropriate.

Follow the application’s recovery procedure after a kill. Check interrupted jobs, incomplete requests, retries, and any database recovery requirements. Avoid replaying work until duplicate-action risks are understood.

Use the server upgrade decision process when measurements indicate a persistent hardware-capacity problem. Ask the provider to confirm upgrade options and downtime; application cgroup policy may remain your team’s responsibility under the rental agreement.

Verify recovery under representative demand

A restarted process proves only that it started again. Observe a controlled workload resembling the trigger, with stop conditions and an approved recovery path. Do not deliberately exhaust production memory to reproduce the incident.

Compare workload memory, applicable limits, new event-counter changes, host availability, latency, and completed work. Continue observation through the relevant batch or traffic window rather than declaring success during an idle period.

If provider involvement is needed, send timestamps, host and service identifiers, relevant logs, and the specific infrastructure question using the support incident workflow. Add the corrected limits and alerts to the maintenance record.

Close the incident with a verified memory budget

  • The termination mechanism is supported by incident-aligned evidence, or explicitly remains unconfirmed.
  • The workload’s limits and relevant parent boundaries are recorded.
  • The recovery action preserves capacity for other required services.
  • Representative work completes without recurring termination or unacceptable latency.
  • Monitoring covers workload memory and limits alongside host memory, with an assigned responder.
Rate article
Servers.Lease
Add a comment