# High Load cPanel Server: Find the Culprit Fast (5 Tools)

Source: https://srvscripts.com/guides/high-load-cpanel-server/
Updated: 2026-10-03
Publisher: srvScripts (https://srvscripts.com/)

“Load is high” is a symptom, not a diagnosis. A load average of 30 on a 16-core server can be a runaway backup, one WordPress site under a bot storm, a single slow query holding table locks, or a disk that has started to fail. The tools to tell these apart ship with every cPanel install; what matters is the order you use them in. The sequence below moves from the whole machine to the one process, account or query that is causing it, and it takes a few minutes rather than an hour of guessing.

In short: Classify the load first with top, vmstat and sar as CPU-bound, I/O-bound, memory pressure or hypervisor steal, then use ps –sort=-pcpu and the D-state list to find the process and the account.

**Short answer:** Classify the load first with `top`, `vmstat` and `sar` as CPU-bound, I/O-bound, memory pressure or hypervisor steal, then use `ps --sort=-pcpu` and the `D`-state list to find the process and the account. For web workers, `whm-server-status` and the domlog show the vhost, URL and IPs being hammered; for `mysqld`, `SHOW FULL PROCESSLIST` and the slow query log name the query and the site that owns it.

## Establish what kind of load it is

Load average counts runnable and uninterruptible processes. Start by finding out whether they are waiting for CPU, disk or memory:

```
uptime
top -bn1 | head -15
vmstat 1 5
```

In the `top` header, compare `%us` (user CPU), `%sy` (system), `%wa` (I/O wait) and `%st` (steal, on VMs). In `vmstat`, watch the `r` (runnable) and `b` (blocked) columns and `si`/`so` (swap in/out). A rough map:

- High `%us`, `r` large, `b` small: CPU-bound. Something is computing, probably PHP.

- High `%wa`, `b` large: I/O-bound. Backups, a scanner, a database doing full scans, or a failing disk.

- `si`/`so` non-zero and free memory near zero: memory pressure. Everything looks slow because the box is swapping.

- High `%st`: the hypervisor is overcommitted. Nothing on this server will fix it.

If the spike has already passed, `sar` has the history. `sysstat` is installed on cPanel and collects every ten minutes:

```
sar -q | tail -20
sar -u -f /var/log/sa/sa$(date -d yesterday +%d) | tail -20
sar -d -p | sort -k10 -n | tail
```

`sar -q` shows load over the day, `sar -u` shows the CPU split at that time, and `sar -d` identifies the busiest block device.

## Find the process and the account

With the type of load known, find who is responsible. Sort by CPU or by state:

```
ps -eo pid,user,pcpu,pmem,stat,etime,cmd --sort=-pcpu | head -20
ps -eo pid,user,stat,cmd | awk '$3 ~ /^D/'
```

The second command lists processes in uninterruptible sleep, which is the I/O-bound set. On a shared server the `user` column immediately tells you the account. If PHP-FPM workers dominate, the pool name in the command line (`php-fpm: pool example.com`) names the site without any further digging. If it is `mysqld`, jump to the database section. If it is `cpbackup`, `clamd`, `imunify`, `lfd` or `rsync`, you have found a maintenance job running at the wrong time.

On CloudLinux, `lveps -c` or `lvetop` shows per-account CPU and I/O within their LVE limits, and an account pinned at 100% of its limit for long periods is the usual answer.

## Look at what Apache is serving

For CPU or I/O load that traces to web workers, `mod_status` shows which vhosts and URLs are being hit right now. It is enabled on cPanel by default for localhost:

```
curl -s 'http://localhost/whm-server-status?auto' | head -20
curl -s 'http://localhost/whm-server-status' | grep -oE '[a-z0-9.-]+\.[a-z]+ +(GET|POST) [^ ]+' | sort | uniq -c | sort -rn | head
```

The second command counts in-flight requests by host and path. A hundred concurrent `POST /wp-login.php` or `GET /xmlrpc.php` requests on one domain is a brute-force run; block it with ModSecurity or CSF and the load drops within seconds. A hundred `GET /?s=...` search requests is a scraper. Correlate with the domlog:

```
tail -5000 /etc/apache2/logs/domlogs/example.com | awk '{print $1}' | sort | uniq -c | sort -rn | head
```

The top IPs by request count, along with their user agents, tell you whether to block a range or tell the customer their plugin is misbehaving. On LiteSpeed, the real-time report in the WebAdmin console gives the same view.

## Check the database

MariaDB is the usual cause of high `%wa` and of PHP workers piling up in `D` state waiting for query results. Two commands give the immediate picture:

```
mysql -e "SHOW FULL PROCESSLIST" | awk -F'\t' '$6 > 5'
mysql -e "SHOW ENGINE INNODB STATUS\G" | grep -A20 'LATEST DETECTED DEADLOCK\|TRANSACTIONS'
```

Queries in `Sending data`, `Copying to tmp table` or `Waiting for table metadata lock` for more than a few seconds, from one database, are the culprit. Then enable the slow log if it is not already on so you can see the pattern rather than a snapshot:

```
mysql -e "SET GLOBAL slow_query_log=1; SET GLOBAL long_query_time=2; SET GLOBAL slow_query_log_file='/var/lib/mysql/slow.log';"
```

Leave it running for an hour and summarise with `mariadb-dumpslow -s t /var/lib/mysql/slow.log | head -40`. The query at the top usually belongs to one plugin on one site. A common pitfall is chasing PHP tuning when a single unindexed `wp_options` autoload or a `wp_postmeta` join with millions of rows is the actual problem. Our [MySQL health snapshot script](/scripts/mysql-health-snapshot/) automates this collection.

## Rule out mail and the scheduled jobs

Two sources are easy to overlook. An outbound spam run makes Exim consume CPU and I/O across many processes; check `exim -bpc` for the queue length and see [finding the source of outgoing spam](/guides/find-source-of-outgoing-spam-cpanel/) if it is in the thousands. And overlapping cron jobs (backups at 01:00, malware scans at 01:00, cpanellogd at 01:00) turn a quiet hour into a daily incident; stagger them in **WHM » Backup Configuration**, the scanner’s schedule, and `/etc/cron.d`.

## Verify and keep it running

Once you have acted (blocked the IPs, suspended the site, killed the query, moved the cron), confirm the load is falling with `uptime` every minute and that `vmstat` shows the blocked count back near zero. Then check `sar -q` the next day to confirm the spike did not recur at the same time. Record what you found: the account, the cause and the fix. Most high-load incidents on a given server repeat, and the second time should take two minutes. If you want an engineer watching for these patterns and acting on them before the pager goes, that is what our [managed services](/services/) are for.

## High load cPanel server at a glance

**Official documentation:** [MySQL reference manual](https://dev.mysql.com/doc/), [cPanel & WHM documentation](https://docs.cpanel.net/), [AlmaLinux wiki](https://wiki.almalinux.org/).

**Related guides:** [Choosing a VPS for a cPanel or DirectAdmin server in 2026](https://srvscripts.com/guides/best-vps-for-cpanel-directadmin-server/) · [CVE-2026-65638, 65639 and 67402 explained: patching the CSF Messenger and URLGET remote-code flaws](https://srvscripts.com/guides/csf-cve-2026-65638-patch/) · [Warm up a new mail server IP or sending domain without landing in spam](https://srvscripts.com/guides/warm-up-new-mail-server-ip-domain/).

## Frequently asked questions

### Does this high-load diagnostic apply to DirectAdmin and LiteSpeed servers as well?

Yes. `top`, `vmstat`, `sar`, `ps` and the MariaDB commands are identical on any Linux host; only the web-server view differs, with LiteSpeed’s WebAdmin real-time report and DirectAdmin’s `/var/log/httpd/domains/` logs replacing `whm-server-status` and the cPanel domlogs.

### How long does it take to find the cause of high load?

Following the sequence in order usually identifies the process or query within five to ten minutes; the slow query log needs an hour of collection when the database is involved, and historical `sar` data answers spikes that have already passed.

### Can I undo this?

Yes. Every command here is read-only except enabling the slow query log, which is switched off again with `SET GLOBAL slow_query_log=0`; blocks, suspensions or killed queries applied as a fix are reversed through CSF, WHM or `mysql` in the usual way.
