Summary
Allow a flow handler to choose the delay before its next retry.
This supports rate-limited APIs that return Retry-After, polling workflows, and transient failures whose recovery time is known only after the handler runs.
Problem
Flow retry timing is currently derived from the static flow or step retry configuration. A handler can report failure, but it cannot durably pass a delay for that specific retry.
Applications that must honor a provider-selected delay therefore need to own queue visibility changes outside pgflow. That breaks pgflow's orchestration boundary and duplicates retry plumbing.
Proposed behavior
Provide one flow-worker error or equivalent directive:
throw new RetryAfterError(delaySeconds, { cause })
The exact public name is open. The behavior should be:
- pass the selected delay to
pgflow.fail_task;
- use it instead of static exponential backoff when the task remains retryable;
- preserve current retry behavior when no override is present;
- ignore the override when attempts are exhausted and fail the task normally;
- reject invalid, negative, non-finite, or out-of-range delays before the database call;
- store the original error message and cause through the existing failure path.
Keep existing pgflow.fail_task callers compatible by adding an optional argument or overload rather than replacing the current contract.
Open design question: attempt accounting
An intentional delayed retry may represent scheduling rather than a failed attempt. Consider whether the directive should optionally avoid incrementing the attempt count, or reset the attempt count, when the handler selected the retry intentionally.
Do not make this part of the first implementation without a separate decision on semantics, limits, and abuse prevention. The minimum useful feature is an exact per-failure delay override with today's attempt accounting unchanged.
Acceptance criteria
Out of scope
- Permanent-failure error types.
- Final-failure hooks.
- Jitter configuration.
- Mutable retry-policy objects.
- Queue routing.
- Changes to attempt accounting until the open design question is resolved.
Summary
Allow a flow handler to choose the delay before its next retry.
This supports rate-limited APIs that return
Retry-After, polling workflows, and transient failures whose recovery time is known only after the handler runs.Problem
Flow retry timing is currently derived from the static flow or step retry configuration. A handler can report failure, but it cannot durably pass a delay for that specific retry.
Applications that must honor a provider-selected delay therefore need to own queue visibility changes outside pgflow. That breaks pgflow's orchestration boundary and duplicates retry plumbing.
Proposed behavior
Provide one flow-worker error or equivalent directive:
The exact public name is open. The behavior should be:
pgflow.fail_task;Keep existing
pgflow.fail_taskcallers compatible by adding an optional argument or overload rather than replacing the current contract.Open design question: attempt accounting
An intentional delayed retry may represent scheduling rather than a failed attempt. Consider whether the directive should optionally avoid incrementing the attempt count, or reset the attempt count, when the handler selected the retry intentionally.
Do not make this part of the first implementation without a separate decision on semantics, limits, and abuse prevention. The minimum useful feature is an exact per-failure delay override with today's attempt accounting unchanged.
Acceptance criteria
fail_taskcalls remain compatible.Out of scope