Your server feels sluggish: pages load slowly, SSH lags, or commands take forever. Before guessing, work through the resources in order. Each one has a quick check, and a few common causes. Most slowdowns can be traced in a few minutes.

0. Is it the server, or the network?

ping -c 20 your-server-ip
mtr -rwc 50 your-server-ip

High latency or packet loss on the way to the server makes everything feel slow, even if the server is idle. Run mtr from your location, and from the server back to you. See ping, traceroute and mtr.

Website slow, but SSH fast? Measure the site’s TTFB:

curl -o /dev/null -s -w 'connect %{time_connect}  ttfb %{time_starttransfer}  total %{time_total}\n' https://example.com/

1. Load and CPU

uptime
top        # press 1 to see each core; check %us, %sy, %wa, %st
  • Load average > vCPU count with high %us/%sy: CPU-bound. Find the process (step 5).
  • High %wa (I/O wait): a disk problem, not CPU (step 3).
  • High %st (steal): the hypervisor is giving your VM less CPU time than it wants. If it’s sustained, contact support with the numbers.

See uptime and load average and htop.

2. Memory and swap

free -h
vmstat 1 5          # si/so columns = swapping in/out
journalctl -k | grep -iE 'oom|killed process'
  • “available” memory near zero, plus swap activity: the server is short on RAM. Swapping makes everything slow.
  • OOM kills: a process was killed to free memory (often MySQL, Java or PHP). See Linux OOM killer and high memory usage.

Note: Linux uses free RAM for cache. A low “free” value with a healthy “available” value is normal.

3. Disk I/O and space

df -h
df -i
iostat -x 1 5        # %util, await (sysstat package)
sudo iotop -o        # which process is doing I/O
  • A full disk breaks databases, logs and sessions. See disk full troubleshooting.
  • High %util and await: heavy I/O (backups, database scans, logging, swap). Find the process with iotop.

4. Network usage on the server

sudo iftop -i eth0       # who's using bandwidth
ss -s                    # connection counts
ss -tan state established | wc -l
  • A saturated port (backups, downloads, or an attack) slows everything. See iftop and nethogs.
  • Thousands of connections from a few IPs: possible abuse or an attack. See VPS DDoS protection.

5. Find the guilty process

ps aux --sort=-%cpu | head -10
ps aux --sort=-%mem | head -10

Common offenders:

Process Typical cause
mysqld / mariadbd Slow queries, missing indexes, tiny buffer pool. See MySQL slow query log
php-fpm Uncached traffic, heavy plugins, bots. See PHP-FPM tuning
java Game server or app heap too large or too small
node / python App loop, memory leak
Unknown process with a random name Possible compromise (crypto miner). See server security monitoring
backup, tar, rsync, restic Backups running at peak times: reschedule

6. Check the logs

journalctl -p err -b              # errors since boot
sudo tail -n 50 /var/log/nginx/error.log
sudo tail -n 50 /var/log/syslog

Look for timeouts, crashes, restarts, and repeated errors. See journalctl.

7. Bots and traffic spikes

sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
sudo awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

Aggressive crawlers, scrapers, brute-force login attempts, or one hot URL can consume all PHP workers. Rate-limit or block them. See Nginx rate limiting and Fail2ban.

Fix, then decide

  • Configuration and caching fixes first (they’re cheaper than upgrades).
  • If a resource is still maxed during normal load, it’s time for more of it. See when to upgrade your VPS.
  • Set up monitoring, so next time you see the trend before users notice. See Netdata.

Quick reference

Check Command
Network path mtr -rwc 50 <ip>
CPU, steal, I/O wait top, vmstat 1
Memory, swap, OOM free -h, vmstat, journalctl -k | grep -i oom
Disk df -h, iostat -x, iotop
Top processes ps aux --sort=-%cpu
Traffic iftop, access log analysis

Related: Linux benchmark tools and CPU and RAM monitoring.

  • Performance
  • Linux
  • Troubleshooting