Last-Modified — adalah header respons HTTP yang menunjukkan tanggal dan waktu perubahan terakhir sumber daya di server, memungkinkan klien melakukan permintaan bersyarat melalui If-Modified-Since. Jika sumber daya tidak berubah sejak tanggal yang ditentukan, server mengembalikan 304 Not Modified tanpa mengirimkan badan respons, yang secara signifikan menghemat bandwidth. Menurut RFC 7232 (IETF, 2014), permintaan bersyarat dengan Last-Modified mengurangi waktu muat halaman sebesar 30–60% pada kunjungan berulang. Header ini secara otomatis didukung oleh sebagian besar server HTTP dan proxy.
Poin Utama
Last-Modified — adalah header HTTP yang termasuk dalam kelompok header permintaan bersyarat (conditional requests). Server menambahkannya ke respons GET atau HEAD, yang menunjukkan tanggal dan waktu perubahan terakhir sumber daya yang diminta dalam format HTTP-date: Last-Modified: Wed, 02 Jul 2025 14:30:00 GMT. Klien (browser, aplikasi seluler, proxy) menyimpan tanggal ini bersama dengan sumber daya yang di-cache. Pada permintaan berulang, klien mengirim header If-Modified-Since dengan tanggal yang sama, dan server membandingkannya dengan waktu perubahan sumber daya saat ini.
Protokol permintaan bersyarat dengan Last-Modified didefinisikan dalam RFC 7232 dan didukung oleh semua server HTTP modern. Format tanggal diatur secara ketat — hanya GMT (Greenwich Mean Time) tanpa menyebutkan zona waktu. Server dapat mengembalikan tanggal dalam tiga format yang mungkin: RFC 1123 (standar), RFC 850 (usang), atau ANSI C asctime. Dalam praktiknya, hampir semua server menggunakan format RFC 1123 dengan panjang tetap 29 karakter.
Last-Modified termasuk dalam kategori mekanisme validasi cache: ia tidak memberi tahu klien apakah respons dapat di-cache, tetapi memberikan alat untuk memeriksa keaktualan sumber daya yang sudah di-cache. Kebijakan caching ditetapkan secara terpisah melalui header Cache-Control. Menurut penelitian Akamai (2025), konfigurasi Last-Modified yang tepat bersama dengan Cache-Control mengurangi beban pada server origin hingga 70% untuk konten statis.
Header Last-Modified telah didefinisikan sejak HTTP/1.0 (RFC 1945, 1996) dan merupakan salah satu mekanisme pertama manajemen cache di web. Sebelum kemunculan ETag di HTTP/1.1, ini adalah satu-satunya cara untuk melakukan permintaan bersyarat. Meskipun sudah berusia tua, header ini tetap relevan karena kesederhanaannya — server tidak perlu menghitung hash konten, cukup membaca timestamp file dari sistem file atau kolom updated_at dari database.
Siklus lengkap mencakup tiga tahap. Pada permintaan pertama, server mengembalikan sumber daya dengan header Last-Modified dan status HTTP 200 OK. Klien menyimpan cache respons bersama dengan tanggal. Pada permintaan berulang, klien mengirim header If-Modified-Since dengan tanggal yang disimpan. Server membandingkan tanggal ini dengan waktu perubahan sumber daya saat ini. Jika sumber daya tidak berubah — dikembalikan 304 Not Modified dengan badan kosong. Jika berubah — 200 OK dengan data baru dan Last-Modified baru.
// Permintaan pertama — server mengembalikan sumber daya dengan tanggal
HTTP/1.1 200 OK
Content-Type: application/json
Last-Modified: Wed, 02 Jul 2025 14:30:00 GMT
[{"id": 1, "name": "Alice"}]
// Permintaan berulang — klien mengirim tanggal yang disimpan
GET /api/users HTTP/1.1
Host: example.com
If-Modified-Since: Wed, 02 Jul 2025 14:30:00 GMT
// Respons — data tidak berubah
HTTP/1.1 304 Not Modified
Untuk aplikasi seluler, Last-Modified sangat berguna saat sinkronisasi data. Aplikasi menyimpan tanggal pembaruan terakhir yang berhasil dan mengirimkannya ke server di If-Modified-Since. Jika ada lebih banyak data atau telah berubah — server mengembalikan set lengkap. Jika tidak — 304, dan aplikasi menggunakan salinan lokal. OkHttp dan URLSession mendukung mekanisme ini secara otomatis melalui sistem caching bawaan.
Untuk file statis, Nginx dan Apache mengambil tanggal dari atribut sistem file — mtime (waktu modifikasi). Untuk konten dinamis, kode server harus secara eksplisit menetapkan Last-Modified berdasarkan logika bisnis: kolom updated_at dari database, tanggal commit terakhir di Git, timestamp pembuatan artefak. Jika Last-Modified tidak ditetapkan secara eksplisit, server mungkin tidak mengembalikan header sama sekali, dan klien tidak dapat melakukan permintaan bersyarat berdasarkan tanggal.
Last-Modified dan ETag menjalankan tugas serupa — memungkinkan klien memeriksa keaktualan cache — tetapi memiliki perbedaan mendasar. Last-Modified menggunakan stempel waktu, ETag — pengidentifikasi versi unik. Setiap pendekatan memiliki skenario di mana ia lebih efektif, dan rekomendasi spesifikasi HTTP adalah menggunakan kedua header secara bersamaan.
| Kriteria | Last-Modified | ETag |
|---|---|---|
| Esensi | Tanggal perubahan terakhir | Pengidentifikasi versi unik |
| Akurasi | Hingga detik | Hingga bit (hash) |
| Kompleksitas implementasi | Rendah — otomatis dari sistem file | Sedang — memerlukan perhitungan hash |
| Server cluster | Masalah: mtime bisa berbeda di node | Stabil dengan data identik di node |
| Dukungan rentang | Tidak memengaruhi Range requests | Memerlukan ETag kuat untuk rentang |
| Rekomendasi | Untuk konten statis dan API sederhana | Untuk API yang memerlukan verifikasi akurat |
Keunggulan utama Last-Modified adalah kesederhanaan. Server tidak perlu menghitung hash konten, yang menghemat sumber daya CPU pada setiap permintaan. Untuk proyek dengan beban tinggi yang mengirimkan file statis atau data dengan stempel waktu yang jelas, Last-Modified tetap menjadi pilihan optimal. ETag memberikan akurasi absolut — perubahan satu huruf dalam respons JSON akan mengubah ETag, tetapi mungkin tidak mengubah tanggal (jika file ditimpa dengan versi yang sama).
Spesifikasi merekomendasikan untuk mengembalikan kedua header secara bersamaan. Server menyertakan Last-Modified dan ETag dalam respons 200 OK. Klien mengirim kedua header bersyarat — If-Modified-Since dan If-None-Match. Server memeriksa ETag terlebih dahulu (memiliki prioritas), lalu Last-Modified. Jika setidaknya satu menandakan perubahan — respons lengkap dikembalikan. Ini memberikan fleksibilitas maksimal: ETag memberikan akurasi, Last-Modified memberikan pemeriksaan cadangan untuk klien yang tidak mendukung ETag.
Konfigurasi Last-Modified tergantung pada jenis server. Untuk Nginx dan Apache, file statis diberi Last-Modified secara otomatis berdasarkan mtime. Untuk aplikasi dinamis, header harus ditetapkan dalam kode server. Mari kita lihat konfigurasi pada platform populer.
// Express.js — mengatur Last-Modified
app.get("/api/users", async (req, res) => {
const updatedAt = await getLastUpdate()
const ifModifiedSince = req.get("If-Modified-Since")
// Memeriksa If-Modified-Since
if (ifModifiedSince && new Date(ifModifiedSince)
>= updatedAt) {
return res.status(304).end()
}
const users = await getUsers()
res.set("Last-Modified", updatedAt.toUTCString())
res.json(users)
})
Dalam contoh Express.js, server mendapatkan tanggal pembaruan data terakhir dari database, memeriksa If-Modified-Since dari klien, dan jika cache masih berlaku, mengembalikan 304. Jika data telah berubah — menetapkan Last-Modified baru dan mengembalikan respons lengkap. toUTCString() mengonversi tanggal ke format HTTP yang diperlukan. Dalam lingkungan produksi, ada baiknya menambahkan caching updatedAt di Redis untuk menghindari kueri database pada setiap permintaan.
Nginx secara otomatis menetapkan Last-Modified untuk file statis berdasarkan waktu modifikasi terakhir file. Menonaktifkan atau mengubah perilaku dapat dilakukan melalui direktif etag (menonaktifkan ETag) atau melalui modul ngx_http_headers_module. Untuk permintaan proxy ke backend, Last-Modified diteruskan dari respons upstream tanpa perubahan. Penting: jika backend tidak mengembalikan Last-Modified, Nginx tidak akan menambahkannya secara otomatis untuk respons dinamis.
Last-Modified memiliki beberapa keterbatasan yang diketahui. Yang utama adalah akurasi hingga detik. Jika sumber daya berubah dua kali dalam satu detik, klien mungkin melewatkan versi baru. Dalam praktiknya, ini adalah skenario yang jarang terjadi, tetapi untuk pembaruan frekuensi tinggi (feed kuotasi, obrolan) ETag direkomendasikan. Keterbatasan kedua adalah masalah clustering: di server yang berbeda, file mungkin memiliki mtime yang berbeda karena penyalinan atau deployment, sehingga Last-Modified menjadi tidak konsisten.
Keterbatasan ketiga — pemrosesan If-Modified-Since dengan akurasi detik dapat menyebabkan permintaan berlebihan saat polling server yang sering. Jika klien mengirim If-Modified-Since setiap 500 ms, server setiap kali mengembalikan 200 OK, karena tanggal tidak berubah, tetapi sumber daya sebenarnya sudah diperbarui. Solusinya adalah kombinasi dengan ETag: ETag akan menangkap perubahan dalam satu detik, sementara Last-Modified tetap sebagai cadangan.
Masalah keempat — Last-Modified tidak membedakan versi berbeda dari sumber daya yang sama dengan tanggal yang sama. Jika file dipulihkan dari cadangan dan mtime-nya cocok dengan aslinya, klien tidak akan melihat bahwa konten telah berubah. ETag memecahkan masalah ini: hash konten pasti akan berubah pada setiap perubahan data, terlepas dari stempel waktu. Untuk data kritis, selalu gunakan kedua header.
Pertanyaan Umum
Hanya GMT (Greenwich Mean Time) dalam format RFC 1123: hari dalam seminggu, tanggal, bulan, tahun, jam:menit:detik. Contoh: Wed, 02 Jul 2025 14:30:00 GMT. Zona waktu selalu GMT, format lain tidak diizinkan.
Secara teknis bisa, tetapi ini melanggar RFC 7232. Jika server mengembalikan tanggal di masa depan, klien tidak akan memperbarui sumber daya hingga tanggal tersebut tiba. Konfigurasi semacam itu dianggap kesalahan — tanggal harus di masa lalu atau sekarang.
Tidak, permintaan bersyarat If-Modified-Since hanya bekerja dengan GET dan HEAD. Permintaan POST tidak di-cache dan tidak menggunakan validasi berdasarkan tanggal. Untuk memeriksa keaktualan data pada POST, gunakan ETag atau mekanisme kustom.
Cache-Control menentukan kebijakan caching (waktu penyimpanan maksimum, siapa yang dapat menyimpan cache), sedangkan Last-Modified adalah mekanisme validasi cache yang kedaluwarsa. Setelah max-age berakhir, klien mengirim If-Modified-Since untuk memeriksa keaktualan.
Periksa apakah server benar-benar menetapkan header dari sumber yang aktual — database, sistem file, atau API. Untuk respons dinamis, pastikan Anda secara eksplisit memanggil res.setHeader(“Last-Modified”, ...) dalam kode handler.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga