Get back to home
2025-04-10

Speeding Up Your GitHub Actions with Cache

We all love GitHub workflows, but I loved it even more when I learned how to use the GitHub Actions cache.

GitHub Actions caching can save your day. I’ll explain it in a simple way: how it works, why it’s important, and how you can speed up your pipelines without being a DevOps expert.


The common problem

Here’s what most of us do in a typical GitHub Actions setup:

steps:
  - uses: actions/checkout@v4
  - name: Install Node.js dependencies
    run: npm install
  - name: Build the app
    run: npm run build

Pretty normal, right?

But the problem is:

Result?
Slow builds.
💸 More wasted CI minutes.


Why Cache Exists (and Why You Should Care)

Caching is basically remembering stuff between runs.

If your dependencies didn’t change, why reinstall them?
If your build artifacts didn’t change, why rebuild everything?

With cache you can:


Let’s Cache Your Node.js Stuff

The easiest win is caching your node_modules or pnpm store.

Here’s a basic example:

steps:
  - uses: actions/checkout@v4

  - uses: actions/setup-node@v4
    with:
      node-version: 18

  - name: Cache Node.js dependencies
    uses: actions/cache@v4
    with:
      path: ~/.npm
      key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
      restore-keys: |
        ${{ runner.os }}-node-

  - name: Install dependencies
    run: npm ci

  - name: Build the app
    run: npm run build

What’s happening here?

✅ If you didn’t change your dependencies → instant install.
✅ If you did → it falls back to a fresh install.


Bonus Tip: Cache Your Build Artifacts Too

Got a heavy build like Next.js or Vite?
You can cache the output too:

- name: Cache build artifacts
  uses: actions/cache@v4
  with:
    path: |
      .next/cache
      dist
    key: ${{ runner.os }}-build-${{ github.sha }}
    restore-keys: |
      ${{ runner.os }}-build-

This way you save your .next/cache or dist/ folders between runs.


Common Mistakes (and How Not to Suffer)

MistakeHow to avoid it
Cache always missesMake sure your cache key is based on a stable file like package-lock.json, not random stuff.
Cache too bigGitHub limits individual caches to 400MB. Split them if needed.
Broken cache breaks buildsAlways use restore-keys as fallback.
Wrong pathsCache your npm or pnpm store, not random folders like node_modules directly.

Real-World Example: React + pnpm

If you’re using pnpm, setup-node has built-in caching now. Even easier:

name: Build and Deploy

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: "pnpm" # 🔥 automatic caching!

      - name: Install dependencies
        run: pnpm install

      - name: Build the app
        run: pnpm run build

👉 No need to even set up actions/cache manually for pnpm/yarn/npm anymore.
GitHub’s smart enough to handle it for you.


Pro Tips


Wrapping Up

Caching in GitHub Actions is one of the easiest hacks to make your pipelines feel fast and efficient.
Less waiting, more coding. 🚀

If you haven’t added cache yet, you’re seriously missing out.

For deeper details, check out the actions/cache docs.


⚡ Bonus Tip

You can literally save minutes per build just by caching smart.
Want proof? Here’s a real before/after I saw:

Before CacheAfter Cache
Install Dependencies1 min 47 sec11 sec
Build App2 min 25 sec50 sec

Worth it, right? 🚀