Skip to main content
Idempotency is a core principle of pyinfra. An idempotent operation produces the same result when run multiple times - the second run detects that the desired state is already achieved and makes no changes. This guide explains how pyinfra achieves idempotency and how to use it effectively.

What is Idempotency?

An operation is idempotent if running it multiple times has the same effect as running it once:
The second run detects that vim is already installed and skips execution, making zero changes.

Why Idempotency Matters

Idempotent operations provide several critical benefits:
  1. Safe to re-run - Deploy scripts can run repeatedly without breaking things
  2. Predictable results - Same code always produces same end state
  3. Change detection - See exactly what will change before applying
  4. Drift correction - Re-running deploys fixes configuration drift
  5. Faster execution - Skip operations that don’t need changes
You can run your deploys as often as you want - pyinfra only makes changes when the current state differs from the desired state.

How pyinfra Achieves Idempotency

Pyinfra achieves idempotency through a two-phase process:

Phase 1: Detect Changes

pyinfra first checks the current state using facts:
Before making changes, pyinfra:
  1. Checks if /etc/myapp/config.txt exists
  2. Checks file permissions, owner, and group
  3. Compares with desired state (mode=644, user=root)
  4. Only generates commands if changes are needed

Phase 2: Apply Changes

If changes are detected, pyinfra generates and executes the minimum commands needed:

Idempotent vs Non-Idempotent Operations

Idempotent Operations

Most pyinfra operations are idempotent by default:

Non-Idempotent Operations

Some operations are inherently non-idempotent and run every time:
Operations marked with is_idempotent=False will execute every time. Use them carefully in production deploys.

Dry-Run Mode

Dry-run mode shows you what will change without making any changes:
Example output:
Always use --dry to preview changes before deploying to production!

Smart Service Restarts

Use operation return values to restart services only when configs change:

Checking Operation Results

Operation return values provide metadata about execution:

Available Methods

Handling Non-Idempotent Commands

When you must use non-idempotent shell commands, add checks to make them idempotent:

Check Before Execute

Better yet, use the idempotent files.directory operation instead of shell commands!

Use Conditional Execution

Working with Facts

Facts are how pyinfra gathers information about the current state:

Common Facts

Facts are cached during the prepare phase. They represent the state before operations are executed.

Caution: Facts During Execution

Be careful when using facts that may change during execution:
Always prefer using idempotent operations over manual fact checks. Operations handle state detection correctly.

File Upload Idempotency

File operations detect changes by comparing checksums:
Pyinfra:
  1. Calculates checksum of local file
  2. Calculates checksum of remote file (if exists)
  3. Only uploads if checksums differ or file doesn’t exist

Template Idempotency

Templates also use checksums to detect changes:
Pyinfra:
  1. Renders template with provided variables
  2. Calculates checksum of rendered content
  3. Compares with remote file checksum
  4. Only uploads if different

Testing Idempotency

Always test that your deploys are truly idempotent:
1

Run deploy first time

2

Run deploy second time

3

Verify no changes

The second run should report:
If your second run shows changes, investigate which operations are not idempotent and fix them.

Best Practices

Use idempotent operations - Prefer built-in operations over raw shell commands:
Check return values - Use operation results for conditional logic:
Use dry-run mode - Preview changes before applying:
Test idempotency - Run deploys twice and verify the second run makes no changes
Avoid state-dependent facts - Don’t use facts that may change during execution for conditional logic

Next Steps