Forge Home


Caches long running facts


1,997 latest version

5.0 quality score

We run a couple of automated
scans to help you access a
module's quality. Each module is
given a score based on how well
the author has formatted their
code and documentation and
modules are also checked for
malware using VirusTotal.

Please note, the information below
is for guidance only and neither of
these methods should be considered
an endorsement by Puppet.

Version information

  • 1.3.1 (latest)
  • 1.3.0
  • 1.2.0
  • 1.1.0
  • 1.0.1
released Dec 4th 2020
This version is compatible with:
  • Puppet Enterprise 2019.8.x, 2019.7.x, 2019.5.x, 2019.4.x, 2019.3.x, 2019.2.x, 2019.1.x, 2019.0.x, 2018.1.x, 2017.3.x, 2017.2.x, 2017.1.x, 2016.5.x, 2016.4.x
  • Puppet >= 4.7.0 < 7.0.0
  • , , , , , , , , , ,
  • purge

Start using this module

  • r10k or Code Manager
  • Bolt
  • Manual installation
  • Direct download

Add this module to your Puppetfile:

mod 'dylanratcliffe-facter_cache', '1.3.1'
Learn more about managing modules with a Puppetfile

Add this module to your Bolt project:

bolt module add dylanratcliffe-facter_cache
Learn more about using this module with an existing project

Manually install this module globally with Puppet module tool:

puppet module install dylanratcliffe-facter_cache --version 1.3.1

Direct download is not typically how you would use a Puppet module to manage your infrastructure, but you may want to download the module in order to inspect the code.



dylanratcliffe/facter_cache — version 1.3.1 Dec 4th 2020


Caches long-running/expensive facts.

Based on waveclaw/facter_cacheable but with a bit more user-friendly API

Note: Facter 4 (Part of Puppet 7) now includes the ability to cache any fact! It isn't as granular as this module but it also doesn't require you to change any facts. Check out the release notes for more info. This module hasn't yet been tested with Facter 4.

Table of Contents

  1. Description
  2. Usage
  3. Reference
  4. Development - Guide for contributing to the module


This creates a cache for facts that are expensive to run, they are still returned by Facter each run, but their values are not recalculated until the cache expires. The cache can be manually removed by deleting the cache folder:






Regular Facts

require 'facter/util/caching'

Facter.add(:expensive) do
  cache_for 10, :seconds

  # The cache has to have a name, doesn't matter what it is but I would
  # recommend the same as the fact name. There is no need to use `setcode`
  # if you are caching the value
  cache(:expensive) do
    sleep 2
    'This is an expensive value'

Aggregate Facts

require 'facter/util/caching'

Facter.add(:aggregate_expensive, :type => :aggregate) do
  cache_for 20, :seconds

  # This fact is extremely expensive and should only be run between midnight
  # and 6am
  execute_only '00:00', '06:00'

  # If we roll out Puppet to a new server during the day, we don't want this
  # fact to run on the first instance. It's okay for it to just return nil. We
  # want to wait until night time to create the cache initially
  initial_run? false

  # This chunk will be cached for the duration specified above
  cache_chunk(:sha256) do
    interfaces = {}

    Facter.value(:networking)['interfaces'].each do |interface, values|
      if values['mac']
        hash                  = Digest::SHA256.digest(values['mac'])
        encoded               = Base64.encode64(hash)
        interfaces[interface] = { :mac_sha256 => encoded.strip }



This module adds the following methods which are accessible if you are creating custom facts. Note that each fact should contain:

require 'facter/util/caching'

To ensure that the methods are available when running Facter.

cache_for(number, unit)

This method sets the duration of the cache. Any node that does not have a cache or the cache is too old will have the fact re-evaluated. If the cache is still valid the cached value will be returned and the fact will not be run.

number: Any integer

unit: Any of the following units:

  • :second
  • :seconds
  • :minute
  • :minutes
  • :hour
  • :hours
  • :day
  • :days
  • :week
  • :weeks

cache_on_changed(:on_changed, on_changed_type) Optional

When using this method, it superceded cache_for method and will only re-evaluated when the specifed resources was changed. This method support 4 type of resources.

  • :string (default) plain string value
  • :file valid file resource name with absolute path, e.g: '/etc/groups'
  • :fact exiting node fact name, e.g: 'memorysize'
  • :data any hash/array that combine the above

cache(:name) do ...

Creates a cache with a given :name which must be unique. The duration of the cache is controlled by the cache_for method which must be specified above.

cache_chunk(:name) do ...

Works exactly the same as cache(:name) but for aggregate facts.

execute_only(from, to) Optional

Ensures that the fact only runs within a certain window. If the cache is invalid, but we are not within the time window, the cache will still be used. Note that if this is the first run and there is no cache, it will run the fact to generate it initially. If you want to suppress this behaviour, set initial_run? to false.

execute_only do ... Optional

execute_only can be passed a block if you need to do some custom logic to if the fact can be run (e.g. check the current load of the server). If the block returns false, the fact will not be run even if the cache is invalid. Note that this does not override fact caching behaviour; if this block returns true, but the cache is still valid, the cache will be used and the fact will not be run.

initial_run? Optional

Accepts true or false and controls whether this fact should be executed initially to populate the cache if it doesn't exist at all. Setting this to false means the fact will return nil if Puppet is installed during the exclusion window, until fact fact is allowed to run and therefore generate the cache.


There are not tests for this module yet to just fork and raise a PR.