NGINX Performance
Performance Tuning and Capacity Planning
Memahami worker process, worker connections, event loop, file descriptor, keepalive, buffers, TLS reuse, HTTP/2, CPU, memory, disk, benchmarking, dan load testing.
Part 021 — Performance Tuning and Capacity Planning
1. Tujuan Part Ini
NGINX sering dianggap "cepat secara default". Itu benar sebagai baseline, tetapi tidak cukup untuk production enterprise system.
Dalam production, bottleneck NGINX biasanya bukan hanya satu angka seperti CPU usage. Bottleneck bisa muncul dari:
worker process
worker connection
file descriptor
kernel backlog
client keepalive
upstream keepalive
TLS handshake cost
HTTP/2 multiplexing
buffer memory
temporary file disk usage
compression CPU cost
slow client
slow upstream
cloud load balancer timeout
Kubernetes readiness/routing behavior
Java thread pool dan connection pool
Part ini membangun cara berpikir performance NGINX sebagai layer traffic, bukan sekadar kumpulan directive.
Targetnya bukan "menyetel semua directive menjadi besar". Targetnya adalah memahami:
kapasitas aktual = min(kapasitas NGINX, kapasitas OS, kapasitas container, kapasitas upstream, kapasitas network, kapasitas Java service)
NGINX yang terlalu kuat di depan backend yang rapuh hanya akan mempercepat kegagalan.
2. Mental Model: NGINX Performance Is Connection-Oriented
Sebagai backend engineer, kita sering berpikir dalam unit:
request per second
latency per endpoint
thread pool
DB connection pool
Kafka consumer lag
NGINX berpikir lebih dekat ke:
connection
socket
file descriptor
event loop
buffer
upstream connection
client connection
TLS session
Satu request HTTP bukan selalu satu connection.
Contoh:
HTTP/1.1 keepalive:
1 connection dapat membawa banyak request secara berurutan
HTTP/2:
1 connection dapat membawa banyak stream secara multiplexed
WebSocket/SSE:
1 connection dapat hidup lama dan menahan slot connection
slow upload:
1 request dapat menahan buffer dan connection dalam waktu lama
large download:
1 response dapat menahan bandwidth dan worker attention lebih lama
Karena itu, tuning NGINX harus mempertimbangkan bukan hanya throughput, tetapi juga connection lifetime.
3. Core Capacity Formula
Formula awal yang sering dipakai:
max_connections ≈ worker_processes × worker_connections
Contoh:
worker_processes auto;
events {
worker_connections 4096;
}
Jika container memiliki 4 CPU dan worker_processes auto, NGINX dapat membuat sekitar 4 worker process.
Secara kasar:
4 worker × 4096 worker_connections = 16384 theoretical connections
Tetapi angka ini bukan kapasitas production final.
Batas riil juga dipengaruhi oleh:
ulimit -n / file descriptor limit
container CPU limit
container memory limit
kernel socket backlog
upstream keepalive pool
client keepalive duration
TLS handshake cost
buffer usage per request
log I/O
network bandwidth
cloud load balancer limit
Kubernetes node capacity
Jangan treat formula ini sebagai janji. Treat sebagai upper-bound awal yang harus divalidasi dengan load test.
4. Worker Process
worker_processes menentukan jumlah worker process yang menangani event.
Contoh umum:
worker_processes auto;
Mental model:
| Setting | Makna |
|---|---|
1 | Satu worker; cukup untuk local/dev atau traffic sangat kecil |
| fixed number | Manual control; berguna jika CPU allocation jelas |
auto | NGINX memilih berdasarkan CPU yang tersedia |
Dalam container, hati-hati.
Jika runtime/container limit tidak terefleksi dengan benar ke proses, auto bisa tidak selalu sesuai ekspektasi platform. Dalam Kubernetes modern, CPU limit biasanya terlihat melalui cgroup, tetapi tetap perlu diverifikasi di runtime aktual.
Prinsip production:
worker_processes harus selaras dengan CPU allocation aktual, bukan CPU fisik node secara membabi buta.
Java/JAX-RS Impact
Jika NGINX memiliki worker capacity tinggi tetapi Java service punya thread pool kecil, maka bottleneck pindah ke backend.
Contoh failure:
NGINX menerima banyak connection
NGINX meneruskan ke upstream
Java worker thread habis
response melambat
NGINX melihat upstream timeout
client melihat 504
NGINX tuning harus dikaitkan dengan:
Java request thread pool
HTTP server connector pool
DB connection pool
external service timeout
GC pause behavior
5. Worker Connections
worker_connections adalah jumlah connection yang dapat ditangani oleh tiap worker.
Contoh:
events {
worker_connections 8192;
}
Tetapi satu proxied request bisa memakai lebih dari satu connection:
client connection ke NGINX
upstream connection dari NGINX ke backend
Jadi 10.000 active client connections tidak selalu berarti hanya 10.000 file descriptors. Jika banyak request sedang diproxy ke upstream, bisa menjadi mendekati:
client socket + upstream socket + log/temp file descriptor
Rule of thumb:
capacity harus dihitung berdasarkan total socket, bukan hanya jumlah client.
Common Mistake
Menaikkan worker_connections tanpa menaikkan file descriptor limit.
Akibatnya:
worker_connections terlihat besar
ulimit tetap kecil
NGINX gagal membuka socket baru
error log menunjukkan too many open files
client melihat 502/503/connection reset
6. Event Loop, epoll, and kqueue
NGINX menggunakan event-driven architecture. Di Linux, mekanisme utamanya biasanya epoll; di BSD/macOS biasanya kqueue.
Mental model:
worker tidak membuat satu thread per request
worker memonitor banyak socket melalui event loop
saat socket siap baca/tulis, worker memproses event tersebut
Ini berbeda dari model blocking thread-per-request.
Dampaknya:
| Area | Dampak |
|---|---|
| Banyak idle keepalive connection | NGINX dapat menahannya relatif efisien |
| Slow client | Bisa tetap berdampak jika buffer/network penuh |
| Blocking operation dalam module | Dapat mengganggu worker |
| Disk temp file I/O | Bisa menjadi bottleneck jika banyak buffering besar |
NGINX cepat bukan karena setiap request mendapat thread sendiri, tetapi karena ia menghindari blocking yang tidak perlu.
7. File Descriptor Limit
Setiap socket dan file membutuhkan file descriptor.
Periksa limit:
ulimit -n
cat /proc/$(pidof nginx | awk '{print $1}')/limits
Dalam Kubernetes:
kubectl exec -n <namespace> <nginx-pod> -- sh -c 'ulimit -n'
Failure signal:
too many open files
socket() failed
accept4() failed
connect() failed
upstream temporarily disabled
Prinsip:
worker_connections tinggi tanpa file descriptor limit cukup adalah konfigurasi palsu.
Internal verification:
Cek ulimit container runtime.
Cek securityContext dan runtimeClass jika memengaruhi limit.
Cek node-level systemd/container runtime limit.
Cek apakah NGINX berjalan sebagai ingress controller managed chart.
8. Connection Backlog and Accept Pressure
Saat traffic burst, connection baru masuk ke queue sebelum diterima oleh NGINX.
Layer yang terlibat:
client
cloud load balancer
node network stack
kernel listen backlog
NGINX accept loop
worker capacity
Jika backlog penuh, gejala bisa berupa:
connection timeout
connection refused
SYN retransmission
load balancer target marked unhealthy
sporadic 502/503 upstream
Directive dan kernel tuning terkait biasanya bukan area aplikasi murni. Di Kubernetes managed environment, sebagian besar dikendalikan oleh node OS, container runtime, dan cloud LB.
Internal verification checklist:
Cek apakah issue terjadi saat traffic spike.
Cek LB target health.
Cek node-level network metrics.
Cek NGINX active/accepted/handled connection metrics.
Cek SYN backlog/drop metrics jika tersedia.
9. Keepalive: Client Side
Client keepalive memungkinkan satu TCP connection dipakai untuk banyak request.
Contoh:
keepalive_timeout 65s;
keepalive_requests 1000;
Trade-off:
| Setting | Benefit | Risk |
|---|---|---|
| keepalive lama | Mengurangi TCP/TLS handshake | Banyak idle connection menahan slot |
| keepalive pendek | Membebaskan connection lebih cepat | Lebih banyak handshake dan latency |
| keepalive_requests besar | Reuse lebih banyak | Connection lama bisa bertahan terlalu panjang |
Untuk API backend, keepalive biasanya baik, tetapi harus diselaraskan dengan:
cloud load balancer idle timeout
client SDK behavior
HTTP/2 behavior
long-lived connection type
worker_connections
Failure umum:
LB idle timeout lebih pendek daripada NGINX/client expectation
client reuse connection yang sudah ditutup LB
sporadic connection reset
10. Upstream Keepalive
Upstream keepalive adalah connection reuse dari NGINX ke backend.
Contoh:
upstream jaxrs_api {
server app-1:8080;
server app-2:8080;
keepalive 64;
}
server {
location /api/ {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://jaxrs_api;
}
}
Tanpa upstream keepalive, NGINX bisa membuat koneksi baru ke backend untuk banyak request. Ini dapat meningkatkan:
TCP handshake
TLS handshake jika upstream HTTPS
backend accept pressure
Java server connector churn
latency tail
Namun upstream keepalive juga punya risiko:
stale connection
connection reset saat backend restart
uneven connection distribution
backend connection pool pressure
Java/JAX-RS Impact
Upstream keepalive yang baik mengurangi beban Java HTTP server connector.
Namun jika Java backend punya limit connection kecil, upstream keepalive yang terlalu besar dari banyak NGINX pod dapat memenuhi connection capacity.
Contoh:
10 NGINX pods × keepalive 128 = 1280 idle upstream connections potential
Jika setiap Java pod hanya siap untuk 200 connection, ini bisa menjadi masalah.
11. HTTP/1.1 vs HTTP/2 Performance
HTTP/1.1:
banyak connection paralel
request per connection mostly sequential
head-of-line blocking di connection level
HTTP/2:
multiplexed streams dalam satu connection
lebih efisien untuk banyak request kecil
butuh perhatian pada stream concurrency
TLS/ALPN biasanya relevan untuk browser/public edge
NGINX bisa menerima HTTP/2 dari client, lalu meneruskan HTTP/1.1 ke upstream Java service.
Traffic shape:
client -> HTTP/2 -> NGINX -> HTTP/1.1 -> Java/JAX-RS
Dampak:
Client melihat multiplexing.
Backend tetap melihat request HTTP/1.1 biasa.
NGINX menjadi translation boundary.
Pertanyaan review:
Apakah HTTP/2 hanya di edge?
Apakah upstream mendukung h2c atau hanya HTTP/1.1?
Apakah gRPC membutuhkan HTTP/2 sampai upstream?
Apakah load balancer mendukung HTTP/2 end-to-end atau hanya client-side?
12. TCP Tuning: sendfile, tcp_nopush, tcp_nodelay
Directive umum:
sendfile on;
tcp_nopush on;
tcp_nodelay on;
Mental model:
| Directive | Fokus |
|---|---|
sendfile | Efisiensi pengiriman file statis dari kernel |
tcp_nopush | Mengoptimalkan packet saat mengirim file/response besar |
tcp_nodelay | Mengurangi latency untuk small interactive response |
Untuk reverse proxy API murni, efeknya berbeda dari static file server. Jangan copy tuning dari static hosting ke API gateway tanpa memahami traffic.
Untuk Java/JAX-RS API:
Latency kecil sering lebih penting daripada throughput file besar.
Streaming/SSE perlu diuji secara khusus.
Binary download besar perlu pengujian berbeda.
13. Buffer Tuning
Buffer memengaruhi memory, disk, latency, dan backpressure.
Directive terkait:
proxy_buffering on;
proxy_buffer_size 16k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
proxy_temp_file_write_size 64k;
Mental model:
response kecil -> buffer memory
response besar -> bisa spill ke temp file
slow client -> NGINX menahan response agar upstream cepat bebas
streaming endpoint -> buffering bisa merusak real-time behavior
Performance trade-off:
| Buffering | Benefit | Risk |
|---|---|---|
| on | Melindungi upstream dari slow client | Memory/disk usage, delayed streaming |
| off | Real-time response lebih langsung | Upstream terpapar slow client |
Jangan mematikan buffering secara global hanya karena satu endpoint SSE. Override per route lebih aman.
14. Compression Trade-Off
Compression mengurangi bandwidth tetapi memakai CPU.
Contoh:
gzip on;
gzip_types application/json text/plain text/css application/javascript;
gzip_comp_level 4;
Trade-off:
lebih tinggi compression level -> bandwidth lebih rendah, CPU lebih tinggi
lebih rendah compression level -> CPU lebih rendah, payload lebih besar
Untuk API JSON, gzip sering berguna, terutama untuk response besar.
Tetapi hindari asumsi:
semua response harus dikompresi
semua level compression tinggi lebih baik
compression tidak berdampak ke latency
Observability yang perlu dicek:
CPU NGINX saat traffic tinggi
response size sebelum/sesudah compression jika tersedia
latency p95/p99
client bandwidth profile
15. TLS Performance: Handshake, Session Reuse, and Certificates
TLS cost muncul di:
handshake CPU
certificate chain validation
key exchange
session resumption
ALPN negotiation
HTTP/2 negotiation
Optimization umum:
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 10m;
Tetapi TLS tuning harus mengikuti security standard organisasi. Jangan menurunkan protokol/cipher hanya demi throughput.
Checklist:
Cek TLS termination layer.
Cek apakah NGINX menerima TLS langsung atau dari cloud LB.
Cek apakah upstream TLS juga aktif.
Cek CPU saat handshake spike.
Cek session reuse metrics jika tersedia.
Cek certificate chain size dan validity.
16. CPU Saturation
CPU NGINX dapat tinggi karena:
TLS handshake
compression
regex location matching berat
WAF/ModSecurity
logging terlalu verbose
large JSON access log
high connection churn
too many worker processes untuk CPU limit kecil
Signal:
CPU throttling container
latency naik tanpa upstream time naik
worker process near 100% CPU
request accepted tapi response lambat
error log tidak selalu jelas
Kubernetes-specific:
CPU limit terlalu rendah dapat menyebabkan throttling.
Throttling sering terlihat sebagai latency tail, bukan error eksplisit.
Review question:
Apakah NGINX CPU-bound atau upstream-bound?
Cara membedakan:
Jika request_time tinggi tetapi upstream_response_time normal, curigai NGINX/client transfer.
Jika upstream_response_time tinggi, curigai backend/upstream.
Jika CPU throttling tinggi, curigai container limit.
17. Memory Usage
Memory NGINX dipakai untuk:
worker process base memory
connection state
request/response buffers
SSL session cache
proxy cache keys/metadata
large headers
temporary buffering metadata
module-specific memory
Memory issue sering muncul saat:
body/header size limit terlalu longgar
banyak concurrent large response
proxy buffering besar
HTTP/2 stream concurrency tinggi
many idle keepalive connections
Kubernetes failure mode:
container OOMKilled
Ingress controller restart
connection reset
sporadic 502/503 saat pod restart
config reload loop jika readiness terganggu
Internal verification:
Cek memory limit.
Cek OOMKilled events.
Cek buffer settings.
Cek traffic payload distribution.
Cek large upload/download endpoint.
18. Disk Temporary File Usage
Saat buffering response besar atau request body besar, NGINX dapat memakai temporary file.
Gejala:
latency naik saat response besar
node disk pressure
container ephemeral storage penuh
error log tentang temp file
pod evicted karena ephemeral-storage
Kubernetes-specific:
emptyDir size limit
ephemeral storage request/limit
node disk pressure
read-only filesystem incompatibility
Jika sistem memiliki upload/download besar, jangan hanya melihat memory dan CPU. Disk temporary path juga bagian dari kapasitas.
Checklist:
Cek proxy_temp_path/client_body_temp_path.
Cek ephemeral storage metrics.
Cek apakah buffering menghasilkan temp files.
Cek limit upload/download.
Cek apakah streaming endpoint harus mematikan buffering.
19. Network Bandwidth and Packet-Level Bottleneck
NGINX bisa sehat tetapi network menjadi bottleneck.
Layer yang perlu dilihat:
client bandwidth
cloud load balancer throughput
node network throughput
pod network overlay
service routing
cross-AZ/cross-zone traffic
upstream backend bandwidth
Signal:
request_time tinggi
upstream_response_time rendah
response body besar
client disconnect 499 meningkat
send_timeout meningkat
network retransmission naik
Interpretasi:
upstream cepat menghasilkan response
NGINX lambat mengirim ke client
masalah bisa di client/network/LB, bukan Java backend
20. Benchmarking: What to Measure
Benchmark yang buruk memberi rasa aman palsu.
Jangan hanya mengukur:
hello world endpoint
single route
no TLS
no compression
no logging
local network
small payload
short duration
Benchmark production-like harus memasukkan:
TLS on/off sesuai deployment
HTTP/1.1 dan HTTP/2 jika relevan
keepalive behavior
realistic payload size
large upload/download
slow client scenario
upstream latency distribution
timeout behavior
header size realistic
log enabled
Kubernetes ingress path
cloud load balancer path
Metrics minimal:
| Metric | Kenapa penting |
|---|---|
| RPS | Throughput umum |
| p50/p95/p99 latency | Tail latency |
| error rate | Correctness under load |
| 499/502/503/504 | Proxy/upstream failure visibility |
| CPU | Saturation |
| memory | Buffer/connection pressure |
| network throughput | Bandwidth limit |
| disk temp usage | Large payload bottleneck |
| upstream response time | Backend bottleneck |
| request time | End-to-end at NGINX |
21. Load Testing Patterns
Pattern 1: Baseline Proxy Test
Tujuan:
Mengukur overhead NGINX terhadap backend sederhana.
Validasi:
NGINX config benar
logging aktif
TLS sesuai
keepalive sesuai
Pattern 2: Backend Saturation Test
Tujuan:
Mengetahui kapan Java/JAX-RS service mulai lambat.
Validasi:
upstream_response_time naik
Java thread pool penuh
DB pool penuh
NGINX 504 meningkat jika timeout terlampaui
Pattern 3: Slow Client Test
Tujuan:
Mengetahui apakah NGINX melindungi upstream dari client lambat.
Validasi:
request_time tinggi
upstream_response_time rendah
buffer/temp file meningkat
499/send_timeout mungkin naik
Pattern 4: Large Payload Test
Tujuan:
Mengetahui efek upload/download besar.
Validasi:
client_max_body_size
proxy_request_buffering
proxy_buffering
ephemeral storage
memory
latency
Pattern 5: Long-Lived Connection Test
Tujuan:
Mengetahui efek WebSocket/SSE/long polling terhadap connection capacity.
Validasi:
active connections
worker_connections
idle timeout
rolling restart behavior
PDB/drain behavior
22. Capacity Planning by Traffic Shape
Tidak semua RPS sama.
| Traffic Shape | Capacity Driver |
|---|---|
| Small JSON API | CPU, upstream latency, keepalive |
| Large JSON response | compression CPU, bandwidth, buffer |
| File upload | body size, temp disk, slow client |
| File download | bandwidth, response buffering, client speed |
| WebSocket | connection count, idle timeout, memory |
| SSE | buffering off, long connection, worker connection |
| gRPC streaming | HTTP/2 stream, timeout, protocol correctness |
| Auth-heavy traffic | auth subrequest latency, auth backend capacity |
| Cacheable static assets | disk/cache, cache key, compression |
Capacity planning harus dimulai dari traffic shape, bukan directive.
23. Kubernetes Capacity Planning
Dalam Kubernetes, kapasitas NGINX dipengaruhi oleh:
replica count
HPA metric
pod resource request/limit
node capacity
pod disruption budget
rolling update maxUnavailable
cloud load balancer target distribution
Service externalTrafficPolicy
cross-zone balancing
readiness probe
liveness probe
ConfigMap reload behavior
Pertanyaan penting:
Apakah NGINX ingress controller HPA berdasarkan CPU, RPS, active connections, atau custom metric?
CPU-only HPA bisa terlambat untuk connection-heavy workload seperti WebSocket.
Untuk ingress controller, scaling signal bisa perlu mempertimbangkan:
active connections
request rate
latency
CPU
memory
network
error rate
24. AWS/Azure/On-Prem Performance Boundary
AWS/EKS
Cek:
ALB/NLB idle timeout
cross-zone load balancing
target group health check interval
security group throughput issue
NLB proxy protocol jika source IP diperlukan
CloudWatch target response time
Azure/AKS
Cek:
Azure Load Balancer/Application Gateway idle timeout
Front Door behavior jika ada
NSG/network path
Azure Monitor metrics
Application Gateway health probe
On-Prem/Hybrid
Cek:
corporate firewall timeout
L4 load balancer connection table
DMZ proxy chain
TLS inspection appliance
internal DNS latency
WAN latency
Performance issue sering terjadi bukan di NGINX, tetapi NGINX menjadi tempat gejalanya terlihat.
25. Common Performance Anti-Patterns
Anti-pattern 1: Copy-Paste Tuning
Mengambil konfigurasi dari blog tanpa traffic model.
Akibat:
buffer terlalu besar
worker_connections tidak selaras dengan ulimit
keepalive terlalu lama
compression terlalu mahal
Anti-pattern 2: Unlimited Body Size
client_max_body_size 0;
Akibat:
large upload dapat menghabiskan disk/memory
backend menerima payload tidak terkendali
DoS risk meningkat
Anti-pattern 3: Global Buffering Off
proxy_buffering off;
Akibat:
slow client langsung menahan upstream
Java thread/connection bisa tertahan lebih lama
throughput backend turun
Anti-pattern 4: Timeout Terlalu Panjang
Timeout panjang bukan solusi latency.
Akibat:
connection tertahan lama
thread backend tertahan lama
incident lebih lambat terlihat
retry storm bisa makin parah
Anti-pattern 5: Observability Dimatikan Saat Load Test
Load test tanpa access log/metrics memberi angka yang tidak sesuai production.
26. Debugging Performance Symptoms
Symptom: p99 latency naik, upstream_response_time normal
Kemungkinan:
slow client
NGINX buffering/transfer
network bandwidth
TLS/compression overhead
CPU throttling di NGINX
Symptom: p99 latency naik, upstream_response_time juga naik
Kemungkinan:
Java service lambat
DB/external dependency lambat
backend thread pool penuh
upstream connection pressure
pod overloaded
Symptom: 499 naik
Kemungkinan:
client timeout lebih pendek dari backend response
mobile/network client disconnect
load balancer timeout mismatch
response terlalu lama dikirim
Symptom: 504 naik
Kemungkinan:
proxy_read_timeout tercapai
backend stuck
upstream network issue
Java request timeout tidak selaras
Symptom: 502 sporadis saat deploy
Kemungkinan:
backend pod restart
readiness belum benar
upstream stale connection
connection draining buruk
rolling update terlalu agresif
27. Performance Review Checklist for PR
Gunakan checklist ini saat mereview perubahan NGINX/Ingress yang menyentuh performance.
[ ] Apakah traffic shape endpoint dipahami?
[ ] Apakah perubahan memengaruhi request size, response size, streaming, atau long-lived connection?
[ ] Apakah timeout selaras dengan cloud LB, NGINX, app, DB, dan client?
[ ] Apakah keepalive client dan upstream masuk akal?
[ ] Apakah worker_connections selaras dengan file descriptor limit?
[ ] Apakah CPU/memory/ephemeral storage cukup?
[ ] Apakah compression level masuk akal?
[ ] Apakah buffering dipakai dengan sengaja?
[ ] Apakah large upload/download diuji?
[ ] Apakah WebSocket/SSE diuji jika relevan?
[ ] Apakah load test memakai path production-like?
[ ] Apakah observability cukup untuk membedakan NGINX vs upstream bottleneck?
[ ] Apakah rollback jelas?
28. Internal Verification Checklist
Untuk konteks enterprise seperti CSG/team internal, jangan mengasumsikan detail arsitektur. Verifikasi:
[ ] Apakah NGINX yang digunakan adalah standalone, ingress-nginx, NGINX Inc controller, atau NGINX Plus?
[ ] Berapa replica ingress controller di setiap environment?
[ ] Apa resource request/limit container NGINX?
[ ] Apakah HPA aktif? Berdasarkan metric apa?
[ ] Berapa worker_processes dan worker_connections aktual?
[ ] Berapa file descriptor limit di pod/container?
[ ] Apakah upstream keepalive aktif?
[ ] Berapa cloud load balancer idle timeout?
[ ] Berapa timeout NGINX/Ingress annotation global dan per-route?
[ ] Apakah ada endpoint upload/download besar?
[ ] Apakah ada WebSocket/SSE/long polling/gRPC streaming?
[ ] Apakah gzip/brotli aktif?
[ ] Apakah proxy buffering aktif secara global?
[ ] Apakah temp file path punya storage cukup?
[ ] Apakah access log menyimpan request_time dan upstream_response_time?
[ ] Apakah dashboard membedakan CPU, memory, connection, RPS, 499, 502, 503, 504?
[ ] Apakah ada load test atau capacity test historis?
[ ] Apakah ada incident notes terkait ingress overload, timeout, atau 502/504?
29. Production Heuristics
Beberapa heuristik yang aman sebagai starting point:
Tuning harus dimulai dari measurement, bukan asumsi.
Jangan menaikkan limit tanpa memahami blast radius.
Jangan mematikan buffering secara global untuk menyelesaikan satu endpoint streaming.
Jangan membuat timeout NGINX lebih panjang tanpa memahami timeout client dan backend.
Jangan mengandalkan CPU-only autoscaling untuk connection-heavy workload.
Jangan menganggap 504 selalu salah Java service.
Jangan menganggap 499 selalu salah client.
Jangan mengoptimalkan gzip sebelum melihat CPU dan bandwidth.
Jangan mengubah ingress controller setting global untuk kebutuhan satu service tanpa governance.
30. Ringkasan
Performance NGINX bukan sekadar directive tuning. Ini adalah capacity engineering untuk traffic layer.
Yang harus selalu dipetakan:
connection capacity
file descriptor limit
CPU limit
memory limit
ephemeral storage
keepalive behavior
upstream capacity
cloud load balancer behavior
Kubernetes scaling behavior
Java/JAX-RS backend capacity
observability signal
NGINX yang sehat harus bisa menjawab:
berapa banyak traffic masuk
berapa banyak connection aktif
berapa lama request diproses
berapa lama upstream merespons
berapa banyak error di edge
berapa banyak error dari upstream
resource mana yang mulai jenuh
Senior engineer tidak hanya bertanya:
setting apa yang harus dinaikkan?
Tetapi:
bottleneck sebenarnya di mana?
limit mana yang disengaja?
limit mana yang tidak terlihat?
kalau limit dinaikkan, layer mana yang akan gagal berikutnya?
You just completed lesson 21 in deepen practice. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.
Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.