Ansible Handlers Explained: How to Use and Flush Handlers
By Luca Berton · Published 2024-01-01 · Category: troubleshooting
How to flush the execution of an Ansible handler after the notification task using the ansible.builtin.meta module.

When do Ansible Handlers run?
> By default, handlers run after all the tasks in a particular play have been completed.
See also: Ansible Multiple Handlers: Run Handlers in Sequence (listen, notify)
Links
• https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html#controlling-when-handlers-runDemo
Let's jump into a real-life example of how to run an Ansible Handler immediately.
First of all, we need a task changed status. The simplest Ansible module returning a "changed" status is Ansible command module with a Linux command, like "uptime".
Let's suppose we would like to execute a handler immediately after the changed status and not wait for the next task using the ansible.builtin.meta module.
Initial Playbook
• flush_before.yml---
- name: handler Playbook
hosts: all
tasks:
- name: changed status
ansible.builtin.command: "uptime"
notify: message 1
- name: message 2
ansible.builtin.debug:
msg: message 2
handlers:
- name: message 1
ansible.builtin.debug:
msg: message 1
inventory
localhost ansible_connection=local
Initial Execution
As you can notice the message 1 handler is executed AFTER the last task (message 2) of the Play being executed.
$ ansible-playbook -i inventory flush_before.yml
PLAY [handler Playbook] *********************************************************************
TASK [Gathering Facts] ******************************************************************
ok: [localhost]
TASK [changed status] *******************************************************************
changed: [localhost]
TASK [message 2] ************************************************************************
ok: [localhost] => {
"msg": "message 2"
}
RUNNING HANDLER [message 1] *************************************************************
ok: [localhost] => {
"msg": "message 1"
}
PLAY RECAP ******************************************************************************
localhost : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Modified Playbook
Let's add the ansible.builtin.meta Ansible module after the first task.
---
- name: handler Playbook
hosts: all
tasks:
- name: changed status
ansible.builtin.command: "uptime"
notify: message 1
- name: flush
ansible.builtin.meta: flush_handlers
- name: message 2
ansible.builtin.debug:
msg: message 2
handlers:
- name: message 1
ansible.builtin.debug:
msg: message 1
Modified Execution
As you can notice the message 1 handler is executed BEFORE the last task (message 2) of the Play being executed.
% ansible-playbook -i inventory flush.yml
PLAY [handler Playbook] *********************************************************************
TASK [Gathering Facts] ******************************************************************
ok: [localhost]
TASK [changed status] *******************************************************************
changed: [localhost]
TASK [flush] ****************************************************************************
RUNNING HANDLER [message 1] *************************************************************
ok: [localhost] => {
"msg": "message 1"
}
TASK [message 2] ************************************************************************
ok: [localhost] => {
"msg": "message 2"
}
PLAY RECAP ******************************************************************************
localhost : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Conclusion
Now you know how to run immediately an Ansible Handler in a Playbook.
See also: Ansible ansible.builtin vs ansible.legacy: Collection Namespaces Explained
Related Articles
• the Ansible inventory deep-dive • listen-based handlers in AnsibleWhen to Flush Handlers
- name: Deploy and configure application
hosts: all
become: true
tasks:
- name: Deploy new config
ansible.builtin.template:
src: app.conf.j2
dest: /etc/myapp/app.conf
notify: restart myapp
# Flush handlers NOW — before the next task needs the service running
- name: Force handler execution
ansible.builtin.meta: flush_handlers
- name: Verify service is running
ansible.builtin.uri:
url: http://localhost:8080/health
status_code: 200
retries: 5
delay: 3
handlers:
- name: restart myapp
ansible.builtin.service:
name: myapp
state: restarted
See also: Ansible troubleshooting - VMware Unknown error while connecting to vCenter or ESXi
Handler Patterns
handlers:
# Chain handlers with listen
- name: restart web stack
ansible.builtin.debug:
msg: "Restarting web stack"
listen: "web config changed"
- name: restart nginx
ansible.builtin.service:
name: nginx
state: restarted
listen: "web config changed"
- name: restart php-fpm
ansible.builtin.service:
name: php-fpm
state: restarted
listen: "web config changed"
FAQ
When should I use meta: flush_handlers?
Use it when a subsequent task depends on the handler having already run — for example, restarting a service before testing it, or reloading configuration before deploying dependent services.
Do handlers run if the play fails?
By default, no. Use --force-handlers or set force_handlers: true in ansible.cfg to run notified handlers even when the play fails.
Can a handler notify another handler?
Yes, starting from Ansible 2.2. Handlers can notify other handlers, creating a chain of actions.
Category: troubleshooting
Watch the video: Ansible Handlers Explained: How to Use and Flush Handlers — Video Tutorial