afterExecution
Run tasks after a flow execution completes.
afterExecution
tasks run once a flow has finished, allowing you to act on the final execution status.
afterExecution
property
afterExecution
is a block of tasks that run after the flow ends. You can use it to run conditional tasks based on the final state, such as SUCCESS or FAILED. This is especially useful for custom notifications and alerts. For example, you can combine afterExecution
with the runIf
property to send different Slack messages depending on the execution state.
id: alerts_demonamespace: company.team
tasks: - id: fail type: io.kestra.plugin.core.execution.Fail
afterExecution: - id: onSuccess runIf: "{{execution.state == 'SUCCESS'}}" type: io.kestra.plugin.notifications.slack.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.notifications.slack.SlackIncomingWebhook url: https://hooks.slack.com/services/xxxxx messageText: "Oh no, {{flow.namespace}}.{{flow.id}} failed!!!"
afterExecution
vs finally
afterExecution
and finally
are both end-of-flow constructs, but they serve different purposes.
The afterExecution
property differs from the finally
property because:
finally
runs tasks at the end of the flow while the execution is still in aRUNNING
state.afterExecution
runs tasks after the execution finishes in a terminal state like SUCCESS or FAILED.
Use finally
for cleanup operations that should always run, regardless of the outcome. See the finally
documentation for examples. When follow-up actions depend on the final state, use afterExecution
to capture the result.
To demonstrate, take the following flow that uses both finally
and afterExecution
:
id: state_demonamespace: 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
After executing the above, you can see that the finally
task has a status of RUNNING while the afterExecution
task says FAILED.
Best practice: Use afterExecution
when you need to act on the final state of an execution. Use finally
when you need to ensure cleanup happens regardless of state.