Skip to main content
AWX can store and retrieve per-host facts via an Ansible Fact Cache Plugin, enabling playbooks to access inventory-wide facts even when using --limit.

Overview

Fact caching is configurable on a per-job-template basis. When enabled, AWX serves fact requests for all hosts in an inventory related to the running job.
This allows users to use Job Templates with --limit while still having access to the entire Inventory of host facts.

How It Works

Fact Cache Implementation

1

Fact Injection

When a job launches with use_fact_cache=True, AWX writes all ansible_facts associated with each host in the inventory as JSON files on the local file system (one file per host)
2

Ansible Plugin Usage

Ansible is configured to use the jsonfile cache plugin:
  • get() calls result in JSON file lookups for host-specific facts
  • set() calls write JSON files to the local file system
3

Cache to Database

When a job with use_fact_cache=True finishes:
  • AWX examines all local JSON files
  • Files with increased modification times (updated by Ansible) are saved to the database
  • Only facts newer than settings.ANSIBLE_FACT_CACHE_TIMEOUT seconds are injected on subsequent runs

Configuration

Enabling Fact Cache on Job Templates

Enable fact caching when creating or updating a Job Template:
curl -X PATCH https://awx.example.com/api/v2/job_templates/42/ \
  -H "Content-Type: application/json" \
  -d '{
    "use_fact_cache": true
  }'
Via UI:
  1. Navigate to Job Templates
  2. Edit the desired template
  3. Enable “Enable Fact Storage”
  4. Save the template

Fact Cache Timeout

Configure the global fact cache timeout in AWX settings:
ANSIBLE_FACT_CACHE_TIMEOUT = 86400  # 24 hours in seconds
Facts older than the timeout will not be used from the cache and must be re-gathered.

Use Cases

Limited Host Operations

Run playbooks against a subset of hosts while maintaining access to all inventory facts:
- name: Configure web server based on database facts
  hosts: webservers
  tasks:
    - name: Configure database connection
      template:
        src: db_config.j2
        dest: /etc/app/database.conf
      vars:
        # Access facts from database hosts even though they're not in limit
        db_host: "{{ hostvars['db-prod-01']['ansible_default_ipv4']['address'] }}"
        db_port: "{{ hostvars['db-prod-01']['database_port'] }}"
Launch with limit:
--limit webservers
Database host facts are still available via the fact cache.

Multi-Tier Applications

Share facts between different tiers:
1

Gather Load Balancer Facts

Job Template 1 gathers facts from load balancers
2

Configure Application Servers

Job Template 2 uses LB facts to configure app servers
3

Update Database Config

Job Template 3 uses app server facts to configure database access
All templates use the same inventory and have use_fact_cache=True.

Performance Optimization

Skip redundant fact gathering:
- name: Quick deployment
  hosts: all
  gather_facts: no  # Use cached facts instead
  tasks:
    - name: Deploy application
      copy:
        src: "{{ ansible_architecture }}-app-binary"
        dest: /usr/local/bin/app
With fact caching enabled, you can set gather_facts: no to skip the gathering phase and use cached facts, significantly reducing playbook run time.

Fact Cache Behavior

When Facts Are Written

Facts are written to the cache:
  • When a playbook runs with gather_facts: yes (default)
  • When using the setup module explicitly
  • When using the set_stats module (for custom facts)
  • When fact cache is enabled on the Job Template
Jobs with use_fact_cache=False:
  • Will NOT write ansible_facts files
  • Will NOT update the fact cache
  • Cannot access cached facts from other jobs

When Facts Are Read

Facts are read from the cache:
  • At the start of job execution (if enabled)
  • Only facts newer than ANSIBLE_FACT_CACHE_TIMEOUT
  • For all hosts in the inventory, not just hosts in the play

Fact Invalidation

Facts are NOT automatically invalidated when:
  • Hosts are modified outside of AWX
  • Infrastructure changes occur
  • Host configurations change
Consider the fact cache timeout carefully based on how dynamic your environment is.

Fact Logging

New and changed facts are logged via AWX’s logging facility. Log Namespace: system_tracking Log Payload Includes:
  • host_name - Name of the host
  • inventory_id - ID of the inventory
  • ansible_facts - Dictionary of all Ansible facts
Example Log Entry:
{
  "host_name": "web-server-01",
  "inventory_id": 42,
  "ansible_facts": {
    "ansible_default_ipv4": {
      "address": "192.168.1.100",
      "interface": "eth0"
    },
    "ansible_distribution": "Ubuntu",
    "ansible_distribution_version": "22.04",
    "ansible_processor_cores": 4,
    "ansible_memtotal_mb": 16384
  }
}

Managing Facts

Viewing Host Facts

Access facts via the API:
curl https://awx.example.com/api/v2/hosts/123/ansible_facts/
Via UI:
  1. Navigate to Inventories
  2. Select an inventory
  3. Click on Hosts
  4. Select a host
  5. View the “Facts” tab

Clearing Facts

Clear facts for a specific host:
curl -X POST https://awx.example.com/api/v2/hosts/123/ansible_facts/ \
  -H "Content-Type: application/json" \
  -d '{}'
The clear_facts endpoint sets hosts/<id>/ansible_facts to {}.

Preventing Fact Clearing

Setting gather_facts: False does NOT result in clearing existing facts. Facts are only cleared when:
  • Explicitly cleared via the API
  • The fact cache timeout is exceeded

Integration with Workflows

Fact caching works seamlessly with workflows:
Workflow:
  1. Discover Infrastructure (gather_facts: yes, use_fact_cache: true)

  2. Configure Services (gather_facts: no, use_fact_cache: true)

  3. Deploy Application (gather_facts: no, use_fact_cache: true)
First job gathers and caches facts; subsequent jobs use cached facts for faster execution.

Custom Facts

Store custom facts using set_stats:
- name: Store custom deployment facts
  set_stats:
    data:
      deployment_timestamp: "{{ ansible_date_time.iso8601 }}"
      deployment_version: "v2.1.0"
      deployment_user: "{{ ansible_user_id }}"
These custom facts are available in subsequent job runs via the fact cache.

Performance Considerations

Faster Playbooks

Skip fact gathering when using cached facts to reduce playbook run time by 5-30 seconds per host

Reduced Load

Fewer SSH connections and fact gathering operations reduce load on managed hosts

Network Efficiency

Less data transfer when facts are served from cache instead of gathering

Scalability

Large inventories benefit significantly from fact caching

Troubleshooting

Facts Not Being Cached

1

Verify Job Template Setting

Ensure use_fact_cache is set to true on the Job Template
2

Check Fact Gathering

Verify playbook has gather_facts: yes or uses the setup module
3

Review Job Output

Check job output for fact gathering task completion
4

Examine Database

Query the API to verify facts are stored: /api/v2/hosts/<id>/ansible_facts/

Stale Facts

If facts appear outdated:
  • Check the ANSIBLE_FACT_CACHE_TIMEOUT setting
  • Manually clear facts using the API
  • Run a job with gather_facts: yes to refresh

Facts Not Available in Playbook

Ensure:
  • Job Template has use_fact_cache: true
  • Facts were gathered in a previous job with caching enabled
  • Facts are not older than the cache timeout
  • Hosts are in the same inventory

Best Practices

Set Appropriate Timeouts

Configure cache timeout based on infrastructure change frequency

Use gather_facts: no

Skip gathering when using cached facts for better performance

Monitor Cache Size

Large inventories with many facts can consume significant database space

Regular Refreshes

Periodically run full fact gathering jobs to ensure cache freshness

Testing

Integration Testing Scenarios

1

Test Clear Facts

Ensure clear_facts sets hosts/<id>/ansible_facts to {}
2

Test gather_facts: False

Verify that gather_facts: False does NOT clear existing facts
3

Test Timeout

Ensure facts older than the timeout are not used from cache
4

Test Multi-Job Workflow

Verify facts from first job are accessible in subsequent jobs

Build docs developers (and LLMs) love