DevOps Bootcamp · Lesson

Why command Breaks Idempotency

The trap of raw shell and how to avoid it.

Lesson 3 of 413 steps

Why command Breaks Idempotency is a free DevOps Bootcamp lesson on CoddyKit. This is lesson 3 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the DevOps Bootcamp learning path, and your progress syncs across the web and the CoddyKit app. The DevOps Bootcamp course includes 4 lessons in total.

command Always Runs

The command module just runs whatever you give it on the host. It has no idea what 'done' looks like, so it runs every single time.

ansible.builtin.command: useradd deploy

Always changed

Because command cannot inspect state, Ansible reports it as changed on every run, even when the command actually did nothing new.

changed: [web1]

Re-running Can Hurt

Worse, some commands fail or duplicate work on a repeat run, like useradd erroring because the user already exists.

Prefer a State-Based Module

For users, reach for the user module instead. It checks if the account exists and only creates it when missing, staying idempotent.

ansible.builtin.user:
  name: deploy
  state: present

There Is Usually a Module

Most common shell tasks have a dedicated module: file, copy, lineinfile, git. Use them so Ansible can compare and skip when correct.

Guard command with creates

If you must use command, add creates. Ansible skips the task when that path already exists, restoring idempotency.

ansible.builtin.command: ./build.sh
args:
  creates: /opt/app/built

Or Guard with removes

The mirror of creates is removes: the command runs only if the named path still exists, useful for cleanup steps.

ansible.builtin.command: rm /tmp/lock
args:
  removes: /tmp/lock

Gate command with when

You can also wrap a command in a when condition driven by a registered check, so it runs only when truly needed.

Tell Ansible It Did Nothing

Set changed_when: false on a read-only command so Ansible stops reporting it as changed on every run.

ansible.builtin.command: cat /etc/hostname
changed_when: false

shell Has the Same Problem

The shell module shares this flaw. It runs through a shell, so it too is non-idempotent unless you guard it the same way.

Treat Raw Commands as a Last Resort

Raw command is an escape hatch, not a default. Each one is a place idempotency can quietly break, so reach for it only when no module fits.

Quick Check

You used command to run a build script and it shows changed on every single run.

Recap

The command and shell modules always run and always report changed. Prefer real modules, or guard them with creates, removes, or changed_when. 🛡️

Free to start

Learn DevOps Bootcamp with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
142
Lessons
568

Frequently Asked Questions

Is the “Why command Breaks Idempotency” lesson free?

Yes — any 3 lessons of the DevOps Bootcamp learning path, including “Why command Breaks Idempotency”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The DevOps Bootcamp course includes 4 lessons in total.

What will I learn in “Why command Breaks Idempotency”?

The trap of raw shell and how to avoid it. You practise DevOps Bootcamp with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start DevOps Bootcamp?

No prior experience is required. DevOps Bootcamp on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.

How long does the “Why command Breaks Idempotency” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this DevOps Bootcamp lesson?

Yes. Every DevOps Bootcamp lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Desired State, Not Step-by-Step Scripts
  2. Reading changed vs ok in Output
  3. Why command Breaks Idempotency
  4. Check Mode: Dry-Run with --check
← Back to DevOps Bootcamp