What is Ansible throttle?

The throttle keyword limits how many hosts can execute a specific task at the same time — even if forks or serial allows more.

This is essential when a task hits a shared resource (database, API, load balancer) that can't handle many simultaneous connections.

Basic Syntax

- name: Run database migration
  ansible.builtin.command: /opt/app/migrate.sh
  throttle: 1  # Only 1 host at a time

throttle vs serial vs forks

SettingScopeWhat it controls
forksGlobal (ansible.cfg)Max SSH connections Ansible opens
serialPlay-levelHow many hosts per batch
throttleTask-levelMax concurrent hosts for one task
# forks=10 (in ansible.cfg)

- name: Rolling deployment
  hosts: webservers
  serial: 5  # Process 5 hosts per batch

  tasks:
    - name: Update application
      ansible.builtin.apt:
        name: myapp
        state: latest
      # Runs on 5 hosts at once (limited by serial)

    - name: Run database migration
      ansible.builtin.command: /opt/app/migrate.sh
      throttle: 1
      # Only 1 host at a time, even though serial=5

Practical Examples

API Rate Limiting

- name: Register with external API
  ansible.builtin.uri:
    url: "https://api.example.com/register"
    method: POST
    body:
      hostname: "{{ inventory_hostname }}"
    body_format: json
  throttle: 2  # API allows max 2 concurrent requests

Database Operations

- name: Apply schema migration
  ansible.builtin.command: python manage.py migrate
  throttle: 1  # One migration at a time to avoid locks
  run_once: true

Load Balancer Registration

- name: Register with load balancer
  ansible.builtin.uri:
    url: "https://lb.example.com/api/register"
    method: POST
    body:
      server: "{{ inventory_hostname }}"
    body_format: json
  throttle: 3  # LB can handle 3 registrations at once

- name: Wait for health check
  ansible.builtin.uri:
    url: "http://{{ inventory_hostname }}:8080/health"
    status_code: 200
  retries: 10
  delay: 5
  throttle: 5

Certificate Renewal

- name: Renew SSL certificates
  ansible.builtin.command: certbot renew
  throttle: 1  # Avoid Let's Encrypt rate limits

Rolling Restart Without Downtime

- name: Rolling restart
  hosts: app_servers
  serial: "30%"

  tasks:
    - name: Stop application
      ansible.builtin.service:
        name: myapp
        state: stopped

    - name: Update code
      ansible.builtin.git:
        repo: https://github.com/myorg/myapp.git
        dest: /opt/myapp
        version: main

    - name: Start application
      ansible.builtin.service:
        name: myapp
        state: started

    - name: Verify health
      ansible.builtin.uri:
        url: "http://localhost:8080/health"
        status_code: 200
      retries: 5
      delay: 3
      throttle: 1  # Verify one at a time

Key Rules

  1. throttle cannot be higher than serial or forks — it only reduces concurrency, never increases it
  2. throttle is set per-task, not per-play
  3. Value must be a positive integer
  4. Works with all strategies (linear, free, host_pinned)

When to Use throttle

  • API rate limits — external services cap concurrent requests
  • Database migrations — prevent lock conflicts
  • License servers — limited concurrent connections
  • Shared storage — avoid I/O bottleneck
  • Certificate authorities — rate-limited issuance
  • Load balancer registration — gradual traffic shifting

Learn more about Ansible execution control in our performance optimization guide and 800+ tutorials.