Skip to content

⏳ Temporal Replay

Record the entire flow lifecycle as a replayable timeline. Scrub forward and backward through time, seeing exact state snapshots at any point.
idle

The Concept

Debugging async bugs is hard because they're temporal — timing matters. Temporal Replay captures every state transition with high-resolution timestamps, letting you scrub through flow history like a video.

Quick Start

ts
const { data, execute } = useFlow(checkout, {
  temporal: {
    record: true,
    maxSnapshots: 200,
    includeArgs: true,
  },
});

Time-Travel API

ts
import { TemporalRecorder } from "@asyncflowstate/core";

const recorder = new TemporalRecorder("checkout", { record: true });

// After several executions...
const timeline = recorder.getTimeline();
// [{ index: 0, trigger: 'start', state: {...}, delta: 0 }, ...]

// Scrub to any point
const snapshot = recorder.scrubTo(5);
console.log(snapshot.state); // Exact state at snapshot #5

// Step forward/backward
recorder.stepForward();
recorder.stepBackward();

// Async playback at 2x speed
for await (const frame of recorder.playback(2)) {
  renderState(frame.state);
}

Export & Share

ts
const exported = recorder.export();
// {
//   flowName: 'checkout',
//   totalDuration: 3200,
//   snapshotCount: 15,
//   snapshots: [...]
// }

// Share as JSON for bug reports
const json = JSON.stringify(exported);

Snapshot Contents

Each snapshot captures:

FieldDescription
indexMonotonic counter
timestampHigh-resolution performance.now() value
stateDeep clone of the flow state at this moment
triggerWhat caused this snapshot (start, success, error, retry, etc.)
deltaMilliseconds since previous snapshot
argsOptional action arguments (if includeArgs: true)

Performance

Snapshots use structuredClone() for isolation. The recorder enforces a maxSnapshots limit (default: 200) to prevent memory issues.

Built with by AsyncFlowState Contributors
Open Source · MIT License