Architecture
An engine that records every state change and replicates it across a Raft cluster. Two stores (engine and flow), one execution model, and plans that do not change while they run.
Overview
Argyll is a distributed engine built on Raft consensus and event sourcing. A cluster runs three or more engine nodes that share state through a Raft log. Every state change is recorded as an event in an append-only store, and current state is derived by replaying events.
(SDK / curl / web UI)"] Proxy["Reverse proxy
(leader-aware routing)"] N1["Engine node 1"] N2["Engine node 2"] N3["Engine node 3"] EngineStore["EngineStore
(catalog, cluster health)"] FlowStore["FlowStore
(flow state)"] Clients --> Proxy Proxy --> N1 Proxy --> N2 Proxy --> N3 N1 -.Raft.- N2 N2 -.Raft.- N3 N1 -.Raft.- N3 N1 --> EngineStore N1 --> FlowStore
Two Stores
State lives in two Raft-backed Timebox stores:
- EngineStore holds the Step catalog and cluster health, including per-node health
- FlowStore holds Flow state and Flow indexes
Both are event-sourced. Writes commit through the Raft log on quorum; reads are served from the local node’s projected state.
The Engine
Each node runs the same engine. It:
- Validates and stores Step definitions in the catalog
- Computes Execution Plans from Goal Steps and Step dependencies
- Dispatches Step invocations over HTTP
- Records Work Item progress as events
- Advances Flows based on committed state only
A node can read from local state at any time. Writes route to the Raft leader. The X-Argyll-Raft-State response header on GET /health tells a load balancer which node is the leader.
Event Sourcing
Every state change is recorded as an event before any side effect happens, where a side effect is a change outside Flow state such as charging a card or updating a database. State is reconstructed by replaying the event log. This gives:
- Determinism: same events always produce the same state
- Durability: committed state survives retries and restarts; services use receipt tokens to prevent duplicate external changes
- Auditability: a complete record of why a Flow did what it did
See Event Sourcing for event types and aggregates.
Step Invocation
Steps are external HTTP services (or in-engine scripts). The engine calls them; they don’t call each other. Each invocation carries Argyll-Flow-ID, Argyll-Step-ID, and Argyll-Receipt-Token headers. Async Steps additionally receive Argyll-Webhook-URL for callbacks.
The receipt token is the engine’s idempotency key. Idempotency means a repeated request does not repeat a side effect. Duplicate webhook completions for the same token are rejected automatically. Services must also use this token when an invocation could otherwise repeat a side effect.
Memoization Cache
Steps marked memoizable: true cache their results in a least-recently-used (LRU) cache local to each engine instance. The cache is in memory only, is not shared across nodes, and is not preserved when the process restarts.