How Session Replay Works Under Flutter (When There Is No DOM)
rrweb records the DOM. Flutter has no DOM. Here is how we rebuilt session replay for Flutter on top of the widget tree, and what the privacy trade-offs look like.
The problem with porting web replay to Flutter
Web session replay works because rrweb serializes DOM mutations into a compact event stream that can be re-applied to rebuild the page. Flutter renders through Skia/Impeller to a canvas — there is no element tree to diff, no stylesheet to capture, and no DOM event to hook.
Our approach: widget-tree events
Instead of pixels, the Flutter SDK records semantic events from the widget layer: navigation pushes, scroll offsets, text field edits (masked), taps on keys, and layout deltas. The player side rebuilds an approximation of the screen from those events inside a simulated device frame.
TODO-content: TODO-content: explain the event schema (navigation, scroll, input with masking regex list, gestures), why we chose semantic over raster snapshots (payload size: ~2KB/min vs ~2MB/min, and PII surface), the ~30s pre-exception buffer that ships with each captured exception, and screenshot-on-exception using screenCapture with privacy redaction. Cover the known limitations: custom canvas painting (charts/maps) shows as placeholder regions, platform views and webviews are opaque boxes, and Hero animations are approximated. Link to the flutter docs page and the product page /product/flutter-session-replay.