A web service that slows down, a worker killed without a clear message, or a server that swaps does not necessarily mean that all the RAM of the machine is exhausted. With systemd, a limit set on a unit may be enough to explain the symptom.
Cgroups allow the Linux kernel to account, limit, and prioritize the resources of a group of processes. Before adding memory or randomly restarting, check what systemd applies to the affected service.

View the cgroup of a service
On recent distributions, systemd places each service in its own cgroup. You do not have to move PIDs by hand to diagnose a classic unit like Nginx, PostgreSQL, or an application worker.
Start by reading the service status and the properties related to resources. Replace nginx.service with the actual name of your unit.
systemctl status nginx.service --no-pager
systemctl show nginx.service -p ControlGroup -p MainPID -p MemoryCurrent -p MemoryMax -p MemoryHigh -p CPUQuotaPerSecUSec
ControlGroup provides the path managed by systemd. MemoryCurrent displays the memory accounted for the unit at the time of reading. If MemoryMax is infinity, systemd has not set a hard memory ceiling on this service.
If you start from a PID, read its cgroup from /proc. In cgroup v2, you will often see a line like 0::/system.slice/nginx.service.
pid=$(systemctl show nginx.service -p MainPID --value)
cat /proc/$pid/cgroup
If MainPID is 0, the service has no active main process. Go back to systemctl status and journalctl instead of concluding from an empty PID.
Read memory and CPU limits
MemoryMax is a hard limit. If the cgroup reaches this ceiling and the kernel does not reclaim enough memory, a process from the group may be killed by the OOM killer.
MemoryHigh is less brutal. The kernel throttles allocations and tries to reclaim memory when the cgroup exceeds this threshold. To contain a service without causing it to drop at the first spike, it’s often a better initial setting than MemoryMax.
CPUQuota limits the available CPU time for the service. CPUQuota=25% gives the equivalent of a quarter of a logical core. On a multi-core machine, CPUQuota=200% allows up to two cores of CPU time.
systemctl show nginx.service
-p MemoryCurrent -p MemoryMax -p MemoryHigh
-p CPUUsageNSec -p CPUQuotaPerSecUSec
Do not confuse quota with priority. A quota prevents the service from exceeding a certain amount of CPU. A priority, with nice or CPUWeight, primarily arbitrates competition when multiple tasks request CPU at the same time.
Finding the source of a limit
A limit can come from the file provided by the package, a systemd drop-in, or a locally created override. Read the complete configuration before altering the service.
systemctl cat nginx.service
systemctl show nginx.service -p FragmentPath -p DropInPaths
A file under /etc/systemd/system/nginx.service.d/ usually overrides the unit provided by the package. Avoid modifying a file directly in /usr/lib/systemd/system/ or /lib/systemd/system/, as an update may overwrite it.
Next, check the symptoms. A slow service may also be due to a slow SQL query, a saturated disk, a full queue, or an application error.
journalctl -u nginx.service -b --no-pager
journalctl -k -b | grep -Ei 'oom|out of memory|killed process|memory cgroup'
If the limits remain at infinity and the kernel log shows no memory events, look elsewhere before touching cgroups: application logs, disk metrics, network latency, or actual process consumption.
Test without touching the service
To validate syntax or measure the effect of a limit, run a temporary unit with systemd-run. The test does not modify Nginx, PostgreSQL, or your business service.
sudo systemd-run --unit=test-memory-limit
--property=MemoryMax=256M
--property=CPUQuota=25%
/usr/bin/bash -c 'sleep 300'
Then read the applied properties. For CPUQuota=25%, systemd may show a value equivalent to 250ms per second.
systemctl show test-memory-limit.service
-p MemoryMax -p CPUQuotaPerSecUSec -p ControlGroup -p ActiveState
systemctl cat test-memory-limit.service
Stop the test unit as soon as you are finished. With sleep, forgetting is not critical, but this reflex avoids surprises when the test runs a real command.
sudo systemctl stop test-memory-limit.service
Apply a systemd override
When logs and measurements confirm that a limit makes sense, go for a systemd override. The example below sets a high threshold at 800 MB, a hard ceiling at 1 GB, and limits the service to the equivalent of one CPU core.
sudo systemctl edit my-service.service
Add only the necessary directives. Do not copy these values to a production service without having observed its normal consumption and its peaks.
[Service]
MemoryHigh=800M
MemoryMax=1G
CPUQuota=100%
Reload systemd, then restart the service only if the interruption is acceptable. Remotely, keep a second SSH session open when touching a critical component.
sudo systemctl daemon-reload
sudo systemctl restart my-service.service
systemctl status my-service.service --no-pager
systemctl show my-service.service -p MemoryCurrent -p MemoryHigh -p MemoryMax -p CPUQuotaPerSecUSec
If the service fails to start or becomes too slow, remove the override with caution. sudo systemctl revert my-service.service removes local overrides of the unit. Do not use it if the same directory contains other settings to keep.
Checks after changes
- Check the status with
systemctl is-active my-service.service. - Review
MemoryCurrent,MemoryHigh,MemoryMax, andCPUQuotaPerSecUSecafter the restart. - Monitor
journalctl -u my-service.service -band the kernel log during the problematic load peak. - Measure the effect on the application side: response time, delayed jobs, queues, user errors.
- Note the reason for the adjustment, the date, the value retained, and the corrected symptom in your operational procedure.
Cgroups protect the rest of the machine and make limits visible. They do not fix a memory leak, an overly costly query, or an improperly sized worker. If the ceiling is reached, keep the log, the observed load, and the configured value to choose between adjusting the limit and fixing the application.
To go further, the page systemd.resource-control(5) details each directive. The guide Nice under Linux helps choose a CPU priority when a strict ceiling is not suitable.