Monitoring CPU, memory, disk and network usage on Linux means answering two different questions: how busy is the server, and is that activity delaying useful work? A processor running near capacity during a scheduled job may be doing exactly what you paid for. A server with modest CPU usage can still crawl because requests are waiting for storage, memory or a remote service.
Start with a small set of tools: top for processes, free and vmstat for memory, df and iostat for storage, and sar and ss for network activity. Read their measurements together rather than treating one percentage as a verdict.
This guide focuses on interpreting those measurements and tracing a slowdown to the responsible workload. If you are still preparing the machine, the guide to setting up your first Linux server covers the groundwork.
Build a Useful Monitoring Toolkit
Check which utilities are available before an incident. Package names vary between distributions: process tools commonly come from packages named procps or procps-ng, while iostat, mpstat, pidstat and sar belong to sysstat. Use your distribution’s repositories rather than downloading an unfamiliar monitoring script during an outage.
If you need help finding the right packages, use the guide to APT, DNF and Pacman package management. The aim is a dependable toolkit, not a terminal full of competing dashboards.
| Question | Starting tool | What to examine |
|---|---|---|
| Which process is busy? | top |
CPU usage, resident memory and process state |
| Is memory becoming scarce? | free, vmstat |
Available memory and current swap activity |
| Is a filesystem filling up? | df, du |
Available space, inode usage and directory growth |
| Are storage requests slowing down? | iostat |
Request latency, queue length and throughput |
| Is network traffic changing? | sar |
Traffic rates, packet rates and errors |
| Which connections need attention? | ss |
Socket states, queues and TCP details |
| Which service owns the workload? | systemd-cgtop |
Resource usage grouped by control group |
Choose the Right Sampling Window
For a live slowdown, start with measurements a few seconds apart and watch several samples. Record the time, affected service and visible symptom. A single observation can catch a harmless burst or miss a recurring stall completely.
Separate current rates from cumulative counters. A byte total tells you how much traffic an interface has handled, not how busy it is now. Likewise, an average covering days of uptime can conceal the ten seconds that matter. Keep units consistent when comparing tools, especially bytes against bits and decimal units against binary units.
Monitor CPU Usage Without Misreading Load Average
Begin with top. Inspect the CPU summary, then sort the process list by CPU usage. Press 1 to switch between the combined CPU view and individual logical CPUs; use Shift+P to sort by CPU and H to toggle thread display. The procps top manual documents these controls and its percentage conventions.
The individual CPU view matters. In a hypothetical eight CPU server, one fully occupied CPU and seven mostly idle CPUs produce a modest combined percentage. A task restricted to one busy thread may already be running as fast as that design permits. Adding more idle CPUs would not automatically help.
Also check how the display scales process percentages. In top’s usual Irix mode, a multithreaded process can exceed 100% because it uses more than one logical CPU. A displayed 250% represents roughly two and a half CPUs over the measurement interval, not a broken percentage counter.
Separate CPU Activity from Work Waiting to Run
Load average is not CPU usage. Linux load averages include runnable tasks and tasks in uninterruptible sleep, commonly associated with I/O waits. The one, five and fifteen minute figures are not divided by the number of CPUs. These definitions are recorded in the procps uptime manual.
Compare load with the CPU count, but do not turn that comparison into a rigid rule. A load of eight on eight logical CPUs means something different from eight on two CPUs. It still does not tell you whether those tasks are calculating, queued for CPU time or blocked elsewhere.
Use the CPU categories to choose the next check. High user time points you toward application work. High system time calls for a closer look at kernel activity and the workload generating it. In a virtual machine, rising steal time warrants investigation of the host or hosting allocation rather than an immediate application rewrite.
Treat I/O wait as a clue, not a storage health score. Its accounting has caveats, particularly across multiple CPUs, and it does not identify a device or process. Confirm suspected storage trouble with request latency and queue measurements.
Once you identify a busy process, record its PID, owner and workload before acting. A database, compression task and runaway worker need different responses. If the process belongs to a managed service, the guide to managing Linux services with systemd explains how to inspect that service without guessing from its executable name.
Monitor Memory Pressure, Not Just Free RAM
Use free for the machine’s memory summary, and pay particular attention to available memory. Linux uses RAM for caches, so a small free figure does not, by itself, mean the server is running out.
MemAvailable estimates how much memory can be used by new applications without swapping. It accounts for free memory and reclaimable memory while allowing for memory the system still needs. The kernel documentation for memory and CPU counters defines this estimate and describes the caveats in I/O wait accounting.
Consider a hypothetical server with 16 GiB of RAM, 300 MiB free and 6 GiB available. The free figure looks alarming in isolation; the available estimate gives a much less urgent starting point. Neither number replaces checking whether application response times are deteriorating.
Distinguish Swap Occupancy from Current Swapping
Swap space containing data is not proof of an active memory problem. Check whether pages are moving between RAM and swap during the slowdown.
Use vmstat with a short sampling delay and several updates. Its si and so columns show swap activity, while r reports runnable processes and b reports processes blocked waiting for I/O. The first report’s rate fields cover time since boot; later reports cover the sampling interval. Process and memory figures remain instantaneous. These distinctions are set out in the procps vmstat manual.
Look for a pattern rather than a lone nonzero value. Falling available memory, sustained swap traffic and worsening response times justify closer investigation. Stable swap occupancy with comfortable available memory is a different situation.
Find the Workload Consuming Memory
Sort processes by memory in top using Shift+M. Resident memory describes memory currently occupying RAM; virtual memory describes a broader address space and should not be read as physical consumption. Shared pages also mean that adding every process’s resident figure can overcount memory.
Track suspected growth over time. Record the process’s memory alongside request volume, worker count and recent deployments. An application using more RAM while serving more concurrent requests is not the same evidence as memory rising steadily under a stable workload.
Do not clear caches or restart services just to make a memory graph look tidier. Preserve measurements first. If a process disappears unexpectedly, inspect the event timeline through Linux service and kernel logs with journalctl before deciding that an out of memory event occurred.
Separate Disk Capacity from Disk Performance
“Disk usage” can mean occupied storage space or active storage work. These are separate checks. A nearly full filesystem may respond quickly, while a filesystem with plenty of room may sit on storage that cannot keep up with requests.
Check Space and Inodes
Use df to inspect mounted filesystem capacity. Its human readable display helps with an initial inspection, while inode reporting checks the filesystem’s file metadata allocation. The GNU df documentation describes both views.
Inspect the filesystem that holds the affected data, not just the root filesystem. Application files, database storage and logs may occupy different mounts. A capacity report for the wrong mount can be perfectly accurate and completely unhelpful.
If the layout is unfamiliar, refer to the guide to Linux filesystems and directory structure before removing anything. Directories such as /var can contain active application data as well as disposable files.
Use du to narrow directory growth. Start at the affected mount or application directory and inspect progressively smaller areas. Allocated disk usage and apparent file size are not always equal, particularly for sparse files; the GNU du documentation distinguishes those measurements.
Plan capacity alerts around remaining space and growth rate. In a hypothetical example, 40 GB remaining on a filesystem growing by 10 GB per day gives roughly four days before exhaustion if that rate continues. That estimate is more actionable than a percentage alone, though changing workloads can invalidate it quickly.
Read Storage Latency and Queues Together
For performance, use iostat with extended statistics and repeated samples. Its -x option selects the extended view; -y omits the initial report covering time since boot when repeated reporting is requested.
Read request rate, throughput, latency and queue length together. The r_await and w_await fields report average read and write completion time in milliseconds, including queuing. aqu-sz reports average queue length. The upstream iostat manual defines these fields and warns that %util does not express the performance ceiling of devices serving requests in parallel, including modern SSDs and RAID arrays.
There is no useful universal latency threshold for every storage workload. Compare with the same device under a similar workload. Rising queues and latency without a corresponding increase in completed work provide a stronger reason to investigate than a busy percentage alone.
Keep competing jobs in view. If a slowdown overlaps backup activity, compare their timing and storage demand before changing schedules. The guide to offsite backups and recovery testing covers the backup design; monitoring should establish whether that job is actually competing with production work.
Monitor Network Rates, Errors and Connections
Network monitoring needs more than a cumulative byte count. Use sar to sample interface traffic: its DEV report includes packet and data rates, while EDEV reports interface errors. Its data rate fields use kibibytes per second. The upstream sar manual documents these reports and its saved activity records.
For a manual rate calculation, subtract an earlier byte counter from a later one and divide by elapsed seconds. As a hypothetical example, an increase of 80 million bytes over ten seconds equals 8 million bytes per second, or approximately 64 megabits per second. Do not compare a bytes per second graph directly with a link advertised in bits per second.
Measure the interface carrying the affected traffic. Keep receive and transmit rates separate, and compare them with the allocation available to the server. With virtual machines, do not assume that a displayed virtual interface speed represents a guaranteed hosting allowance.
Watch error and drop counters for changes during the incident. A historical total tells you little about whether packets are being lost now. Record the direction and interface involved before investigating the network path.
Use Socket Information to Narrow the Problem
Use ss to inspect connections and listening sockets. Select numeric output when you want addresses and ports without name resolution, then narrow the view to the affected protocol or connection state. Process information and internal TCP details can help connect an unexpected socket to a workload. Available options are documented in the iproute2 ss manual.
A high connection count is not automatically a fault. Compare it with normal traffic and application design. If socket queues grow while requests slow down, investigate whether the application is keeping up and whether the remote endpoint is responding as expected.
Do not jump straight from “the network is slow” to changing firewall rules. Check listening addresses, connection states and the application’s own timing first. If the evidence points to filtering, continue with the guide to UFW, firewalld and nftables.
Measure Resource Pressure and Service Usage
Utilization tells you how busy a resource is. Pressure Stall Information, or PSI, measures time tasks spend stalled because resources are contended. Where available, the files under /proc/pressure/ expose CPU, memory and I/O pressure.
The some figures describe periods when at least some tasks are stalled. For memory and I/O, full describes periods when all nonidle tasks are stalled together. The averages cover ten, sixty and three hundred seconds; system level CPU full pressure is not a meaningful measurement. The kernel PSI documentation defines these distinctions.
Use pressure to strengthen a diagnosis, not replace one. High CPU activity accompanied by CPU pressure and slower requests points to a different problem from high CPU activity while response times remain steady.
Group Processes by Service
A service may consist of many workers. Looking only at its largest process can miss much of its demand. On systemd systems, systemd-cgtop groups CPU, memory and disk activity by control group. Memory and I/O reporting depends on the appropriate controllers and accounting settings, so missing data is not proof of zero consumption. The systemd-cgtop documentation describes those requirements.
For container workloads, compare the workload’s configured resource allowance with host availability. A host can have spare capacity while an individual workload encounters its own boundary. The guide to Docker and Podman on Linux provides the container context; keep both host and workload measurements in the incident record.
Keep History and Set Alerts That Lead to Action
Interactive tools help during an incident. Historical collection helps when someone reports that the server was slow twenty minutes ago.
Sysstat provides tools for current and recorded activity, including CPU, memory, storage, network and process measurements. Its official feature documentation lists the available measurement groups. Configure collection before you need it, then verify that records are actually appearing.
Check your distribution’s collection schedule, enabled measurements and retention settings. Installing a package is not a substitute for confirming that it has captured a normal workday. Historical reporting cannot reconstruct samples that were never collected.
Keep enough history to compare ordinary traffic, busy periods and scheduled maintenance. Record deployments, backups and workload changes alongside measurements. Otherwise, an expected change in demand can look like a regression.
Alert on Sustained Risk and User Impact
Avoid making every brief spike an emergency. Design alerts with a clear owner and a next action. Start with sustained pressure, capacity depletion and service failure, then adjust thresholds after observing normal operation.
- CPU: investigate sustained contention alongside slower requests or growing work queues.
- Memory: combine declining available memory with swap activity, pressure or allocation failures.
- Storage: track remaining space, inode availability, growth rate and changes in request latency.
- Network: watch traffic against the available allocation and investigate new errors or retransmission growth.
Pair host measurements with application results. For a web service, track response time, failed requests and request volume as well as resource usage. The guide to hosting a website with Nginx and HTTPS covers the service setup; monitoring should tell you whether that service is delivering acceptable responses.
For several servers, central collection makes comparisons easier. Keep monitoring access restricted and avoid collecting unrestricted process arguments or other sensitive details without a reason.
A Practical Sequence for Investigating a Slow Server
Start with the symptom and its time window. Is the problem slow responses, failed writes, stalled jobs or lost connections? Note when it began and whether it affects every request or only one workload.
Next, inspect CPU activity, available memory, filesystem capacity and current network traffic. Use that first pass to choose the next measurement rather than opening every tool at once. If CPU demand looks modest but storage queues rise, follow storage. If available memory falls and swap activity grows, follow memory.
Then identify ownership. Match the busy process, service, mount or connection to the application involved. Compare the incident with recent deployments and scheduled jobs. Keep observations separate from hypotheses: “write latency rose during the backup” is evidence; “the backup caused the outage” still needs confirmation.
Change one thing at a time where practical, and measure again under comparable demand. A lower CPU percentage is not a successful fix if requests now take longer.
The aim is not an idle server. It is a server with enough capacity, acceptable response times and measurements that explain what happened when those conditions changed.