Episode 20 membangun arsitektur caching end-to-end: caching server-side dengan cache warming dan invalidation, lapisan cache dari CDN sampai Redis, normalized cache Apollo Client dengan type policies, pola update cache dan eviction, hingga pengenalan GraphQL CDN.

Cache adalah salah satu alat paling efektif untuk mempercepat aplikasi — dan juga salah satu sumber bug paling licik. Episode 20 membangun arsitektur caching end-to-end yang benar: dari sisi server sampai sisi client, dengan pemahaman tentang normalisasi, invalidation, dan eviction. Kita akan membahas caching server-side, lapisan-lapisan cache yang tersedia, normalized cache Apollo Client, cara memperbarui dan meng-evict cache, serta pengenalan GraphQL CDN.
async function cachedQuery(operation, key) {
const cached = await ctx.redis.get(key);
if (cached) return JSON.parse(cached);
const result = await execute(operation);
await ctx.redis.set(key, JSON.stringify(result), "EX", 60);
return result;
}async function createPost(_, args, ctx) {
const post = await ctx.db.posts.create(args.input);
await ctx.redis.del("feed:home");
await ctx.redis.del(`posts:${args.input.authorId}`);
return post;
}docker run -d -p 6379:6379 redis:7Praktik umum: gabungkan lapisan dengan aturan — cache hasil query untuk data publik di CDN, data autentikasi dan per-user di Redis (jalankan via docker run -d -p 6379:6379 redis:7), dan hindari cache di level aplikasi yang sulit di-invalidate secara terpusat.
Sisi client punya cache sendiri — ini yang membuat UI terasa instan. Apollo Client menyimpan hasil query dalam normalized cache, menyimpan setiap objek sekali berdasarkan __typename dan id:
import { ApolloClient, InMemoryCache } from "@apollo/client";
const client = new ApolloClient({
uri: "http://localhost:4000",
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
posts: {
keyArgs: ["category"],
},
},
},
},
}),
});Normalized cache menyimpan setiap objek sekali berdasarkan __typename dan id, lalu menghubungkannya — sehingga dua query yang berbagi objek yang sama otomatis berbagi data tanpa fetch ulang.
cache-first (default): gunakan cache bila ada, network hanya jika kosong.cache-only: hanya cache, tanpa network.network-only: selalu jaringan, abaikan cache.cache-and-network (default untuk UI feed): tampilkan cache segera lalu update dari jaringan.Normalisasi bekerja dengan menggabungkan __typename dan id. Untuk tipe tanpa id, konfigurasi keyFields agar tetap bisa dinormalisasi. Tanpa key yang stabil, query yang sama akan di-fetch berulang — penyebab umum "cache tidak berfungsi" di Apollo Client:
const cache = new InMemoryCache({
typePolicies: {
Review: {
keyFields: ["id"],
},
Person: {
keyFields: ["firstName", "lastName"],
},
},
});Tanpa key yang stabil, objek tidak dinormalisasi dan query yang sama akan di-fetch berulang. Ini penyebab umum "cache tidak berfungsi" di Apollo Client.
const [createPost] = useMutation(CREATE_POST, {
update(cache, { data }) {
const existing = cache.readQuery({ query: GET_POSTS });
cache.writeQuery({
query: GET_POSTS,
data: {
posts: [data.createPost, ...existing.posts],
},
});
},
});Untuk membuang data dari cache (misalnya saat logout), panggil cache.evict dan cache.gc:
client.cache.evict({ id: `User:${userId}` });
client.cache.gc();Optimistic UI menampilkan perubahan sementara sebelum server menjawab (episode 5): Apollo menyimpan hasil optimistik di cache, lalu menggantinya dengan hasil asli saat mutation selesai. Ini memberikan pengalaman UI yang instan.
GraphQL CDN menyimpan hasil query di edge network, sehingga latensi menurun drastis untuk pengguna global. Layanan seperti Stella (Netlify) dan GraphCDN menghubungkan langsung ke origin GraphQL:
npx graphcdn pushKonfigurasi biasanya berupa file YAML yang menandai query mana yang boleh di-cache dan aturan purging:
originUrl: https://api.kalian.com
scopes:
- operationName: HomeFeed
maxAge: 60Cache di CDN di-purge saat data berubah — biasanya lewat webhook dari mutation. Ini melengkapi arsitektur caching: CDN di depan, Redis di tengah, dan normalized cache di client.
Inti yang harus dibawa pulang:
Di episode 21 selanjutnya kalian akan mempelajari testing GraphQL — test pyramid, unit testing resolver dengan mock, integration testing dengan apollo-server testing dan supertest, schema testing dengan GraphQL Inspector, mocking data, hingga E2E testing dengan Cypress. Kualitas API kalian akan teruji dari unit sampai end-to-end!