Run Actions After Flow Completion with afterExecution

For the complete documentation index, see llms.txt. For a full content snapshot, see llms-full.txt. Append .md to any kestra.io/docs/* URL for plain Markdown.

afterExecution tasks run once a flow reaches a terminal state, giving you access to the final execution status for notifications, reporting, or conditional follow-up actions.

The following example branches on the final execution state using runIf:

id: alerts_demo
namespace: company.team
tasks:
- id: fail
type: io.kestra.plugin.core.execution.Fail
afterExecution:
- id: onSuccess
runIf: "{{ execution.state == 'SUCCESS' }}"
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
url: https://hooks.slack.com/services/xxxxx
messageText: "{{ flow.namespace }}.{{ flow.id }} finished successfully!"
- id: onFailure
runIf: "{{ execution.state == 'FAILED' }}"
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
url: https://hooks.slack.com/services/xxxxx
messageText: "Oh no, {{ flow.namespace }}.{{ flow.id }} failed!!!"

afterExecution vs errors

Both run near the end of a flow, but at different moments and for different purposes:

afterExecutionerrors
When it runsAfter the execution reaches a terminal stateWhen a task or flow errors
State visibilitySees the final execution state (SUCCESS, FAILED, etc.)Sees RUNNING; the execution hasn’t settled yet
ScopeFlow level onlyFlow level or local to a flowable task

afterExecution receives the final execution state, making it suitable for status-branched logic (one action for SUCCESS, another for FAILED, another for WARNING). errors runs before the execution reaches a terminal state and handles failure-specific or task-local logic. See the errors documentation for details.

afterExecution vs finally

finally runs while the execution is still RUNNING; it cannot see the terminal state. afterExecution runs after the execution settles, so it sees SUCCESS, FAILED, or WARNING.

id: state_demo
namespace: company.team
tasks:
- id: run
type: io.kestra.plugin.core.log.Log
message: Execution {{ execution.state }} # Will show RUNNING
- id: fail
type: io.kestra.plugin.core.execution.Fail
finally:
- id: finally
type: io.kestra.plugin.core.log.Log
message: Execution {{ execution.state }} # Will show RUNNING
afterExecution:
- id: afterExecution
type: io.kestra.plugin.core.log.Log
message: Execution {{ execution.state }} # Will show FAILED

The finally task logs Execution RUNNING because it runs before the execution reaches its terminal state. The afterExecution task logs Execution FAILED because it runs after. See the finally documentation for more on cleanup patterns.

Execution logs showing the finally task logging Execution RUNNING and the afterExecution task logging Execution FAILED

Was this page helpful?