On a VPS, WordPress speed is mostly about the server: how quickly PHP runs, how often the database is hit, and whether pages are served from cache. This guide walks through the changes that make the biggest difference, in order of impact, for an Nginx + PHP-FPM + MariaDB stack on Ubuntu or Debian.

1. Measure first

Record a baseline so you know what each change does:

# Time to first byte for the home page (run a few times)
curl -o /dev/null -s -w 'TTFB: %{time_starttransfer}s\n' https://example.com/

Also run PageSpeed Insights on a typical post and note LCP and TTFB. Install Query Monitor temporarily to see slow queries and heavy plugins.

2. Use a current PHP version with OPcache

PHP 8.2+ is significantly faster than PHP 7.x. OPcache keeps compiled PHP in memory so files aren’t parsed on every request:

; /etc/php/8.3/fpm/conf.d/10-opcache.ini
opcache.enable=1
opcache.memory_consumption=192
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=60

3. Size PHP-FPM for your RAM

Too few workers and requests queue; too many and the server swaps. Estimate:

max_children ≈ (RAM available for PHP) / (average PHP process size)

Check the average process size:

ps -o rss= -C php-fpm8.3 | awk '{s+=$1; n++} END {print s/n/1024 " MB avg"}'

On a 4 GB VPS, with ~1.5 GB for MariaDB, Redis and the OS, and processes around 80 MB, about 25–30 children is reasonable:

; /etc/php/8.3/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 28
pm.start_servers = 6
pm.min_spare_servers = 4
pm.max_spare_servers = 10
pm.max_requests = 500

systemctl reload php8.3-fpm after changes.

4. Add full-page caching

This is the biggest win: cached pages skip PHP and the database entirely. Two options:

A caching plugin (e.g. WP Super Cache, W3 Total Cache, LiteSpeed Cache on LiteSpeed servers, or a commercial plugin). Easiest to manage.

Nginx FastCGI cache — fastest, works at the server level:

# http {} block
fastcgi_cache_path /var/cache/nginx/wp levels=1:2 keys_zone=WP:100m inactive=60m max_size=1g;

# server {} block
set $skip 0;
if ($request_method = POST) { set $skip 1; }
if ($query_string != "") { set $skip 1; }
if ($request_uri ~* "/wp-admin/|/wp-login.php|/cart/|/checkout/|/my-account/") { set $skip 1; }
if ($http_cookie ~* "wordpress_logged_in|comment_author|woocommerce_items_in_cart") { set $skip 1; }

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    fastcgi_cache WP;
    fastcgi_cache_valid 200 301 60m;
    fastcgi_cache_bypass $skip;
    fastcgi_no_cache $skip;
    add_header X-Cache $upstream_cache_status;
}

Use a purge plugin (such as Nginx Helper) so the cache clears when you publish.

5. Add Redis object caching

Logged-in users, WooCommerce carts and admin pages can’t be page-cached. A persistent object cache keeps database query results in memory:

apt install -y redis-server php8.3-redis
systemctl enable --now redis-server

Install the Redis Object Cache plugin and enable it (or wp redis enable with WP-CLI). Limit Redis memory in /etc/redis/redis.conf:

maxmemory 256mb
maxmemory-policy allkeys-lru

6. Tune MariaDB

The key setting is the InnoDB buffer pool — enough to hold your database in RAM:

# /etc/mysql/mariadb.conf.d/60-tuning.cnf
[mysqld]
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
max_connections = 100

Check your database size with wp db size --tables, then set the pool to that size plus room to grow, within your RAM budget. Clean up old revisions, transients and orphaned meta — see WordPress post meta.

7. Front-end basics

  • Compress images and serve WebP/AVIF.
  • Enable Brotli or gzip in Nginx.
  • Cache static files in the browser: expires 30d; for images, CSS and JS.
  • Remove plugins you don’t use; each can add queries and scripts.
  • Consider a CDN for global audiences — see speeding up a VPS with Cloudflare.

8. Measure again

Re-run the curl test and PageSpeed Insights. Cached pages on a well-tuned VPS typically return in well under 100 ms of server time. If uncached pages are still slow, Query Monitor will usually point to a specific plugin or query.

Choosing the right size

As a rough guide: a single busy WordPress site with caching runs comfortably on 2 vCPU and 4 GB of RAM; WooCommerce stores and several sites on one server benefit from 4 vCPU / 8 GB or more. Pick a location close to your visitors — USA VPS for the Americas and Europe, Hong Kong or Tokyo for Asia. More on the server side in Linux server performance and hosting multiple websites on one VPS.

  • WordPress
  • Performance
  • Nginx