Nginx vs Apache #
Ketika kita memilih web server, dua nama ini selalu muncul: Nginx dan Apache. Pertanyaan “mana yang lebih baik?” tidak memiliki jawaban tunggal — karena keduanya memiliki kekuatan di skenario yang berbeda. Yang lebih berguna adalah memahami mengapa keduanya berbeda secara fundamental, lalu memilih berdasarkan kebutuhan spesifik proyek kita. Artikel ini membangun pemahaman itu dengan perbandingan yang jujur.
Perbedaan Arsitektur: Akar dari Segalanya #
Hampir semua perbedaan performa dan perilaku antara Nginx dan Apache bisa ditelusuri ke satu keputusan desain mendasar: bagaimana mereka menangani koneksi bersamaan.
Apache: Process-Based (dan Thread-Based) #
Apache menggunakan Multi-Processing Module (MPM) untuk mengelola koneksi. Ada beberapa MPM yang bisa dipilih:
flowchart LR
subgraph ApachePrefork ["Apache MPM Prefork (Process-per-Connection)"]
direction TB
R1["Request 1"] --> P1["Process 1 (Blocking)"] --> Resp1["Kirim Respons"]
R2["Request 2"] --> P2["Process 2 (Blocking)"] --> Resp2["Kirim Respons"]
R3["Request 3"] --> P3["Process 3 (Blocking)"] --> Resp3["Kirim Respons"]
RN["Request N"] --> PN["Process N (Blocking)"] --> RespN["Kirim Respons"]
end
style ApachePrefork stroke:#d32f2f,stroke-width:2px- Karakteristik: Setiap koneksi = 1 proses terpisah. Konsumsi RAM per proses berkisar 8–25 MB.
Apache juga menyediakan MPM Worker (menggunakan thread, lebih efisien dari prefork) dan MPM Event (lebih modern, mendekati model Nginx). Namun, bahkan dengan MPM Event, Apache tetap memiliki overhead yang lebih tinggi daripada Nginx untuk skenario beban koneksi yang sangat tinggi.
Nginx: Event-Driven Asinkron #
Nginx menggunakan pendekatan yang secara fundamental berbeda:
flowchart TD
subgraph NginxEvent ["Nginx Event-Driven Model"]
direction TB
M["Master Process"] --> W1["Worker Process 1 (Event Loop)"]
M --> W2["Worker Process 2 (Event Loop)"]
M --> W3["Worker Process 3 (Event Loop)"]
W1 --> C1["Koneksi 1 (Menunggu Disk AIO)"]
W1 --> C2["Koneksi 2 (Mengirim Respons)"]
W1 --> C3["Koneksi 3 (Baru Terhubung)"]
W1 --> C4["Koneksi 4 (Menunggu Backend)"]
end
style NginxEvent stroke:#0288d1,stroke-width:2px
style W1 stroke:#388e3c,stroke-width:1.5px
style W2 stroke:#388e3c,stroke-width:1.5px
style W3 stroke:#388e3c,stroke-width:1.5px- Karakteristik: Jumlah worker biasanya disesuaikan dengan jumlah core CPU. Setiap worker dapat menangani ribuan koneksi secara asinkron dan non-blocking.
Kunci dari model ini adalah non-blocking I/O dan event loop. Ketika Nginx menunggu respons dari disk atau dari backend, ia tidak memblok proses tersebut — ia mendaftarkan event “kabari aku kalau sudah selesai” dan melanjutkan menangani koneksi lain. Ketika datanya siap, event loop akan langsung menanganinya.
| Jumlah Koneksi Simultan | Apache (Prefork) | Apache (Worker MPM) | Nginx |
|---|---|---|---|
| 1.000 Koneksi | ~8.000 MB (8 GB RAM) | ~1.000 MB (1 GB RAM) | ~12 MB RAM (Total) |
[!TIP] Dalam menangani 1.000 koneksi simultan, Nginx menggunakan memori hingga 650 kali lebih sedikit dibandingkan Apache Prefork.
Perbandingan Performa: Benchmark dan Realita #
Benchmark web server sering diperdebatkan karena hasilnya sangat bergantung pada kondisi pengujian. Tapi beberapa pola konsisten muncul di berbagai pengujian selama bertahun-tahun:
Melayani File Statis #
| Web Server | Kecepatan Relatif | Keunggulan Utama |
|---|---|---|
| Nginx | 100% (Baseline) | Menggunakan system call sendfile() (zero-copy), tanpa overhead proses/thread |
| Apache | ~60% - 70% | Memiliki overhead alokasi thread/proses, throughput di bawah Nginx |
Untuk melayani file HTML, CSS, JS, gambar — Nginx secara konsisten lebih cepat dan lebih efisien daripada Apache. Ini adalah use case yang paling umum dan paling sering di-benchmark.
Koneksi Bersamaan Tinggi #
| Jumlah Koneksi Simultan | Nginx | Apache |
|---|---|---|
| 10 Koneksi | Sangat Stabil | Sangat Stabil |
| 1.000 Koneksi | Stabil, Throughput Tinggi | Mulai Mengalami Latensi Tinggi |
| 10.000 Koneksi | Tetap Berjalan Stabil | Mengalami Penurunan Drastis / Crash (OOM) |
Konten Dinamis (PHP, Python, dll.) #
Ini area yang lebih seimbang. Untuk konten dinamis, kedua server harus berkomunikasi dengan backend eksternal (PHP-FPM, Python WSGI, dll.). Bottleneck biasanya ada di backend, bukan di web server itu sendiri.
flowchart LR
subgraph Dinamis ["Alur Konten Dinamis"]
direction LR
K["Klien"] --> WS["Web Server (Nginx / Apache)"]
WS -->|"FastCGI / WSGI Proxy"| BE["Backend Engine (PHP-FPM/Go)"]
BE -->|"Bottleneck Komputasi / DB Query"| DB[("Database")]
endDalam skenario ini, perbedaan performa antara Nginx dan Apache lebih kecil karena bottleneck ada di eksekusi kode backend, bukan di web server.
Konfigurasi: Pendekatan yang Berbeda #
Salah satu perbedaan yang paling terasa dalam penggunaan sehari-hari adalah cara keduanya dikonfigurasi.
Apache: .htaccess dan Per-Directory Config #
Apache mendukung file konfigurasi .htaccess yang bisa ditempatkan di direktori manapun. Ini memungkinkan konfigurasi per-direktori tanpa perlu akses ke file konfigurasi utama server.
# File: /var/www/html/app/.htaccess
# (Apache membaca ini setiap ada request ke direktori ini)
RewriteEngine On
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# Password protect direktori tertentu
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
- Kelebihan
.htaccess: Pengguna shared hosting bisa mengkonfigurasi web server untuk direktori mereka tanpa akses root. - Kekurangan
.htaccess: Setiap request, Apache harus memeriksa.htaccessdi setiap direktori dari root hingga direktori yang diminta. Ini bisa berpengaruh signifikan pada performa, terutama di server dengan susunan folder yang dalam.
flowchart TD
Request["Request: GET /blog/2024/jan/post.html"] --> A["1. Cek /var/www/html/.htaccess"]
A --> B["2. Cek /var/www/html/blog/.htaccess"]
B --> C["3. Cek /var/www/html/blog/2024/.htaccess"]
C --> D["4. Cek /var/www/html/blog/2024/jan/.htaccess"]
D --> Send["5. Proses & Kirim Respons"]
style Request stroke:#0288d1,stroke-width:2px
style Send stroke:#43a047,stroke-width:2pxProses pengecekan berulang ini dapat memicu 4 kali operasi baca disk tambahan (disk read) hanya untuk satu request tunggal. Di sistem dengan jutaan request per hari, overhead I/O disk ini sangat menurunkan performa (bottleneck). Hal ini terjadi karena kernel Linux harus melakukan inode lookup pada setiap level direktori dari root document path hingga subdirektori terdalam. Operasi ini memicu pemanggilan sistem tingkat rendah (system calls) seperti stat() berulang kali yang menghabiskan siklus CPU dan menghambat antrean request baru di web server. Hal inilah yang mendasari keputusan arsitektur Nginx untuk meniadakan dukungan .htaccess demi mempertahankan performa I/O yang optimal di level sistem operasi.
Nginx: Konfigurasi Terpusat #
Nginx tidak mendukung .htaccess. Semua konfigurasi harus ada di file konfigurasi utama (atau file yang di-include dari sana). Ini adalah keputusan desain yang disengaja.
# /etc/nginx/sites-available/myapp.conf
server {
listen 80;
server_name example.com;
root /var/www/html;
# Ini yang setara dengan .htaccess untuk URL rewriting
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
include fastcgi_params;
}
}
| Fitur Konfigurasi | Apache | Nginx |
|---|---|---|
Mendukung .htaccess | ✓ | ✗ |
| Konfigurasi Per-Direktori | ✓ (Dinamis) | ✗ (Harus via Global Server Block) |
| Pemuatan Konfigurasi | Parsial di setiap request | Terpusat sekali saat reload |
| Dampak Performa I/O | Lebih Tinggi (Disk overhead) | Sangat Rendah |
| Audit Keamanan | Sulit (Tersebar di subfolder) | Mudah (Terpusat di /etc/nginx/) |
Modul: Cara Ekstensi yang Berbeda #
Cara keduanya di-extend juga mencerminkan filosofi yang berbeda.
Apache: Modul Dinamis yang Mudah #
Apache memiliki sistem modul yang sangat fleksibel. Kita bisa mengaktifkan dan menonaktifkan modul tanpa kompilasi ulang:
# Apache: aktifkan/nonaktifkan modul sangat mudah
sudo a2enmod rewrite # aktifkan mod_rewrite
sudo a2enmod ssl # aktifkan mod_ssl
sudo a2enmod headers # aktifkan mod_headers
sudo a2dismod status # nonaktifkan mod_status
sudo systemctl reload apache2
Modul-modul ini berjalan di dalam proses Apache itu sendiri (in-process modules).
Nginx: Modul Statis (dengan Pengecualian) #
Secara tradisional, Nginx membutuhkan kompilasi ulang untuk menambah modul. Ini berubah dengan diperkenalkannya dynamic modules di Nginx 1.9.11 (2016):
# Nginx: lihat modul yang sudah dikompilasi
nginx -V 2>&1 | tr -- - '\n' | grep module
# Di-load secara dinamis dalam file utama:
# /etc/nginx/nginx.conf
load_module modules/ngx_http_geoip_module.so;
load_module modules/ngx_stream_module.so;
| Karakteristik Modul | Apache | Nginx |
|---|---|---|
| Instalasi Modul | Sangat Mudah (a2enmod) | Lebih Rumit (Sering butuh kompilasi ulang) |
| Isolasi Proses | ✗ Modul crash bisa merusak server | ✓ Modul dinamis terisolasi secara stabil |
| Footprint Memori | Lebih Besar (Banyak modul ter-load) | Sangat Ringkas (Hanya memuat yang dibutuhkan) |
| Ekosistem Pihak Ketiga | Sangat Besar & Matang | Lebih Kecil, fokus pada modul inti |
Penanganan Konten Dinamis: .htaccess vs Proxy #
Ini salah satu area di mana developer sering bingung tentang perbedaan pendekatan.
Apache + mod_php: PHP In-Process #
flowchart LR
K1["Klien"] --> Ap["Apache Server Process"]
subgraph ApProcess ["Proses Apache"]
mod["mod_php Module"] --> exec["Eksekusi PHP & Return HTML"]
end
exec --> K1
style Ap stroke:#d32f2f,stroke-width:2px- Kelebihan: Setup sederhana, langsung bekerja tanpa konfigurasi FastCGI.
- Kekurangan: Jika eksekusi PHP mengalami crash, proses Apache tersebut ikut mati. Memori yang digunakan per koneksi menjadi besar karena thread Apache membawa overhead library PHP.
Nginx + PHP-FPM: PHP Out-of-Process #
flowchart LR
K2["Klien"] --> NGX["Nginx Server (Port 80/443)"]
NGX -->|"FastCGI Protokol"| FPM["PHP-FPM Process (Terpisah)"]
FPM -->|"Return Data"| NGX
NGX --> K2
style NGX stroke:#0288d1,stroke-width:2.5px
style FPM stroke:#388e3c,stroke-width:2px- Kelebihan: PHP-FPM berjalan secara terpisah, kegagalan proses PHP tidak mengganggu kestabilan engine Nginx utama. Skalabilitas pool worker proses PHP dapat dikonfigurasi secara mandiri.
Nginx mendorong model out-of-process untuk semua konten dinamis — PHP-FPM untuk PHP, Gunicorn/uWSGI untuk Python, Passenger untuk Ruby, dan sebagainya. Ini dianggap arsitektur yang lebih sehat karena memisahkan tanggung jawab penanganan koneksi dengan pengeksekusian kode.
Manajemen Pool Proses PHP-FPM: Static vs Dynamic vs Ondemand #
Ketika kita memasangkan Nginx dengan PHP-FPM, kita harus memilih strategi manajemen proses worker untuk mengoptimalkan penggunaan RAM server kita. Ada tiga mode utama yang bisa kita konfigurasikan di berkas konfigurasi pool PHP-FPM (biasanya di /etc/php/X.Y/fpm/pool.d/www.conf):
- Static: Jumlah proses worker PHP selalu tetap (misalnya,
pm.max_children = 50). Mode ini memberikan performa terbaik dan latensi terendah karena tidak ada overhead pembuatan/penghancuran proses secara dinamis ketika ada request baru masuk. Namun, ia memakan memori RAM secara konstan, bahkan saat server dalam kondisi tidak menerima trafik (idle). - Dynamic: Jumlah proses worker berfluktuasi secara dinamis berdasarkan beban request (ditentukan oleh kombinasi parameter
pm.start_servers,pm.min_spare_servers, danpm.max_spare_servers). Mode ini adalah jalan tengah yang baik antara efisiensi memori dan kesiapan menangani lonjakan beban trafik secara instan. - Ondemand: Proses worker PHP hanya dibuat saat request baru masuk dan langsung dihancurkan setelah periode idle tertentu (ditentukan oleh
pm.process_idle_timeout). Ini adalah pilihan paling hemat memori RAM, sangat cocok untuk server pengembangan (development environment) atau server web yang menghosting banyak situs web bertrafik rendah (setup multi-tenant shared hosting berbasis VPS). Namun, ia memiliki konsekuensi adanya latensi cold start untuk request pertama yang membangunkan worker proses yang tertidur.
Dengan memisahkan web server (Nginx) dari application server (PHP-FPM), kita bisa menerapkan optimasi yang berbeda pada masing-masing layer. Nginx dapat dikonfigurasi untuk menyaring dan menolak request yang tidak valid sebelum menyentuh PHP-FPM, melakukan pembatasan laju trafik (rate limiting), atau menyajikan cache halaman dinamis yang sudah jadi (FastCGI Cache) langsung dari memori tanpa membebani PHP-FPM sama sekali.
Shared Hosting vs Dedicated Hosting #
| Karakteristik Lingkungan | Apache | Nginx |
|---|---|---|
| Shared Hosting | Sangat Cocok: Pengguna dapat mengonfigurasi direktori web via .htaccess tanpa perlu akses root, terintegrasi baik dengan cPanel. | Kurang Cocok: Perubahan konfigurasi membutuhkan reload engine utama secara global yang memicu perlunya hak akses root. |
| Dedicated/VPS/Cloud | Bisa: Namun cenderung memakan resource RAM server secara boros seiring peningkatan trafik. | Sangat Cocok: Memberikan efisiensi memori maksimal, kontrol konfigurasi terpusat di sisi DevOps, dan performa tinggi. |
Decision Tree: Mana yang Harus Dipilih? #
flowchart TD
Start{"Pilih Web Server"} --> Q1{"Apakah Anda berjalan di Shared Hosting?"}
Q1 -->|"Ya"| Apache["Gunakan Apache HTTP Server"]
Q1 -->|"Tidak"| Q2{"Apakah aplikasi Anda membutuhkan .htaccess dinamis?"}
Q2 -->|"Ya"| Apache
Q2 -->|"Tidak"| Q3{"Apakah trafik Anda sangat tinggi atau RAM terbatas?"}
Q3 -->|"Ya"| Nginx["Gunakan Nginx Open Source"]
Q3 -->|"Tidak"| Recommend["Gunakan Nginx (Rekomendasi Standar Industri Modern)"]
style Nginx stroke:#0288d1,stroke-width:3px
style Apache stroke:#d32f2f,stroke-width:2pxMigrasi dari Apache ke Nginx #
Jika kita sudah menggunakan Apache dan ingin beralih ke Nginx, ada beberapa hal penting yang perlu kita perhatikan:
Menerjemahkan .htaccess ke Nginx Configuration
#
Ini adalah tantangan terbesar dalam proses migrasi. Setiap aturan .htaccess harus didefinisikan ulang secara terpusat di server block Nginx.
- WordPress URL Rewrite:
- Apache
.htaccess:RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] - Nginx Equivalent:
location / { try_files $uri $uri/ /index.php?$args; }
- Apache
- Redirect HTTP ke HTTPS:
- Apache
.htaccess:RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] - Nginx Equivalent:
server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri; }
- Apache
Penggunaan Bersamaan: Nginx sebagai Front-End Apache #
Salah satu topologi arsitektur yang cukup populer (terutama pada server transisi yang ingin mempertahankan legacy system) adalah menggabungkan keduanya:
flowchart TD
Trafik["Trafik Masuk (Port 80 / 443)"] --> NGX["Nginx (Front-End)"]
NGX -->|"1. Melayani Langsung"| Static["Aset Statis (CSS, JS, PNG)"]
NGX -->|"2. Meneruskan Request (Port 8080)"| APA["Apache (Back-End)"]
APA -->|"Memproses Konten Dinamis"| Dynamic["Aplikasi PHP + .htaccess"]
style NGX stroke:#0288d1,stroke-width:2.5px
style APA stroke:#d32f2f,stroke-width:2pxKonfigurasi ini memberikan kita performa Nginx yang optimal untuk pengiriman berkas statis dan enkripsi SSL, sambil tetap mempertahankan dukungan .htaccess di tingkat backend Apache.
SSL Performance: Apache vs Nginx #
Untuk penanganan HTTPS, baik Nginx maupun Apache modern menggunakan library kriptografi yang sama (seperti OpenSSL). Perbedaan performa jabat tangan (handshake) awal sangatlah kecil. Namun, Nginx memiliki mekanisme pengelolaan cache session yang sangat efisien:
# Konfigurasi optimal session resumption di Nginx
ssl_session_cache shared:SSL:10m; # 10MB shared cache antar worker process
ssl_session_timeout 1d; # Session valid selama 1 hari
ssl_session_tickets off; # Nonaktifkan tiket session demi PFS (Perfect Forward Secrecy)
Dengan mengaktifkan session resumption, klien yang kembali mengakses server kita tidak perlu melakukan jabat tangan TLS penuh (full handshake), sehingga mempercepat waktu muat halaman secara signifikan.
Detail Teknis Penanganan Protokol Modern: HTTP/2 dan HTTP/3 (QUIC) #
Selain penanganan koneksi biasa, kita juga perlu meninjau bagaimana kedua web server ini mengadopsi protokol internet modern. HTTP/2 memperkenalkan fitur multiplexing di mana beberapa request dan respons dapat dikirimkan secara bersamaan melalui satu koneksi TCP tunggal. Di sini, arsitektur event-driven Nginx bersinar karena ia dapat mengelola ribuan aliran stream HTTP/2 aktif di dalam satu event loop tanpa perlu mengalokasikan thread baru untuk setiap stream yang berpotensi membebani memori RAM.
Sedangkan HTTP/3 yang berjalan di atas protokol transport UDP (menggunakan QUIC), tantangannya bergeser dari pengelolaan soket TCP ke pemrosesan paket UDP berkecepatan tinggi di ruang pengguna (user space). Nginx (mulai versi 1.25.0) mendukung HTTP/3 secara native. Karena UDP tidak memiliki konsep koneksi di level kernel Linux, beban pemrosesan paket jatuh sepenuhnya pada aplikasi web server. Event loop asinkron Nginx mampu menangani event UDP epoll dengan overhead minimal melalui teknik penggabungan paket (packet batching) menggunakan modul bawaan. Sebaliknya, pendekatan berbasis thread milik Apache membutuhkan sinkronisasi mutex yang lebih intensif antar-thread untuk merakit kembali aliran data QUIC dari paket-paket UDP yang acak, sehingga menghasilkan penggunaan CPU yang jauh lebih tinggi saat menangani trafik enkripsi HTTPS berbasis HTTP/3 pada skala besar.
Kesimpulan: Konteks yang Menentukan #
Kita Memilih Nginx Jika: #
- Melakukan deployment baru di cloud server (AWS, GCP, DigitalOcean, dsb.) atau VPS mandiri.
- Mengantisipasi lonjakan trafik yang tinggi dengan konsumsi memori minimal.
- Kita memegang kontrol penuh atas konfigurasi server root.
- Infrastruktur berbasis microservices, Docker, atau cluster Kubernetes.
- Membutuhkan reverse proxy, API gateway, atau SSL termination terpusat yang efisien.
Kita Memilih Apache Jika: #
- Berada di lingkungan shared hosting terkelola (menggunakan cPanel / Plesk).
- Menggunakan CMS lama yang konfigurasinya sangat bergantung pada file
.htaccess. - Tim pengembang kita sudah sangat terbiasa dengan Apache dan tidak memiliki alokasi waktu untuk masa transisi pembelajaran.
| Dimensi Perbandingan | Nginx | Apache |
|---|---|---|
| Model Arsitektur | Event-driven asinkron | Process / Thread per koneksi |
| Konsumsi Memori | Sangat rendah (~3 MB per worker) | Lebih tinggi (8–25 MB per proses) |
| Pengiriman Aset Statis | Sangat Cepat (Zero-copy sendfile()) | Cepat |
| Koneksi Simultan Tinggi | Sangat Stabil | Menurun drastis seiring naiknya beban |
| Konten Dinamis | Melalui FastCGI proxy eksternal | Melalui modul in-process (mod_php) |
| Konfigurasi Lokal | ✗ Tidak mendukung .htaccess | ✓ Mendukung file .htaccess lokal |
| Shared Hosting | Kurang Cocok | Sangat Cocok |
| Cloud & Container | Sangat Cocok & Teroptimasi | Bisa, namun kurang efisien |
Ringkasan #
- Perbedaan fundamental: Nginx menggunakan arsitektur event-driven async sedangkan Apache process-per-connection. Ini adalah akar dari seluruh perbedaan performa keduanya.
- Nginx sangat unggul dalam menangani file statis, melayani koneksi bersamaan berskala besar, serta di lingkungan cloud/container modern.
- Apache unggul dalam fleksibilitas konfigurasi lokal via
.htaccessserta kemudahan integrasi di shared hosting.- Nginx tidak mendukung
.htaccesssecara sengaja untuk menghindari disk I/O overhead yang merusak performa.- Topologi hibrida (Nginx front-end + Apache backend) dapat digunakan sebagai solusi jalan tengah untuk mendapatkan keunggulan performa statis sekaligus dukungan
.htaccess.
← Sebelumnya: Sejarah & Evolusi Berikutnya: Arsitektur Event-Driven →