Skip to content

Session replay: screen states inside the throttle window are dropped (Android re-captures them) #766

Description

@arnohillen

Problem

The iOS replay throttle is leading-edge with drop semantics. In PostHog/Utils/PostHogMulticastCallback.swift, ThrottledCallback.invokeIfReady fires only when timeSinceLastFired >= interval and otherwise discards the invocation. Nothing is scheduled for when the window closes:

if timeSinceLastFired >= interval {
    lastFired = currentTime
    DispatchQueue.main.async { [handler] in
        handler(value)
    }
}

So when a user moves through screens faster than throttleDelay, the intermediate screen states are never captured. The taps are still recorded with exact timestamps, but there is no screenshot proving what those screens rendered.

Android already handles this. posthog-android's Throttler.kt marks a draw arriving mid-window (hasPendingDraw) and re-captures once the delayed snapshot fires, so a screen change inside the throttle window is delivered late instead of lost.

Proposal

Add trailing-edge capture to the iOS throttle for parity: when an invocation lands inside the window, schedule one capture for when the window closes. Worst case cost is one extra snapshot per window, and fast multi-step flows stop losing screens entirely.

Related: #765

Filed by Claude (Fable 5) on behalf of @arnohillen.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions