larzstate
Durable workflows, sagas, and state machines. Pure Python, zero dependencies.
Two complementary tools for modelling processes that must stay correct even when things crash:
Workflow— an ordered pipeline of steps with durable, resumable execution. Progress is checkpointed after every step, so an interrupted run resumes exactly where it stopped. Steps retry on failure, and a failed workflow compensates (rolls back) its completed steps in reverse — the saga pattern.StateMachine— a finite state machine with guards, actions, and enter/exit callbacks, defined as plain data.
No broker and no database required — bring your own checkpoint store (memory or file, or plug in larzdb).
from larzstate import Workflow
wf = Workflow("checkout")
@wf.step(retries=3)
def reserve(ctx):
ctx["reservation"] = reserve_stock(ctx["items"])
@reserve.compensate
def _(ctx):
release_stock(ctx["reservation"])
@wf.step()
def charge(ctx):
ctx["charge_id"] = charge_card(ctx["amount"])
result = wf.run("order-123", {"items": [...], "amount": 100})
result.status # "completed" — or WorkflowFailed (after rollback)
Why
- Crash-resumable. Kill the process mid-workflow and call
run(run_id)again — completed steps are skipped, execution continues from the first unfinished one. State is checkpointed (and fsync'd, withFileStore) after every step. - Sagas built in. When something fails partway through, the compensations of already-completed steps run in reverse to undo their effects — the standard way to get "all-or-nothing" across systems that don't share a transaction.
- Retries per step. Set
retries(and optionalretry_delay) per step. - Zero dependencies, no infrastructure. No Temporal server, no queue, no DB. A directory (or memory) is enough.
- A clean state machine too. Guards, actions, enter/exit hooks, wildcard transitions, history — as plain, inspectable data.
Install
pip install larzstate
Durable workflows
from larzstate import Workflow, FileStore, WorkflowFailed
wf = Workflow("payment", store=FileStore("workflows/"))
@wf.step(retries=2)
def authorize(ctx): ctx["auth"] = gateway.authorize(ctx["amount"])
@authorize.compensate
def _(ctx): gateway.void(ctx["auth"])
@wf.step()
def capture(ctx): ctx["capture"] = gateway.capture(ctx["auth"])
try:
wf.run("txn-42", {"amount": 5000})
except WorkflowFailed as e:
e.step # which step failed
e.cause # the exception
e.compensated # whether rollback ran
- The shared, mutable
ctxdict flows through every step and is part of the checkpoint, so resumed runs see the same state. - On resume, pass just the
run_id— the checkpointed context is authoritative.
State machines
from larzstate import StateMachine
sm = StateMachine(initial="draft", transitions=[
{"event": "submit", "from": "draft", "to": "review"},
{"event": "approve", "from": "review", "to": "published",
"guard": lambda m, **k: k["by"] == "editor"},
{"event": "archive", "from": "*", "to": "archived"},
])
sm.trigger("submit") # -> "review"
sm.can("approve") # True
sm.trigger("approve", by="editor") # guard passes -> "published"
sm.history # ["draft", "review", "published"]
Supports guard, action, on_enter/on_exit callbacks, wildcard from: "*",
and allowed_events().
Scope
larzstate runs workflows in-process — it's the durable orchestration core, not a distributed cluster. Pair it with larztask to run workflows off a queue, or larzdb as a store. It gives you exactly-once-ish step semantics via checkpointing and idempotent resume — the hard part — without any infrastructure.
Tests
python -m unittest discover -s tests -v # 16 tests incl. crash-resume + saga
The Larz stack
Pure-Python, zero-dependency building blocks:
- larz — money-native web framework
- larzchain — from-scratch PoW blockchain
- larzmoney — exact, penny-perfect money
- larzcrypt — pure-Python cryptography toolkit
- larzdb — crash-safe embedded database
- larzagent — zero-dep AI agent framework
- larzchart — data to inline SVG charts
- larzmark — Markdown + SEO static sites
- larztask — durable background job queue
- larzvault — encrypted secrets manager
- larzvm — deterministic gas-metered VM
- larzcache — LRU/TTL/tiered caching
- larzvalidate — schema validation
- larzid — decentralized identity
- larzrpc — JSON-RPC over HTTP
- larzstate — this library
License
MIT © larz-scripter
Metadata
Release files for larzstate 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| larzstate-0.1.0.tar.gz | 10.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| larzstate-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 19.7 kB
Release files / larzstate-0.1.0.tar.gz
| Download URL | larzstate-0.1.0.tar.gz |
|---|---|
| Size | 10.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a868d01cfd6b16f2b82c3921bf553c458c9d6819e39dd73da4f6a71d62c8f3f1
|
|
BLAKE2b-256 checksum How to use checksums |
b20826e9c9fc6674d6e30aebb4a3f4fe08d89c131cd0d0b257ff21bf91271441
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / larzstate-0.1.0-py3-none-any.whl
| Download URL | larzstate-0.1.0-py3-none-any.whl |
|---|---|
| Size | 9.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9ecfd5c8fbb5d720a85a60c6b9f011d0cf507d8ebeb54b5f98a1203f50d745d6
|
|
BLAKE2b-256 checksum How to use checksums |
c29499131fb6ea7bc070300d986b9e550ca12ab9317a6c07bfc9db0c9125cad7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Security for larzstate 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.