Hey everyone,
I recently migrated my site to a standard Ubuntu Droplet. The site serves a lot of downloads, and while page load times are good, I occasionally see CPU usage spike to 100% during traffic surges.
Before I simply upgrade the Droplet, I want to make sure the server is properly optimized. I’m currently running Nginx with Redis object caching.
I’d appreciate some advice from anyone with experience managing high-traffic WordPress sites:
What PHP-FPM pool settings (such as pm.max_children) have worked well for handling sudden traffic spikes?
Which DigitalOcean monitoring alerts do you find most useful for keeping an eye on CPU, memory, and PHP-FPM without getting too many false alarms?
Are there any other Nginx, Redis, or WordPress optimizations you’d recommend before scaling the server?
Thanks in advance for any suggestions!
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.
Hi there,
Good that you are optimizing before scaling, that is the right order.
For PHP-FPM, the key setting is pm.max_children which should be based on how much RAM each PHP process uses. Check your average process size first:
ps --no-headers -o "rss,cmd" -C php-fpm8.x | awk '{ sum+=$1 } END { print sum/NR/1024 " MB average" }'
Then divide your available RAM by that number. A rough starting point for a 2GB Droplet with Redis already handling object cache:
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 8
pm.max_requests = 500
For downloads specifically, the CPU spike is often not PHP at all but Nginx serving large files. Make sure you are using X-Accel-Redirect to let Nginx handle file delivery directly rather than routing downloads through PHP/WordPress:
location /protected-downloads/ {
internal;
alias /var/www/your-files/;
}
For DigitalOcean monitoring alerts, CPU above 80% for 5 minutes is a useful threshold that avoids false alarms from short spikes. Memory above 85% is worth watching too since WordPress with Redis can creep up. You can set these under Manage > Monitoring in the control panel.
On Redis, make sure you are also using a page cache plugin like WP Rocket or W3 Total Cache with full page caching enabled, not just object caching. Object caching alone still runs PHP for every request, full page caching serves cached HTML directly from Nginx and bypasses PHP entirely for repeat visitors.
Hi there,
Bobby’s PHP-FPM sizing and X-Accel-Redirect points are the right foundation for a downloads site, worth building on rather than repeating.
If gzip is on in your nginx config, check that gzip_types doesn’t include already-compressed formats. Compressing a zip or any binary download wastes CPU for no size benefit, sometimes it makes the file bigger:
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
Leave application/zip, application/octet-stream, and image formats out of that list entirely.
On the PHP side, if your download links run any permission check or download counter before the X-Accel-Redirect header fires, that’s still a PHP-FPM hit per download even with the redirect in place. Worth confirming OPcache is tuned for it, the defaults are conservative:
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=60
If you deploy plugin updates through wp-admin rather than CI, keep validate_timestamps=1 with that revalidate_freq, it avoids stale bytecode after an update while still cutting filesystem checks under load.
Last thing worth considering for a downloads site specifically: if the files themselves are large or bandwidth heavy, moving them off the Droplet onto DigitalOcean Spaces with the CDN enabled offloads both the bandwidth and the CPU cost of serving them, WordPress just issues a redirect to the Spaces URL instead of an X-Accel-Redirect to local disk. One thing to know before doing that: if downloads need to stay gated behind login or permission checks, presigned Spaces URLs bypass the CDN and hit origin on every request, so that architecture only pays off for downloads that are effectively public once issued.
Hope that this helps!
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Scale up as you grow — whether you're running one virtual machine or ten thousand.

From GPU-powered inference and Kubernetes to managed databases and storage, get everything you need to build, scale, and deploy intelligent applications.
