TroubleshootingWritten by GLWS14 min readUbuntu 24.04 LTS / AlmaLinux 9
Commands run on your server unless a section says otherwise. Replace example usernames, addresses and paths with your own values. Keep a working session open when changing remote access.

Work out which resource is the bottleneck

A slow server is almost always short of one of four things: CPU time, memory, disk speed or network. Each leaves a different fingerprint, and the fix for one makes no difference to another. Adding memory does not help a disk problem, and a bigger plan does not help a runaway process.

Look first, then change anything. Run the commands below while the slowness is happening, because a quiet server will look healthy. Note the time and keep the output.

Both systems: a first overview
uptime
nproc
free -h
df -h /
vmstat 1 5
Measure a slow VPS before making changes: CPU and steal time with top or vmstat, available memory and swap with free, disk latency with iostat, and network reachability with ping or mtr.
Measure a slow VPS before making changes: CPU and steal time with top or vmstat, available memory and swap with free, disk latency with iostat, and network reachability with ping or mtr.

Read the load average and CPU figures

The load average at the top of uptime counts processes that are running or waiting. Compare it with the number of cores: a load of 2 on a 2-core server means full, and a sustained load well above the core count means queues. High load can come from CPU work, but also from processes stuck waiting for disk, so load alone does not name the cause.

Run top and read the CPU line. us is time spent in user programs, sy in the kernel, wa waiting for disk, and st is steal. Press 1 to see each core separately.

Both systems
top -b -n 1 | head -n 15
ps -eo pid,user,%cpu,%mem,comm --sort=-%cpu | head -n 8

CPU steal: the host is busy, not your server

Steal time (st) is time your virtual CPU wanted to run but the physical host was busy with other virtual machines. On shared vCPU plans a little steal is normal. Sustained steal of several percent while your own processes are modest means the host is contended. That is not something you can fix with tuning, and a bigger plan on the same host will not remove it.

Measure it over a few minutes rather than one reading, and write down the times. Steal that comes and goes at the same hours each day is useful evidence for support.

Both systems: sample steal every 5 seconds for a minute
vmstat 5 12
# the last column, st, is steal
Log steal over time
while true; do echo "$(date +%T) $(top -b -n 1 | grep -m1 Cpu)"; sleep 30; done

Memory pressure and swapping

When memory runs out the kernel first drops caches, then swaps, and finally kills a process. Swapping is the usual cause of a server that suddenly feels sluggish, because swap is far slower than memory. In vmstat, nonzero si and so columns, which count swap-in and swap-out, mean memory trouble. In free, check the available figure, not the free one, because Linux keeps spare memory as cache.

If the kernel killed something, it logs it. Look for out-of-memory messages, and for the biggest memory users.

Both systems
free -h
swapon --show
sudo journalctl -k --since "1 day ago" | grep -i "out of memory"
ps -eo pid,user,%mem,rss,comm --sort=-rss | head -n 8

Disk bottlenecks

A busy or slow disk shows as high wa in top, a high load with little CPU use, and processes in the D state. iostat shows how busy the device is: a utilisation near 100% with long wait times means the disk is saturated. Install the sysstat package for iostat and pidstat. Check also that the disk is not simply full, which causes its own failures.

Ubuntu only
sudo apt install sysstat
AlmaLinux only
sudo dnf install sysstat
Both systems
iostat -x 2 5
ps -eo state,pid,comm | awk '$1=="D"'
df -h /; df -i /
A rough write-speed test that cleans up after itself
dd if=/dev/zero of=./ddtest bs=1M count=512 oflag=direct status=progress; rm -f ./ddtest
Do not run disk tests on a server that is already struggling, and run them at a quiet time. A single dd figure is only a rough indication.

Find the process responsible

Once you know the resource, find who is using it. pidstat shows per-process CPU and disk activity over time. Look for a runaway job, a cron task or backup running at the same time as the slowdown, or a service that is restarting repeatedly.

Both systems
pidstat 2 5
sudo journalctl --since "30 minutes ago" -p warning --no-pager | tail -n 30
systemctl list-timers --all | head -n 15

Decide what to do

If a process is the culprit, fix or limit it. If memory is the limit, reduce what runs, add swap as a safety net (see the swap guide), or move to a plan with more memory. If the disk is the limit, reduce writes such as verbose logs and frequent backups. If steal is high while your processes are quiet, collect the vmstat output with timestamps and contact support, because only the host operator can address it.

Compare against a baseline: run the same commands when the server is healthy and keep that output.

Save a snapshot of evidence for support
{ date; uptime; vmstat 5 6; free -h; iostat -x 2 3; } > ~/slow-evidence-$(date +%F-%H%M).txt 2>&1

Official documentation

These upstream references provide more detail on the commands and workflows in this guide.