# Durable workflow spike (`id_effect_workflow`)
This chapter describes the **experimental** `id_effect_workflow` crate: a **SQLite-backed**, **append-only** log of completed steps that supports **single-process restart resume** — the Phase **G** spike aligned with `docs/effect-ts-parity/phases/phase-g-cluster-workflow.md`.
## What problem it solves
Long-running business processes often need **at-least-once** execution with **stable outputs** per logical step. After a crash, a process should **not** repeat side effects for steps that already completed successfully.
`DurableWorkflowLog` persists each completed `(workflow_id, seq)` with a JSON payload. On restart, `run_step_typed` **returns the stored value** instead of invoking the closure again.
## What it deliberately does *not* solve
- **Distributed cluster execution** (no membership, no shard routing).
- **Multi-writer** correctness without external coordination (add your own leasing or use an orchestrator).
- **Compensation / saga policies** beyond what your application encodes in ordinary Rust.
For most production **multi-service** workflows, prefer **Temporal**, **Cadence**, or cloud **Step Functions** — see `docs/effect-ts-parity/phases/phase-g/adr-iep-g-011-temporal-vs-saga-vs-out-of-scope.md`.
## Composition with `Effect`
The log API is **synchronous** (Rusqlite). Keep SQLite on a **blocking** boundary:
- **Inside `effect!`:** perform log IO directly when your interpreter runs on a blocking runtime (see unit tests in `id_effect_workflow`).
- **Async hosts:** wrap calls in `from_async` + `spawn_blocking` (or your platform’s blocking pool) so you do not block async executors.
## Security and replay notes
Persisted JSON may contain **PII** — treat it like any other database column (encryption, retention, access control are application concerns). If stored JSON is **corrupted**, replay surfaces `WorkflowError::Json`; recovery is **policy-driven** (do not silently re-run financial side effects). Details: `docs/effect-ts-parity/phases/phase-g/iep-g-012-security-replay.md`.
## Semver
The crate ships at **0.1.x** as **experimental**; storage layout may change without migrations until a stabilization ADR lands.