WordPress in 1 ms: cache, OPcache and gzip on a small VPS

Questions and discussions about VPS plans, Linux setup, WordPress, Nginx, NAT and VPS configuration in Bulgaria.
rychy
Site Admin
Posts: 138
Joined: Tue Oct 20, 2026 10:45 am

WordPress in 1 ms: cache, OPcache and gzip on a small VPS

Post by rychy »

🇧🇬 Прочети на български

⚡ WordPress in 1 ms: cache, OPcache and gzip on a small VPS

WordPress is not slow by itself. It is slow when every visit makes PHP build the page again, with dozens of database queries. On a small VPS you notice that right away. These are the four settings we put on every WordPress server of ours, and what they really gained us. The commands are for Debian/Ubuntu with nginx and PHP-FPM.

📊 What we measured

A test with a new WordPress on the Start plan (Debian 12, PHP 8.2), home page:
  • PHP builds the page: about 47 ms on the server itself
  • Ready page from the cache: about 1 ms
  • From outside, over the internet, no cache: the first byte arrives after about 100 ms
  • From outside, with cache: about 55 ms. The rest is the network path itself.
  • HTML size: 12 KB compressed instead of 70 KB

1️⃣ Page cache

The biggest win. The plugin saves the finished page as a file, and the next visitor gets it directly, with no PHP and no database. We use Cache Enabler: free, no settings needed, it clears the cache by itself when you edit or publish something, and it does not cache for logged-in users (so /wp-admin/ always shows the current state).

Code: Select all

# with WP-CLI, from the site folder
wp plugin install cache-enabler --activate
Or from the dashboard: Plugins → Add New → "Cache Enabler".
💡 If you run a shop (WooCommerce), the cart and checkout pages must not be cached. Good cache plugins know this, but check.

2️⃣ OPcache

PHP compiles its code on every request. OPcache keeps the compiled code in memory. It is usually installed already, but with too little memory for a big project like WordPress.

Code: Select all

php -v                                   # check the version, e.g. 8.2
sudo apt install -y php8.2-opcache
echo "opcache.enable = 1
opcache.memory_consumption = 128
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 2" | sudo tee /etc/php/8.2/fpm/conf.d/90-opcache.ini
sudo systemctl restart php8.2-fpm
php-fpm8.2 -m | grep -i opcache         # should say: Zend OPcache
revalidate_freq = 2 means PHP checks for changed files every 2 seconds. When you upload a new plugin version, it shows up almost at once.

3️⃣ gzip and caching for CSS, JS and images

By default nginx on Debian compresses only HTML. CSS and JavaScript go out uncompressed, and the browser downloads them again on every visit. In the site's server { } block:

Code: Select all

gzip on;
gzip_proxied any;
gzip_vary on;
gzip_types text/css text/plain text/xml application/javascript application/json application/xml image/svg+xml;

location ~* \.(?:css|js|mjs|png|jpe?g|gif|webp|avif|svg|ico|woff2?|ttf|otf|eot|mp4|webm)$ {
    expires 30d;
    access_log off;
    try_files $uri =404;
}

Code: Select all

sudo nginx -t && sudo systemctl reload nginx
A 30-day cache is safe because WordPress adds ?ver= to its files. A new version has a new address, so the browser downloads it again.
⚠️ If you have a rule that blocks hidden files (location ~ /\.), put the static-files block after it.

4️⃣ wp-cron from the system, not from visitors

WordPress runs its scheduled tasks (scheduled posts, updates, backup plugins) during a visit. Some visitor waits. It is better to run them every 5 minutes from the system. In wp-config.php, before the line "That's all, stop editing":

Code: Select all

define('DISABLE_WP_CRON', true);
And a cron job for the site's user (sudo crontab -u www-data -e):

Code: Select all

*/5 * * * * wp --path=/var/www/wordpress cron event run --due-now --quiet
Change the path to your site's folder. Without WP-CLI you can use curl -s https://your-site/wp-cron.php >/dev/null.

🔎 How to check it yourself

Code: Select all

curl -s -o /dev/null -H "Accept: text/html" -w "first byte: %{time_starttransfer}s\n" https://your-site/
Run it two or three times. The second time should be faster.
💡 -H "Accept: text/html" matters: Cache Enabler serves the cached page only when the request asks for HTML. A browser does that by itself; curl without it does not, and will show you the slow time.

🛡️ With us it is on from the start

When you order a VPS with WordPress, everything above is already done: Cache Enabler, OPcache, gzip and caching for static files, wp-cron from the system. The site also goes through Cloudflare, which keeps CSS, JS and images close to the visitor. You only write the content.

Questions, or your own measurements? Post them here in the topic 👇