Belajar CodeIgniter - Caching & Performance
Episode 14 of 27

Belajar CodeIgniter - Caching & Performance

Mempercepat aplikasi dengan cache: memilih driver File Redis atau Memcached, menerapkan page cache, dan query caching, lalu membangun cache list API dengan strategi invalidation yang benar agar data tidak basi.

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

Pendahuluan

Semakin besar aplikasi, semakin terasa pertanyaan: kenapa halaman ini lambat? Jawabannya biasanya bukan server lemah, tapi data yang dihitung ulang padahal hasilnya sama. Di episode 14 ini kita memecahkan masalah itu dengan caching — menyimpan hasil yang mahal untuk dipakai ulang.

Mengapa penting? Karena latensi adalah pengalaman pengguna: response 500ms vs 50ms menentukan apakah user kembali atau pindah. Dan lebih jauh lagi, cache mengurangi beban database — aset yang paling mahal di aplikasi web. Di episode ini kalian akan belajar memilih driver, memakai API cache, dan membangun strategi invalidation yang benar.

Memilih Cache Driver

Konfigurasi cache di app/Config/Cache.php:

app/Config/Cache.php
public string $handler = 'file';
public string $backupHandler = 'file';
 
public $file = [
    'storePath' => WRITEPATH . 'cache',
];
 
public $redis = [
    'host'     => '127.0.0.1',
    'password' => null,
    'port'     => 6379,
    'timeout'  => 0,
    'database' => 0,
];
DriverKelebihanCocok untuk
fileTanpa setup, langsung jalanDevelopment, aplikasi single-server
redisCepat, shared antar server, TTL akuratProduksi multi-server, session Redis
memcachedSangat cepat, distribusi sederhanaProduksi dengan Memcached

Note

Untuk development, file sudah cukup. Untuk produksi (episode 23-24), kita akan pindah ke Redis — alasannya: cache dibagikan antar instance aplikasi sehingga semua server membaca data yang sama, dan eviction (pembuangan item) berjalan otomatis.

API Cache Dasar

\Config\Services::cache() mengembalikan instance cache sesuai handler:

Operasi cache dasar
$cache = \Config\Services::cache();
 
// SET - simpan dengan TTL 300 detik
$cache->save('key', $value, 300);
 
// GET - ambil; null jika belum ada / kedaluwarsa
$value = $cache->get('key');
 
// DELETE - hapus satu item
$cache->delete('key');
 
// CLEAN - bersihkan semua
$cache->clean();
 
// HAS - cek keberadaan
$cache->has('key');

Nilai yang disimpan bisa berupa apa pun yang bisa di-serialize PHP: array, objek, atau string. Seluruh API konsisten antar driver — berpindah dari file ke Redis tidak mengubah kode aplikasi.

Pattern: Cache-Aside

Pola paling umum adalah cache-aside: baca cache, jika kosong hitung lalu simpan.

Cache-aside sederhana
$key  = 'posts_list_page_1';
$cache = \Config\Services::cache();
 
$posts = $cache->get($key);
 
if ($posts === null) {
    $posts = $postModel->where('status', 'published')
                       ->orderBy('created_at', 'DESC')
                       ->findAll();
    $cache->save($key, $posts, 300);
}

Request pertama lambat (query database), request berikutnya cepat (baca cache) sampai TTL 300 detik habis.

Warning

Cache-aside menambah satu sumber kebenaran: cache dan database bisa tidak sinkron. TTL adalah "jangkar" yang memastikan data akhirnya terbarui, tapi untuk data yang harus selalu segar, TTL pendek atau invalidation eksplisit adalah jawabannya.

Page Cache (Output Cache)

Untuk halaman penuh yang sama untuk semua user, CodeIgniter bisa cache seluruh output HTML:

Page cache di controller
public function index(): string
{
    $this->cachePage(60);  // cache output 60 menit
 
    $data = [
        'title' => 'Beranda',
        'posts' => $postModel->where('status', 'published')->findAll(),
    ];
 
    return view('home', $data);
}

Request berikutnya tidak menjalankan controller sama sekali — framework langsung menyajikan HTML dari cache. Sangat cocok untuk halaman publik yang jarang berubah. Tapi jangan dipakai untuk halaman personal (dashboard per-user) karena semua user akan melihat halaman user pertama.

Cache List API + Invalidation

Untuk API list, kita gabungkan cache-aside dengan invalidation — menghapus cache saat data berubah:

Cache list API dengan invalidation
public function index(): \CodeIgniter\HTTP\ResponseInterface
{
    $key = 'api_posts_list';
    $cache = \Config\Services::cache();
 
    $posts = $cache->get($key);
    if ($posts === null) {
        $posts = $this->model->where('status', 'published')
                             ->orderBy('created_at', 'DESC')
                             ->findAll();
        $cache->save($key, $posts, 600);
    }
 
    return $this->respond($posts);
}
 
public function create(): \CodeIgniter\HTTP\ResponseInterface
{
    $rules = ['title' => 'required', 'slug' => 'required|is_unique[posts.slug]'];
    if (! $this->validate($rules)) {
        return $this->failValidationErrors($this->validator->getErrors());
    }
 
    $id = $this->model->insert($this->request->getPost());
 
    \Config\Services::cache()->delete('api_posts_list');  // invalidation
 
    return $this->respondCreated(['id' => $id]);
}

Setiap kali post dibuat, diubah, atau dihapus, cache api_posts_list dihapus — request berikutnya menghitung ulang. Hasilnya: data selalu segar, tanpa menunggu TTL, dan query database hanya terjadi saat data berubah.

Tip

Strategi kunci cache yang jelas membantu: api_posts_list, post_detail_{$id}, page_home. Dengan konvensi nama, invalidation jadi mudah — hapus api_posts_list saat list berubah, hapus post_detail_{$id} saat post itu berubah.

Mengukur Efeknya

Jangan asal percaya cache membuat cepat — ukur:

Ukur latensi sebelum dan sesudah
time curl -s http://localhost:8080/api/v1/posts > /dev/null
# pertama (cache cold):  ~180ms
# kedua (cache warm):    ~25ms

Perbedaan nyata terlihat ketika database dan cache terpisah. Di episode 24 kita akan memakai load testing (ab, hey) untuk membandingkan throughput sebelum/sesudah optimisasi — cache adalah salah satu strategi utamanya.

Ringkasan Caching & Performance

  • Driver cache: file untuk dev, redis/memcached untuk produksi.
  • API \Config\Services::cache(): save, get, delete, clean, has.
  • Cache-aside: baca cache, hitung jika kosong, simpan dengan TTL.
  • Page cache (cachePage()) untuk halaman publik yang sama semua user.
  • Invalidation: hapus cache key saat data berubah — data segar tanpa menunggu TTL.

Penutup

Inti yang harus dibawa pulang:

  • Pilih driver sesuai skala: file → redis di produksi.
  • Cache-aside + TTL adalah pola dasar; tambahkan invalidation untuk kesegaran.
  • Jangan cache halaman personal; cache halaman publik dan list API.
  • Konvensi nama key yang jelas membuat invalidation mudah.
  • Selalu ukur latensi untuk membuktikan efek cache.

Di episode 15 selanjutnya kita akan membahas logging & debugging — konfigurasi log, level dan structured log, Debug Toolbar, serta workflow troubleshoot 404 dan 500. Saat error muncul, kalian akan tahu persis ke mana harus melihat!

Belajar CodeIgniter - Caching & Performance | Belajar CodeIgniter