Skip to content
CloudOps
All prompts
AI for Infrastructure as Code Difficulty: Intermediate ClaudeChatGPT

Ansible Handlers & Notification Prompt

Use Ansible handlers correctly — notify, listen, force handlers, multi-handler chains, when handlers don't fire.

Target user
Ansible engineers handling service restarts
Difficulty
Intermediate
Tools
Claude, ChatGPT

The prompt

You are a senior Ansible engineer who has debugged "handler didn't fire" countless times. You know the rules: notify only on change, deferred to end of play, handlers can listen.

I will provide:
- The handler config
- The notifying task
- Symptom (handler not firing, wrong order, multiple handlers)

Your job:

1. **Handler basics**:
   - Defined in `handlers:` section of play or `roles/<role>/handlers/main.yml`
   - Triggered by `notify: <handler_name>`
   - Runs ONCE per play after all tasks
   - Only if task reported `changed`
2. **For handler not firing**:
   - Task didn't change anything (idempotent skipped)
   - Notify name doesn't match handler name
   - Play failed before handler section (use `--force-handlers`)
   - Handler in different play (handlers are play-scoped)
3. **For ordering**:
   - Handlers run in ORDER DEFINED, not order notified
   - Useful for dependency chains
4. **For multiple notifies**:
   - Same handler notified multiple tasks → runs once
   - Deduplicates
5. **For `listen:` (handlers)**:
   - Multiple handlers listen for same topic
   - Decoupled from task notification
   - One notify triggers all listeners
6. **For force-handlers**:
   - Playbook `force_handlers: true` runs handlers even on play failure
   - Useful for partial recovery
7. **For role handlers**:
   - In `roles/<role>/handlers/main.yml`
   - Notify by name (no role prefix needed within play)
   - Or import_handler for explicit
8. **For task-level handler-like behavior**:
   - `meta: flush_handlers` runs all pending handlers immediately
   - Useful when subsequent tasks depend on restarted service

Mark DESTRUCTIVE: forcing handlers on critical failure (incomplete state), removing handler dependencies (broken restart chain), flush_handlers in wrong place (premature restart).

---

Handler config: [PASTE]
Notifying task: [PASTE]
Symptom: [DESCRIBE]

Why this prompt works

Handlers have subtle rules. This prompt walks them.

How to use it

  1. Match notify name exactly.
  2. Order handlers in dependency order.
  3. Use listen for decoupling.
  4. flush_handlers when need before next task.

Useful commands

# Verbose to see handler firing
ansible-playbook playbook.yml -v

# Force handlers (run even if play fails)
ansible-playbook playbook.yml --force-handlers

# Check (handlers normally don't run in check)
ansible-playbook playbook.yml --check

Patterns

Basic handler

- hosts: webservers
  tasks:
  - name: Render nginx config
    template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: restart nginx

  - name: Render upstream config
    template:
      src: upstreams.conf.j2
      dest: /etc/nginx/conf.d/upstreams.conf
    notify: restart nginx     # same handler; runs once

  handlers:
  - name: restart nginx
    service:
      name: nginx
      state: restarted

Listen for decoupling

- hosts: web
  tasks:
  - name: Update certs
    copy: ...
    notify: certs updated     # topic

  - name: Update config
    template: ...
    notify: config updated

  handlers:
  - name: restart nginx
    service: { name: nginx, state: restarted }
    listen:                    # listens for topics
    - certs updated
    - config updated

  - name: notify slack
    uri: ...
    listen:
    - certs updated

flush_handlers (run immediately)

- hosts: web
  tasks:
  - name: Install postgresql
    package: { name: postgresql, state: present }
    notify: start postgresql

  - name: Run handlers now (before next task that needs DB)
    meta: flush_handlers

  - name: Initialize DB
    shell: psql -c "CREATE DATABASE myapp;"
    # postgresql is started; this works

  handlers:
  - name: start postgresql
    service: { name: postgresql, state: started, enabled: true }

Force handlers on failure

- hosts: all
  force_handlers: true        # even if play fails, run handlers
  tasks:
  - name: Risky task
    ...
    notify: cleanup

  handlers:
  - name: cleanup
    file: { path: /tmp/lock, state: absent }

Common findings this catches

  • Handler not firing → task idempotent, no change.
  • Notify name mismatch → typo.
  • Handler runs but service still old config → handler order; restart in wrong order.
  • flush_handlers too early → service restarts unnecessarily mid-play.
  • Cross-role handler notified but not present → import_role or include handler.
  • force_handlers: true on partial config = bad state.
  • Multiple handlers same topic listen → all fire on one notify.

When to escalate

  • Handler chain redesign — strategic.
  • Cross-role handler coordination — role library.
  • Failure recovery patterns — review.

Related prompts

Newsletter

Get weekly AI workflows for DevOps engineers

Practical prompts, automation ideas, and tool reviews for infrastructure engineers. One email per week. No spam.