78 Caching Query dan Result Resolver: Efisiensi, Best Practice, dan Implementasi Nyata
Oleh: [Nama Anda], Senior Software Engineer
Caching merupakan salah satu strategi paling efektif untuk meningkatkan performa sistem, terutama di dunia yang serba real-time dan high traffic seperti sekarang. Dalam artikel ini, saya akan membahas secara detail tentang query caching dan result resolver caching, membedakan keduanya, kapan dan bagaimana mengimplementasikan, serta membagikan best practice berdasarkan pengalaman di beberapa proyek scale-up. Saya juga akan menyertakan contoh kode, simulasi nyata, serta visualisasi proses menggunakan diagram alur mermaid.
Memahami Dasar: Query Caching vs Result Resolver
Sebelum masuk ke kode dan simulasi, penting sekali untuk memahami perbedaannya:
1. Query Caching
Query caching menyimpan hasil eksekusi query tertentu terhadap data source (biasanya database). Jadi, jika query yang identik dijalankan kembali, maka hasil cache dikembalikan tanpa perlu akses ke database.
2. Result Resolver Caching
Result resolver caching biasanya digunakan pada layer business logic atau data fetching framework (seperti GraphQL atau DataLoader). Resolver caching mengoptimalkan pemanggilan data antar komponen atau field sehingga menghindari pemanggilan sumber data yang berulang untuk entitas yang sama.
Manfaat Kedua Caching Ini
Query Caching | Result Resolver Caching | |
---|---|---|
Keuntungan | Mengurangi beban DB, response time cepat | Mengurangi duplikasi fetch pada data yang sama |
Skala | Sering dipakai di level DB/server | Framework/Business Logic Layer |
Kelemahan | Rentan data stale jika table berubah | Perlu manajemen dependencies antar field |
Ilustrasi Kasus: Sistem Article Recommendation
Bayangkan sistem article recommendations dengan query seperti:
SELECT * FROM articles WHERE published = true ORDER BY recommended_score DESC LIMIT 10;
Atau pada GraphQL:
{
articles(recommended: true) {
id
title
author {
id
name
}
}
}
Di sini:
- Query caching akan menyimpan hasil seluruh list artikel.
- Result resolver caching akan berperan saat field
author
dipanggil berulang.
Simulasi Tanpa Caching: Bottleneck si Author
Misal, kita fetch 10 artikel rekomendasi. Setiap artikel akan fetch data author
. Tanpa cache resolver, akan ada 10x query ke table authors
.
Pseudo-code ilustrasi (tanpa cache):
const articles = await db.query('SELECT * FROM articles WHERE ...');
const results = [];
for (const article of articles) {
const author = await db.query('SELECT * FROM authors WHERE id = ?', [article.author_id]);
results.push({ ...article, author });
}
// Total = 1 (artikel) + 10 (author) = 11 query
Simulasi Dengan Result Resolver Caching
Dengan result resolver caching (misal pakai DataLoader), sistem akan mengumpulkan semua ID unik, lalu fetch author cukup sekali.
Pseudo-code dengan cache resolver:
const articles = await db.query('SELECT * FROM articles WHERE ...');
const authorIds = articles.map(a => a.author_id);
const authors = await loadAuthorsByIds(authorIds); // batch
const results = articles.map(article => ({
...article,
author: authors[article.author_id],
}));
// Total query: 1 (artikel) + 1 (semua author unik)
Simulasi Query Caching di Database
Bagaimana jika query artikel rekomendasi yang berat ini sering dipanggil (misal setiap user visit homepage)? Aktifkan query caching.
Diagram alur Query Caching (Mermaid):
flowchart LR A[Client Request] --> B[Check Cache Layer] B -->|Cache Hit| C[Return Cached Result] B -->|Cache Miss| D[Process to DB] D --> E[Store in Cache] E --> C
Implementasi: Query Caching (Node.js + Redis)
Misal, stack yang digunakan adalah Express, PostgreSQL, dan Redis sebagai cache.
Middleware caching sederhana:
const redis = require('redis').createClient();
async function cacheMiddleware(req, res, next) {
const cacheKey = "homepage:articles";
const cachedResult = await redis.get(cacheKey);
if (cachedResult) {
return res.json(JSON.parse(cachedResult));
}
// Simpan ke res.locals supaya handler bawahnya bisa pakai
res.locals.cacheKey = cacheKey;
next();
}
// Handler utama
app.get('/api/homepage', cacheMiddleware, async (req, res) => {
const articles = await db.query("SELECT ..."); // Query berat
await redis.set(res.locals.cacheKey, JSON.stringify(articles), 'EX', 60); // TTL 1 menit
return res.json(articles);
});
Kelebihan:
- Hanya satu query berat setiap 1 menit/cache TTL.
- Sangat mengurangi load ke database.
Implementasi: Result Resolver Caching (Node.js + DataLoader)
DataLoader sangat populer untuk GraphQL dan REST mediation.
const DataLoader = require('dataloader');
const authorLoader = new DataLoader(async (authorIds) => {
const rows = await db.query('SELECT * FROM authors WHERE id = ANY($1)', [authorIds]);
// Buat map id => author
const map = new Map(rows.map(row => [row.id, row]));
return authorIds.map(id => map.get(id));
});
// Dalam resolver/handler
const articleIds = [...]; // hasil query artikel
const authors = await authorLoader.loadMany(articleIds);
Best Scenario:
- Request masuk, fetch semua
article
. - DataLoader kumpulkan semua unique
author_id
. - Query hanya 1X ke authors.
- Hasil di-cache (per request - jika ingin global bisa pakai redis layer lagi).
Tabel: Perbandingan Performa Query
Skema | Jumlah Query | Latency (ms, simulasi) | Keterangan |
---|---|---|---|
Tanpa Caching | 11 | 500 | Fetch author N times |
Query Caching Saja | 1 | 50 | Semua cached |
Resolver Caching Saja | 2 | 120 | 1x artikel, 1x author |
Keduanya | 1 | 50 | Cache total jalur |
Studi Kasus: Cache Invalidation
Bagian tersulit dari caching adalah invalidation. Ketika ada artikel baru, harus memastikan cache query dan resolver tidak mengandung data stale.
Cara sederhana:
- Untuk query cache, pakai TTL pendek (misal 1 menit).
- Untuk result resolver, invalidate/clear cache ketika data subject (misal author) berubah.
Tips dari lapangan:
- Untuk cache resolver yang pendek (per-request) tidak perlu invalidasi manual.
- Untuk query cache yang lebih besar, selalu seimbangkan antara performance vs data freshness.
Kesimpulan
Caching query dan result resolver adalah senjata rahasia dalam development aplikasi data-driven modern. Dengan penerapan dua lapis cache ini, Anda bisa menekan latency dari ratusan milidetik ke puluhan milidetik — bahkan under 10ms untuk repeated request — tanpa membebani database.
Checklist best practice:
- Aktifkan query cache untuk query berat dan sering diulang.
- Implementasikan resolver caching untuk field atau entitas yang sering berulang pada batch.
- Selalu siapkan cache invalidation atau TTL yang masuk akal.
- Monitor cache hit-rate dan latency secara real-time.
Struktur caching yang cermat akan membawa sistem Anda mendekati 99% reliability dan 10x lebih hemat resource dibanding brute-force querying.
Mau belajar lebih?
Lihat kode sumber dan diskusi lebih lanjut di Github atau DM saya di Twitter untuk konsultasi arsitektur caching di sistem Anda.
Terima kasih sudah membaca!
Referensi
Happy caching, engineers! 🚀
77 N+1 Problem dan Solusinya dengan DataLoader
Artikel Terhangat
78 Caching Query dan Result Resolver
09 Sep 2025
76 Optimasi Resolver agar Tidak Lambat
09 Sep 2025

78 Caching Query dan Result Resolver
