Skip to main content

12. History and archive

Stores and lifetimes

StoreContentsServiceLifetime
Live stateWhat a run needs to continue: task statuses, timers, awaited eventsDurable Task SchedulerUntil the run ends, then purged after 7 days
HistoryOne row per run and per task; logs; event executions; poll dataAzure SQL13 months by default, settable per workflow name
PayloadsInputs and outputs above the size thresholdBlobSame as history
ArchiveFinished runs past retention, one JSON file eachBlob, cool tier, archive tier after 12 monthsIndefinite

Every read by the API or the UI goes to Azure SQL or the archive. Nothing reads live state directly.

History tables

workflow_run (workflow_id, name, version, status, correlation_id, priority, input, output,
variables_json, started_at, ended_at, reason, parent_workflow_id, parent_task_id,
owner, instruction_versions_json, idempotency_key, retry_of, restart_of, rerun_of)
task_run (task_id, workflow_id, task_ref, task_type, task_def_name, status, attempt, worker_id,
domain, scheduled_at, started_at, ended_at, input, output, reason,
callback_after_s, poll_count, queue_wait_ms)
task_log (id, task_id, logged_at, line)
poll_data (task_type, domain, worker_id, last_poll_at)
event_execution (id, handler_name, source, message_id, status, action, result_json, at)
workflow_message(workflow_id, seq, payload_json, pushed_at, pulled_at)
task_cache (key, output_json, expires_at)

The engine writes workflow_run at start and end, and task_run at every status change. Task logs are capped at 100 lines per task.

Indexes: (name, status, started_at), (correlation_id), (status, ended_at), and a full-text index on reason. GET /api/workflow/search and GET /api/tasks/search use them. Analytics over history runs on the Fabric mirror of these tables, never on the API.

Redaction

  • maskedFields in a definition lists input and output paths to redact before writing.
  • Values from ${workflow.secrets.*} are resolved at the moment of use and never written to history or logs.

Archival

A daily function selects runs with a terminal status older than the retention period, writes each run with its tasks and logs to archive/{yyyy}/{mm}/{workflow_id}.json, and deletes the rows. GET /api/workflow/{id} reads Azure SQL first and the archive second, so an archived run is still readable.