Caching dependencies to speed up workflows

To make your workflows faster and more efficient, you can create and use caches for dependencies and other commonly reused files.

GitHub Actions is available with GitHub Free, GitHub Pro, GitHub Team, and GitHub Enterprise Cloud. GitHub Actions is unavailable for per-repository plans, which are legacy billing plans. For more information, see "GitHub's products."

In this article

About caching workflow dependencies

Workflow runs often reuse the same outputs or downloaded dependencies from one run to another. For example, package and dependency management tools such as Maven, Gradle, npm, and Yarn keep a local cache of downloaded dependencies.

Jobs on GitHub-hosted runners start in a clean virtual environment and must download dependencies each time, causing increased network utilization, longer runtime, and increased cost. To help speed up the time it takes to recreate these files, GitHub can cache dependencies you frequently use in workflows.

To cache dependencies for a job, you'll need to use GitHub's cache action. The action retrieves a cache identified by a unique key. For more information, see actions/cache.

Warning: We recommend that you don't store any sensitive information in the cache of public repositories. For example, sensitive information can include access tokens or login credentials stored in a file in the cache path. Also, command line interface (CLI) programs like docker login can save access credentials in a configuration file. Anyone with read access can create a pull request on a repository and access the contents of the cache. Forks of a repository can also create pull requests on the base branch and access caches on the base branch.

Comparing artifacts and dependency caching

Artifacts and caching are similar because they provide the ability to store files on GitHub, but each feature offers different use cases and cannot be used interchangeably.

  • Use caching when you want to reuse files that don't change often between jobs or workflow runs.
  • Use artifacts when you want to save files produced by a job to view after a workflow has ended. For more information, see "Persisting workflow data using artifacts."

Restrictions for accessing a cache

You can only access the cache in workflows triggered by push and pull_request events. For more information, see "Events that trigger workflows."

A workflow can access and restore a cache created in the current branch, the base branch (including base branches of forked repositories), or the default branch (usually master). For example, a cache created on the default branch master would be accessible from any pull request. Also, if the branch feature-b has the base branch feature-a, a workflow triggered on feature-b would have access to caches created in the default branch (master), feature-a, and feature-b.

Access restrictions provide cache isolation and security by creating a logical boundary between different workflows and branches. For example, a cache created for the branch feature-a (with the base master) would not be accessible to a pull request for the branch feature-b (with the base master).

Using the cache action

The cache action will attempt to restore a cache based on the key you provide. When the action finds a cache, the action restores the cached files to the path you configure.

If there is no exact match, the action creates a new cache entry if the job completes successfully. The new cache will use the key you provided and contains the files in the path directory.

You can optionally provide a list of restore-keys to use when the key doesn't match an existing cache. A list of restore-keys is useful when you are restoring a cache from another branch because restore-keys can partially match cache keys. For more information about matching restore-keys, see "Matching a cache key."

For more information, see actions/cache.

Input parameters for the cache action

  • key: Required The key created when saving a cache and the key used to search for a cache. Can be any combination of variables, context values, static strings, and functions. Keys have a maximum length of 512 characters, and keys longer than the maximum length will cause the action to fail.
  • path: Required The file path on the runner to cache or restore. This can be an absolute path or relative to the working directory. The path input must be a directory. You cannot cache a single file. The path must be located inside of the GITHUB_WORKSPACE directory. For more information, see "Using environment variables."
  • restore-keys: Optional An ordered list of alternative keys to use for finding the cache if no cache hit occurred for key.

Output parameters for the cache action

  • cache-hit: Set to true for a cache hit, and set to false for a cache miss.

Example using the cache action

This example creates a new cache when the packages in package-lock.json file change, or when the runner's operating system changes. The cache key uses contexts and expressions to generate a key that includes the runner's operating system and a SHA-256 hash of the package-lock.json file.

name: Caching with npm

on: push

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1

    - name: Cache node modules
      uses: actions/cache@v1
      with:
        path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.os }}-build-${{ env.cache-name }}-
          ${{ runner.os }}-build-
          ${{ runner.os }}-

    - name: Install Dependencies
      run: npm install

    - name: Build
      run: npm build

    - name: Test
      run: npm test

When key matches an existing cache, it's called a cache hit, and the action restores the cached files to the path directory.

When key doesn't match an existing cache, it's called a cache miss, and a new cache is created if the job completes successfully. When a cache miss occurs, the action searches for alternate keys called restore-keys.

  1. If you provide restore-keys, the cache action sequentially searches for any caches that match the list of restore-keys.

    • When there is an exact match, the action restores the files in the cache to the path directory.
    • If there are no exact matches, the action searches for partial matches of the restore keys. When the action finds a partial match, the most recent cache is restored to the path directory.
  2. The cache action completes and the next workflow step in the job runs.
  3. If the job completes successfully, the action creates a new cache with the contents of the path directory.

To cache files in more than one directory, you will need a step that uses the cache action for each directory. Once you create a cache, you cannot change the contents of an existing cache but you can create a new cache with a new key.

Using contexts to create cache keys

A cache key can include any of the contexts, functions, literals, and operators supported by GitHub Actions. For more information, see "Contexts and expression syntax for GitHub Actions."

Using expressions to create a key allows you to automatically create a new cache when dependencies have changed. For example, you can create a key using an expression that calculates the hash of an npm package-lock.json file.

npm-${{ hashFiles('package-lock.json') }}

GitHub evaluates the expression hash "package-lock.json" to derive the final key.

npm-d5ea0750

Matching a cache key

The cache action first searches for cache hits for key and restore-keys in the branch containing the workflow run. If there are no hits in the current branch, the cache action searches for key and restore-keys in the parent branch and upstream branches.

You can provide a list of restore keys to use when there is a cache miss on key. You can create multiple restore keys ordered from the most specific to least specific. The cache action searches for restore-keys in sequential order. When a key doesn't match directly, the action searches for keys prefixed with the restore key. If there are multiple partial matches for a restore key, the action returns the most recently created cache.

Example using multiple restore keys

restore-keys: |
  npm-foobar-${{ hashFiles('package-lock.json') }}
  npm-foobar-
  npm-

The runner evaluates the expressions, which resolve to these restore-keys:

restore-keys: |
  npm-foobar-d5ea0750
  npm-foobar-
  npm-

The restore key npm-foobar- matches any key that starts with the string npm-foobar-. For example, both of the keys npm-foobar-fd3052de and npm-foobar-a9b253ff match the restore key. The cache with the most recent creation date would be used. The keys in this example are searched in the following order:

  1. npm-foobar-d5ea0750 matches a specific hash.
  2. npm-foobar- matches cache keys prefixed with npm-foobar-.
  3. npm- matches any keys prefixed with npm-.
Example of search priority
key:
  npm-feature-d5ea0750
restore-keys: |
  npm-feature-
  npm-

For example, if a pull request contains a feature branch (the current scope) and targets the default branch (master), the action searches for key and restore-keys in the following order:

  1. Key npm-feature-d5ea0750 in the feature branch scope
  2. Key npm-feature- in the feature branch scope
  3. Key npm- in the feature branch scope
  4. Key npm-feature-d5ea0750 in the master branch scope
  5. Key npm-d5ea0750 in the master branch scope
  6. Key npm in the master branch scope

Usage limits and eviction policy

GitHub will remove any cache entries that have not been accessed in over 7 days. You can store as many cache entries as you'd like for free, as long as you are within these usage limits:

  • Individual files in a cache don't exceed 400 MB. You will receive a 400 - Bad Request if you exceed this limit.
  • The total size of all caches in a repository don't exceed 2 GB. If you exceed this limit, GitHub will save your cache but will begin evicting caches until the total size is less than 2 GB.

Ask a human

Can't find what you're looking for?

Contact us