Error handling and retries in Inngest
Inngest functions automatically retry failed work, persist step state, and let you decide what should happen when a retry cannot recover. This means transient errors like network timeouts, API outages, database locks, and deploy interruptions can be retried without re-running work that already completed.
Use Inngest error handling in four layers:
- Automatic retries retry failed functions and steps with backoff.
- Step-level error handling lets you catch failed steps with native language features such as
try/catch. - Failure handlers run after a function exhausts all retries.
- Rollbacks and idempotency keep side effects safe when work is retried.
Each step.run() has its own retry counter. When a step succeeds, its result is saved and reused on later executions, so retries continue from the failed step instead of replaying every completed operation.
Error handling options
Automatic retries
Configure how many times Inngest retries a function or step after it throws.
Failure handlers
Run cleanup, alerts, or compensating logic after all retries are exhausted.
Step-level rollbacks
Catch a failed step and run fallback or rollback logic without failing the entire workflow.
How retries work
By default, Inngest retries a function or step up to four times in addition to the initial attempt. You can customize this with the retries option on your function, or set retries: 0 when a function should not retry.
Retries happen at the step boundary:
- If code inside a
step.run()throws, Inngest retries that step. - If the retry succeeds, the function continues from that point.
- If the step exhausts retries, it fails and throws back into your function.
- If previous steps already succeeded, their saved results are reused and not re-run.
Throw a non-retriable error when an error is permanent and should bypass remaining retries, such as invalid user input or a missing record that will not become available later.
Errors vs. failures
Inngest helps you handle both errors and failures:
- An error is an exception thrown by your function or step. Errors cause retries while attempts remain.
- A failed step is a step that has exhausted all retry attempts. You can catch it with native language error handling.
- A failed function is a function run that has exhausted retries or received an unhandled failed step. It is marked as failed in the Inngest UI.
Use failure handlers when you need a final callback after every retry is exhausted. Use rollbacks when you want to handle one failed step and continue or compensate inside the same workflow.
Keep retried work idempotent
Retried code should be idempotent, which means running it more than once does not create duplicate or inconsistent side effects. For example, inserting a new user can create duplicates if the first write succeeded but the response timed out. Upserting a user, using deterministic IDs, or checking for existing records before writing are safer retry patterns.
Learn how to write retriable steps safely in the handling idempotency guide.
FAQ
Does Inngest retry functions automatically?
Yes. Inngest retries failed functions and steps by default. The default is four retries after the first attempt, and you can change the retry count in the function configuration.
Are retries applied to the whole function or each step?
Retries are applied to each step independently. A failed step.run() can retry without re-running earlier successful steps because Inngest persists each completed step result.
How do I handle a step that fails after all retries?
Wrap the step in native language error handling such as try/catch, then run fallback logic, a rollback step, or a different provider. See step-level rollbacks.
How do I run code after a function fails permanently?
Use a function-level onFailure handler, or listen for the inngest/function.failed system event to centralize failure handling across an environment.