Seluk-beluk Cache HTTP
Aditya Phra•
Di artikel ini, aku akan membahas tentang Cache HTTP yang masih jarang dimanfaatkan, terutama oleh para pengguna CDN. Padahal, fitur ini bisa mempercepat waktu load situs web sekaligus mengurangi beban server.
Cara kerja HTTP cache
Saat pengguna mengakses pertama kali ke server maka bentuk rekues HTTP-nya seperti ini:
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
Kemudian server merespons:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Sun, 28 Jun 2026 11:37:33 GMT
Last-Modified: Sun, 28 Jun 2026 11:00:00 GMT
Cache-Control: max-age=3600
<!doctype html>
...
Header Last-Modified adalah waktu terakhir data dimodifikasi, header ini nanti digunakan untuk menvalidasi apakah data di cache masih fresh atau tidak (stale).
Sedangkan, header Cache-Control berfungsi untuk mengontrol mekanisme cache, seperti untuk mengatur berapa lama respons bisa disimpan di cache.
Dengan adanya header Last-Modified dan Cache-Control: max-age=3600 berarti telah memenuhi syarat untuk di-cache-kan, maka browser akan menyimpan respons di cache selama 3600 detik atau 1 jam.
Selama satu jam ini, saat pengguna mengakses data kembali, browser langsung mengambilnya dari cache dan tidak ada rekues ke jaringan.
Setelah satu jam, respons di cache berarti sudah kedaluwarsa (stale), saat pengguna mengaksesnya kembali, browser tidak langsung mengambil data baru dari server, tetapi browser akan memvalidasi terlebih dahulu data di cache, masih bisa digunakan lagi atau tidak.
Seperti ini bentuk rekues HTTP saat proses validasi oleh browser:
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-Modified-Since: Sun, 28 Jun 2026 11:00:00 GMT
Kalau data tidak berubah, server akan merespons dengan status 304 Not Modified:
HTTP/1.1 304 Not Modified
Content-Type: text/html
Date: Sun, 28 Jun 2026 13:37:33 GMT
Last-Modified: Sun, 28 Jun 2026 11:00:00 GMT
Cache-Control: max-age=3600
Respons yang berasal dari server terdiri dari header saja (tidak ada body) sehingga ukurannya jauh lebih kecil, hasilnya akan terasa lebih cepat daripada mengambil data baru secara utuh.
Setelah menerima respons berstatus 304 Not Modified, artinya respons yang ada di dalam cache browser masih fresh, jadi bisa digunakan lagi selama 1 jam.
Kalau data yang ada di server ada perubahan, server akan merespons dengan status 200 OK beserta dengan data barunya:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Sun, 28 Jun 2026 16:40:33 GMT
Last-Modified: Sun, 28 Jun 2026 16:00:00 GMT
Cache-Control: max-age=3600
<!doctype html>
...
Browser kemudian membuang respons lama di cache dan menggantinya dengan respons baru.
Selain memakai Last-Modified dan If-Modified-Since, ada header alternatif, yaitu ETag dan If-None-Match.
Bedanya, kalau Last-Modified mengandalkan waktu terakhir data diubah, kalau ETag bisa berupa apa saja yang penting bisa untuk identifikasi versi datanya, bisa dari hash-nya atau nomor versinya.
Seperti ini contoh respons dari server memakai ETag:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Sun, 28 Jun 2026 16:00:00 GMT
ETag: "08a610c3a9745844f8952955f8f17952"
Cache-Control: max-age=3600
<!doctype html>
…
Dan ini kalau browser saat melakukan validasi respons:
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-None-Match: "08a610c3a9745844f8952955f8f17952"
Nilai dari header If-None-Match sama dengan header ETag dari respons tadi.
Server akan merespons dengan 304 Not Modified kalau datanya masih sama atau 200 OK kalau datanya berubah.
Jenis cache
Ada dua jenis cache HTTP, yaitu cache privat dan cache proksi.
Cache privat, artinya datanya disimpan di cache browser seperti pada contoh di atas, sedangkan cache proksi, datanya disimpan di antara pengguna (browser) dengan situs web tujuan.
Misalnya, cache di CDN untuk mempercepat waktu load dengan men-cache data di data center yang dekat dengan penggunanya atau proksi korporat yang umum dipakai di korporat untuk memantau aktivitas internet penggunanya.
Cache-Control
Mekanisme cache di browser, CDN, dan proksi dikontrol lewat header Cache-Control.
Konfigurasinya harus ditulis dalam huruf kecil dan dipisahkan dengan tanda koma kalau ada lebih dari satu konfigurasi.
Inilah konfigurasi dan fungsinya masing-masing:
max-age
Untuk mengatur lama data bisa di simpan di cache dalam satuan detik.
Cache-Control: max-age=3600
private
Data hanya bisa disimpan di cache browser pengguna, konfigurasi ini cocok untuk data bersifat personal.
Cache-Control: private
public
Data bisa disimpan di cache browser dan cache perantara (CDN/proksi), yang artinya data dibagikan dengan pengguna lain.
Cache-Control: public
no-store
Untuk mengatur agar tidak menyimpan data ke cache, baik privat & proksi.
Cache-Control: no-store
must-revalidate
Spesifikasi cache HTTP mengizinkan memakai data yang sudah kedaluwarsa di cache kalau terputus dari situs web tujuan.
Fungsi konfigurasi must-revalidate agar data di cache wajib divalidasi dahulu setelah kedaluwarsa, jadi kalau validasi gagal dilakukan, bakalan dibuatkan respons 504 Gateway Timeout.
Cache-Control: max-age=604800, must-revalidate
no-cache
Konfigurasi ini yang sering disalahartikan. no-cache bukan berarti respons tidak bisa disimpan di cache. Justru, respons tetap bisa disimpan di cache, tetapi setiap kali akan digunakan kembali, wajib melakukan validasi ke server terlebih dahulu untuk memastikan data masih valid.
Cache-Control: no-cache
Konfigurasi ini sama dengan no-cache:
Cache-Control: max-age=0, must-revalidate
Konfigurasi ini cocok untuk men-cache-kan file html seperti yang sudah aku implementasikan ke blog ini (bisa kamu pastikan sendiri lewat network inspector di browser).
immutable
Konfigurasi ini ada karena sejarahnya dulu di browser, saat pengguna me-refresh halaman, browser akan menvalidasi ulang setiap aset (CSS, JS, dan gambar) di halaman ke server meskipun masih dalam kondisi fresh.
Karena itu, immutable diperlukan agar browser tidak perlu lagi memvalidasi ulang saat halaman di-refresh selama data masih fresh:
Cache-Control: public, max-age=604800, immutable
Umumnya immutable digunakan untuk cache busting, yaitu asetnya diberi nomor versi agar browser bisa menyimpannya di cache dalam waktu lama tanpa perlu melakukan validasi.
Jadi, saat ada perubahan pada aset tinggal mengganti nomor versi pada aset.
<script src="https://example.com/index.v67.js"></script>
s-max-age
Fungsinya sama seperti max-age, tetapi konfigurasi ini hanya berlaku di cache proksi.
Cache-Control: s-max-age=604800
proxy-revalidate
Fungsinya sama seperti must-revalidate, tetapi konfigurasi ini hanya berlaku di cache proksi.
Cache-Control: s-max-age=0, proxy-revalidate
no-transform
Konfigurasi ini ditujukan untuk proksi cache agar proksi tidak mentransformasikan konten respons dari situs web tujuan. Misalnya, fitur yang mengubah isi HTML dari salah satu CDN populer.
Cache-Control: no-transform
stale-while-revalidate
Fungsinya agar data yang tersimpan di cache bisa digunakan meskipun sudah kedaluwarsa.
Sementara itu, proses validasi dan pembaruan data tetap dilakukan di background.
Misalnya, dengan konfigurasi ini, boleh memakai data yang sudah kedaluwarsa selama 86400 detik sampai data berhasil divalidasi atau perbarui:
Cache-Control: max-age=604800, stale-while-revalidate=86400
Setelah data berhasil divalidasi atau diperbarui, saat pengguna mengakses kembali data, langsung diambilkan data dari cache selama masih fresh (maksimal 604800 detik berada di cache).
stale-if-error
Fungsinya agar data yang tersimpan di cache bisa digunakan kalau mendapatkan respons error dari situs web tujuan.
Misalnya, dengan konfigurasi ini, boleh memakai data yang sudah kedaluwarsa selama 86400 detik:
Cache-Control: max-age=604800, stale-if-error=86400
Vary
Header Vary digunakan untuk men-cache-kan konten dari URL yang ada variasinya, misal isi konten bisa bervariasi tergantung bahasa pengaksesnya alias berdasarkan header Accept-Language.
Maka, respons dari server harus mengandung header ini:
Vary: Accept-Language
Misal, kalau ada pengguna yang berbahasa Indonesia (Accept-Language: id), maka respons dari server adalah:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Sun, 28 Jun 2026 11:37:33 GMT
Last-Modified: Sun, 28 Jun 2026 11:00:00 GMT
Cache-Control: max-age=3600
Vary: Accept-Language
<!doctype html>
<html lang="id">
...
Sedangkan, pengguna yang berbahasa Inggris:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Sun, 28 Jun 2026 11:37:33 GMT
Last-Modified: Sun, 28 Jun 2026 11:00:00 GMT
Cache-Control: max-age=3600
Vary: Accept-Language
<!doctype html>
<html lang="en">
...