Introduction

Mitogen is a Python library that replaces Ansible's default SSH + SFTP module execution with a single persistent Python-to-Python channel. Instead of opening multiple SSH connections per task (upload module, execute, download result), Mitogen sends pure Python bytecode over one connection. The result: 2x to 10x faster playbook execution with zero changes to your playbooks. The trade-off: compatibility limitations with some Ansible features.

How Default Ansible Works

For each task on each host, Ansible's default strategy:

1. Open SSH connection
2. Create temp directory on remote
3. SFTP upload module + arguments
4. SSH execute module
5. SSH read stdout/stderr
6. SSH delete temp files
7. Close connection

That's 5-7 SSH round trips per task per host. With 50 tasks on 100 hosts, that's up to 35,000 SSH operations.

How Mitogen Works

1. Open one persistent SSH connection
2. Bootstrap a Python interpreter on the remote
3. Send module bytecode over the existing connection
4. Execute in-process, return results over the same channel

One connection per host for the entire playbook run. Modules execute as pure Python functions — no temp files, no SFTP, no repeated SSH handshakes.

┌─────────────┐                  ┌─────────────┐
│  Controller  │───── 1 SSH ─────│  Target      │
│  (Ansible)   │     channel     │  (Python)    │
│              │◄────────────────│              │
│  Send module │   bytecode +    │  Execute     │
│  bytecode    │   results flow  │  in-process  │
│              │   over same     │              │
│              │   connection    │              │
└─────────────┘                  └─────────────┘

Install

# Install Mitogen
pip install mitogen

# Find the path
python3 -c "import mitogen; print(mitogen.__path__[0])"
# /home/user/.local/lib/python3.12/site-packages/mitogen

Configure

ansible.cfg

[defaults]
strategy_plugins = /path/to/mitogen/ansible_mitogen/plugins/strategy
strategy = mitogen_linear

Or with environment variable:

export ANSIBLE_STRATEGY_PLUGINS=/path/to/mitogen/ansible_mitogen/plugins/strategy
export ANSIBLE_STRATEGY=mitogen_linear

Dynamic Configuration

# In playbook — use Mitogen for specific plays
- name: Fast configuration tasks
  hosts: webservers
  strategy: mitogen_linear
  tasks:
    - name: Install packages
      ansible.builtin.apt:
        name: nginx
        state: present

Per-Environment Configuration

# ansible.cfg for production (use Mitogen)
[defaults]
strategy = mitogen_linear
strategy_plugins = /opt/venv/lib/python3.12/site-packages/mitogen/ansible_mitogen/plugins/strategy

# Mitogen-specific tuning
[mitogen]
# Maximum concurrent interpreters per host
# (default: number of CPUs on controller)

Benchmarks

Typical results on a 50-host fleet running a 30-task playbook:

MetricDefault SSHMitogenImprovement
Wall time12 min2 min6x faster
SSH connections~1,5005097% fewer
Network bytes~200 MB~15 MB93% less
CPU (controller)LowModerateExpected
Temp files created~1,5000Zero disk I/O

Quick Benchmark

# Without Mitogen
time ansible-playbook -i inventory site.yml
# real    12m34s

# With Mitogen
ANSIBLE_STRATEGY=mitogen_linear \
ANSIBLE_STRATEGY_PLUGINS=/path/to/mitogen/ansible_mitogen/plugins/strategy \
time ansible-playbook -i inventory site.yml
# real    1m58s

What Works Well

  • All standard modules — apt, yum, copy, template, file, service, user, etc.
  • Roles and includes — no changes needed
  • Handlers — work normally
  • Variables and facts — fully supported
  • Vault-encrypted variables — works
  • become/sudo — supported (Mitogen handles privilege escalation internally)
  • Multi-platform — Linux, macOS targets
  • Large inventories — scales well with 100+ hosts

Known Limitations

Not Compatible With

FeatureStatusWorkaround
raw module❌ Not supportedUse command or shell
script module❌ Not supportedCopy script + execute
synchronize (rsync)⚠️ PartialUse copy for small files
Custom connection plugins❌ Replaced by MitogenCan't stack
ansible_ssh_common_args⚠️ PartialSome SSH options ignored
Windows (WinRM)❌ Not supportedSSH targets only
Network devices (CLI)❌ Not supportedSSH + Python targets only
async tasks⚠️ PartialMay not work with all modules

Version Compatibility

Mitogen 0.3.x → ansible-core 2.15, 2.16, 2.17
Mitogen 0.2.x → ansible-core 2.10-2.14 (legacy)

Check the Mitogen changelog for latest compatibility.

Strategies

Mitogen provides drop-in replacements for Ansible's built-in strategies:

Ansible StrategyMitogen Equivalent
linearmitogen_linear
freemitogen_free
host_pinnedmitogen_host_pinned
# ansible.cfg
[defaults]
strategy = mitogen_free  # Maximum parallelism

Combining with Other Optimizations

# ansible.cfg — maximum performance
[defaults]
strategy = mitogen_linear
strategy_plugins = /path/to/mitogen/ansible_mitogen/plugins/strategy
forks = 50
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible-facts
fact_caching_timeout = 86400

[connection]
pipelining = true  # Still helps for non-Mitogen fallback

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s

Troubleshooting

"No module named 'mitogen'"

# Verify installation
pip show mitogen
python3 -c "import mitogen; print(mitogen.__path__[0])"

# Use absolute path in ansible.cfg
strategy_plugins = /home/user/.local/lib/python3.12/site-packages/mitogen/ansible_mitogen/plugins/strategy

"Target has no Python interpreter"

Mitogen needs Python on the target:

# Bootstrap Python first (without Mitogen)
ansible -i inventory all -m raw -a "apt install -y python3" \
  -e ansible_strategy=linear

Task Fails Under Mitogen but Works Without

# Fall back to default strategy for problematic plays
- name: Tasks needing raw/script modules
  hosts: targets
  strategy: linear   # Use default SSH strategy
  tasks:
    - name: Run raw command
      ansible.builtin.raw: echo hello

Debug Mitogen Issues

# Enable Mitogen debug logging
MITOGEN_LOG_LEVEL=debug ansible-playbook site.yml 2>mitogen-debug.log

When to Use Mitogen

Use Mitogen when:

  • Managing 10+ Linux/macOS hosts
  • Playbooks take >5 minutes
  • Running many small tasks (package installs, file operations, service management)
  • Network bandwidth to targets is limited
  • You want faster CI/CD feedback

Don't use Mitogen when:

  • Managing Windows hosts (WinRM)
  • Managing network devices (Cisco IOS, Arista EOS, etc.)
  • Using raw, script, or synchronize modules heavily
  • You need bleeding-edge ansible-core features (wait for Mitogen support)

Alternative: Pipelining

If Mitogen doesn't fit, enable SSH pipelining for a smaller speedup:

# ansible.cfg
[connection]
pipelining = true

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=600s

This reduces SSH operations per task from ~7 to ~3 (no SFTP, executes via stdin).

Conclusion

Mitogen replaces Ansible's SSH + SFTP module execution with a single persistent Python channel per host — reducing SSH connections by 97%, network traffic by 93%, and wall time by 2-10x. Install it with pip install mitogen, add two lines to ansible.cfg, and your existing playbooks run faster with zero modifications. The main trade-off is compatibility: raw, script, Windows, and network device modules don't work under Mitogen, so use strategy: linear for those specific plays.