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.

What to expect: Following these optimisations, a 2-core/4GB VPS can comfortably handle 5,000+ concurrent visitors serving WordPress pages in under 200ms.

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:

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:

Real-World Results

On a typical UK VPS (2 vCPU, 4GB RAM, NVMe), these optimisations deliver:

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 →
🚀

The Hostingowy Engineering Digest

Get monthly deep-dives on UK VPS hosting, infrastructure benchmarks, DevOps tooling, and cloud cost optimisation. Built by engineers, for engineers.

2 issues sent · 7 subscribers · No spam, ever

No spam. Unsubscribe anytime. Read our Privacy Policy.