DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
FREEDOM251

Freedom251 › Blog › Ansible

How to Define and Use Handlers in Ansible Playbooks

By Freedom251 Team · · 11 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

An Ansible handler is a deferred task that runs only when another task reports a change and notifies it. Define handlers in a play’s handlers: section, connect changing tasks with notify, and let Ansible run each notified handler once after the play’s ordinary task sections. This pattern is the safest way to restart a service only when its configuration actually changed.

What an Ansible handler does

A handler is a normal Ansible task with deferred execution. It is skipped unless a notifying task finishes with changed: true. Typical handlers restart or reload a service, rebuild a cache, refresh a daemon, or perform another follow-up action that is necessary only after a change.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Handlers belong to the play-level handlers: section. A task names one with notify. Ansible records the notification while processing the task and normally runs pending handlers after all regular task sections for that play have completed on a host.

This separation keeps configuration deployment idempotent. A template task can run on every playbook invocation, but the service restart happens only when the rendered file differs from the copy already on the host.

#1 Best Overall
Sale
TOZO A1 Wireless Earbuds Bluetooth 5.3 Light Weight in Ear Headphones | IPX5 Waterproof,2 Mics for AI Calls,Immersive Premium Sound Bass Headset with Charging Case,32 EQ via App Black
  • [Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g and features a compact, ergonomic in-ear design made especially for small ears. Secure, low-profile, and comfortable for workouts, all-day wear or overnight sleeping.The ultra-slim profile sits flush in your ear with no hard edges poking or rubbing, so you can even sleep on your side without discomfort.
  • [Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals, balanced mids, and natural stereo sound for music, podcasts, and videos.
  • [Long Battery Life for Daily Use] Get up to 7 hours of playtime on a single charge, with up to 32 hours total using the charging case—ideal for workdays, commuting, and extended listening sessions.
  • [Bluetooth 5.3 & Stable Connection] Bluetooth 5.3 provides fast pairing, stable wireless performance, and reduced dropouts as you move around home or office.
  • [Deep Bass with Clear Vocals] High-performance drivers produce punchy bass while keeping vocals clean and detailed for everyday listening.

The smallest working example

- hosts: webservers
  become: true
  tasks:
    - name: Write the Apache configuration
      ansible.builtin.template:
        src: httpd.j2
        dest: /etc/httpd.conf
        owner: root
        group: root
        mode: '0644'
      notify: Restart Apache

  handlers:
    - name: Restart Apache
      ansible.builtin.service:
        name: httpd
        state: restarted

The template module compares the rendered result with /etc/httpd.conf. If the content is identical, the task is unchanged and the handler is not queued. If the content differs and the file is replaced, the task changes and Ansible queues Restart Apache. The handler then restarts httpd once during that play run.

Handler names are strings, so capitalization and punctuation must match exactly between notify and name. A missing or misspelled name is one of the most common reasons a handler appears not to run.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How handler execution is ordered

Handlers are not executed immediately after the task that notified them. Ansible waits until the normal task sections for the play reach their handler phase. This allows several related changes to be made before a service is restarted.

  • Notifications are coalesced. If five tasks notify the same handler on one host, Ansible runs that handler once, not five times.
  • Definition order wins. When several handlers are pending, Ansible runs them in the order they appear in the handlers: section, even if a task’s notify list names them in a different order.
  • Notifications are host-specific. A change on one host queues its handler for that host; it does not automatically run the handler on every host in the play.
  • A failed host may not reach the normal handler phase. If a host fails or becomes unreachable before the play completes, its pending handlers may be skipped. Plan failure handling separately when a restart must be forced despite a task failure.

Multiple tasks, one restart

- hosts: app
  become: true
  tasks:
    - name: Install the application package
      ansible.builtin.package:
        name: example-app
        state: present
      notify: Restart example app

    - name: Deploy the application configuration
      ansible.builtin.template:
        src: example-app.conf.j2
        dest: /etc/example-app.conf
      notify: Restart example app

  handlers:
    - name: Restart example app
      ansible.builtin.service:
        name: example-app
        state: restarted

When both tasks change, the shared handler still runs only once. If only the package changes, or only the configuration changes, the same single restart is queued.

Notify by handler name

Direct notification is the clearest choice when one event maps to one handler. Use a scalar for one handler or a YAML list for several:

      notify: Restart example app
      notify:
        - Reload proxy
        - Restart example app

All names in a list are queued when the task changes. The list’s order does not override the order in which handlers were defined. Keep names globally unique within the play’s handler scope; duplicate names can make a later-loaded handler shadow an earlier one.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
Smart Watch for Men Women Compatible with iPhone Samsung Android Phone 1.69 inch Full Touch Screen IP68 Waterproof Bluetooh Fitness Tracker Heart Rate/Sleep Monitor (Black)
  • 【IP68 Waterproof Multifunctinal Smart Watch】Torjalph fitness activity tracker smart watch is IP68 waterproof technology ,you can wear it when swimming,handwashing,it's rain-proof which means that you perform multiple exercise modes outside without worrying about sweat or rain corroding your fitness smart watch,and this watch equipped with a 230 mAh large capacity battery magnetic charging ,and this sports activity tracker watch can be used 5-7 days If fully charged.
  • 【Larger 1.83'' Full Screen Watch & Multi-dial Selection】1.83 inch full HD color touch screen smart watch for men / women provides excellent 240*284 resolution image quality ,This Bluetooth smart watch offers a better touch experience and remarkable immersion and ,more than 200 watch faces for you to choose from App"Da Fit ", you can change the dial style according to your mood to wear keeping the world on your wrist
  • 【Accurate Activity Tracker Smart Watch 】sports watch activity tracker uses sweat and dust resistant breathable silicone strap, our Fitness Tracker Smart Watch for Android iOS Phones supports 12 sports modes,walking,running,bicycle,swimming,badminton,basketball,football,rope skipping. This bluetooth calls smart watch for men women is lightweight and stylish, bringing more convenient and relaxing sports experience while also providing more protection.
  • 【Your 24 Hour Personal Daily Health Monitor】Fitness watch for women men full touch screen IP67 waterproof bluetooth smartwatch for Android iOS Phones with heart rate blood pressure monitor multifunction Andriod smart watch with steps counter sleep monitor sports fitness watch, monitoring blood oxygen saturation allows you to understand your physical condition in real time to track fitness progress ,to know your health status in time.
  • 【More Functions Bluetooth Call Smart Watch】This fitness activity smart watch full screen for iPhone and Android phones includes a bunch of new features including:The bluetooth smart watch can hang up the phone, receive and display WhatsAPP /Text /Facebook /Twitter /Messenger reminder.Support sedentary reminder, alarm clock, stopwatch, timer,weather information,music control, remote camera control compatible with Android 5.0 and above or iOS 9.0 and above smartphones.

Use listen topics to decouple events from handler names

A handler can subscribe to a topic with listen. Tasks notify the topic instead of a particular handler name. Every handler listening to that topic runs when the topic is notified.

- hosts: web
  become: true
  tasks:
    - name: Deploy the proxy configuration
      ansible.builtin.template:
        src: proxy.conf.j2
        dest: /etc/proxy.conf
      notify: proxy configuration changed

  handlers:
    - name: Validate proxy configuration
      ansible.builtin.command: /usr/sbin/proxyctl --check /etc/proxy.conf
      listen: proxy configuration changed

    - name: Reload proxy
      ansible.builtin.service:
        name: proxy
        state: reloaded
      listen: proxy configuration changed

Here the task depends only on the stable event vocabulary proxy configuration changed. The implementation can gain or lose handlers without editing every notifying task.

Consideration Direct handler name listen topic
Coupling The task refers directly to one handler’s name. The task refers to an event; handler names can change independently.
Fan-out Several names must be listed when one task should trigger several handlers. One topic can trigger every subscribed handler.
Collision risk Names must be unique across the play and loaded roles. Topic names also need a clear vocabulary, but implementation names are less exposed to tasks.
Best fit Small playbooks where each event has one obvious action. Shared roles or larger playbooks with reusable events and multiple reactions.

A listen topic is an event label, not a handler name. Keep it descriptive and stable. Topics cannot be templated, so choose their text statically.

Flush handlers before the play ends

Sometimes later tasks depend on the service already having the new configuration. Insert the ansible.builtin.meta: flush_handlers task at that point:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
- hosts: app
  become: true
  tasks:
    - name: Deploy application configuration
      ansible.builtin.template:
        src: app.conf.j2
        dest: /etc/example-app.conf
      notify: Restart example app

    - name: Run pending handlers before continuing
      ansible.builtin.meta: flush_handlers

    - name: Run a check against the restarted service
      ansible.builtin.command: /usr/local/bin/example-app-healthcheck
      changed_when: false

  handlers:
    - name: Restart example app
      ansible.builtin.service:
        name: example-app
        state: restarted

flush_handlers runs the handlers notified up to that point. It does not queue handlers that have not yet been notified, and it does not cause unchanged tasks to notify anything. After the flush, new notifications can accumulate and be flushed again later or at the normal end of the play.

Use an early flush deliberately: it can restart a service in the middle of a change sequence, before subsequent files or packages are deployed. If the service needs the complete set of changes, notify normally and let the final handler phase run instead.

Rank #3
New Bee Guitar Cable 10ft Electric Instrument Bass AMP Cord
  • [Low Noise High Fidelity] New bee guitar cord with 22AWG oxygen-free-copper center conductors provides enhanced signal transfer, the PVC insulation material and the high-density stranded copper double shield provide noise rejection for quiet operation
  • [Ideal for Choice] New bee 1/4 straight and right angle metal connectors, ensures a secure connection in any instrument, pedal, or amp jack. L shape great fro on stage guitar stands
  • [Wide Compatible] Suitable for mixer, power amplifier, microphone, effector, decoder, equalizer, electoronic organ, electric guitar, electric bass and other electronic equipments. Widely used in the installation of smart home, karaoke speaker, professional stage audio, etc
  • [Easy Disassemble] Making incidental repairs quick and easy! Very nice, flexible cable
  • [Dont Hesite to Order] 24 hours customer services and professional technology team are standing by

Make sure the notifying task reports a change

Handlers respond to Ansible’s changed status, not to whether a command happened to execute. Modules such as template, copy, package, and lineinfile normally calculate this status for you. For command and shell, define it explicitly when the command’s exit status does not describe whether a meaningful change occurred.

- name: Update generated certificate bundle
  ansible.builtin.command: /usr/local/bin/build-bundle
  register: bundle_result
  changed_when: bundle_result.stdout is search('updated')
  notify: Reload proxy

Without an appropriate changed_when, a command may report changed on every run and cause an unnecessary reload, or report unchanged and never trigger the handler. Test the expression against the command’s actual output and return behavior.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When changed_when contains a list, Ansible combines the expressions with implicit and semantics. Use a single expression with explicit parentheses when the intended logic is easier to read that way.

Inspect the task result in normal output or with increased verbosity. The notifying task must show changed; an ok result cannot queue its handler. Also verify that the task was not skipped by a condition, tag selection, or a failed prerequisite.

Loops can trigger broader actions than expected

For a loop, one changed item makes the loop task changed. Ansible then triggers every handler notified by that task, even if only one item changed.

- name: Install configuration fragments
  ansible.builtin.template:
    src: '{{ item }}.j2'
    dest: '/etc/example/{{ item }}'
  loop:
    - limits.conf
    - logging.conf
    - workers.conf
  notify: Restart example app

A change to logging.conf is enough to restart the application, which may be correct if all fragments are read at startup. If different files require different follow-up actions, split them into separate tasks with separate notifications rather than relying on one loop task.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
BSIMB 15.6" Digital Family Calendar & Chore Chart, No Subscription Fees
  • Digital Family Calendar: BSIMB digital calendar wall touch screen puts an end to your chaotic life. Designed for busy families, the digital calendar keeps you organised and in step with your family. Assign different colours and tasks to each family member to make family scheduling easier and more intuitive.
  • Easy Setup and Auto-Sync: Plug in, connect to WLAN and auto-syn your electric calendar in minutes. Digital wall calendar compatible with Google calendar, iCloud calendar, Outlook calendar, Cozi calendar and Yahoo calendar. Add events directly on the device or through the ecalendar app. Electronic calendar stays current whether you're at work or traveling—no manual updates needed.
  • All-In-One Home Assistant: Smart calendar builds habits and encourage independence with personalised chores. Display daily meal plan to reduce the daily ‘What's for dinner?’ stress. To-do lists keep track of everything you want. Turning chores into valuable achievements with stars and rewards, making life easier and more enjoyable.
  • Manage Anytime Anywhere: BSIMB electronic calendar for family stay connected with the powerful ecalendar app. Access and manage your digital wall calendar anytime, anywhere with free features like stars & rewards, photo screensaver, chore charts, meals plans, to-do lists etc. Electronic planner paid features like Magic Import tailor advanced tools for users with special needs.
  • Stay in Touch with Loved Ones: Share photos or videos from your phone to electronic wall calendar with app, instantly update your life moment, and keep in touch with your family, especially those who are far away; you can also surprise your smart calendar digital wall by sending him a wish card; it's also great for keeping tech-illiterate elders in touch with the youngsters.

Handler names, variables, and roles

Keep names unique across the play scope

Handlers share play scope, including handlers brought in by roles. Give names a distinctive purpose, such as Restart payments worker rather than a generic Restart service. If two loaded handlers have the same name, a later-loaded definition can shadow an earlier one, producing surprising behavior.

Qualify a role handler when needed

Role handlers are available outside the role in which they are defined. When a role-qualified notification is needed, use the role name, a colon, and the handler name:

- name: Restart the role-managed daemon
  ansible.builtin.debug:
    msg: configuration changed
  changed_when: true
  notify: 'web_role : Restart daemon'

Use the exact role name and exact handler name. Qualification is especially useful when several roles expose similarly named actions.

Put distribution-specific values in module parameters

Handler names are templated early. Do not try to make one handler name vary by operating-system family or another late-bound variable. Keep the name stable and template the value passed to the module instead:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
- name: Deploy service configuration
  ansible.builtin.template:
    src: service.conf.j2
    dest: '{{ service_config_path }}'
  notify: Restart managed service

handlers:
  - name: Restart managed service
    ansible.builtin.service:
      name: '{{ service_name }}'
      state: restarted

This keeps notification matching deterministic while allowing variables such as service_name and service_config_path to differ by distribution or host.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Includes, imports, and meta handlers

Dynamic task includes can be notified

A dynamic task include can itself be a handler. When notified, Ansible executes the tasks in the included file at handler time:

handlers:
  - name: Apply optional tuning tasks
    ansible.builtin.include_tasks: tune.yml

This is useful when a change should trigger a small sequence rather than one module invocation. Ensure the included tasks are safe to run as a deferred operation and that their own variables are available when the handler executes.

Static imports cannot be notified as a unit

A static import_tasks is expanded before execution. The import statement itself is not a runtime task that can be notified as a handler. If you need deferred behavior, use a dynamic include_tasks handler or define each required action as a handler.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Meta tasks as handlers

Since ansible-core 2.14, meta tasks can be used as handlers. The flush_handlers meta action is the exception: it cannot itself be used as a handler. Use it as an ordinary task at the point where pending notifications must be processed.

A reliable configuration-change pattern

The following structure validates a file, installs it only when needed, and reloads the service once. The validation command is shown as a separate task so that a bad configuration fails before the replacement is accepted.

- hosts: web
  become: true
  tasks:
    - name: Render and validate web configuration
      ansible.builtin.template:
        src: web.conf.j2
        dest: /etc/web/web.conf
        owner: root
        group: root
        mode: '0644'
        validate: '/usr/sbin/webctl --test %s'
      notify: Reload web service

    - name: Deploy the certificate when managed here
      ansible.builtin.copy:
        src: files/web-chain.pem
        dest: /etc/web/chain.pem
        owner: root
        group: root
        mode: '0644'
      notify: Reload web service

  handlers:
    - name: Reload web service
      ansible.builtin.service:
        name: web
        state: reloaded

Both changed tasks share one handler, so a play that updates both files still performs one reload. A play that changes neither file performs no reload.

Troubleshoot a handler that did not run

Symptom What to check Correction
The task shows ok, but no handler runs. The task did not report a change. Fix the module inputs or define accurate changed_when logic for command or shell tasks.
Ansible reports an unknown handler. The notification string does not exactly match a handler name or topic, or the handler is outside the current play scope. Correct spelling and capitalization; place the handler under the play’s handlers: section or load the role that defines it.
The wrong action runs. Two handlers share a name, or a role-qualified name was expected but an unqualified name was used. Make names unique and use role_name : handler_name when qualification is required.
A handler runs once when several files change. This is normal notification coalescing. Use separate tasks and distinct handlers only when each change truly needs an independent action.
A loop causes an unexpectedly broad restart. One changed loop item marked the entire task changed. Split the loop into tasks with narrower notifications, or accept the single shared restart if all items have the same dependency.
A service is still using old settings in a later task. The handler is deferred until the normal handler phase. Insert ansible.builtin.meta: flush_handlers before the dependent task.
An imported file cannot be notified. It is a static import_tasks. Use a dynamic include_tasks handler or define explicit handlers for the actions.
The handler works on one operating system but not another. The handler name was templated instead of its module parameters. Keep one stable handler name and template values such as the service name or configuration path inside the handler.
The handler never runs after an earlier failure. The host did not reach the normal end-of-play handler phase. Review failure handling and whether forcing handlers for that play is appropriate for the operation.

Practical design checklist

  • Define every deferred action under handlers: and give it a unique, descriptive name.
  • Attach notify only to tasks whose change genuinely requires the follow-up action.
  • For commands and shell scripts, verify that changed_when reflects a real state change.
  • Use a shared handler when several changes can be safely consolidated into one restart or reload.
  • Use listen when a stable event should fan out to several handlers or when task code should not depend on implementation names.
  • Remember that handler definition order controls execution order.
  • Split loops when different items need different follow-up behavior.
  • Use role-qualified names for deliberate cross-role references and avoid collisions across loaded roles.
  • Keep variables in handler module arguments rather than templating handler names.
  • Use meta: flush_handlers only when subsequent tasks require the deferred action to have completed immediately.
  • For version-sensitive behavior, especially meta tasks as handlers and include/import semantics, check the documentation for the ansible-core version running your playbook.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

AnsibleAnsible PlaybooksAutomationconfiguration managementDevOps

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.