GitHub Actions Tutorial — Pricing & Limits

2 minute read

Pricing & Limits

GitHub Actions pricing is generous, especially for open-source projects. Understanding the limits helps you avoid unexpected charges and optimize your workflow runs.


Free Tier

Every GitHub account gets free GitHub Actions minutes:

Plan Monthly Minutes (Private Repos) Storage
GitHub Free 2,000 minutes 500 MB
GitHub Pro 3,000 minutes 1 GB
GitHub Team 3,000 minutes 2 GB
GitHub Enterprise 50,000 minutes 50 GB

Public repositories: All plans get unlimited free minutes for public repos. This makes GitHub Actions ideal for open-source projects.


Per-Minute Costs by Runner OS

When you exceed your free tier, GitHub charges per-minute rates:

Runner OS Minute Multiplier Effective Cost (Free plan rate)
Linux 1× $0.008/min
Windows 2× $0.016/min
macOS 10× $0.080/min

Example: A workflow that runs for 10 minutes on macOS uses 100 of your free minutes (10 × 10 multiplier).


What Counts Toward Minutes

Counts Doesn’t Count
Jobs running on GitHub-hosted runners Jobs running on self-hosted runners
Time spent executing steps Time waiting in a queue
Container setup time Workflow file parsing

Usage Limits

Limit Value
Concurrent jobs (Free) 20
Concurrent jobs (Team/Enterprise) 60 / 180
Job execution time 6 hours max per job
Workflow run time 35 days max
API requests 1,000 per hour per repo
Workflow file size 512 KB max
Matrix combinations 256 max per workflow
Artifacts retention 90 days (default)
Cache size 10 GB per repo

Cost Optimization Tips

1. Use Linux Runners When Possible

Linux runners are 1×, Windows is 2×, macOS is 10×. If your tests can run on Linux, you’ll save significant minutes.

2. Cancel Redundant Runs

Use concurrency groups to cancel in-progress runs when a new push arrives:


concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

3. Cache Dependencies

Caching node_modules, pip packages, or Maven dependencies avoids re-downloading on every run:


- uses: actions/cache@v4
  with:
    path: node_modules
    key: node-${{ hashFiles('package-lock.json') }}

4. Use Path Filters

Don’t run CI on every push — filter to relevant paths:

on:
  push:
    paths:
      - 'src/**'
      - 'package.json'

5. Use Self-Hosted Runners for Heavy Workloads

Self-hosted runners don’t consume GitHub-hosted minutes. If you have high-volume pipelines, self-hosted runners can reduce costs dramatically.


Monitoring Usage

Check your usage at: Settings → Billing → Actions

You can also set spending limits to prevent overages:

  • Default: $0 (no paid overage)
  • You must explicitly increase the limit to allow paid minutes

Quick Reference

Item Free (Private) Public Repos
Minutes 2,000/month Unlimited
Storage 500 MB 500 MB
Linux multiplier 1× 1×
macOS multiplier 10× 10×
Job timeout 6 hours 6 hours
Self-hosted cost Free (no minutes) Free (no minutes)

← Previous: Actions vs Alternatives

Next: Marketplace Overview →

Updated: