Skip to content

Core

Events and failure detection

The typed event stream every sink receives, and how release-health reaches a crash-loop verdict without a crash SDK.

Every sink receives the same typed ReleaseHealthEvents. Each event carries a sessionId and a timestamp; the table below lists what else it means and when it fires.

The event stream

EventFired when
session_startEvery launch, with update id, native version, build number, platform, and cohort
update_downloadedThe adapter reports a new update ready to apply
update_apply_successA probation update was marked healthy
update_apply_failedProbation failed (crash loop or timeout chain), with a reason
crashA fatal JS error was caught in this session
healthymarkHealthy() was accepted, with time-to-healthy
rollback_recommendedAn update was judged failed, with reason crash-loop or apply-failed
rollback_executedautoRollback ran the adapter's rollback(), with a success flag

These events are what a sink consumes. The HTTP sink posts them as JSON; the Sentry sink turns them into tags and breadcrumbs.

How failure detection works

Crash detection needs no crash SDK. The native module (a TurboModule in Swift/Objective-C and Kotlin, persisting to UserDefaults and SharedPreferences) records a clean-exit flag on graceful background or terminate. A launch that follows neither is treated as an abnormal exit. Fatal JS errors are additionally caught in-session through the global error handler.

The engine counts consecutive failed probation launches and judges at launch start, so the crash-loop verdict lands even when the crash itself killed the process before anything could be sent. Dev reloads never count (__DEV__ short-circuits probation), and an intentional reloadAsync-style apply mid-probation restarts the probation timer instead of counting as a failure, provided you called notifyReload() first.

What the heuristic is, honestly

This detects "the app did not exit cleanly", not "the app crashed at this stack trace". It correlates; it does not symbolicate. Force-quits, OS memory kills, and device reboots read as abnormal exits too, and during probation one such exit counts against the update like a crash.

Pair it with a crash reporter for ground truth. The Sentry sink exists exactly for that: it tags every Sentry issue with the update id and health status so the two systems tell one story. Read Limitations before you rely on the verdict.