Before restarting anything, spend five minutes finding out which resource is short. The commands below each take a few seconds, and each one narrows down what the next should look at. The order follows Brendan Gregg’s 60-second checklist from Netflix, shortened to what a single server needs. The example output comes from different machines, each showing the problem that command is best at finding.
Four of them come from sysstat, which isn’t installed by default. Install it before you need it: sudo apt install sysstat on Debian and Ubuntu, sudo dnf install sysstat on RHEL.
1. Load average with uptime
$ uptime 14:02:11 up 41 days, 3:17, 2 users, load average: 11.84, 9.02, 4.10$ nproc4
The three numbers are the load averaged over 1, 5 and 15 minutes. Compare them with the CPU count: 11.84 on four CPUs means about three times more work is waiting than the machine can run, and the 1-minute value above the 15-minute one means it’s getting worse. On Linux the load also counts processes waiting for the disk, so a high load can also mean a busy disk. The next commands tell the two apart.
2. Kernel messages with dmesg
$ sudo dmesg -T | tail -20[Sat Oct 24 13:58:40 2026] Out of memory: Killed process 30112 (java) total-vm:6123456kB, anon-rss:4890112kB[Sat Oct 24 13:59:02 2026] I/O error, dev sdb, sector 81920 op 0x1:(WRITE) flags 0x0 phys_seg 1 prio class 2
Look for the OOM killer, disk and filesystem errors, and network links going up and down. Any of these explains a slow server on its own, and none of the later commands would show it as clearly.
3. CPU, memory, and waits with vmstat
$ vmstat 1 5procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 2 9 1572864 81240 10212 412880 612 904 9812 1204 2210 4120 6 4 22 68 0 1 11 1574912 79112 10212 409744 588 1012 10240 988 2301 4388 5 5 19 71 0
The first line is the average since boot. Read the ones after it. In this example the CPUs are mostly idle (us + sy is about 10%), but 9 to 11 processes are blocked (b), the CPUs spend 70% of their time waiting for disk (wa), and pages move to and from swap every second (si, so). That’s a machine out of memory, swapping, and slowed down by its own disk.
| Column | What it tells you |
|---|---|
r | Processes ready to run. Above the CPU count for long means CPU saturation. |
b | Processes blocked, usually waiting for the disk. |
si, so | Memory swapped in and out per second. Anything above 0 for long means too little memory. |
us, sy | CPU time in programs and in the kernel. |
wa | CPU time spent idle while waiting for disk. |
st | Steal: time the hypervisor gave to other virtual machines. Above a few percent, the host is overbooked. |
4. Each CPU with mpstat
$ mpstat -P ALL 1 1# %guest and %gnice left out, and only the first two CPUs shownAverage: CPU %usr %nice %sys %iowait %irq %soft %steal %idleAverage: all 26.50 0.00 1.75 0.25 0.00 0.50 0.00 71.00Average: 0 99.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00Average: 1 3.00 0.00 2.00 1.00 0.00 1.00 0.00 93.00
One CPU at 100% while the others are idle means a single-threaded process is the limit. Adding cores won’t help; the process has to do less or work in parallel. If every CPU is busy, find the process next.
5. Busy processes with pidstat
$ pidstat 1 3Average: UID PID %usr %system %guest %wait %CPU CPU CommandAverage: 1001 30544 94.33 2.00 0.00 0.67 96.33 - javaAverage: 999 2210 3.00 2.00 0.00 1.00 5.00 - postgres
Like top, but it prints a line per interval instead of redrawing the screen, so you can copy it into a ticket. pidstat -d 1 shows disk reads and writes per process instead of CPU.
6. Disk latency with iostat
$ iostat -xz 1 3# columns trimmed to the ones that matter hereDevice r/s rkB/s r_await w/s wkB/s w_await aqu-sz %utilsda 812.00 10240.00 38.12 64.00 988.00 51.40 33.10 99.60
r_await and w_await are how long a read or write takes in milliseconds, queueing included. On an SSD they’re usually below 1. aqu-sz is how many requests are waiting. %util near 100 says the device is busy all the time, though an SSD or a RAID set can serve more than one request at once and still have room at 100%. Long waits are the reliable sign.
7. Available memory with free
$ free -h total used free shared buff/cache availableMem: 7.8Gi 7.3Gi 79Mi 12Mi 404Mi 230MiSwap: 2.0Gi 1.5Gi 512Mi
Read available, not free. Linux uses spare memory as a disk cache and gives it back when programs need it, so a low free on its own is normal. 230 MB available out of 7.8 GB, with 1.5 GB in swap, isn’t. To see which processes hold the memory:
$ ps aux --sort=-rss | head -58. Network traffic with sar and ss
$ sar -n DEV 1 3Average: IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutilAverage: eth0 412.00 388.00 61.20 502.90 0.00 0.00 0.00 0.41$ ss -s
Compare the throughput with the link speed: 503 kB/s is about 4 Mbit/s, 0.4% of a 1 Gbit/s link. ss -s counts connections by state. Thousands in timewait or a growing number of established connections point at a client or a backend that doesn’t let go.
What the numbers point to
| You see | It points to | Look next at |
|---|---|---|
| Load above the CPU count, us + sy high | CPU | pidstat and top for the process, then the process itself |
| One CPU at 100%, the others idle | A single-threaded process | What that process is doing |
| b above 0, wa high, long r_await or w_await | The disk | pidstat -d 1 for the process doing the I/O |
| si and so above 0, available low | Memory | ps aux --sort=-rss, then the OOM lines in dmesg |
| st above a few percent | The host under the VM | Your provider |
| Nothing stands out | Something outside the machine | The database, an API the app calls, DNS |
Last checked on 24 October 2026 against Debian 12, Ubuntu 24.04, RHEL 9, procps-ng 4, and sysstat 12. If a step doesn’t match what you see, contact us with the command and what it printed.