When a server slows down, the first instinct is usually "let us upgrade the plan". But adding resources without knowing which layer is the bottleneck usually means spending money without fixing anything.
The sequence below rules out four layers in a few minutes.
1. Look at the overall state
bashuptimeThe three numbers at the end are the load average (last 1, 5 and 15 minutes). Compare them with your core count:
bashnprocOn a 4-core server, a load average below 4 means the processor is not the bottleneck. Consistently seeing 8-10 means either CPU saturation or disk wait.
The direction matters too: if the 1-minute figure exceeds the 15-minute one, load is rising; if lower, you are coming down from a peak.
2. CPU, or disk wait?
bashtop -bn1 | head -5In the %Cpu(s) line, read:
- us (user) high → your applications are consuming CPU
- sy (system) high → a kernel-level issue, usually excessive syscalls
- wa (iowait) high → the CPU is idle waiting; the disk cannot keep up
- st (steal) high → neighbouring load in the virtualisation layer; on a plan with guaranteed resources this should be near zero
If wa is above 10%, look at the disk, not the processor.
3. Is memory really full?
bashfree -hThe used column misleads — Linux uses free memory as file cache and releases it instantly when needed. The column to read is available.
The real warning sign is swap:
bashvmstat 1 5If the si and so columns stay above zero, the server is reading and writing swap. This is one of the harshest causes of slowness, and there is no lasting fix other than more memory.
4. What is keeping the disk busy?
bashapt install -y sysstat # if needed
iostat -x 1 3If %util approaches 90%, the disk is saturated. The await column is average request wait time; on an NVMe disk it should stay below a millisecond.
There is also a simple check that gets skipped:
bashdf -h
df -iA full disk is the most common cause of a service failing silently. The second command shows inode usage — on servers with many small files, inodes can run out while the disk looks free.
5. Which process is responsible?
bash# top 10 by memory
ps aux --sort=-%mem | head -11
# top 10 by CPU
ps aux --sort=-%cpu | head -11If web server or PHP processes lead the list, the problem is in the application layer. If the database leads, go looking for slow queries:
bashmysqladmin -u root -p processlistA long-running query means you have found your bottleneck.
6. The network
bashss -s
ss -ant | awk '{print $1}' | sort | uniq -cPlenty of connections in TIME-WAIT is normal. But an unusually high SYN-RECV count may mean a SYN flood — see our DDoS protection guide.
7. Read the logs
bashjournalctl -p err -n 50 --no-pager
dmesg -T | tail -30If dmesg shows OOM killer entries, the kernel is killing processes because memory ran out. That is the most common explanation for "the server stops intermittently".
After the diagnosis
Once you find the bottleneck, the fix is usually not more resources:
- CPU → caching, fixing slow queries, removing unnecessary plugins
- Memory → finding the leaking process, tuning PHP-FPM worker counts
- Disk → database indexes, log rotation, moving to NVMe
- Network → caching, CDN, rate limiting
Do not scale before you measure. Once you have measurements, we can size it together.
