Skip to content

Time-Travel Debugging

Time-travel debugging lets you inspect a workflow run’s state at any historical point in time. The system reconstructs snapshots on the fly by replaying audit events up to the requested timestamp — no pre-computed snapshots are stored.

Time-Travel Debugging — showing state reconstruction at any point and diff between two moments

Prerequisites

Time-travel requires recording to be enabled on the function. Only runs from recording-enabled functions have the audit events needed for state reconstruction.

import { ironflow } from "@ironflow/node";
const processOrder = ironflow.createFunction(
{
id: "process-order",
recording: true, // enable recording, it is disabled by default
recordingRetention: "90d",
triggers: [{ event: "order.placed" }],
},
async ({ event, step }) => {
const validated = await step.run("validate", async () => {
return validateOrder(event.data);
});
const charged = await step.run("charge", async () => {
return chargeCard(validated);
});
return { validated, charged };
},
);

Dashboard

Open a run’s detail page. When the function has recording enabled, a timeline scrubber appears at the top of the page.

  1. Scrub to a point in time — click or drag on the timeline to see the run’s state at that moment. The step list updates to show which steps had completed, their outputs, and the run’s status.
  2. Ghost steps — steps that had not yet executed at the selected time appear dimmed. This makes it easy to see what was still ahead.
  3. Diff view — select two timestamps on the timeline to compare the run’s state between them. The diff highlights which step outputs changed (useful for spotting hot-patches or injected values).
  4. Return to live — click the Live button to leave time-travel mode and return to the real-time view.

TUI

The ironflow inspect command supports time-travel via --at and --replay flags.

Frozen snapshot

Inspect the run’s state at a specific timestamp:

Terminal window
ironflow inspect run_abc123 --at "2024-01-15T10:30:00Z"

The TUI renders the run as it existed at that moment. Steps completed after the timestamp appear as ghost steps (dimmed).

Frame-by-frame replay

Step through the run’s audit events one at a time:

Terminal window
ironflow inspect run_abc123 --replay

Use --all-events to include step.started events (omitted by default to reduce noise):

Terminal window
ironflow inspect run_abc123 --replay --all-events

Key bindings

KeyAction
or lNext frame (next audit event)
or hPrevious frame
j or Next step in list / scroll detail
k or Previous step in list / scroll detail
gGo to first frame
GGo to last frame
TabSwitch between steps and detail panels
qQuit

SDK API

Get run state at a timestamp

Reconstruct the full run state as it existed at a specific point in time.

import { createClient } from "@ironflow/node";
const client = createClient({ serverUrl: "http://localhost:9123" });
const state = await client.getRunStateAt("run_abc123", new Date("2024-01-15T10:30:00Z"));
console.log(state.runId); // "run_abc123"
console.log(state.status); // "running" | "completed" | "failed" | ...
console.log(state.steps); // Array<{ id, name, status, output }> — completed steps at that moment
console.log(state.timestamp); // ISO string of the requested timestamp

Get run timeline

Fetch the full list of audit events for a run. This is what powers the dashboard’s timeline scrubber.

const events = await client.getRunTimeline("run_abc123");
for (const event of events) {
console.log(`${event.timestamp} ${event.eventType} ${event.stepName}`);
}

Get step output at a timestamp

Retrieve a specific step’s output as it existed at a point in time. Useful for checking what a step returned before a hot-patch was applied.

const output = await client.getStepOutputAt(
"run_abc123",
"step_001",
new Date("2024-01-15T10:30:00Z"),
);
console.log(output.stepId); // "step_001"
console.log(output.output); // the step output at that time
console.log(output.timestamp); // ISO string of the requested timestamp

Limitations

  • Recording required — time-travel is only available for functions with recording: true. Runs created before recording was enabled have no audit events to reconstruct from.
  • Query-time reconstruction — state snapshots are reconstructed on the fly by replaying audit events. There are no pre-computed snapshots. For runs with a very large number of audit events, reconstruction may take longer.
  • Retention applies — audit events are subject to the function’s recordingRetention policy. Once events are cleaned up, time-travel for those runs is no longer possible.

What’s Next?