# Why a workflow must survive the process dying

Canonical: https://stevenmoriasi.com/blog/enterprise-automation-platform
By [Steven Moriasi](https://www.linkedin.com/in/steven-moriasi/).
Source: https://github.com/steven-moriasi/enterprise-automation-platform
Date: 2025-06-11

## Context

A workflow that cannot be restarted mid-flight is a demo. Tool-calling agents are the same engine with a probabilistic step: if you cannot recover `assign` / `condition` / `emit_event`, you will not recover a model call that timed out after it already posted to a CRM.

[Enterprise Automation Platform](https://github.com/steven-moriasi/enterprise-automation-platform) is the durable half of that problem.

## Decision

PostgreSQL owns executions. Redis is a delivery bus, not the record. The API commits the execution and an outbox row in one transaction. The scheduler publishes. The worker atomically claims only a `queued` execution.

API commit → outbox row → Redis publish → leased claim → success, retry, or dead letter

Transient failures retry with bounded exponential backoff. Exhausted failures become a dead letter an operator can inspect and replay.

## What I rejected

Treating Redis as source of truth, and advertising exactly-once processing. A crash can duplicate a queue message. Connector adapters still need their own idempotency keys. I would rather say that in the README than pretend a queue made the world safe.

## Failure scenario

The worker dies after the broker accepted the message but before the row left `queued`. Restart delivers the duplicate. The claim is a no-op. Work continues from PostgreSQL, not from whatever was in memory.

## Evidence

Compose stack, worker lease tests, fencing tokens, and an operator recovery path for exhausted deliveries.

Inspect: [Repository](https://github.com/steven-moriasi/enterprise-automation-platform) · [Run locally](https://github.com/steven-moriasi/enterprise-automation-platform#readme)

_—by [Steven Moriasi](https://www.linkedin.com/in/steven-moriasi/)_
