Durable step helpers available as input.step inside an Inngest function.
Steps split function work into durable units that can be retried and memoized
by Inngest. Step IDs are hashed with SHA-1 before they are reported to the
executor. When the same step ID appears more than once in a function, the SDK
appends :1, :2, and so on before hashing each repeated occurrence.
Reporting
| SDK call | Reported opcode | Notes |
|---|---|---|
run/3 | StepRun | Used when immediate execution is allowed and the step body runs in the current call request. Includes data, even when the result is nil. |
run/4 | StepRun | Same as run/3, with replay options such as keys: :atoms. |
run/3 | StepPlanned | Used when ctx.disable_immediate_execution prevents running the step body in the current call request. |
run/3 | StepError | Used when an executed step body raises. Includes the serialized error payload. |
targeted stepId | StepNotFound | Returned when a targeted hashed step ID cannot be found during deterministic traversal. |
sleep/3, sleep_until/3 | Sleep | Uses opts.duration for the duration or ISO timestamp. |
wait_for_event/3 | WaitForEvent | Uses opts for event name, timeout, and matching expression. |
invoke/3 | InvokeFunction | Uses the active client ID for module targets, plus opts.payload and optional opts.timeout. |
send_event/3 | StepRun | Implemented as a durable run step around event sending with the active client. |
Memoization
Run and invoke-style steps memoize successful values as %{"data" => value}
and failed values as %{"error" => error}. Successful values are unwrapped
before being returned to user code. Failed memoized steps raise
Inngest.StepError; if that error bubbles out of the function, the SDK returns
it as a non-retriable function error.
Sleep steps are memoized as nil. Wait-for-event steps are memoized as the
received event payload or nil when the wait times out.
Legacy raw run-step values are not supported by the spec-compliant
memoization path. A raw memoized run-step value raises Inngest.StepError so
payload shape problems fail clearly.
Map Keys
Freshly executed run/3 results are returned exactly as user code returns
them. Replayed memoized results come from JSON payloads, so map keys are
strings by default:
%{"foo" => "bar"} =
step.run(ctx, "load", fn ->
%{foo: "bar"}
end)Use run/4 with keys: :atoms when you need to pattern match on atom keys
after replay:
%{foo: "bar"} =
step.run(ctx, "load", fn ->
%{foo: "bar"}
end, keys: :atoms)keys: :atoms converts string keys recursively with
String.to_existing_atom/1. It will not create new atoms. If a memoized key
does not already exist as an atom, the SDK raises Inngest.StepError.
Warning
Atoms are not garbage collected by the Erlang VM. Creating too many atoms can
exhaust the atom table and crash the VM. The SDK intentionally avoids
creating atoms from arbitrary memoized JSON keys. Only use keys: :atoms for
known, bounded response shapes whose atom keys already exist in your
application.
Summary
Functions
Invokes another Inngest function and waits for its result.
Runs a durable step.
Runs a durable step with replay options.
Sends one or more events as a durable step.
Pauses the function for a duration such as "10s", "5m", or "1h".
Pauses the function until a date or timestamp.
Waits for another event before continuing.
Types
@type datetime() :: binary() | DateTime.t() | Date.t() | NaiveDateTime.t()
@type id() :: binary()
@type run_opt() :: {:keys, :strings | :atoms}
Functions
@spec invoke(Inngest.Function.Context.t(), binary(), map()) :: map()
Invokes another Inngest function and waits for its result.
Options include:
| Option | Description |
|---|---|
:function | Function module to invoke. |
:data | Payload data for the invoked function. |
:v | Optional event payload version. |
:timeout | Optional timeout for the invocation. |
New invocations report an InvokeFunction opcode. Replayed memoized results
are unwrapped from %{"data" => value} or raised as Inngest.StepError from
%{"error" => error}.
When :function is a module, the reported function ID is built from the
active Inngest.Client in the invocation context. This keeps step invokes
aligned with the client used to register and serve functions.
@spec run(Inngest.Function.Context.t(), id(), fun()) :: any()
Runs a durable step.
Fresh execution returns the value from func exactly as provided by user code.
When the step has already been memoized, the SDK unwraps the executor payload
from %{"data" => value} and returns value without reporting another
opcode.
Use run/4 when replayed memoized map keys need to be converted to atoms.
@spec run(Inngest.Function.Context.t(), id(), fun(), [run_opt()]) :: any()
Runs a durable step with replay options.
Supported options:
| Option | Values | Default | Description |
|---|---|---|---|
:keys | :strings, :atoms | :strings | Controls map keys for replayed memoized %{"data" => value} payloads. |
keys: :atoms recursively converts string keys using
String.to_existing_atom/1. It does not create atoms and raises
Inngest.StepError if a replayed key does not already exist as an atom.
This option only applies to replayed memoized data. Freshly executed results
are returned exactly as func returns them.
Sends one or more events as a durable step.
The event send is executed once, then reported as a StepRun containing the
sent event IDs. Replayed memoized results return the stored event-send result
without sending again.
During function execution, sends use the active invocation client so event URL, event key, mode, and environment headers match the served app.
@spec sleep(Inngest.Function.Context.t(), id(), binary()) :: nil
Pauses the function for a duration such as "10s", "5m", or "1h".
The SDK reports a Sleep opcode with opts.duration. Once the sleep is
memoized by the executor, replay returns nil.
@spec sleep_until(Inngest.Function.Context.t(), id(), datetime()) :: nil
Pauses the function until a date or timestamp.
Accepts a binary timestamp, DateTime, Date, or NaiveDateTime. The SDK
validates and reports the timestamp as a Sleep opcode with opts.duration.
Once memoized by the executor, replay returns nil.
@spec wait_for_event(Inngest.Function.Context.t(), id(), map()) :: map()
Waits for another event before continuing.
Options may include:
| Option | Description |
|---|---|
:event | Event name to wait for. |
:timeout | Maximum wait duration. |
:if | Spec expression used to match the incoming event. |
:match | Elixir shorthand that renders to event.<match> == async.<match>. |
Replayed memoized values return an Inngest.Event when an event was received
or nil when the wait timed out.