Terms
| Term | Meaning |
|---|---|
| App | One deployment of your code that hosts workflows, in a project. A push app has an HTTPS endpoint that EZGH calls. A pull app has a task queue that your workers poll. Its ID is a UUID, and its slug starts with wfa_. See Push and pull apps. |
| Workflow | A function in your code, registered under a name that matches ^[A-Za-z0-9_-]{1,64}$. A workflow runs only in the app that hosts it. |
| Run | One execution of a workflow, with a JSON input. It has a UUID id that EZGH assigns, and an optional runKey that you choose. |
| Step | A named unit of work inside a workflow: running a function, sleeping, recording a time or UUID, waiting for a callback, or running a child workflow. Each step’s outcome is recorded once. |
| Invocation | One call of your workflow code by EZGH, as an HTTPS request to a push app or a task for a pull worker. A run takes several invocations. |
| Schedule | Starts runs of one workflow on a cron timetable. Its slug starts with wfs_. See Schedules. |
How a run executes
- You start a run with an SDK client or the API. EZGH
records it and answers with the run, status
running. - EZGH invokes your code with the run’s input and the outcomes of the steps recorded so far.
- Your workflow function runs from the start. Each step already recorded returns its recorded result at once, without running again. This is replay.
- At the first step that isn’t recorded, the SDK tells EZGH the step is starting, waits for the acknowledgement, runs it, and records its result. It continues with the next steps the same way.
- At a sleep, a callback wait, a child workflow or parallel steps, the invocation ends. EZGH invokes your code again when there’s something to continue with: the timer fires, the callback is completed, the child ends or the parallel steps finish.
- When the function returns, the run ends
completedwith the return value as its output. When it throws an error, the run endsfailed.
So a run continues after your process crashes, is redeployed or is down for a while: the next invocation replays the recorded steps and carries on. A step whose result wasn’t recorded before a crash runs again, which is why steps run at least once.
Run statuses
| Status | Meaning |
|---|---|
running |
The run is in progress, including while it sleeps or waits |
cancelling |
A cancel was requested; cleanup code may still run steps (Cancellation) |
completed |
The workflow returned; its output can be read |
failed |
The workflow threw an error, or EZGH couldn’t invoke it; it can be retried |
cancelled |
The run was cancelled |
timedOut |
The run went past its time limit |
A run’s steps list each step’s name, kind, status and attempt. Step kinds are run, sleep,
value (now and uuid), callback and invoke. Step statuses are running, retrying,
completed, failed, cancelled, sleeping and waiting. The run’s history,
ListRunEvents, lists every invocation and step outcome
with the deployment that ran it. To find runs, search them.
Determinism
Because the workflow function runs again on every invocation, code outside steps must take the same path every time:
- Put every side effect (an API call, a database write, an email) in a step.
- Read the time and random values through the
nowanduuidsteps, not the clock or a random generator, so a replay sees the same values. - Values that steps return are JSON. The SDK passes a result through JSON before your code sees
it, so the first execution and every replay get the same value: in TypeScript a
Datebecomes a string andundefinedbecomesnull.
Runs continue on whatever code is deployed. Each invocation records your deployment ID, which the SDKs detect on Vercel, AWS Lambda, Cloud Run, Fly.io and Render, or which you set. Before you change a workflow that has runs in progress, read how steps are identified in Steps and determinism.
Run IDs and run keys
idis a UUID that EZGH assigns. It’s in every run URL and is never reused.runKeyis optional and set when you start a run:^[A-Za-z0-9._:-]{1,128}$, unique in the project among runs that haven’t been deleted yet. Starting a run with a key that exists answers the existing run (200) when the workflow and input are the same, and409 run_key_conflictwhen they aren’t. Use it to make starts idempotent, for examplesignup-<userId>.
Runs started by a schedule or as a child workflow have IDs derived from their schedule or parent, so they start exactly once, and no run key.
Data and retention
- Inputs, outputs, step results and callback bodies are JSON, at most 1 MiB each.
- A run’s data is deleted 30 days after it ends.
- A run can last up to a year.