Skip to main content
Version: 2.0

Constraints Summary

ConstraintWorkflow codeActivity code
IONot allowedAllowed
Mutable global variablesNot allowedAllowed
Non-deterministic functionsNot allowedAllowed
Carbon::now()Not allowedAllowed
sleep()Not allowedAllowed
External side effectsMove them into activitiesAllowed only when safe to repeat

Workflow code must be deterministic because the engine rebuilds a workflow's state by replaying its history of durable steps — it re-invokes the workflow body, not activities. If the body produces different decisions on replay, the engine cannot reconstruct the workflow's state and continue execution correctly. The workflow body does not need to be idempotent; determinism is the replay requirement.

Activities must be idempotent because activity execution is at-least-once. Retries, lease expiry, and redelivery can cause the same attempt to be observed more than once, and that is first-class behavior rather than an error. Making the activity body or its external target safe to repeat — with an idempotency key, a deterministic target resource, or a naturally idempotent operation — is what keeps duplicate execution from producing duplicate side effects.

See Idempotent vs. Deterministic Workflows for a direct comparison and examples that separate the two properties.

See Execution Guarantees and Idempotency for the public v2 contract behind those terms.