Skip to content

WordPress Docker stack serving 5,000 users at 187ms on a 1GB VPS with Redis & Caddy.

License

aleixnguyen-vn/docker-wordpress-performance

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Benchmark Redis Hit Lighthouse

Built With Docker NGINX + PHP-FPM Redis Cache Caddy Server VPS Ubuntu

🎈 [CASE STUDY] WordPress on Docker: 5000 Client Benchmark on 1GB RAM VPS

"Optimizing WordPress at this level isn’t about plugins β€” it’s about removing bottlenecks one by one."

⚠️ Disclaimer: This repo focuses solely on the technical side – site architecture, deployment, and performance tuning skills.


1. πŸ“Œ Objectives

  • Run WordPress with Docker on a basic VPS (1vCPU, 1GB RAM)
  • Serve 5000 concurrent clients/minute
  • Achieve 189ms average response time
  • Use only free or open-source stack (Docker, Caddy, Redis, MariaDB)

2. βš™οΈ Stack Overview

  • VPS: Vultr 6$ VPS (1vCPU, 1GB RAM, 25GB SSD NVMe)
  • OS: Ubuntu 22.04 LTS
  • Web Server: NGINX (behind Caddy for HTTPS)
  • CMS: WordPress (php8.2-fpm)
  • DB: MariaDB 10.5
  • Cache: Redis (Object Cache)
  • SSL Proxy: Caddy (reverse proxy + HTTP/3)
  • CDN: Cloudflare (free plan)

3. πŸ’ͺ Key Optimizations

3.1 PHP-FPM Pool (wp-app)

pm = dynamic
pm.max_children = 4
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_requests = 500       ; auto recycle to avoid memory leak


; increased php execution timeout 
request_terminate_timeout = 30s

3.2 OPCache

opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.validate_timestamps=0  ; if dont require hot reload file
opcache.revalidate_freq=60

3.3 Redis Configuration

maxmemory 256mb
maxmemory-policy allkeys-lru
  • Redis as object cache for WordPress
  • Hit rate: 99.93%
  • No manual preload yet, cache populated purely through real traffic

3.4 NGINX Performance

gzip on;
gzip_disable "msie6";

gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;               # 1 - 9(5 for best performance)
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;

gzip_types
    text/plain
    text/css
    application/json
    application/javascript
    application/x-javascript
    text/xml
    application/xml
    application/xml+rss
    image/svg+xml;

3.5 Caddy for SSL

example.com {
    reverse_proxy nginx:80 {
        header_up X-Forwarded-Proto https
    }

    encode gzip

    @static {
        path_regexp \.(jpg|jpeg|png|gif|ico|css|js|woff2?|ttf|svg)$
    }

    header @static {
        Cache-Control "public, max-age=31536000"
        Expires "Sun, 31 Dec 2037 23:55:55 GMT"
    }
}

4. πŸ“Š Benchmark Results (Loader.io)

Scenario:

  • 5000 clients over 1 minute
  • All requests to homepage (cached via Redis)
Metric Value
Avg Response Time 189ms
Redis Hit Rate 99.93%
Success Rate 100%
Max Latency 486ms
RAM Usage (peak) ~451MB
CPU 2-6%
Errors / Timeouts 0

πŸš€ Even at 5000 users/minute, no Redis or MySQL bottlenecks were observed. Cache was warmed purely by live traffic.


5. πŸ† Summary

  • Dockerized WordPress stack on 1vCPU/1GB RAM VPS
  • No paid services: all open-source or free-tier
  • Redis cache hit 241,595 / 179 β†’ 99.93% hit rate
  • Caddy offloaded SSL + HTTP/3
  • Cloudflare added as CDN layer (compression + edge cache)

Result:

🌟 5000 concurrent users served in 1 minute at 187ms average, no crash, no errors. RAM used: ~431MB.


6. πŸ–Ό Some screenshots

Below are key screenshots capturing performance results and system metrics during the tests.

πŸ”Ή 1. Loader.io Benchmark – 5000 Users,

πŸ§ͺ Scene 1 – Warm cache, optimal performance

Loader.io benchmark 5000 users 187ms

Final round:
5,000 concurrent users Β· 187ms avg Β· 0% errors Β· 100% valid redirects
Max latency only 391ms β€” demonstrates steady-state performance under full load.

🧊 Scene 2 – Cold start (post page)

Loader.io benchmark 5000 cold start 200ms

Real-world uncached access: 198ms avg, 0% errors Shows how the stack handles cache-warming and first-hit scenarios with zero degradation.


πŸ”Ή 2. 93 Google Lighthouse Score

Google Lighthouse

Score: 93/100 (Desktop) Minimal layout shift, optimized loading. cf-cache-status: HIT, HTML gzip, no render-blocking JS.

⚠️ Note: idk why Pingdom score stuck at 87/100 despite full gzip and cache header tuning β€” likely due to CDN location and test heuristics.


πŸ”Ή 3. Redis Hit Rate

Redis CLI hit rate 241,595 cache hits vs. 179 misses β€” 99.93% hit rate without preload.


πŸ”Ή 4. Docker Stats + htop During Load Test

Docker Stats htop

RAM usage: ~431MB peak
All services stayed under control, including PHP-FPM, Redis, MariaDB
Swap barely touched, CPU stable at 2–6%


πŸ”Ή 5. Chrome DevTools: Network Tab

TTFB + headers

βœ… cf-cache-status: HIT
βœ… gzip enabled
βœ… HTTP/3 from Caddy
TTFB under 200ms, total load <2s across 67 assets.


πŸ”Ή 6. Folder Structure / Project Layout

Repo layout Modular Docker-based layout with isolated services and shared volumes.

πŸ–₯ 7. Server Specs – Vultr 1GB VPS

Vultr server overview

Benchmark environment: Vultr 1vCPU / 1GB RAM VPS (Frankfurt). Stack deployed on Ubuntu 22.04 with Docker. Current cost: $0.07.*


For more screenshots of alternative configs and test iterations, browse the full /screenshots folder in the repository.

7. πŸ“† Future Improvements

  • Add FastCGI Cache (NGINX-level full page caching)
  • Integrate GitHub Actions to trigger Redis preload after deploy
  • Explore ESI + Edge Caching (via QUIC.cloud or Cloudflare Workers)
  • Auto-monitor Redis hit rate and auto-flush if fallback detected

8. πŸ’Ό Repository & Source Code

https://github.com/aleixnguyen-vn/docker-wordpress-performance


⏱️ I picked up Docker at 2PM. This stack was live β€” and benchmarking β€” before midnight. πŸ”Š "You don't need a bigger server. You need better config."

About

WordPress Docker stack serving 5,000 users at 187ms on a 1GB VPS with Redis & Caddy.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published