Mengimplementasikan caching Redis dalam API NestJS produksi mengurangi waktu respons rata-rata dari 450ms menjadi 42ms — peningkatan 10x — dengan rasio cache hit 89% dan beban database berkurang sekitar 70%. Angka-angka ini berasal dari proyek NestJS nyata di Commsult Indonesia di mana kami memiliki endpoint dashboard yang memukul PostgreSQL dengan JOIN 6 tabel yang kompleks pada setiap permintaan.
@nestjs/cache-manager default NestJS menggunakan penyimpanan in-memory, yang berfungsi untuk setup single-process tetapi langsung rusak saat Anda melakukan scale ke beberapa instance atau me-restart server. Redis memecahkan kedua masalah: ia bertahan di seluruh restart (opsional), bertahan dari restart container, dan dibagikan di semua instance aplikasi NestJS Anda.
Instal @nestjs/cache-manager, cache-manager, dan @keyv/redis. Konfigurasikan CacheModule di AppModule Anda dengan Redis store. Setelah dikonfigurasi, Anda dapat menggunakan dekorator @UseInterceptors(CacheInterceptor) pada metode controller mana pun untuk men-cache responsnya secara otomatis, dengan kunci cache yang diturunkan dari rute dan parameter query.
Cache-aside (juga disebut lazy loading) adalah pola yang paling umum dan fleksibel. Aplikasi memeriksa cache terlebih dahulu; pada miss, ia mengambil dari database, menyimpan hasilnya di Redis, dan mengembalikannya. Pada permintaan berikutnya, cache hit disajikan langsung. Pola ini memberi Anda kontrol atas apa yang di-cache dan kapan.
┌─────────────────────────────────────────────────────┐
│ CACHE-ASIDE PATTERN FLOW │
└─────────────────────────────────────────────────────┘
Request
│
▼
NestJS Service
│
├─► Redis CACHE ──► HIT ──► Return cached data
│ │
│ └─► MISS
│ │
│ ▼
└──────► PostgreSQL DB
│
▼
Store in Redis (TTL)
│
▼
Return to clientDari pengalaman saya dengan NestJS di Commsult Indonesia, gunakan notifikasi keyspace Redis untuk mengimplementasikan invalidasi cache berbasis event daripada hanya kedaluwarsa TTL. Ketika pengguna memperbarui rekaman ERP, publikasikan event invalidasi cache melalui Redis pub/sub. Layanan cache manager terpisah mendengarkan dan langsung menghapus kunci yang terpengaruh.
Invalidasi cache adalah masalah tersulit dalam caching. Ada tiga strategi utama: kedaluwarsa berbasis TTL (paling sederhana, tetapi berpotensi menyajikan data basi), invalidasi berbasis event (akurat, tetapi memerlukan sistem event invalidasi), dan caching write-through (perbarui cache dan database bersama-sama saat penulisan, memastikan konsistensi).
Desain kunci cache sangat kritis. Gunakan kunci bernama namespace: user:{userId}:profile, report:{reportId}:data, inventory:{productId}. Ini memungkinkan invalidasi yang ditargetkan — ketika pengguna memperbarui profilnya, Anda dapat menghapus user:{userId}:* tanpa menyentuh data pengguna lain.
# Redis configuration — /etc/redis/redis.conf
maxmemory 512mb
maxmemory-policy allkeys-lru
save 900 1
save 300 10
# Redis CLI: check cache hit ratio
redis-cli INFO stats | grep -E "keyspace_hits|keyspace_misses"
# Namespaced key pattern
SET user:1234:profile '{"name":"Matthews","role":"admin"}' EX 300
SET report:5678:data '{"rows":42,"total":150000}' EX 600
DEL user:1234:* # invalidate single user's cache
# NestJS: manual cache-aside pattern
const cacheKey = 'report:' + reportId + ':data'
const cached = await this.cacheManager.get(cacheKey)
if (cached) return cached
const data = await this.db.getReport(reportId)
await this.cacheManager.set(cacheKey, data, 300)
return dataUntuk endpoint traffic sangat tinggi, pertimbangkan cache dua lapisan: cache LRU in-process berumur pendek (menggunakan node-lru-cache atau serupa) untuk kunci terpanas, didukung oleh Redis untuk cache yang lebih luas. Cache in-process menghilangkan round-trip jaringan Redis untuk data yang paling sering diakses.
Saya pernah men-deploy Redis di VPS 1GB tanpa mengonfigurasi maxmemory dan kebocoran memori di lapisan caching kami mengisi instance sepenuhnya. Redis OOM, crash, dan aplikasi NestJS kami jatuh ke database untuk setiap permintaan secara bersamaan — menyebabkan kegagalan cascade yang membutuhkan 20 menit untuk pulih. Selalu atur maxmemory di redis.conf (misalnya maxmemory 512mb).
Lacak metrik Redis ini dalam produksi: keyspace_hits dan keyspace_misses (hitung rasio hit Anda), used_memory vs maxmemory, evicted_keys (bukan nol berarti Anda membutuhkan lebih banyak memori atau kebijakan eviksi yang berbeda), dan connected_clients. Ekspos metrik ini ke Prometheus melalui redis_exporter untuk dashboard Grafana.
Tidak semua hal harus ada di Redis. Cache data yang mahal untuk dihitung atau diambil (query JOIN kompleks, respons API eksternal, agregat yang dihitung) dan dibaca jauh lebih sering daripada ditulis. Jangan cache data yang harus akurat secara real-time atau data yang sudah cepat diambil.