How to Troubleshoot a Slow Server

By Anurag Singh

Updated on Sep 22, 2025

How to Troubleshoot a Slow Server

In this tutorial, we'll learn how to troubleshoot a slow server.

When a server slows down, panic often sets in. Applications crawl, users complain, and the pressure builds. But performance issues rarely come from a single cause. They’re the product of many layers working together—CPU, memory, disk, and network. If we want to troubleshoot effectively, we need a structured workflow that removes guesswork and helps us pinpoint the bottleneck quickly.

Below is a practical step-by-step approach we can rely on every time performance problems appear.

Step 1: Confirm the Symptoms

We start by verifying that slowness isn’t just anecdotal.

Check system logs:

journalctl -xe --no-pager | tail -n 50
dmesg | tail -n 50

Look for kernel errors, OOM (Out of Memory) kills, or hardware warnings.

Check application logs (example for Nginx + systemd app):

tail -f /var/log/nginx/error.log
journalctl -u myapp.service -f

Step 2: Check CPU Utilization

Real-time usage per process:

top -o %CPU

If one process dominates, that’s your culprit.

Better view with colors:

htop

Watch per-core usage and load averages.

Detailed stats:

mpstat -P ALL 2 5

Shows per-core utilization every 2 seconds, 5 times.

Step 3: Investigate Memory Usage

Quick overview:

free -m

Focus on available memory, not just free.

Detailed stats:

vmstat 2 5

Look at si/so (swap in/out). Non-zero values mean swapping.

Find top memory hogs:

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

Step 4: Analyze Disk I/O

Check utilization and wait time:

iostat -x 2 5
  • %util close to 100 = disk saturated.
  • await > 20–30 ms on SSDs = trouble.

See processes hitting disk hardest:

iotop -ao

-a shows accumulated usage, so culprits don’t hide.

Queue depth:

cat /sys/block/sd*/queue_depth

Step 5: Evaluate Network Performance

Check active connections:

ss -s

Shows how many sockets are in use.

Real-time traffic by process:

iftop -i eth0

Replace eth0 with your NIC.

Latency and packet loss:

ping -c 10 hostmycode.com
traceroute hostmycode.com

Interface stats:

ip -s link

Look for drops, errors, overruns.

Step 6: Map Dependencies

If your server is waiting on a database or external API, local checks won’t show the whole picture.

Check database latency (PostgreSQL example):

psql -U dbuser -d mydb -c "SELECT now();"

If this is slow, your app is innocent; the DB is guilty.

HTTP service latency:

curl -w "@-" -o /dev/null -s http://backend.local <<EOF
time_namelookup:  %{time_namelookup}\n
time_connect:  %{time_connect}\n
time_starttransfer:  %{time_starttransfer}\n
time_total:  %{time_total}\n
EOF

Step 7: Correlate Metrics

Use monitoring tools to avoid tunnel vision. For quick correlations without dashboards:

Collect everything at once:

dstat -cdngytl --top-cpu --top-mem 2

This shows CPU, disk, network, memory, and top processes side by side every 2 seconds.

Step 8: Build a Repeatable Flow

Here’s the “decision tree” workflow with commands built in:

  • Logs first: journalctl, app logs.
  • CPU check: top, htop, mpstat.
  • Memory check: free -m, vmstat, ps aux.
  • Disk check: iostat -x, iotop -ao.
  • Network check: ss -s, iftop, ping.
  • Dependencies: curl -w, DB query timing.
  • Correlation: dstat or your monitoring stack.

Final Thoughts

Troubleshooting isn’t about random guessing—it’s about narrowing the funnel. By walking through CPU, memory, disk, network, and dependencies in order, we avoid blind spots and zero in on the root cause faster.

Servers slow down for many reasons, but reacting blindly wastes time. A disciplined workflow is our best defense against chaos. By systematically analyzing CPU, memory, disk, network, and dependencies, we eliminate noise and uncover the true cause. Over time, this habit transforms troubleshooting from firefighting into science.

Checkout our dedicated servers India, Instant KVM VPS, and cPanel Hosting India