API Caching — API

Caching adalah cara termudah membuat API kamu jauh lebih cepat dan hemat resource. Kalau data tidak sering berubah, kenapa compute ulang untuk setiap request? H

Caching adalah cara termudah membuat API kamu jauh lebih cepat dan hemat resource. Kalau data tidak sering berubah, kenapa compute ulang untuk setiap request?

HTTP caching bekerja di 3 level: browser, CDN, server. Yang kamu kontrol via header response.

Cache-Control Header

Header paling penting. Bilang ke klien/proxy/CDN: "cache response ini, berapa lama, dan apakah public atau private?"

app.get("/api/products/:id", (req, res) => {
  const product = getProduct(req.params.id);

  // Cache 5 menit di browser + CDN
  res.set("Cache-Control", "public, max-age=300");
  res.json(product);
});

Directive yang wajib kamu tahu:

Directive Arti
public Boleh di-cache siapapun (browser, CDN, proxy)
private Hanya boleh cache browser user (untuk data per-user)
no-cache Harus validasi ulang ke server sebelum dipakai (via ETag/Last-Modified)
no-store Jangan cache sama sekali (data sensitif — bank, medical)
max-age=N Cache valid N detik
s-maxage=N Cache valid N detik untuk shared cache (CDN), override max-age
immutable Data tidak akan berubah selama hidup cache (cocok untuk hash-named assets)
stale-while-revalidate=N Serve stale response + refresh di background selama N detik

Pola real-world:

// Static product catalog — aman cache lama
res.set("Cache-Control", "public, max-age=3600, s-maxage=86400");

// User profile sendiri — per-user, cache browser saja
res.set("Cache-Control", "private, max-age=60");

// Dashboard real-time — jangan cache
res.set("Cache-Control", "no-store");

// Boleh stale 5 menit saat refresh background
res.set("Cache-Control", "public, max-age=300, stale-while-revalidate=600");

ETag + Conditional Request — Cache Validation

Kadang data bisa di-cache tapi cache-time tidak diketahui. Solusi: ETag (identifier unik dari response). Klien kirim ETag di request berikutnya; kalau belum berubah, server return 304 Not Modified (tanpa body).

import crypto from "crypto";

app.get("/api/articles/:id", (req, res) => {
  const article = getArticle(req.params.id);
  const etag = crypto.createHash("md5").update(JSON.stringify(article)).digest("hex");

  // Klien sudah punya versi ini?
  if (req.headers["if-none-match"] === etag) {
    return res.status(304).end();  // No body, hemat bandwidth
  }

  res.set("ETag", etag);
  res.set("Cache-Control", "private, max-age=0, must-revalidate");
  res.json(article);
});

Browser otomatis kirim If-None-Match: <etag> di request berikutnya. Kalau sama, server hemat compute body + network tidak perlu kirim bytes. Cocok untuk data yang jarang berubah tapi tidak bisa di-cache lama (misal: user profile yang kadang di-edit).

Last-Modified — Alternatif ETag

Mirip ETag tapi pakai timestamp:

app.get("/api/articles/:id", (req, res) => {
  const article = getArticle(req.params.id);
  const lastMod = new Date(article.updated_at).toUTCString();

  if (req.headers["if-modified-since"] === lastMod) {
    return res.status(304).end();
  }

  res.set("Last-Modified", lastMod);
  res.json(article);
});

ETag lebih akurat (granularitas lebih tinggi), Last-Modified lebih mudah (pakai kolom updated_at yang sudah ada).

CDN Caching untuk API

CDN (Cloudflare, Fastly, AWS CloudFront) bisa cache API response di edge — user di Jakarta dapat response dari server CDN di Jakarta, bukan server asli di Singapore.

Syarat CDN cache:

// Response yang CDN-cacheable
res.set("Cache-Control", "public, s-maxage=300");
res.set("Vary", "Accept-Language, Authorization");
res.set("CDN-Cache-Control", "max-age=600");  // override untuk CDN saja (Cloudflare)

Cache Invalidation

"There are only two hard things in Computer Science: cache invalidation and naming things." — Phil Karlton

Strategi umum:

  1. Time-based (TTL) — paling simple; cache expired setelah N detik. OK untuk data yang boleh stale beberapa menit.
  2. Event-based purge — saat data berubah, kirim purge request ke CDN. Cloudflare: POST /zones/{id}/purge_cache. Cepat tapi butuh koordinasi.
  3. Versioned URLapi/v2/products vs api/v1/products. Ganti version = cache baru. Mahal tapi 100% correctness.
  4. Cache key dengan hash konten/assets/app.abc123.js. Berubah = nama baru = cache baru. Ideal untuk static assets.

Anti-Pattern Umum

Cache response dengan Set-Cookie header di CDN — semua user dapat cookie user pertama yang hit. Keamanan breach. Selalu Cache-Control: private untuk response berisi cookie user.

Cache error responses — 500 bisa transient, jangan cache 500 detik. Pakai Cache-Control: no-store untuk status 5xx.

Lupa Vary: Authorization — CDN cache response user A dan kirim ke user B. Gunakan Vary untuk header yang mempengaruhi response.

Checklist

Yang akan kamu pelajari