# Workflow orchestration — compensation strategy

## Philosophy

**Distributed rollback is not assumed.** Across databases, processes, or time, the only safe models are:

1. **Single transaction** (same DB) for everything that must be atomic together, or  
2. **Forward recovery**: explicit **compensating** domain commands (reversals, voids, contra movements) with audit, or  
3. **Tolerated eventual consistency** with **reconciliation** and human escalation when repair is ambiguous.

Orchestration chooses among these per workflow; it does not “undo the universe” with a global two-phase commit fantasy.

---

## Reversal rules

- **Reversals** are **domain-owned** commands: e.g. inventory **adjustment** or **reversal movement**, procurement **void/correct receipt** per policy—not raw deletes of posted facts.
- Each compensation **references** the original operation (`corrects_*_id`, `related_correlation_id`) and records **actor** and **reason code**.
- **Posted** financial or regulatory facts follow **finance/legal** reversal rules, not orchestrator convenience.

---

## Retry vs compensate

| Situation | Prefer |
|-----------|--------|
| Transient failure (deadlock, timeout) inside **one** atomic unit | **Retry** the same bounded closure with same **idempotency** key. |
| Step 1 committed, step 2 permanently failed (partner rejected) | **Compensate** step 1 if business requires symmetry, or enter **manual** resolution state—never silent partial success. |
| Unknown outcome (timeout after request sent) | **Reconcile** (query partner, compare local state) before retrying a **non-idempotent** partner call. |

**Rule:** Never **retry** a non-idempotent partner or stock post without a **stable** business idempotency key and a **known** prior outcome.

---

## Compensation vs “delete and redo”

- **Delete and redo** is forbidden for **posted** operational ledgers (stock, receipt posted to supplier, payroll snapshot).
- **Compensate** with additive reversals or controlled void workflows.

---

## Relationship to architecture docs

- Transaction boundaries: `docs/architecture/cross-domain-transactions.md`  
- Failure isolation: `docs/architecture/cross-domain-failure-isolation.md`  
- Idempotency: `docs/architecture/cross-domain-idempotency.md`

---

## Critical stance

**Compensation safety beats rollback assumptions.** If you cannot name the compensating domain command, the workflow is not production-safe.
