Nginx Optimization for VPS: 10x WordPress Performance Guide
Learn how to tune Nginx, PHP-FPM, Redis, and caching layers to handle 10x more traffic on your UK VPS without upgrading your plan.
Most VPS hosting setups run at 10-20% of their actual capacity. With the right Nginx and PHP-FPM configuration, you can handle 10x the traffic on the same hardware — no upgrade required.
This guide covers production-proven optimisations for WordPress sites on Nginx + PHP-FPM, tested on UK VPS hosting environments.
1. Nginx Worker Optimisation
The number of worker processes and connections directly impacts how many concurrent visitors your server can handle.
# /etc/nginx/nginx.conf
# Set worker processes to number of CPU cores
worker_processes auto;
# Increase worker connections
events {
worker_connections 4096;
multi_accept on;
use epoll;
}
# Keepalive settings for better throughput
http {
keepalive_timeout 30;
keepalive_requests 500;
# Increase sendfile efficiency
sendfile on;
tcp_nopush on;
tcp_nodelay on;
}
Key tunables explained:
worker_processes auto— Automatically set to match CPU core countworker_connections 4096— Each worker can handle 4096 connectionsmulti_accept on— Accept all new connections at once, not one-by-oneuse epoll— Most efficient event model for Linux
2. PHP-FPM Pool Tuning
PHP-FPM is often the bottleneck. The key is finding the right balance between pm.max_children and available memory.
# /etc/php/8.x/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 8
pm.min_spare_servers = 4
pm.max_spare_servers = 16
pm.max_requests = 1000
Memory calculation formula:
Available RAM × 0.8 ÷ Average PHP process memory = max_children
Example: 4GB × 0.8 ÷ 64MB = 50 max children
PHP-FPM Pool Settings for WordPress
# Dedicated pool for WordPress
[wordpress]
listen = /var/run/php/wordpress.sock
pm = ondemand
pm.max_children = 20
pm.process_idle_timeout = 10s
pm.max_requests = 500
# Security: chroot WordPress to its directory
chroot = /var/www/wordpress
3. Nginx FastCGI Caching
FastCGI caching caches the full HTML output of WordPress pages, serving subsequent requests directly from memory without hitting PHP or the database.
# /etc/nginx/nginx.conf — in http block
fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
# WordPress site config
server {
# Cache configuration
set $skip_cache 0;
# Skip cache for logged-in users and comments
if ($http_cookie ~* "comment_author|wordpress_logged_in|wp-postpass_") {
set $skip_cache 1;
}
# Skip cache for POST requests and admin pages
if ($request_method = POST) {
set $skip_cache 1;
}
location ~ \.php$ {
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 200 301 302 60m;
fastcgi_cache_use_stale error timeout updating invalid_header http_500;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache_lock on;
add_header X-Cache $upstream_cache_status;
}
}
With FastCGI caching enabled, WordPress pages are served in 2-5ms instead of 200-500ms — a 100x improvement.
4. Redis Object Cache for WordPress
Redis provides in-memory caching for WordPress database queries, dramatically reducing MySQL load:
# Install Redis
sudo apt install redis-server -y
# Configure Redis for WordPress caching
# /etc/redis/redis.conf
maxmemory 256mb
maxmemory-policy allkeys-lru
save "" # Disable persistence for cache-only use
# Install Redis PHP extension
sudo apt install php8.x-redis -y
# Install WordPress Redis plugin
# Download Redis Object Cache plugin and activate
wp plugin install redis-cache --activate
wp redis enable
5. Gzip and Brotli Compression
Compression reduces bandwidth usage by 60-80% and speeds up page loads, especially for UK mobile users:
# /etc/nginx/nginx.conf
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 256;
gzip_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
image/svg+xml;
# Brotli (if compiled with nginx)
brotli on;
brotli_comp_level 6;
brotli_types text/* application/* image/svg+xml;
6. Static File Caching and Cache-Control Headers
Browser caching for static assets reduces repeat load times significantly:
location ~* \.(jpg|jpeg|png|gif|ico|css|js|webp|avif)$ {
expires 365d;
add_header Cache-Control "public, no-transform";
access_log off;
}
location ~* \.(woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
access_log off;
}
location ~* \.(svg|svgz)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
add_header Vary "Accept-Encoding";
}
7. Rate Limiting for Security
Rate limiting protects your VPS from brute force attacks and abusive traffic patterns:
# Define rate limit zones
limit_req_zone $binary_remote_addr zone=login:10m rate=3r/m;
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;
# Apply to login page
location /wp-login.php {
limit_req zone=login burst=5 nodelay;
fastcgi_pass wordpress;
}
# Apply to REST API
location /wp-json/ {
limit_req zone=api burst=20 nodelay;
fastcgi_pass wordpress;
}
8. Monitoring Your Optimisations
Track the impact of your optimisations with these tools:
- Nginx Amplify — Real-time Nginx performance monitoring
- PHP-FPM status page — Monitor pool health and process counts
- Redis CLI —
redis-cli info statsfor cache hit rates - htop — Track CPU and memory usage in real-time
- GTmetrix / PageSpeed Insights — Front-end performance measurement
Real-World Results
On a typical UK VPS (2 vCPU, 4GB RAM, NVMe), these optimisations deliver:
- Page load time: 800ms → 120ms (87% reduction)
- Concurrent users: 500 → 5,000+ (10x capacity)
- PHP-FPM memory usage: 1.2GB → 400MB (67% reduction)
- MySQL query load: 500qps → 50qps (90% reduction with Redis)
Ready to Deploy an Optimised VPS?
Get a pre-optimised VPS with Nginx, Redis, and PHP-FPM tuned for WordPress from day one. First month free with LAUNCH100.
Deploy Now →