Why WordPress is Slow (and How to Fix It)
WordPress out of the box serves every page dynamically — each request runs PHP, queries the database, and builds HTML. On a VPS, you control the entire stack and can dramatically improve performance.
Step 1: PHP Configuration
# /etc/php/8.3/fpm/php.ini
memory_limit = 256M
max_execution_time = 30
upload_max_filesize = 64M
post_max_size = 64M
# OPcache (crucial for PHP performance)
opcache.enable = 1
opcache.memory_consumption = 128
opcache.max_accelerated_files = 10000
opcache.validate_timestamps = 1
opcache.revalidate_freq = 60
Step 2: PHP-FPM Pool Tuning
# /etc/php/8.3/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10
pm.max_requests = 500
| RAM | max_children |
|---|---|
| 1 GB | 5-10 |
| 2 GB | 10-20 |
| 4 GB | 20-40 |
| 8 GB | 40-80 |
Step 3: Page Caching
Install a caching plugin that generates static HTML files:
| Plugin | Type | Best For |
|---|---|---|
| WP Super Cache | Disk-based | Simple sites |
| W3 Total Cache | Multi-tier | Complex setups |
| WP Rocket | Premium, easy | Most users |
| LiteSpeed Cache | Server-level | LiteSpeed servers |
Step 4: Object Caching with Redis
sudo apt install -y redis-server php8.3-redis
In wp-config.php:
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
Install the "Redis Object Cache" plugin and enable it.
Step 5: Database Optimization
-- Clean up post revisions (keep last 5)
DELETE FROM wp_posts WHERE post_type = 'revision'
AND ID NOT IN (
SELECT * FROM (
SELECT ID FROM wp_posts WHERE post_type = 'revision'
ORDER BY post_date DESC LIMIT 5
) AS t
);
-- Clean transients
DELETE FROM wp_options WHERE option_name LIKE '%_transient_%';
-- Optimize tables
mysqlcheck -o wordpress -u root -p
Limit revisions in wp-config.php:
define('WP_POST_REVISIONS', 5);
define('AUTOSAVE_INTERVAL', 120);
define('EMPTY_TRASH_DAYS', 7);
Step 6: Image Optimization
- Use WebP format (50-80% smaller than JPEG)
- Lazy load images below the fold
- Serve responsive images with
srcset - Use a CDN for static assets
Benchmarking
# Test page load time
curl -o /dev/null -s -w "Time: %{time_total}s\n" https://example.com
# Load testing
ab -n 100 -c 10 https://example.com/
Tip The single biggest WordPress performance improvement is page caching. A cached page serves in 20ms instead of 200-500ms. Everything else is secondary.