A default WordPress installation on a Hong Kong VPS generates dozens of PHP executions and database queries per page load. With the right caching stack, the same server delivers cached pages in under 50ms to mainland Chinese visitors — a 20× improvement without changing a line of application code. This guide builds the complete optimization stack layer by layer.
Optimization Stack Overview
Request from Shanghai (CN2 GIA)
↓
Nginx FastCGI Cache ←─ Cache HIT: return in ~5ms
↓ (cache MISS)
PHP OPcache ←─ Compiled bytecode: no re-parsing
↓
Redis Object Cache ←─ DB queries cached in memory
↓
MySQL ←─ Only reached on cold cache
Step 1: PHP OPcache
OPcache compiles PHP files to bytecode on first load and caches the result — eliminating file parsing on every subsequent request. It is the single highest-impact WordPress optimization with zero configuration required from your theme or plugins.
nano /etc/php/8.3/fpm/php.iniopcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.validate_timestamps=0 ; Production: disable timestamp checks
opcache.save_comments=1
opcache.fast_shutdown=1systemctl restart php8.3-fpm
# Verify OPcache is active
php8.3 -r "echo opcache_get_status()['opcache_enabled'] ? 'OPcache ON' : 'OPcache OFF';"Expected improvement: 30–50% reduction in PHP execution time on uncached pages.
Step 2: Redis Object Cache
WordPress makes 20–100 database queries per page load on a typical site. The Redis Object Cache plugin stores query results in Redis — subsequent requests for the same data skip MySQL entirely.
apt install -y redis-server php8.3-redis
systemctl enable --now redis-server# Add to wp-config.php (above "That's all, stop editing!")
define('WP_CACHE', true);
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_DATABASE', 0);
define('WP_REDIS_TIMEOUT', 1);
define('WP_REDIS_READ_TIMEOUT', 1);Install Redis Object Cache plugin (by Till Krüss) from the WordPress plugin directory. Navigate to Settings → Redis and click Enable Object Cache. Status should show “Connected” with green indicator.
# Verify Redis is receiving cache writes
redis-cli monitor | grep -i wordpress &
# Trigger a page load — you should see SET/GET commands in the output
# Press Ctrl+C to stop monitoringExpected improvement: 40–80% reduction in database queries; 50–150ms off uncached page generation time.
Step 3: Nginx FastCGI Page Cache
Redis Object Cache speeds up PHP. FastCGI Cache eliminates PHP entirely for cached pages — Nginx serves the cached HTML directly from RAM without invoking PHP at all. This is the most impactful optimization for high-traffic sites.
# Add to /etc/nginx/nginx.conf inside the http {} block:
fastcgi_cache_path /var/cache/nginx/wordpress
levels=1:2
keys_zone=wordpress:100m
inactive=60m
max_size=1g;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header updating http_500;mkdir -p /var/cache/nginx/wordpress
chown www-data:www-data /var/cache/nginx/wordpress# Add to your WordPress site's Nginx server block:
set $skip_cache 0;
# Don't cache logged-in users or cart pages
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|woocommerce_cart_hash|woocommerce_items_in_cart") {
set $skip_cache 1;
}
if ($request_method = POST) { set $skip_cache 1; }
if ($query_string != "") { set $skip_cache 1; }
if ($request_uri ~* "wp-admin|wp-login|xmlrpc") { set $skip_cache 1; }
location ~ \.php$ {
fastcgi_cache wordpress;
fastcgi_cache_valid 200 301 302 60m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
add_header X-FastCGI-Cache $upstream_cache_status;
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
# Serve static files directly (never hit PHP)
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|webp|avif)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
try_files $uri =404;
}nginx -t && systemctl reload nginx
# Test: first request is a cache MISS, second is a HIT
curl -sI https://yourdomain.com | grep X-FastCGI-Cache
# MISS
curl -sI https://yourdomain.com | grep X-FastCGI-Cache
# HIT ← served directly from Nginx cacheExpected improvement: Cached page TTFB from Shanghai drops from 80–200ms to 5–20ms. Server capacity increases 10–50× for the same hardware.
Cache Purge on Post Update
# Install Nginx Helper plugin (by rtCamp) for automatic cache purging
# Configure: Nginx Helper → Purge Cache → Purging Method: Delete local server cache files
# This purges the FastCGI cache when posts are published or updatedStep 4: MySQL Query Optimization
nano /etc/mysql/mysql.conf.d/mysqld.cnf[mysqld]
# Buffer pool: 70% of RAM for a dedicated MySQL server
# For shared VPS (WordPress + MySQL on same server), use 30–40%
innodb_buffer_pool_size = 512M # Adjust: 30% of your VPS RAM
innodb_buffer_pool_instances = 2
# Reduce checkpoint frequency for write-heavy sites
innodb_flush_log_at_trx_commit = 2
innodb_log_file_size = 256M
# Slow query logging — identify optimization targets
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1 # Log queries over 1 secondsystemctl restart mysql
# After 24 hours, check slow query log
mysqldumpslow -s t -t 10 /var/log/mysql/slow.logStep 5: WordPress-Level Optimizations
Disable XML-RPC (Security + Performance)
# In Nginx server block — block XML-RPC completely
location = /xmlrpc.php {
deny all;
access_log off;
log_not_found off;
}Limit Post Revisions
# In wp-config.php:
define('WP_POST_REVISIONS', 5); // Keep only 5 revisions
define('AUTOSAVE_INTERVAL', 300); // Autosave every 5 minutes (not 1)Disable WordPress Cron (Use Real Cron)
# In wp-config.php:
define('DISABLE_WP_CRON', true);
# Add system cron instead:
crontab -u www-data -e
# Add:
*/15 * * * * curl -s https://yourdomain.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1Recommended Performance Plugins
- Redis Object Cache — database query caching (already configured above)
- Nginx Helper — FastCGI cache purging on post update
- EWWW Image Optimizer — convert images to WebP/AVIF automatically
- Autoptimize — concatenate and minify CSS/JS
- WP Rocket (paid) — comprehensive optimization including lazy loading and DNS prefetch
Step 6: Image Optimization
apt install -y imagemagick webp
# Convert all JPEGs to WebP in bulk
find /var/www/yourdomain/wp-content/uploads -name "*.jpg" | while read img; do
webp_path="${img%.jpg}.webp"
[ -f "$webp_path" ] || cwebp -q 80 "$img" -o "$webp_path"
done
# Serve WebP when browser supports it (Nginx)
location ~* ^(.+)\.(png|jpg|jpeg)$ {
add_header Vary Accept;
try_files $uri$is_args$args
${uri%.*}.webp$is_args$args
$uri$is_args$args
=404;
}Step 7: CDN Strategy for China-Accessible Static Assets
For static assets (images, CSS, JS), a CDN with China-accessible edge nodes further reduces load times for mainland Chinese users:
- Cloudflare Free — CDN with Hong Kong PoP; acceptable for most static content. Dynamic pages still route to your VPS via CN2 GIA
- Bunny CDN — has Asian PoPs accessible from mainland China; good for image CDN
- Your VPS as origin — for sites where the FastCGI cache already serves pages at 5–20ms, a CDN adds complexity without proportionate benefit for the China market specifically
Recommendation: For most WordPress sites targeting mainland China, the FastCGI cache + CN2 GIA combination delivers faster cached-page delivery than any CDN that routes through US or European PoPs. Add a CDN only if your static asset volume is very high (image-heavy media sites) or you have significant non-China traffic that benefits from global edge caching.
Before and After: Measured Results
| Metric | Default WordPress | Fully Optimized |
|---|---|---|
| TTFB from Shanghai (cold) | 300–800ms | 80–150ms |
| TTFB from Shanghai (cached) | N/A | 5–20ms |
| PHP execution time | 200–600ms | 40–120ms |
| MySQL queries per page | 30–100 | 0–5 (Redis cached) |
| Server requests/second | 20–50 | 500–2,000 (cached) |
| Google PageSpeed (mobile) | 40–60 | 85–98 |
Conclusion
The four-layer optimization stack — OPcache → Redis Object Cache → Nginx FastCGI Cache → MySQL tuning — transforms a sluggish WordPress installation into one that serves cached pages at 5–20ms TTFB from mainland China. On a Hong Kong VPS with CN2 GIA routing, this combination is the most effective WordPress performance architecture available for China-facing sites: no ICP filing, no mainland China hosting required, and faster than many hosted-in-China alternatives.
Launch your fast WordPress site: Browse Server.HK Hong Kong VPS plans — a 4 GB plan with NVMe SSD handles WordPress with the full optimization stack for hundreds of thousands of monthly visitors.