GitHub Actions billing is a bit of a labyrinth, but the most surprising truth is that you’re probably paying for actions you don’t even realize are running, and the primary culprit is often not the jobs themselves, but the artifacts and logs they leave behind.

Let’s look at a real-world scenario. Imagine a repository with a CI pipeline that builds and tests code.

name: CI

on: [push]

jobs:
  build_and_test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      - name: Install dependencies
        run: npm ci
      - name: Run tests
        run: npm test
      - name: Upload coverage report
        uses: actions/upload-artifact@v3
        with:
          name: coverage-report
          path: ./coverage

This looks innocent enough, right? It checks out code, sets up Node.js, installs dependencies, runs tests, and then uploads a coverage report as an artifact. Each of these steps consumes compute minutes. But the real cost often comes from the storage of that artifact.

The Hidden Cost: Artifacts and Logs

GitHub Actions billing is primarily based on two things:

  1. Compute Minutes: The time your jobs spend running on GitHub-hosted runners.
  2. Storage: The space occupied by artifacts and logs retained from your workflows.

While compute minutes are often what people monitor, artifact storage can quickly become a significant, and often overlooked, expense, especially for projects that generate large reports, test results, or build outputs. By default, GitHub retains artifacts for 90 days. If you have many workflows generating large artifacts, this can add up.

Understanding Your Usage

To get a grip on your billing, you need to access your organization’s billing page.

  1. Navigate to your organization’s page on GitHub.
  2. Click on Settings.
  3. Under the "Billing and plans" section, click on Billing.

Here, you’ll see a breakdown of your usage. Look for sections related to "Actions" and specifically "Storage." This is where you’ll find the total amount of storage consumed by artifacts and logs.

Taking Control: Strategies and Configuration

The key to controlling costs is to be deliberate about what you keep and for how long.

1. Limiting Artifact Retention:

This is the most direct way to cut down on storage costs. You can configure how long artifacts are kept directly within your workflow.

      - name: Upload coverage report
        uses: actions/upload-artifact@v3
        with:
          name: coverage-report
          path: ./coverage
          retention-days: 3 # Keep for only 3 days

Why this works: By setting retention-days to a lower value (e.g., 3 days instead of the default 90), you instruct GitHub Actions to automatically delete the artifact after that period, freeing up storage space and reducing your bill.

2. Selective Artifact Uploads:

Do you really need to store every single artifact? If an artifact is only useful for immediate debugging or for a short period, consider not uploading it at all, or only uploading it conditionally.

      - name: Upload test results (conditional)
        if: failure() # Only upload if the job fails
        uses: actions/upload-artifact@v3
        with:
          name: test-failures
          path: ./test-results
          retention-days: 1

Why this works: Uploading artifacts only when necessary, like when a test fails, ensures you’re not accumulating storage for successful runs where the artifacts might be redundant.

3. Cleaning Up Old Artifacts Manually (If Needed):

While retention-days is automatic, you might find yourself in a situation where you need to clean up older artifacts immediately. You can do this through the GitHub UI.

  1. Go to your repository’s Actions tab.
  2. Click on Artifacts in the left sidebar.
  3. You’ll see a list of all artifacts. You can click the X next to each artifact to delete it.

Why this works: This provides an immediate way to reclaim storage space if your automated retention policies aren’t sufficient or if you discover a large, old artifact that needs to be purged.

4. Monitoring Compute Minutes:

While storage is often the sneaky cost, compute minutes are the primary driver for many. Keep an eye on the "Compute minutes" section on your billing page.

  • Optimize your workflows: Can you combine steps? Can you use more efficient actions?
  • Choose the right runner: For computationally intensive tasks, consider self-hosted runners if you have the infrastructure, as they don’t incur compute minute charges from GitHub.
  • Parallelize wisely: While parallelization speeds up CI, running too many jobs concurrently can increase your compute minute usage.

5. Disabling Unused Workflows:

Sometimes, you might have old workflows that are no longer needed but are still running and consuming resources.

  1. Navigate to the Actions tab of your repository.
  2. In the left sidebar, under "Workflows," you’ll see a list of all your workflows.
  3. Click on a workflow you want to disable.
  4. Click the menu in the top right corner and select Disable workflow.

Why this works: This stops the workflow from triggering on its defined events, preventing any further compute minute usage or artifact generation.

One of the less obvious aspects of artifact management is that GitHub’s billing for storage is based on the total size of all retained artifacts across all repositories in your organization. This means a single large artifact in one repository can impact the billing for the entire organization, making organization-wide visibility crucial.

By actively managing artifact retention and selectively uploading data, you can significantly reduce your GitHub Actions billing and ensure you’re only paying for what you truly need.

The next challenge you’ll likely face is optimizing the compute time itself, looking for ways to shave seconds off your CI/CD pipelines.

Want structured learning?

Take the full Github-actions course →