Sentry for crash + performance monitoring on React and React Native (v8 of the RN SDK catches pre-bootstrap crashes); add app/route-level error boundaries and wire them to it at the production stage.
on Expo (SDK 55+) and want build/OTA regression tracing or per-route time-to-interactive → EAS Observe (add alongside Sentry; expo-observe + markInteractive(); needs a new binary; does not capture native crashes)
already on Firebase → Firebase Crashlytics (for crashes; add Sentry or EAS Observe for performance)
already on Bugsnag → Bugsnag (keep it for crashes; 9.0.0 is a new major, read its changelog before upgrading)
need component-level profiling of a RELEASE build → @callstack/inspector (0.1.x; dev-mode profiles misrepresent production)
profiling React on the web or following an older runbook → React DevTools 8.0 (browser Performance panel React tracks; the Timeline tab is gone)
the field considered — and why each one isn’t the default here
option
tradeoff
evidence
Sentry (v8)
Crash + performance monitoring on both platforms; v8 of @sentry/react-native captures crashes before RN bootstraps via sentry.options.json (the 'instant death on TestFlight' class). @sentry/react-native 8.28.0 (2026-09-24, verified vs npm); web uses @sentry/react 11.0.0 (2026-09-23, verified vs npm).
ships in 16/34
EAS Observe (Expo)
Production performance monitoring for Expo apps: real-session startup/TTI/bundle-load/update-apply metrics with every build and OTA update as a marker, plus per-route TTI. Not a crash reporter — no native crashes, keep Sentry alongside. GA 2026-08-25 (verified vs the GA post); expo-observe 57.0.24 (2026-09-24, verified vs npm). See note: EAS OBSERVE.
Firebase Crashlytics / Bugsnag
Established crash reporting; neither gives Observe-style build/update attribution. @react-native-firebase/crashlytics 26.4.0 (2026-09-05), @bugsnag/react-native 9.0.0 (2026-09-22, new major; both verified vs npm).
ships in 2/34
Rozenite (Callstack incubator)
Plug-and-play panels inside React Native DevTools (network/storage/performance, custom type-safe panels), no extra window or server; plugins are auto-disabled in production builds. rozenite 2.4.0 (2026-09-03, verified vs npm). See note: ROZENITE.
React DevTools 8.0
8.0.0 (2026-09-08, verified vs CHANGELOG) removes the Timeline profiler tab — React profiling moves to the browser Performance panel's React tracks — and turns the Suspense tab on by default. A runbook that says 'open the Timeline tab' is out of date. See note: REACT DEVTOOLS 8.0.
@callstack/inspector
React-level component profiling in RELEASE builds via React DevTools, zero native changes — the honest lens, since dev-mode profiling misrepresents production. 0.1.1 (2026-05-22, verified vs npm): very young.
npm weekly downloads (from the corpus's last signals run): @callstack/inspector 803
Verified notes
Observability is three questions, not one tool: did it crash, is it slow, and which release did it. Sentry holds the default because one SDK covers the first two on both platforms, and v8 of the RN SDK closed the classic blind spot of crashes before the JS bundle loads. Error boundaries are the collection points that turn an uncaught render error from a blank tree into a report, which is why the source scan flags production repos with none. It is a production-stage concern: a prototype does not need dashboards; a production app without them cannot see what users hit.
EAS OBSERVE (2026-08-25 GA, verified vs the Expo GA post; open beta May→Aug): install expo-observe, wrap the root in <ObserveRoot> and call markInteractive(); it reports startup (cold/warm), time-to-interactive/time-to-render, bundle load and EAS Update download/apply times from real sessions, P50/P90/P99 across devices, plus JS errors and device context. Two things Sentry-style tools do not give: every build AND OTA update lands as a marker, so a regression traces to the release that caused it, and the Expo Router / React Navigation integration breaks time-to-interactive down per route. Metrics are queryable from the EAS CLI as JSON (there is an eas-observe Expo Skill for agent handoff). Pricing is per event, not per MAU: 100K events/mo free; Starter $19/mo and Production $199/mo each include 500K; $5 per million beyond; 90-day minimum retention. Floors: SDK 55+ for startup metrics, 56+ for per-route metrics, 57+ for JS error reporting (in preview); enabling it needs a new binary, not just config. It does not capture native crashes, and Expo's own guidance is to keep Sentry alongside.
EXPO-OBSERVE SDK 58 SURFACE (2026-09-21, verified vs the Expo SDK 58 beta changelog): the error side grows — ObserveErrorBoundary and reportError, an errorHandlingEnabled option, Observe.registerIntegration, an expo-image integration, and Observe.clientId (the EAS client id stamped on every event) — and the `AppMetrics` export is DEPRECATED in favour of `Observe`. Beta-era tutorials use the old name, so a copied example now warns; the fix is a rename. Three smaller deprecations in the same release touch code observability setups tend to own: expo-file-system File.md5 → File.digest(), expo-modules-core NativeArrayBuffer → ArrayBuffer, and @expo/ui iOS backgroundOverlay → background.
REACT DEVTOOLS 8.0 (2026-09-08, verified vs the React DevTools CHANGELOG): the Timeline profiler tab is removed and React profiling moves to the browser's Performance panel, which carries React tracks; the Suspense tab is on by default (see what caused a component to suspend); the browser Elements panel gains a React Element pane mapping the inspected DOM node to its component; <Activity> subtrees are shown and dimmed when hidden.
ROZENITE (2026-09-10, verified vs the GitHub repo and v2.3.0 release notes; version re-checked 2026-09-24 vs npm): fills the gap between "React DevTools shows me the component tree" and "I need a whole APM". Works on Expo and bare RN across Metro and Re.Pack; Rozenite >=2.0 needs Expo SDK 52+ / RN 0.76+ / Re.Pack 5.2+. Reaches Lynx via rspeedy and RN Web via a browser extension (both experimental). About 656 stars, active since 2025-07 — young but past the prototype stage. Agent angle: `rozenite agent tap` streams plugin/runtime state to stdout, the same job the Reactotron MCP row in RB-E-AI-DEVTOOLS does, so on an RN project it serves both the human debugging surface and the agent one.
CROSS-REFERENCES: RB-E-OTA owns staged rollout and rollback (the action side of Observe's attribution); RB-E-AI-DEVTOOLS owns agent-facing runtime inspection (Reactotron MCP); RB-E-META-FRAMEWORKS owns rendering strategy behind the web metrics.
HISTORY: 2026-09-24 REOPENED: version receipts re-checked vs npm; Bugsnag 9.0.0 (2026-09-22) and the web Sentry SDK major (@sentry/react 11) recorded. 2026-09-21 REOPENED: expo-observe AppMetrics deprecated → Observe; SDK 58 error-reporting surface. 2026-07-10 GAP CLOSED: @callstack/inspector added (release-build profiling, verified vs npm).
Canonical reading
Editorial annotations on why each piece matters — the articles themselves are the originals; read them there.
Production heap-diagnosis methodology on a real case: three Next.js framework leaks between 15.5 and 16.2 (router LRU cache ignoring URL-key size — hundreds of MB proportional to unique routes; RSC streams retained on client disconnect, worst on Node 22/24; middleware timeout IDs never released), all fixed by 16.3.0. The durable half is the method — chart process.memoryUsage() against candidate variables (unique URLs, traffic, middleware) to match the growth SIGNATURE before assigning blame, then diff heap snapshots and read retainer chains (LRUNode / reactServerStream / TimeoutsManager name the culprits). Also: raising heap limits is a band-aid against a monotonic slope, and on serverless memory problems surface as latency, so profile that instead.
Adapts web Core Web Vitals (TTFF/TTI/FID) into a React Native performance hook with composite scoring, from a real ViewJob rollout. A durable blueprint for measuring (not just crash-reporting) RN performance in production.
Web-side production-perf diagnosis from real consulting: a single hydration mismatch makes React recreate the DOM, and because LCP only tracks NEW elements, the remounted (font-swapped, larger) text re-triggers LCP at hydration time — green→red with no obvious cause. Durable lessons: keep server/client renders identical, scope unavoidable mismatches with Suspense, and know how the metric itself measures (the metric mechanics are the observability half — the rendering-strategy background lives in RB-E-META-FRAMEWORKS's readings). The web counterpart to the Indeed RN piece above.
The reviewed long-form essay behind this entry — the why, not a how-to. Also on GitHub.
About observability — three questions production must answer
Diataxis: Explanation. This page builds understanding of the monitoring landscape — the
reasoning behind the picks. It is not a setup guide. CI gating is RB-E-DX; update delivery
is RB-E-OTA; web rendering strategy behind the metrics is RB-E-META-FRAMEWORKS.
The one principle that organises everything: you can't fix what production won't tell you
Local testing answers "does it work here"; observability answers "what is it doing to users."
The landscape stops being a vendor list once you see it as three distinct questions, each
needing its own instrumentation:
Did it crash? — error/crash reporting. Table stakes, and subtler than it looks on RN,
where a JS exception, a native crash, and a startup crash before the JS loads are three
different animals.
Is it slow? — performance measurement. Needs metrics, not vibes: startup time, frame
drops, interaction latency (the CWV-for-RN reading), and on web the hydration/LCP mechanics.
Which release did it? — attribution. Mobile ships by store release and OTA update
(RB-E-OTA); a regression is only actionable when telemetry names the build or update that
introduced it.
Most teams buy tool #1 and believe they have all three.
The default, and why
Sentry for crash + performance monitoring (v8 catches pre-bootstrap crashes); add error
boundaries and wire it up at the production stage.
Sentry earns the default by covering the most of questions 1–2 in one SDK on both platforms —
and v8 fixed RN's classic blind spot: crashes before RN bootstraps (the "instant death on
TestFlight" class) are now captured via sentry.options.json. Error boundaries are the
collection points that make React errors reportable instead of blank screens — which is why the
corpus's source-scan flags production repos with no boundary at all (an uncaught render error
blanks the tree and tells you nothing). "Production stage" is honest calibration: a prototype
doesn't need dashboards; a production app without them is flying blind.
EAS Observe (Expo) — question 3, natively, plus much of question 2: real-session startup,
time-to-interactive and update-apply metrics with every build and OTA update as a marker, so a
regression traces to a specific build or OTA update. Generally available since 2026-08-25
(SDK 55+; per-route metrics on 56+; JS error reporting in preview on 57+). Two limits change how
you adopt it: turning it on needs a new binary, and it does not capture native crashes —
keep Sentry (or your existing reporter) alongside, as Expo itself advises.
Firebase Crashlytics / Bugsnag — established question-1 alternatives; Crashlytics is fine
when you're already on Firebase.
@callstack/inspector — a gap-filler: React-level component profiling in release builds
via React DevTools, no native changes. Dev-mode profiling lies about production; this is the
honest lens. Very young (v0.1.x) — treat as experimental.
React DevTools 8.0 — the web profiling workflow moved: the Timeline profiler tab is gone
(8.0.0, 2026-09-08) and React profiling now lives in the browser's Performance panel as React
tracks. Guides that say "open the Timeline tab" predate it.
Rozenite — day-to-day RN inspection panels (network, storage, performance) inside React Native
DevTools; plugins are disabled in production builds.
The measurement readings — Indeed's CWV-for-RN (build the metrics: TTFF/TTI/FID-analogues
with composite scoring) and the 3perf hydration piece (web: one hydration mismatch re-creates the
DOM and silently re-triggers LCP — know how the metric itself measures).
Tradeoffs and failure modes to name out loud
No error boundary in a production app. The corpus's absent-rule exists because it keeps
being found: one uncaught render error blanks the whole tree, uncollected.
Crash reporting mistaken for performance monitoring. Zero crashes and 9-second cold starts
coexist happily. Question 2 needs deliberate metrics, not an SDK's default dashboard.
Shipping OTA without attribution. Fast updates (RB-E-OTA) cut both ways: without
build/update-level telemetry, a bad update is invisible until reviews arrive. Staged rollouts
are only as good as the monitoring that decides go/no-go.
Profiling dev builds. Dev mode disables the optimizations that shape production behavior;
release-build profiling (inspector) or production sampling is the truth.
Vendor lock via instrumentation sprawl. Route custom events through one thin wrapper;
swapping SDKs later shouldn't mean touching every screen.
How it interacts with the rest of the stack
OTA (RB-E-OTA). Staged rollout + abort/rollback is an observability loop: Observe-class
attribution is what makes the rollback decision data instead of panic.
DX (RB-E-DX). CI gates catch regressions before release; observability catches the ones
that ship anyway. Same philosophy — mechanized feedback — different end of the pipeline.
Meta-frameworks (RB-E-META-FRAMEWORKS). Web metrics are rendering-strategy-shaped;
hydration mismatches are a rendering bug that presents as a metrics mystery.
Security (RB-E-SECURITY). Crash/telemetry pipelines carry user data — scrubbing and
data-minimization are part of wiring them, not an afterthought.
In one paragraph
Observability is three questions, not one tool: did it crash (Sentry v8, plus the error
boundaries that make React errors collectable), is it slow (deliberate metrics — CWV-for-RN on
native, hydration/LCP mechanics on web, release-build profiling when you need component truth),
and which release did it (EAS Observe-class attribution across store builds and OTA
updates). It's a production-stage concern that pairs with RB-E-OTA's staged rollouts — fast
shipping without attribution is just fast guessing — and the cheapest first step is the one the
corpus scans for: put an error boundary at the top of the tree and wire it to the reporter.
See also: RB-E-OTA (rollout/rollback is the action side of this loop), RB-E-DX (the
pre-release half of mechanized feedback), RB-E-META-FRAMEWORKS (web rendering behind the
metrics), RB-E-SECURITY (telemetry data hygiene).