VPS CPU Spikes: 7 Steps to Find What Is Eating Your Server
VPS CPU spikes pinning your server at 100%? Follow 7 simple checks with logs, cron and atop to find the exact process behind each spike.
Your VPS CPU is stuck at 100% for a few minutes, then drops back to normal. Nothing seems broken, but you want to know why. VPS CPU spikes almost always come from one scheduled job or one burst of traffic, and you can find it with seven simple checks.
This guide uses a Linux VPS with a control panel like Webmin or Virtualmin, but the same steps work on any Ubuntu or Debian server. Work through them in order. Each one narrows the search.
1. Read the shape of the graph
Open your CPU graph and look at the shape before you touch the server. The shape tells you what kind of problem you have.
| Shape | Likely cause |
|---|---|
| Flat plateau at 90–100% for minutes, then a clean drop | One scheduled job running start to finish (backup, cron, build) |
| Many short, sharp spikes | Web requests, wp-cron or a busy PHP process |
| Slow climb that never comes down | A stuck process or a memory leak |
A plateau is the best case. It means something started, ran for a fixed time, and finished. That is much easier to trace than random noise.
Write down the exact start and end time of the spike. You need it for every step below. Also note how long it lasted, because the length is a clue. A six-minute plateau often matches a backup or a build, while a 30-second burst often matches a crawl.
2. Check the server's time zone
Graphs often show your local time, but servers often log in UTC. If you search the logs at the wrong hour, you will find nothing and think the spike left no trace.
Run this command to see the server time and zone:
timedatectl
If the server is on UTC and you are 8 hours ahead, a spike at 2:05 PM local time is 06:05 in the logs. Convert the time first.
3. Look at what started in the system journal
The system journal records every service and job that starts. Ask it for only the minutes around the spike. See the journalctl manual for more options.
journalctl --since "2026-10-07 14:03" --until "2026-10-07 14:12" --no-pager
Look for lines that mention backups, timers, package updates, or a service starting right when the graph jumped. Ignore the noise from normal logins. You are only looking for something that started within a minute or two of the spike.
If the journal is empty for that window, the time zone is probably wrong. Go back to step 2 and widen the range by a few hours.
4. Check cron jobs and scheduled tasks
Most plateaus come from a scheduled job. Check what cron ran in the same window:
journalctl -u cron --since "2026-10-07 14:00" --until "2026-10-07 14:15" --no-pager
Also list the jobs for each user with crontab -l, and look in /etc/cron.d/. In your control panel, check the scheduled backup settings too. A backup that compresses many sites can pin the CPU for minutes. If your site runs on WordPress, remember that WP-Cron also runs jobs when visitors load pages.
5. Check the web access logs for bots and floods
A burst of requests can look just like a scheduled job. Count the requests per IP in your access log for the spike window. Replace the path with your own log file:
awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -10
Compare the top numbers with a normal hour. If one address sent thousands of requests while the others sent a few dozen, you likely have a bad bot or an aggressive crawl. Search engine crawlers can also cause this when they hit many pages at once. Block it at the firewall, or read my VPS security audit guide for the full hardening checklist.
6. Catch it live with top
If the spike comes back, watch it while it happens. Run top, press P to sort by CPU, and note the top process name and its user.
top -o %CPU
A PHP-FPM worker points to a site. A database process points to slow queries. A node process points to an app or a build. If the server runs out of capacity under load, you may also see errors like the ones in my WordPress 503 error guide.
7. Install atop so the next spike leaves a trail
Logs tell you what started. They do not always tell you what used the CPU. atop records process activity over time, so you can replay a spike after it happened. Read the atop manual page or visit the atop project site for details.
sudo apt install atop
The default log interval is 600 seconds, which is too coarse for short spikes. Set it to 60 seconds in /etc/default/atop (the LOGINTERVAL line), then restart the service:
sudo systemctl restart atop
To replay a past day, open its log file and step through time:
atop -r /var/log/atop/atop_20261007
Press t to step forward and T to step back. Sort by CPU and the culprit shows at the top.
When should you worry about VPS CPU spikes?
Do not worry about one clean spike at the same time each day. That is a job doing its work.
Act when you see any of these:
- The CPU stays high for hours.
- Spikes get longer or more frequent each week.
- Your sites slow down or time out during the spike.
- One unknown process keeps coming back.
If a job causes the spike, move it to a quiet hour. If a bot causes it, block it. If a site causes it, fix the slow plugin or query. My guide on speeding up slow WordPress websites covers that last case.
Need a hand with your server?
If you cannot find the cause, or you want someone to watch your server for you, I can help. See my WordPress maintenance service or contact me and describe what you are seeing.