Episode ini membekali aplikasi TanStack dengan mata: memonitor data fetching dan rendering di sisi client, melacak perilaku cache dan performa query, error reporting untuk UI dan data layer, serta analytics performa dan pengalaman pengguna.

Aplikasi yang di-deploy tanpa observability adalah kotak hitam: kalian baru tahu ada masalah saat pengguna melaporkannya. Episode 21 membahas observability dan monitoring untuk aplikasi TanStack: memonitor data fetching dan rendering di sisi client, melacak perilaku cache dan performa query, error reporting untuk UI dan data layer, serta analytics pengalaman pengguna.
TanStack Query sudah menyediakan panggung observability lewat query cache, event, dan hook callback seperti onError dan onSuccess. Tugas kalian adalah menangkap sinyal itu dan meneruskannya ke sistem monitoring agar masalah terdeteksi lebih dini.
Di akhir episode, aplikasi kalian akan mengirim telemetri yang cukup untuk menjawab pertanyaan: data apa yang gagal dimuat, berapa lama, dan apakah pengguna merasa aplikasi lambat.
TanStack Query menerbitkan peristiwa di setiap tahap query: fetch dimulai, berhasil, gagal, dan data kedaluwarsa. Peristiwa itu bisa dipakai untuk mengirim metrik ke backend monitoring.
const queryClient = new QueryClient({
defaultOptions: {
queries: {
queryCacheNotify: true,
},
},
})
queryClient.getQueryCache().subscribe((event) => {
if (event.type === "queryUpdated") {
trackMetric(event.query.queryKey.join("."), event.query.state.status)
}
})queryClient.getQueryCache().subscribe(event => ...) memungkinkan kalian mendengarkan semua perubahan cache dalam satu tempat. Key query dijadikan nama metrik, dan status menjadi nilai yang dicatat, sehingga dashboard langsung menunjukkan query mana yang sering gagal.
Rendering yang boros bisa dilihat lewat React Profiler dan penghitung render. Untuk aplikasi TanStack Table yang besar, pastikan perubahan state tidak me-render ulang seluruh tabel — column visibility dan sorting harus berjalan efisien dengan state yang terkotak per fitur.
TanStack Query menyediakan queryClient.getQueryCache().getAll() untuk mengintip seluruh isi cache: berapa query, umurnya, dan kapan terakhir di-fetch.
const queries = queryClient.getQueryCache().getAll()
const ringkasan = queries.reduce((acc, query) => {
acc[query.state.status] += 1
return acc
}, { error: 0, success: 0, pending: 0 })queryClient.getQueryCache().getAll() mengembalikan semua query di cache beserta statusnya. Rekap ringkasan bisa dikirim berkala ke monitoring untuk melihat kesehatan cache aplikasi secara agregat.
Ukur durasi fetch di dalam queryFn dan kirim sebagai histogram. Perbedaan mencolok antara dev dan production sering menjadi sinyal pertama masalah backend.
const queryFn = async () => {
const mulai = performance.now()
try {
const data = await ambilData()
trackTiming("query.pengguna", performance.now() - mulai)
return data
} catch (error) {
trackError("query.pengguna", error)
throw error
}
}performance.now() memberi stempel waktu presisi milidetik untuk mengukur durasi. Dengan trackTiming dan trackError, setiap query mengirim dua sinyal: berapa lama dan apakah berhasil.
Gabungkan default option di QueryClient dengan boundary error untuk menangkap kegagalan data dan kegagalan render dalam satu strategi.
const queryClient = new QueryClient({
queryCache: new QueryCache({
onError: (error, query) => {
reportError("query", query.queryKey, error)
},
}),
})new QueryCache({ onError }) menangkap semua error query di satu tempat tanpa mengubah satu pun hook. Error diteruskan ke sistem reporting, sementara UI tetap menampilkan state error melalui ErrorBoundary masing-masing halaman.
Tidak semua kegagalan perlu memicu alarm. Retry otomatis TanStack sudah menangani fluktuasi jaringan; laporkan hanya error yang menetap setelah retry habis. Di sisi UI, pastikan error boundary menampilkan fallback yang ramah, bukan halaman kosong.
Metrik seperti LCP dan INP mengukur pengalaman nyata pengguna, bukan hanya performa mesin development. Kirim metrik ini bersama konteks halaman dan route yang aktif, sehingga tim bisa melihat halaman mana yang paling lambat.
export function KirimVitals({ onPerfEntry }) {
useEffect(() => {
if (typeof onPerfEntry !== "function") return
import("web-vitals").then(({ onLCP, onINP, onCLS }) => {
onLCP(onPerfEntry)
onINP(onPerfEntry)
onCLS(onPerfEntry)
})
}, [onPerfEntry])
return null
}Dynamic import import("web-vitals") memuat library hanya saat dibutuhkan, menjaga bundle tetap kecil. Callback onPerfEntry mengirim metrik ke analytics bersama informasi route yang sedang aktif.
Karena TanStack Router menangani navigasi, mudah menghubungkan setiap metrik dengan route yang sedang dilihat. Gabungkan nama route ke label metrik agar analisis turun ke level halaman, bukan hanya level aplikasi.
Episode 21 menutup observability dan monitoring: lifecycle events dan cache subscription untuk monitoring fetch, statistik cache dan pengukuran durasi untuk performa query, error reporting untuk UI dan data layer, serta Web Vitals untuk pengalaman pengguna nyata.
Inti yang harus dibawa pulang:
Di episode 22 selanjutnya kita akan membahas stable modern features dan trends — fitur stabil terbaru di seluruh ekosistem TanStack, pembaruan Router, Table, Query, Virtual, dan Charts, tren library headless dan React data-driven, serta strategi menjaga skill TanStack tetap relevan. Waktunya melihat masa depan ekosistem ini!