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.

By Rodney Lungayan5 min read

Flat illustration of a CPU usage graph with a spike and a magnifying glass, for a guide on VPS CPU spikes

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.

ShapeLikely cause
Flat plateau at 90–100% for minutes, then a clean dropOne scheduled job running start to finish (backup, cron, build)
Many short, sharp spikesWeb requests, wp-cron or a busy PHP process
Slow climb that never comes downA 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.

Work with me

Have a project in mind? Let's build it together.

I'm Rodney Lungayan, a full stack developer who builds fast, secure WordPress websites and custom front-ends. If this article helped, imagine what we can do on your project.

Hire me for your project See my work