MONITORING
July 23, 2026

The Essential Server Metrics You Should Be Watching

6 min read
Author
CloudStick Team
WordPress Engineer
Share this article
The Essential Server Metrics You Should Be Watching
CloudStick
Server Metrics

Load average

If you can only glance at one number to answer "is something wrong right now," make it load average. Run uptime and you get three numbers — the average number of processes wanting CPU time over the last 1, 5, and 15 minutes. The 1-minute figure tells you what's happening this instant; the 5- and 15-minute figures tell you whether that spike is new or has been building. A rising trend across all three, rather than a single 1-minute blip, is the pattern worth acting on.

The number on its own is meaningless without context. Load average isn't a percentage — it's a count of work queued against your CPU cores. A load of 4.0 is idle on a 16-core box and badly overloaded on a single-core VPS. Always check nproc first and divide the load figure by that number; a result consistently above 1.0 per core means processes are queuing for CPU time rather than running immediately.

$ nproc
4
$ uptime
14:22:01 up 12 days, 3:41, 2 users, load average: 3.98, 3.10, 2.05

CPU usage

A single "CPU usage" percentage hides more than it reveals. A total CPU figure of 40% across an 8-core machine could mean every core is running at a comfortable 40%, or it could mean two cores are pinned at 100% while the rest sit idle — the second case is a real bottleneck for anything single-threaded, like a PHP-FPM worker or a MySQL query stuck on one core. Press 1 inside top to break the aggregate down per core and see which ones are actually maxed out.

It's also worth separating real CPU work from waiting. The %wa (iowait) field in top's header row shows time the CPU spent idle because it was waiting on a disk operation to finish. That time is counted as "busy" in some monitoring tools even though the processor isn't computing anything — a server can show high CPU usage while the real problem is a slow or overloaded disk, not an undersized CPU.

Memory and swap

Run free -h and ignore the "free" column — look at "available" instead. Linux deliberately uses spare RAM for disk cache to speed up file access, which makes "free" look alarmingly low even on a healthy server. "Available" already accounts for cache that the kernel will happily release the moment an application actually needs the memory, so it's the number that tells you what headroom you really have.

$ free -h
total used free shared buff/cache available
Mem: 7.8Gi 2.1Gi 1.2Gi 180Mi 4.5Gi 5.4Gi
Swap: 2.0Gi 640Mi 1.4Gi

The Swap line above isn't decoration — sustained swap usage, whether you check it there or with swapon --show, is a signal, not background noise. Swap exists as an emergency valve; a server that's routinely pushing megabytes into it is telling you it needs more RAM, or that a process is leaking memory over time and needs to be restarted (or fixed). Watching the swap figure stay flat at zero, day after day, is what a healthy server looks like.

Disk usage and I/O

Disk has two separate ceilings, and hitting either one takes a server down: raw space (df -h) and inode count (df -i). A partition can show 40% space used and still refuse to create a single new file if it has run out of inodes — usually caused by an application (a logger, a session store, a cache) writing enormous numbers of tiny files. Check both independently; they never move in lockstep.

$ df -h /
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 40G 16G 22G 43% /
$ df -i /
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 2621440 2600110 21330 99% /

On a database-heavy server, space is only half the story — throughput matters just as much. iostat -x 2 (from the sysstat package) shows %util and await per device; a disk pinned near 100% utilization with rising await times will make MySQL feel slow long before df -h shows any warning sign.

Network throughput and connections

Two figures matter here: raw throughput and connection count. Bytes in and out per second — visible live with ifstat or read directly from /proc/net/dev — tell you whether you're approaching your provider's bandwidth cap or a NIC bottleneck. Connection count tells you a different story: how many clients are actually talking to the server right now.

ss -s is the modern replacement for netstat -s and gives an instant summary of total open TCP connections. A sudden spike here — say, from a baseline of a few hundred to tens of thousands — is worth investigating immediately. It could be a legitimate traffic surge from a marketing campaign going viral, or it could be a DoS-style abuse pattern hammering a single endpoint; either way, the connection count is usually the first metric to move before CPU or memory even notice.

WARNING

Don't rely on a single manual check of connection count during an incident. By the time you notice a problem and run ss -s, a fast-moving spike may have already passed — or already taken the server down. Connection count needs to be graphed continuously, the same way CPU and memory are, so you can see the shape of the spike after the fact and tell a traffic surge from an attack.

Application-level metrics

Response time, error rate, and queue depth predict user-facing pain in a way that none of the system-level numbers above do on their own. Response time is the direct measure of what a visitor experiences. Error rate — specifically the count of 5xx responses in your nginx access or error logs — tells you how often that experience is actually broken rather than just slow. Queue depth, for anything running background jobs (mail sending, image processing, report generation), tells you whether work is piling up faster than it's being processed, which is often the earliest warning sign of all, showing up minutes before CPU or memory graphs move at all.

A server can look perfectly healthy on every system metric — load average under 1, plenty of available memory, disks nowhere near full — while a specific endpoint quietly times out for every third visitor because of an inefficient database query or a stuck external API call. That failure mode simply doesn't show up in CPU, memory, disk, or network graphs; it only shows up if you're measuring the application itself.

This is where CloudStick already does half the work for you without any setup. Every server connected to CloudStick has Zabbix Agent 2 (v7.0) installed automatically, reporting CPU, memory, and disk metrics straight back to the dashboard — powering the real-time Server Stats graphs on every plan, including Free. That covers all four of the system-level metrics discussed above with zero configuration, which means the effort you'd otherwise spend wiring up a monitoring agent is free to go toward the metrics that actually need custom instrumentation: tracking response times and 5xx counts in your application or reverse proxy logs, and queue depth if you're running background jobs. Start there — add response-time and error-rate logging to your highest-traffic endpoint this week, and you'll have the one category of metric CloudStick can't see for you covered too.

Leave a comment
Full Name
Email Address
Message
Contents