How We Reduced Our Open Source Project’s GitHub Actions Bill by 70% (Without Sacrificing Speed)

1 comment
(GitHub and Open Source) - Our open source project was burning through $800/month in GitHub Actions minutes. We hired a Vietnamese team to optimize our workflows, and they cut costs by 70% while keeping builds under 5 minutes. Here's exactly how we did it.

How We Reduced Our Open Source Project’s GitHub Actions Bill by 70% (Without Sacrificing Speed)

Let me be blunt: our open source project was bleeding money on CI/CD.

We had a 10K+ star repo with 40+ contributors. Every PR triggered a full matrix build across 6 OSes, 4 Python versions, and 3 Node versions. It was overkill. But we were afraid to touch it. “If it ain’t broke, don’t fix it,” right?

How We Helped an EdTech Startup Survive a 10x Traffic Spike Without Burning Cash

How We Helped an EdTech Startup Survive a 10x Traffic Spike Without Burning Cash

How We Helped an EdTech Startup Survive a 10x Traffic Spike Without Burning Cash It’s a Thursday afternoon.… ...

Wrong.

Our monthly GitHub Actions bill hit $800. That’s not sustainable for a project with zero revenue. We needed to cut costs—fast.

Build a Custom AI-Powered Lint Fixer with Python and GitHub Actions: A Step-by-Step Developer Tutorial

Build a Custom AI-Powered Lint Fixer with Python and GitHub Actions: A Step-by-Step Developer Tutorial

Build a Custom AI-Powered Lint Fixer with Python and GitHub Actions: A Step-by-Step Developer Tutorial You’ve seen the… ...

I brought in a team from ECOA AI in Can Tho, Vietnam. They’re not just cheap labor; they’re engineers who live and breathe CI/CD optimization. Together, we slashed the bill to $240/month—a 70% reduction—without increasing merge times.

Here’s the exact playbook.

The Problem: Bloated Matrix Builds

Our workflow looked like this:

yaml
name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: ['3.9', '3.10', '3.11', '3.12']
        node-version: ['16', '18', '20']
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - run: pip install -e .[dev]
      - run: pytest

That’s 36 parallel jobs per push. Most of them tested the same code in slightly different environments. We didn’t need all combinations—just the critical ones.

Step 1: Identify Redundant Combinations

The Vietnamese team analyzed our test failure history. Here’s what they found:

  • Python 3.9 and 3.10 had identical failure rates on Ubuntu and macOS.
  • Windows builds accounted for only 2% of our user base but 25% of our CI minutes.
  • Node 16 was EOL and irrelevant.

We cut the matrix to:

OS Python Node When to run
ubuntu-latest 3.11, 3.12 20 Always
macos-latest 3.11 20 Only on PRs with macOS-specific changes
windows-latest 3.11 20 Only on scheduled weekly runs

Result: 12 jobs instead of 36. Cost dropped by 60% immediately.

Step 2: Cache Everything That Moves

Dependency installation was eating 40% of our build time. We added caching for pip and npm:

yaml
- uses: actions/cache@v4
  with:
    path: ~/.cache/pip
    key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
    restore-keys: |
      ${{ runner.os }}-pip-

This cut install time from 3 minutes to 15 seconds. Combined with the reduced matrix, our average build time went from 12 minutes to 4.2 minutes.

Step 3: Use Self-Hosted Runners for Heavy Jobs

The biggest savings came from moving CPU-intensive integration tests to self-hosted runners. We set up two cheap VMs in Ho Chi Minh City (cost: $40/month total) and configured GitHub Actions to route specific jobs there.

yaml
jobs:
  integration-tests:
    runs-on: [self-hosted, linux, x64]
    steps:
      - run: docker-compose up -d
      - run: pytest tests/integration/

Self-hosted runners cost $0 per minute. That single change saved us $180/month in runner minutes.

Step 4: Conditional Triggers

We stopped running CI on pushes to `docs/` and `*.md` files. Simple `paths-ignore` saved 5% more.

yaml
on:
  push:
    paths-ignore:
      - 'docs/**'
      - '*.md'

The Final Result

Metric Before After Improvement
Monthly cost $800 $240 70% reduction
Average build time 12 min 4.2 min 65% faster
Failed builds 8% 2% 75% fewer failures
Contributor satisfaction Low High No more waiting

Honestly, we should have done this a year ago. But we were scared to touch the workflow. The Vietnamese team brought fresh eyes and deep GitHub Actions expertise. They didn’t just cut costs—they made our CI faster and more reliable.

Why This Matters for Open Source

Open source projects run on goodwill and limited budgets. Every dollar saved on CI is a dollar you can reinvest into community events, documentation, or paying maintainers. And speed matters: slow CI drives contributors away.

Here’s the kicker: we didn’t sacrifice quality. Our test coverage stayed the same. We just stopped testing things that never broke.

Can You Do This Too?

Yes. Start by auditing your workflow. Look for:

  • Massive matrix builds with redundant combinations
  • Long dependency installs without caching
  • Jobs that run on every push but shouldn’t
  • Expensive macOS/Windows runners for trivial tasks

But if you’re busy shipping features (like you should be), consider bringing in experts. The ECOA AI team in Vietnam did this for us in two weeks for less than what we saved in the first month.

Frequently Asked Questions

Q: How do I calculate my current GitHub Actions cost?

Go to your repo’s Settings → Billing → GitHub Actions. You’ll see minutes used per month. Multiply by the runner type cost ($0.008/min for Linux, $0.016 for Windows, $0.08 for macOS). That’s your bill.

Q: Is it safe to use self-hosted runners for open source projects?

Yes, but isolate them. Use dedicated VMs that can’t access your production secrets. We use a separate GitHub environment for self-hosted runners with restricted permissions.

Q: What’s the biggest mistake teams make when optimizing CI costs?

They optimize for speed first, cost second. That’s backwards. Start by removing unnecessary jobs, then add caching, then consider self-hosted runners. Speed is a side effect of efficiency, not the primary goal.

Q: How do I convince my team to change the CI workflow?

Show them the numbers. Our $800/month bill was a wake-up call. Run a cost report, present it at a team meeting, and propose a two-week optimization sprint. The savings speak for themselves.

Related reading: Why Outsourcing Software Development to Vietnam Beats India and the Philippines in 2025

Leave a Comment

Your email address will not be published. Required fields are marked *

Ready to Build with AI-Powered Developers?

Hire Vietnamese engineers augmented by ECOA AI Platform + Claude Code. 5x faster, 40% cheaper.