Idempotency: Why My Playbook Changed Nothing the Second Time

Written by

in

“Idempotent” was a word I memorized for courses without really understanding it. Then I ran my Ansible playbook a second time and saw it for myself.

What I saw

The first run installed MySQL, Apache, PHP, and WordPress across my two servers. The second run finished with this:

PLAY RECAP
db   : ok=10  changed=0  unreachable=0  failed=0  skipped=0
web  : ok=12  changed=0  unreachable=0  failed=0  skipped=1

changed=0 on both servers. Ansible checked every task, found everything already correct, and changed nothing.

What idempotent means

Running the same automation twice gives the same result. The second run only changes what’s different.

Ansible tasks describe the state you want, not steps to blindly repeat. For example, state: present means “make sure this package is installed.” If it already is, Ansible moves on.

The “skipped” task

One task was skipped on the second run: downloading WordPress. That task has a creates rule, which tells Ansible to skip it if the WordPress folder already exists:

- name: Download and unpack WordPress
  ansible.builtin.unarchive:
    src: https://wordpress.org/latest.tar.gz
    dest: /var/www/
    remote_src: true
    creates: /var/www/wordpress

Why it matters

  • It’s safe to re-run. If something goes wrong halfway through, I can just run it again.
  • It fixes drift. If someone changes a setting by hand, the next run puts it back the way the code says.
  • It scales. The same playbook works on 2 servers or 200.

Compare that to a basic script that runs useradd client1: the second time, it fails because the user already exists. That’s the difference idempotency makes.