Ansible Handler notify vs register

So after reading Ansible docs, I found out that Handlers are only fired when tasks report changes, so for example:

some tasks ...
notify: nginx_restart

# our handler
- name: nginx_restart

vs

some tasks ...
register: nginx_restart

# do this after nginx_restart changes
when: nginx_restart|changed

Is there any difference between these 2 methods? When should I use each of them? For me, register seems to have more functionality here, unless I am missing something...


There are some differences and which is better depends on the situation.

Handlers will only be visible in the output if they have actually been executed. Not notified, there will be no skipped tasks in Ansibles output. Tasks always have output no matter if skipped, executed with change or without. (except they are excluded via tags/skip-tags)

Handlers can be called from any role. This gets handy if you have more complex roles which depend on each other. Let's say you have a role to manage iptables but which rules you define is actually depending on other roles (e.g. database role, redis role etc...) Each role can add their rules to a config file and at the end you notify the iptables role to reload iptables if changed.

Handlers by default get executed at the end of the playbook. Tasks will get executed immediately where they are defined. This way you could configure all your applications and at the end the service restart for all changed apps will be triggered per handler. This can be dangerous though. In case your playbook fails after a handler has been notified, the handler will actually not be called. If you run the playbook again, the triggering task may not have a changed state any longer, therefore not notifying the handler. This results in Ansible actually not being idempotent. Since Ansible 1.9.1 you can call Ansible with the --force-handler option or define force_handlers = True in your ansible.cfg to even fire all notified handlers after the playbook failed. (See docs)

If you need your handlers to be fired at a specific point (for example you configured your system to use an internal DNS and now want to resolve a host through this DNS) you can flush all handlers by defining a task like:

- meta: flush_handlers

A handler would be called only once no matter how many times it was notified. Imagine you have a service that depends on multiple config files (for example bind/named: rev, zone, root.db, rndc.key, named.conf) and you want to restart named if any of these files changed. With handlers you simply would notify from every single task that managed those files. Otherwise you need to register 5 useless vars, and then check them all in your restart task.

Personally I prefer handlers. It appears much cleaner than dealing with register. Tasks triggered per register was safer before Ansible 1.9.1.


On the Ansible Variables page, you can see how register works.

Another major use of variables is running a command and using the result of that command to save the result into a variable.

Registered variables are just like facts:

Effectively registered variables are just like facts.

This is very different from notify, which triggers handlers. It does not save or store variables or facts.


with ignore_errors: True you can avoid the failed handler from stopping other handlers defined after it continue to run