Belajar CodeIgniter - Scaling & Optimisasi
Episode 24 of 27

Belajar CodeIgniter - Scaling & Optimisasi

Mengoptimalkan aplikasi untuk skala lebih besar: mengaktifkan Opcache, menyempurnakan strategi cache, indexing database, session Redis untuk multi-server, dan membuktikan hasil dengan load testing.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Aplikasi kalian sudah produksi: HTTPS, Docker, CI/CD, cache, log. Sekarang pertanyaannya: bagaimana kalau traffic naik 10x? Apakah satu server cukup, atau perlu dua? Bagaimana mengukur semuanya?

Di episode 24 ini kita membahas scaling & optimisasi — dari tuning sederhana di satu server (Opcache, PHP-FPM, indexing) hingga horizontal scaling dengan session Redis. Dan karena optimisasi tanpa pengukuran hanyalah perasaan, kita tutup dengan load testing yang membuktikan hasilnya.

Opcache: Optimisasi Termurah

Opcache menyimpan bytecode PHP terkompilasi di memori — tidak perlu menerjemahkan file PHP setiap request. Ini satu-satunya optimisasi dengan pengembalian terbesar untuk usaha terkecil:

/etc/php/8.4/cli/conf.d/opcache.ini (contoh)
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 10000
opcache.validate_timestamps = 0

validate_timestamps = 0 berarti Opcache tidak mengecek perubahan file setiap request — cepat, tapi jangan aktifkan di development (file yang diedit tidak ter-reload sampai cache dibersihkan atau PHP-FPM di-restart). Verifikasi:

Cek status Opcache
php -i | grep opcache.enable
php spark env | grep OPcache   # atau lewat halaman info

Warning

opcache.validate_timestamps = 0 hanya untuk produksi. Di development, matikan atau set 1 agar setiap edit langsung terlihat. Salah setting di development membuat kalian bertanya "kenapa kode saya tidak berubah?" padahal Opcache menyimpan versi lama.

Strategi Cache yang Matang

Di episode 14 kita punya cache-aside + invalidation. Di produksi, rapikan jadi strategi menyeluruh:

LayerIsiDriver
Page cacheHalaman publik (cachePage())File/Redis
Data cacheHasil query berat (list, laporan)Redis
SessionLogin state semua userRedis
.env produksi
cache.default.handler = redis
cache.redis.host = 127.0.0.1
cache.redis.port = 6379
session.driver = RedisHandler
session.savePath = 'tcp://127.0.0.1:6379'

Mengapa Redis untuk keduanya? Karena state dibagikan antar server — ketika nanti ada 2+ instance aplikasi, session dan cache yang disimpan di file lokal akan tidak konsisten (login di server A tidak dikenali server B). Redis adalah single source of truth untuk semua instance.

Indexing Database

Index mempercepat query yang memfilter atau mengurutkan kolom. Tambahkan lewat migration (bukan manual):

Migration: tambah index
public function up()
{
    $this->forge->addKey('slug');          // WHERE slug = ...
    $this->forge->addKey('category_id');   // WHERE category_id = ...
    $this->forge->addKey(['status', 'created_at']); // composite: filter + sort
    $this->forge->processIndexes('posts');
}

Aturan praktis indexing:

  • Index kolom yang sering ada di WHERE/JOIN/ORDER BY.
  • Jangan index semua kolom — setiap index memperlambat write dan memakan disk.
  • Composite index untuk kombinasi filter yang umum.
  • Ukur dulu dengan EXPLAIN sebelum menambah index.
Periksa query dengan EXPLAIN
php spark db:query "EXPLAIN SELECT * FROM posts WHERE status='published' ORDER BY created_at DESC"

EXPLAIN menunjukkan apakah query memakai index (possible_keys/key) atau melakukan full table scan (type: ALL). Ini bukti, bukan tebakan.

Tuning PHP-FPM

PHP-FPM mengelola proses PHP. Konfigurasi pool di /etc/php/8.4/fpm/pool.d/www.conf:

Pool PHP-FPM (contoh tuning)
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 8
pm.max_requests = 500
  • pm.max_children = maksimum proses bersamaan; patokan umum: RAM server / RAM per request.
  • pm.max_requests = 500 — proses di-restart setelah 500 request, mencegah kebocoran memori.

Jangan menaikkan max_children membabi buta — setiap proses makan memori. Hitung: server 2 GB dengan rata-rata request 50 MB → sekitar 30-40 max_children adalah batas aman.

Load Testing

Setelah tuning, buktikan dengan load test. Dua tool umum:

Load test dengan ab (ApacheBench)
ab -n 1000 -c 50 http://localhost/
Load test dengan hey
hey -n 1000 -c 50 http://localhost/

-n 1000 = total 1000 request, -c 50 = 50 concurrent. Metrik yang diperhatikan:

MetrikArtiTarget wajar
Requests per secondThroughputNaik setelah optimisasi
Time per request (mean)Latensi rata-rataStabil di peningkatan traffic
Failed requestsHarus 00
Percentage served withinLatensi p95/p99Sekitar 2-5x latensi rata-rata

Tip

Bandingkan sebelum dan sesudah setiap optimisasi: matikan cache → ukur, aktifkan cache → ukur, matikan Opcache → ukur. Angka yang berubah menunjukkan apa yang benar-benar berpengaruh — dan mencegah optimisasi yang hanya terasa di kepala.

Horizontal Scaling

Saat satu server tidak cukup (atau ingin high availability), tambah instance aplikasi. Kunci horizontal scaling:

100%

Prasyarat untuk multi-server:

  1. Session di Redis — login dikenali semua server.
  2. Cache di Redis — cache konsisten, bukan file lokal.
  3. writable/ di storage bersama (atau pindahkan upload ke S3/object storage).
  4. Load balancer membagi traffic (Nginx, HAProxy, atau cloud LB).

Tanpa poin 1-3, menambah server justru menimbulkan bug sesi acak — user login di server A tapi server B tidak mengenalinya.

Ringkasan Scaling & Optimisasi

  • Opcache: bytecode cache, validate_timestamps = 0 hanya di produksi.
  • Cache strategy: page/data cache di Redis, session di Redis.
  • Indexing: index kolom yang difilter/di-sort; buktikan dengan EXPLAIN.
  • PHP-FPM: pm.max_children dihitung dari RAM, pm.max_requests mencegah leak.
  • Load test: ab/hey, bandingkan sebelum-sesudah, fokus pada p95 & failed requests.
  • Horizontal scaling: session+cache Redis, storage bersama, load balancer.

Penutup

Inti yang harus dibawa pulang:

  • Opcache adalah optimisasi termurah — aktifkan di produksi.
  • Redis untuk session & cache = kunci horizontal scaling.
  • Index tanpa EXPLAIN hanyalah tebakan.
  • Selalu ukur sebelum-sesudah; optimisasi yang tidak terukur bukan optimisasi.
  • Multi-server butuh state terpusat (Redis) — bukan file lokal.

Di episode 25 selanjutnya kita akan membahas ekosistem & tren modern 2026 — fitur CodeIgniter 4.7.x, Shield dan Queue, perbandingan dengan Laravel dan Symfony, serta arah PHP 8.4/8.5 dan modernisasi dari CI3. Pilihan framework yang tepat untuk kebutuhan yang tepat!

Belajar CodeIgniter - Scaling & Optimisasi | Belajar CodeIgniter