Sometimes tasks need breathing room — wait for a service to start, pause between API calls to avoid rate limits, or delay a reboot check. Ansible provides several mechanisms: pause, wait_for, until loops with delay, and async. This guide covers when to use each.
ansible.builtin.pause
# Wait 30 seconds
- name: Wait for service to stabilize
ansible.builtin.pause:
seconds: 30
# Wait with a message
- name: Pause before cutover
ansible.builtin.pause:
minutes: 2
prompt: "Waiting 2 minutes for DNS propagation..."
# Wait for user confirmation
- name: Confirm before proceeding
ansible.builtin.pause:
prompt: "Press Enter to continue or Ctrl+C to abort"
pause Parameters
Parameter
Description
seconds
Number of seconds to pause
minutes
Number of minutes to pause
prompt
Message to display during pause
echo
Whether to echo user input (default: true)
wait_for — Wait for a Condition
# Wait for port to be open
- name: Wait for PostgreSQL to start
ansible.builtin.wait_for:
port: 5432
host: localhost
delay: 2
timeout: 60
# Wait for file to appear
- name: Wait for lock file to be removed
ansible.builtin.wait_for:
path: /tmp/deploy.lock
state: absent
timeout: 300
# Wait for string in file
- name: Wait for app to log "ready"
ansible.builtin.wait_for:
path: /var/log/myapp.log
search_regex: "Application started successfully"
timeout: 120
wait_for Parameters
Parameter
Default
Description
port
—
TCP port to check
host
127.0.0.1
Host to check
path
—
File path to check
search_regex
—
Regex to search in file
state
started
started, stopped, present, absent, drained
delay
0
Seconds to wait before first check
timeout
300
Max seconds to wait
sleep
1
Seconds between checks
until Loop with delay
# Retry API call until success
- name: Wait for API to return healthy
ansible.builtin.uri:
url: http://localhost:8080/health
status_code: 200
register: health_check
until: health_check.status == 200
retries: 30
delay: 10 # Wait 10 seconds between retries
# Retry command until output matches
- name: Wait for cluster to be ready
ansible.builtin.command: kubectl get nodes
register: nodes_output
until: "'Ready' in nodes_output.stdout"
retries: 20
delay: 15
changed_when: false
Common Patterns
Reboot and Wait
- name: Reboot the server
ansible.builtin.reboot:
reboot_timeout: 600
pre_reboot_delay: 5
post_reboot_delay: 30
connect_timeout: 10
# Or manually:
- name: Reboot
ansible.builtin.command: shutdown -r now
async: 1
poll: 0
- name: Wait for host to come back
ansible.builtin.wait_for_connection:
delay: 30
timeout: 300
- name: Start application
ansible.builtin.service:
name: myapp
state: started
- name: Wait for app to listen on port
ansible.builtin.wait_for:
port: 8080
delay: 5
timeout: 60
- name: Verify app responds
ansible.builtin.uri:
url: http://localhost:8080/health
register: health
until: health.status == 200
retries: 5
delay: 3
Rolling Deployment Spacing
---
- name: Rolling deploy
hosts: webservers
serial: 1 # One host at a time
tasks:
- name: Deploy new version
ansible.builtin.copy:
src: app.tar.gz
dest: /opt/app/
- name: Restart service
ansible.builtin.service:
name: webapp
state: restarted
- name: Wait for health check
ansible.builtin.wait_for:
port: 8080
delay: 10
timeout: 60
- name: Pause between hosts
ansible.builtin.pause:
seconds: 30
when: ansible_play_hosts_all | length > 1
Database Migration Wait
- name: Run migration
ansible.builtin.command: /opt/app/migrate.sh
async: 600 # Allow up to 10 minutes
poll: 0
register: migration_job
- name: Wait for migration to complete
ansible.builtin.async_status:
jid: "{{ migration_job.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 60
delay: 10
Comparison
Method
Use Case
Blocks Play?
pause
Fixed wait time, user prompt
Yes
wait_for
Port/file/string condition
Yes (with timeout)
until + delay
Retry until success
Yes (with retries)
loop_control.pause
Space between loop items
Yes
async + poll: 0
Fire and forget
No
wait_for_connection
SSH/WinRM reconnect
Yes
Troubleshooting
Issue
Solution
pause not working in --check mode
Expected — pause is skipped in check mode
wait_for times out
Increase timeout, check service actually starts
until loop exhausts retries
Increase retries or delay, check the condition
Task hangs forever
Set explicit timeout on all wait operations
pause slows down large inventories
Use run_once: true if pause should happen once
Best Practices
Prefer wait_for over pause — condition-based waits are more reliable
Always set timeout — never wait forever
Use until for external services — APIs, databases, clusters
Use loop_control.pause for rate limits — cleaner than pause task
Use async for long operations — don't block the playbook
Add delay to wait_for — give services time to begin starting
Conclusion
Use pause for fixed delays and user prompts. Use wait_for when waiting for ports, files, or strings. Use until loops with delay for retry-based waiting (API health checks, cluster readiness). Use loop_control.pause to space out loop iterations. Always set timeouts to prevent infinite waits.