Learn TanStack - Observability & Monitoring
Episode 21 of 24

Learn TanStack - Observability & Monitoring

This episode equips your TanStack app with eyes: monitoring data fetching and rendering on the client side, tracking cache behavior and query performance, error reporting for the UI and data layers, and performance and user experience analytics.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

An app deployed without observability is a black box: you only find out something's wrong when users report it. Episode 21 covers observability and monitoring for TanStack apps: monitoring data fetching and rendering on the client side, tracking cache behavior and query performance, error reporting for the UI and data layers, and user experience analytics.

TanStack Query already provides the observability stage through the query cache, events, and callback hooks like onError and onSuccess. Your job is to capture those signals and forward them to a monitoring system so problems are detected earlier.

By the end of the episode, your app will send enough telemetry to answer the questions: which data failed to load, how long did it take, and does the user feel the app is slow.

Monitoring Data Fetching and Rendering

Query Lifecycle Events

TanStack Query publishes events at every stage of a query: fetch started, succeeded, failed, and data expired. Those events can be used to send metrics to a monitoring backend.

JSKirim metrik setiap query selesai
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 => ...) lets you listen to all cache changes from one place. The query key becomes the metric name and the status becomes the recorded value, so the dashboard immediately shows which queries fail often.

Monitoring Rendering

Wasteful rendering can be spotted with the React Profiler and render counters. For large TanStack Table apps, make sure state changes don't re-render the whole table — column visibility and sorting should run efficiently with state scoped per feature.

Tracking Cache Behavior and Query Performance

TanStack Cache Statistics

TanStack Query provides queryClient.getQueryCache().getAll() to peek at the entire cache contents: how many queries, how old they are, and when they were last fetched.

JSRekap status semua query
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() returns all queries in the cache with their statuses. The ringkasan summary can be sent periodically to monitoring to see the health of the app's cache in aggregate.

Measuring Fetch Time

Measure fetch duration inside queryFn and send it as a histogram. A striking difference between dev and production is often the first signal of a backend problem.

JSUkur durasi queryFn
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() gives millisecond-precision timestamps for measuring duration. With trackTiming and trackError, every query sends two signals: how long it took and whether it succeeded.

Error Reporting for the UI and Data Layers

Capturing Global Query Errors

Combine the QueryClient default options with an error boundary to catch data failures and render failures in a single strategy.

JSQueryCache dengan onError global
const queryClient = new QueryClient({
  queryCache: new QueryCache({
    onError: (error, query) => {
      reportError("query", query.queryKey, error)
    },
  }),
})

new QueryCache({ onError }) catches all query errors in one place without changing a single hook. Errors are forwarded to the reporting system, while the UI still shows error state through each page's ErrorBoundary.

Distinguishing Expected and Unexpected Errors

Not every failure needs to trigger an alarm. TanStack's automatic retry already handles network fluctuations; report only the errors that persist after retries are exhausted. On the UI side, make sure the error boundary shows a friendly fallback, not a blank page.

User Experience Analytics and Performance Metrics

Web Vitals for Real Experience

Metrics like LCP and INP measure real user experience, not just the performance of a development machine. Send these metrics along with the active page and route context so the team can see which pages are slowest.

JSKirim Web Vitals
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
}

The dynamic import import("web-vitals") loads the library only when needed, keeping the bundle small. The onPerfEntry callback sends metrics to analytics along with the currently active route info.

Connecting Metrics to TanStack Routes

Because TanStack Router handles navigation, it's easy to associate every metric with the route being viewed. Attach the route name to the metric label so analysis goes down to the page level, not just the app level.

Conclusion

Episode 21 wrapped up observability and monitoring: lifecycle events and cache subscription for fetch monitoring, cache statistics and duration measurement for query performance, error reporting for the UI and data layers, and Web Vitals for real user experience.

Key takeaways:

  • Subscribe to the Query cache to monitor the whole fetch cycle from one place.
  • Send query statuses and durations as aggregate metrics to the dashboard.
  • QueryCache onError catches global data errors without changing hooks.
  • Report only errors that persist after retries are exhausted.
  • Web Vitals monitor real experience, not just the dev machine.
  • Connect metrics to TanStack routes for per-page analysis.

In the next episode, episode 22, we'll discuss stable modern features and trends — the latest stable features across the entire TanStack ecosystem, updates to Router, Table, Query, Virtual, and Charts, trends in headless libraries and data-driven React, and strategies for keeping your TanStack skills relevant. Time to look at the future of this ecosystem!

Learn TanStack - Observability & Monitoring | Learn TanStack