Event Sourcing
All state in Argyll lives in event logs that only grow. Each aggregate records changes for one resource, and each projection is current state produced by applying those events in order. Includes the full event-type catalog.
Foundation
Every state change in Argyll is recorded as an event in a log that only grows. A projection is current state rebuilt by applying events in order, never stored separately. This makes results repeatable, preserves state after failures, and provides a complete audit trail.
Aggregates
Events are organized into aggregates: one event stream for one resource, identified by an ID path:
| Aggregate ID | Contents |
|---|---|
["catalog"] | Registered step definitions |
["cluster"] | Per-step health across the cluster |
["flow", "flow-id"] | One flow’s execution history |
Event Types
Catalog (["catalog"])
step_registeredstep_unregisteredstep_updated
Cluster (["cluster"])
step_health_changed
Flow Lifecycle (["flow", "flow-id"])
flow_startedflow_completedflow_failedflow_deactivated
flow_completed and flow_failed establish an outcome that callers can use immediately: no new Steps start, but work that has already started may still produce side effects (changes to external systems) and compensation may still run. flow_deactivated is recorded only after no pending, active, or compensating Work Items remain.
Step Execution (["flow", "flow-id"])
step_startedstep_completedstep_failedstep_skipped
Work Items (["flow", "flow-id"])
work_startedwork_succeededwork_failedwork_not_completedwork_retry_scheduleddispatch_deferred— raised when a node cannot dispatch work, retry, or compensation locally; propagates to all nodes so one with a healthy path to the step can pick it up
Compensation (["flow", "flow-id"])
comp_startedcomp_succeededcomp_failedcomp_retry_scheduled
Compensation event names use the short comp_* prefix. The Work Item status set by comp_failed is compensation_failed; it is a state value, not an event name.
Attributes (["flow", "flow-id"])
attribute_set
Side Effects Follow Committed State
The engine writes the event before it triggers any external action. If a node crashes mid-write, the event either committed (and the work runs after recovery) or it didn’t (and nothing ran). Retries resume from the last committed state, with no double execution from missing acks.
A terminal outcome does not mean side effects have stopped: a caller can need the outcome as soon as flow_completed or flow_failed is recorded while previously started work or compensation is still running.
State Reconstruction
A Flow’s current state is the result of applying all its events in order. You can:
- Replay any flow’s event log to inspect its history
- Subscribe to live events via WebSocket to track execution in real time
- Verify why a flow reached its current state by reading the event sequence
Subscribing
The WebSocket API streams events as they occur. Subscribers can filter by aggregate ID and event type, and request the current state before new events are streamed. See the WebSocket API for the protocol.