Updated: September 29, 2025 at 04:02 PM
3 min read
Solusi 1: Implementasi Caching lewat nginx
Lewat nginx, kita bisa melakukan caching sebelum konten ini diantarkan ke user. Dengan pendekatan ini, jika sudah ada yang membuka suatu item, item ini akan tinggal di cache di server maka selanjutnya (selama cache masih valid) data akan di serve langsung dari cache, bukan lewat PHP process lagi. Ini bisa membawa speed yang cukup signifikan.

Sebelum saya melakukan cache ini, untuk mengakses homepage saja butuh waktu 2 detik (2100ms) sebelum server merespons request kita. Ini akan membuat website terasa “lelet“. Setelah nginx cache, response time server turun jadi hanya 75ms! Ini sangat signifikan.

Pendekatan ini ada kekurangannya, yaitu kalau item ini belum ada yang buka sama sekali, nginx pasti tak punya cache untuk di serve dan harus menunggu Apache + mod_php (WordPress) untuk merender konten terlebih dahulu. Ini lah yang menyebabkan situasi saat “coldstart” menjadi sangat lama
Konfigurasi compose.yml
services:
wordpress:
image: wordpress
restart: always
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: (username database)
WORDPRESS_DB_PASSWORD: (password database)
WORDPRESS_DB_NAME: dws-notes-db
WORDPRESS_HOME: http://wp.server.drl
WORDPRESS_SITEURL: http://wp.server.drl
WORDPRESS_DEBUG: false
PHP_OPCACHE_ENABLE: 1
PHP_OPCACHE_MEMORY_CONSUMPTION: 128
PHP_OPCACHE_MAX_ACCELERATED_FILES: 10000
PHP_OPCACHE_REVALIDATE_FREQ: 0
volumes:
- ./wordpress:/var/www/html
nginx:
image: nginx:alpine
restart: always
ports:
- 8055:80
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./wordpress:/var/www/html:ro
- nginx-cache:/var/cache/nginx
depends_on:
- wordpress
db:
image: mysql:8.0
restart: always
environment:
MYSQL_DATABASE: dws-notes-db
MYSQL_USER: (username database)
MYSQL_PASSWORD: (password database)
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- ./db:/var/lib/mysql
deploy:
resources:
limits:
memory: 350M
reservations:
memory: 64M
command: [
'--innodb-buffer-pool-size=128M',
'--innodb-log-file-size=16M',
'--performance-schema=0'
]
volumes:
nginx-cache:
driver: local
Konfigurasi nginx.conf:
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=WORDPRESS_CACHE:200m inactive=120m max_size=1024m;
proxy_cache_key "$scheme://$host$request_uri";
# don't cache for logged-in users or when specific cookies are present
map $http_cookie $no_cache {
default 0;
~SESS 1;
~wordpress_logged_in 1;
}
upstream wordpress {
server wordpress:80;
keepalive 16;
}
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ @wp;
}
location @wp {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto http;
proxy_cache WORDPRESS_CACHE;
proxy_cache_bypass $no_cache;
proxy_no_cache $no_cache;
proxy_cache_valid 200 10m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering on;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://wordpress;
}
location ~ \.php$ {
proxy_pass http://wordpress;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto http;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering on;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
location ~ /\.ht {
deny all;
}
}
}
Solusi 2: Ganti Apache + mod_php sepenuhnya dan pakai stack nginx + PHP-FPM
Solusi ini nyaris bisa dibilang “drop-in replacement” karena kita tidak menggunakan Apache untuk serving dan processing file PHP dan kita langsung menggunakan nginx.


Konfigurasi lengkap bisa cek lewat Repository GitHub disini
Sekian notes kali ini, selamat bereksperimen!