Diagnosing High Server Load
Server pegged at 100%? Find what’s eating CPU, RAM, or disk - and what to send support.
5 min read
Your VPS is unresponsive, sites are timing out, or SSH feels like it’s running through molasses. Before opening a ticket that says “server slow, please help,” work through these steps. You’ll either fix it yourself or arrive at support with the exact data we need to fix it fast.
One sanity check before you start: status.gozenhost.com - if the underlying host or network is in an incident, the metrics you collect below will be telling a story about our problem, not yours.
Step 1: Confirm the Symptom
SSH in (or use the console if SSH is too slow) and check load average:
uptime
You’ll see something like:
14:32:01 up 47 days, load average: 8.42, 7.91, 6.10
The three numbers are the average number of processes running, waiting for CPU, or stuck waiting on disk I/O over the last 1, 5, and 15 minutes.
| Load Average vs CPU Cores | What It Means |
|---|---|
| Below core count | Healthy - server has capacity |
| Around core count | Fully utilized but coping |
| 2x core count | Overloaded - requests are queuing |
| 4x+ core count | Severely overloaded - things will time out |
Check how many cores you have:
nproc
A load average of 8 on a 2-core VPS is a fire. The same load on a 16-core server is fine.
Step 2: Find the Culprit Process
Run top and press Shift+P to sort by CPU, Shift+M to sort by memory:
top
Or if you have htop installed (recommended - prettier and interactive):
htop
| Process You Often See | What It Usually Means |
|---|---|
mysqld / mariadbd at top | Slow query, missing index, or undersized database |
php-fpm / lsphp workers piling up | Slow PHP code, plugin loop, or traffic spike |
apache2 / nginx / httpd | Traffic spike or someone hammering an endpoint |
kswapd0 | Out of RAM, kernel is thrashing swap |
| Unknown process eating 100% | Possibly compromised - investigate before killing |
Don’t blindly kill -9 a runaway process if it’s a database. Killed mid-write, MySQL/MariaDB can corrupt tables. Try systemctl restart mariadb instead, which lets it shut down cleanly.
Step 3: Check Memory Pressure
free -h
total used free shared buff/cache available
Mem: 3.8Gi 3.6Gi 80Mi 12Mi 120Mi 100Mi
Swap: 2.0Gi 1.9Gi 80Mi
Red flags:
availablenear zero: you’re out of RAM, the kernel is about to start killing processes- Swap heavily used: disk is being used as RAM, everything slows to a crawl
buff/cachevery low under load: kernel had no free memory to cache files
Check whether the OOM (Out Of Memory) killer has already struck:
sudo dmesg -T | grep -i "killed process"
If you see entries, the kernel has been terminating processes to stay alive. The process name in the log tells you what’s been eating memory.
Step 4: Check Disk I/O
A server can be at 100% load with low CPU usage - that’s almost always disk I/O. Install and run iotop:
-oP shows only processes currently doing I/O. If you see sustained reads/writes from a single process, that’s your bottleneck.
Common I/O culprits: backup jobs running during peak hours, log files being written too aggressively, full-table MySQL scans, a process thrashing swap because RAM is exhausted.
Step 5: Check Disk Space and Inodes
A full disk masquerades as “everything is broken.” MySQL won’t start, sites 500, cron fails silently.
# Disk space
df -h
# Inodes (the kernel runs out of these before space if you have millions of small files)
df -i
If a partition is at 100% on either, find the culprit:
sudo du -sh /var/* 2>/dev/null | sort -rh | head -10
Usual suspects: /var/log (runaway logs), /var/lib/mysql (database growth), /home (user backups or mail), /tmp (orphaned session files).
Step 6: Check Network Activity
If load is high but no process looks busy, you might be under a flood of connections:
# Active connections grouped by remote IP
sudo ss -ntu | awk 'NR>1 {print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
# Total established connections
sudo ss -s
One IP holding hundreds of connections is suspicious - either a misbehaving client or a small-scale attack. Block it temporarily:
sudo iptables -I INPUT 1 -s 198.51.100.42 -j DROP
-I INPUT 1 puts the rule at the top of the chain. Appending it with -A can leave it below an existing ACCEPT rule, where it never matches. If you use ufw or CSF, block through them instead (sudo ufw insert 1 deny from 198.51.100.42 or csf -d 198.51.100.42).
Replace the IP with the offender. This is a quick stop-the-bleeding move - for anything sustained, see Firewall Setup.
Step 7: Check Recent Logs
The system journal often shows what tripped first:
sudo journalctl --since "30 minutes ago" -p err
For web server errors:
sudo tail -100 /var/log/nginx/error.log
sudo tail -100 /var/log/apache2/error.log
What to Send to Support
If you can’t resolve it yourself, paste this output into your ticket - it saves a full round-trip of “can you run X?”:
uptime
nproc
free -h
df -h
df -i
top -bn1 | head -25
sudo dmesg -T | tail -30
Plus:
- When it started (e.g. “load spiked around 14:00 UTC”)
- What changed recently - new plugin, traffic source, cron job, deployment
- Whether it’s constant or intermittent
See How to Get Support for the full ticket-writing guide.
Quick Triage Table
| Symptom | Likely Cause | Where to Look |
|---|---|---|
| High CPU, one process | Bad code, runaway script, malware | top - the top process |
High CPU, many php-fpm workers | Traffic spike or slow PHP | Web server access log |
| Load high, CPU low | Disk I/O bottleneck | iotop |
| OOM kills in dmesg | Not enough RAM | Upgrade plan or tune services |
| Database crashing | Disk full or corruption | df -h, MySQL error log |
| Everything timing out, network slow | DDoS or flood | ss -s, connection counts |
What to Do Next
- Monitoring Your Server - set up proactive monitoring so you catch this before users do
- Slow Website Performance - if the issue is application-level, not server-level
- Firewall Setup - block abusive IPs and rate-limit connections
- How to Get Support - what to include when you escalate
Last updated 21 Oct 2026, 00:00 +0300.