Skip to content

AWS compute for our GitHub Actions runners ​

Assessed 2026-09-23. The question: keep the entire GitHub Actions flow exactly as built (same workflows, same gates, same deploy controls), and use AWS only to supply the compute the jobs run on, so GitHub's 2,000-minute quota stops being the constraint. Can that run at a hard ₹0/month?

This is not a move to AWS-native CI. CodePipeline and CodeBuild-as-a-pipeline would replace Actions, and they are out of scope (see What is out of scope).

Prices are USD from the AWS Price List API for Mumbai (ap-south-1) unless marked us-east-1. Rupee figures assume ≈ ₹88 / $ (an assumption, not a sourced rate), and AWS India adds 18% GST to every charge. Anything not confirmed on an official page is marked UNVERIFIED.

CORRECTION 2026-09-23: the workload figures on this page are overstated

What was wrong. They counted 818 quota-blocked jobs (jobs GitHub refused without running, which bill nothing) at one minute each. August's executed usage was 1,381 Linux + 65 macOS minutes up to the 11 August block, not 2,409 + 90. The measured breakdown is in GitHub Actions usage forensics.

What stands. The conclusions don't change: ₹0 only during the ≤ 6-month Free plan, and no ₹0 macOS. AWS cost estimates here are, if anything, high.

Why AWS may be unnecessary. That page found the quota burn is a configuration problem (a failing nightly schedule and Dependabot CI), fixable without new compute.

VERDICT

AWS can supply the compute, but only for a limited period at ₹0.

  • For up to 6 months: ₹0, guaranteed. A new account on AWS's Free plan cannot be charged; usage draws down $100 of credits (up to $200 with activities). At our measured volume, CodeBuild runners fit inside that for the whole 6-month window.
  • After month 6: not ₹0. The Free plan ends and the account closes unless upgraded to Paid. On Paid, the same compute costs about $12–24/month (≈ ₹1,250–2,500 incl. GST) at August's volume.
  • macOS: never ₹0 on AWS. Mac runs only on Dedicated Hosts with a 24-hour minimum ($15–29/day), so the iOS job stays on GitHub-hosted runners.
  • What changes in the repo: only each job's runs-on: line, which is unavoidable for any non-GitHub machine. Workflows, gates, environments and deploy rules stay as they are.
Key figureValue
GitHub charge for jobs on our own (self-hosted) runners, AWS included$0, and those minutes don't count against the 2,000
Linux compute used in August (last complete month)2,409 min (≈ 40 hours)
Paying CodeBuild for all of it$12 (general1.small, 4 GB) to $24 (general1.medium, 8 GB)
Free-plan runway at that rate6 months fully covered with $200 credits; 4–6 months with $100
GitHub quota left in use after moving Linux jobs≈ 930 min/month (iOS at 10×, plus deploys), inside 2,000

How AWS compute plugs into our existing Actions ​

GitHub Actions keeps orchestrating everything. A job simply names a different machine in runs-on, and GitHub hands it to that machine. GitHub bills nothing for self-hosted runners and their minutes don't come out of the 2,000 (billing docs). Every AWS option below counts as self-hosted.

AWS compute optionHow the job gets therePay forFits our jobs
CodeBuild-hosted runner (recommended)CodeBuild listens for GitHub's "job queued" event and starts a fresh, single-use runner for that one job, then terminates itbuild minutes only; nothing while idle; no public IP billed to usLinux x64 and ARM, 4/8/16 GB sizes; Docker works on EC2 compute
EC2 instance running the GitHub runnera VM with the runner agent installed; it polls GitHub over outbound 443instance hours + disk + public IPv4, whether or not a job is runninganything, sized as chosen; you patch and clean the machine
EC2 spot autoscaling (terraform-aws-github-runner)Lambda starts a spot VM per queued job and removes it afterspot hours + disk + IPv4 per job; Lambda/SQS/API Gateway glueanything; built for teams with high concurrency

Why CodeBuild-hosted runners fit best. They give us the "spin up only for the job" model without our having to build it. Each job gets a clean machine, so there is nothing to patch or clean up, and idle time costs nothing. An always-on EC2 runner pays for 730 hours a month to do about 40 hours of work.

The workflow change, made switchable. Once per job:

yaml
runs-on: ${{ vars.RUNNER_LINUX == 'aws' && format('codebuild-qrsetu-{0}-{1}', github.run_id, github.run_attempt) || 'ubuntu-latest' }}

With the repository variable RUNNER_LINUX set to aws, the job runs on CodeBuild. Delete the variable and it runs on GitHub-hosted exactly as today. Switching becomes a setting, not a code change. The runner size can be pinned per job with CodeBuild's instance-size: label override.

Label format UNVERIFIED in combination

The codebuild-<project>-<run_id>-<run_attempt> form is documented, and so is the vars context in runs-on. Their combination via format() is our construction. Prove it on one job before rolling it out.

What the workload actually is ​

Measured from GitHub's run history: 976 workflow runs and 1,906 jobs, July to 23 Sep 2026. Each job's duration comes from its started_at/completed_at, rounded up to the whole minute per job (GitHub's billing rule). 226 jobs never started and cost nothing.

The /timing endpoint is not a measurement any more

GitHub's actions/runs/{id}/timing reported 0 billable minutes for every run. Under the new billing platform that field is simply empty, so it was not used.

MonthJobsLinux minmacOS minQuota draw (macOS ×10)…of which Dependabot updatesNote
July 20263261,05101,05188Incomplete. The quota ran out on 30 Jul, so earlier runs are missing from the API history.
August 20261,1152,409903,309382The last complete month; over the 2,000 included.
September 1–232398741192,064291Watchdog and scheduled iOS disabled early in the month; still over quota.
Job (all months)RunsAvg min / runQuota drawCompute
parity-native · iOS (macOS)375.62,090stays on GitHub (no ₹0 macOS on AWS)
parity-native · Android6315.8998AWS, 8 GB, x86
Dependabot update runs2253.4761GitHub's own job; whether it is billed is UNVERIFIED
ci · e2e-web1295.7737AWS
ci · workspace1492.9432AWS, 8 GB
security · semgrep + gitleaks178 each1.5 / 1.0447AWS
payments-watchdog1481.0148now disabled
backend-ci · Database (pgTAP)572.5143AWS (Docker)
ci · sonar314.2131AWS, 8 GB (Docker)
All others (docs, card-ui-gate, env-drift, EF, grants, release-gate, deploys)—1.0–4.0≈ 540AWS, or keep deploys on GitHub

How to read this.

  • iOS is the biggest single quota consumer. 37 short runs used 2,090 minutes of quota, more than every job in ci.yml combined (1,533), purely because of the 10× macOS rate.
  • AWS can't take that one at ₹0. The good news is that it doesn't need to. With every Linux job moved to AWS, August's GitHub usage would have been about 900 (iOS) + ~30 (deploys) ≈ 930 of 2,000.

Is it ₹0? The Free-plan runway ​

AWS changed its Free Tier on 15 July 2025. A new account gets $100 credit, plus up to $100 more for completing activities, and chooses a plan:

  • Free plan. It cannot incur charges, because usage draws down credits.
    • It ends at 6 months or when credits run out, whichever comes first.
    • The account then closes, is kept 90 days, and is deleted unless upgraded.
    • This is the only true hard ₹0 in AWS.
  • Paid plan. Credits apply first, then pay-as-you-go. There is no hard cap.

(Free Tier plans · FAQ)

How long the credits carry our Linux jobs, at August's 2,409 minutes:

Compute for all Linux jobs$/month$100 credit lasts$200 credit lasts₹0 for the full 6 months?
CodeBuild general1.small (2 vCPU, 4 GB) at $0.005/min12.056 months (plan cap)6 months (plan cap)yes, but 4 GB is too small for Android, typed lint and Sonar
CodeBuild mixed: 8 GB medium for heavy jobs, small for the rest≈ 18≈ 5.5 months6 months (plan cap)yes with $200, nearly with $100
CodeBuild general1.medium (4 vCPU, 8 GB) for everything, $0.010/min24.09≈ 4 months6 months (plan cap)yes with $200
EC2 m7i-flex.large runner (2 vCPU, 8 GB, free-tier type) 24×7≈ 79.90 (73.55 instance + 3.65 IPv4 + 2.74 disk)≈ 1.3 months≈ 2.5 monthsno
EC2 m7i-flex.large, stopped outside ~10 working hours/day≈ 34.50≈ 2.9 months≈ 5.8 monthsnearly, with $200

The "mixed" row assumes Android, workspace, e2e and sonar on medium. That split comes from the job table above, so read it as an estimate. EC2 figures use a 30 GB gp3 disk.

Two eligibility unknowns to settle on day one

  • Is CodeBuild usable on a classic Free-plan account? AWS lists CodeBuild as available on the Free Tier in the new sign-up experience. For the classic ("advanced") sign-up, no page says so explicitly: UNVERIFIED.
    • If it is not, the EC2 route is the certain one: m7i-flex.large is an explicitly free-tier-eligible type for new accounts (EC2 free tier).
  • Does the Free plan apply to AWS India accounts? The FAQ excludes only China and GovCloud, so it very likely does: UNVERIFIED.

After month 6. Upgrade to Paid and the CodeBuild route costs about $12–24/month (≈ ₹1,250–2,500 incl. GST) at today's volume. Or let the account close and move the jobs elsewhere. There is no permanent ₹0 AWS compute at our size: the always-free allowance is 100 CodeBuild minutes/month, about 4% of August's Linux usage.

What AWS compute cannot do at ₹0 ​

  • macOS / iOS. AWS Mac runs only on Dedicated Hosts with a 24-hour minimum: $15.60 (M1) to $29.52 (M4) per day in us-east-1, and Mumbai offers Intel mac1 only ($27.36/day). CodeBuild Mac fleets are reserved-only, also 24 hours minimum, and not in Mumbai. Not free under any plan.
  • Anything permanent. The ₹0 lasts 6 months at most.
  • An always-on runner also exhausts the credits within 1–3 months (see the runway table).

Keeping it at ₹0 while it lasts ​

On the Free plan, the plan itself is the cap: nothing can be charged until you choose to upgrade. Two things still matter.

1. Don't upgrade by accident. These actions convert the account to Paid:

  • joining AWS Organizations, which, per the FAQ, also forfeits the credits;
  • setting up Control Tower;
  • joining the APN, or signing an enterprise agreement.

So on the Free plan there are no SCP guardrails, and none are needed.

2. Watch the credits, not a bill. A credit-burning mistake does not charge you; it shortens the runway.

SettingWhy
AWS Budgets zero-spend budget + Free Tier usage alerts (85%)early warning; both are free
CodeBuild project concurrency 1 (the default)one job at a time bounds the burn rate
CodeBuild build timeout ≈ 30–45 mina hung job can't burn hours
CloudWatch Logs retention 7 dayslog storage otherwise grows forever
No VPC for the CodeBuild projectavoids NAT Gateway ($0.056/hr)
Secrets in SSM Parameter Store (standard), not Secrets Managerstandard parameters are free; Secrets Manager is $0.40 per secret-month
If EC2: a stop schedule (EventBridge + Lambda, both always-free)idle hours are the biggest credit drain

If you later upgrade to Paid, there is no hard cap. Budgets alert up to 8–12 hours late, and Budget Actions can only stop EC2/RDS or attach deny policies; they never delete anything. AWS's new spend limit has a $20/month minimum and isn't available on the classic sign-up. The protection on Paid is the settings above, plus a Budget Action that attaches a deny policy to the CodeBuild role when a monthly amount is reached.

India specifics

  • Seller: an Indian address contracts with Amazon Web Services India Pvt Ltd.
  • Billing: INR invoices, 18% GST, and a ₹2 card-verification charge that is refunded.
  • KYC: CERT-In KYC is mandatory (PAN or Certificate of Incorporation, name matching exactly).
  • Sign-up path: use "Sign up for AWS (advanced)" to keep Mumbai. The new sign-up experience (16 Sep 2026) puts India accounts in Sydney.

Hidden-cost risks ​

On the Free plan these burn credits. On Paid they bill.

ResourceHow it catches people (Mumbai)Our rule
Public IPv4 / Elastic IP$0.005/hr per address, in use or idle (≈ $3.65/mo); no free allowance for new accountsCodeBuild avoids it; on EC2, stop the instance so the auto-assigned IP is released
EC2 left running24×7 is 730 hours; an idle runner costs the same as a busy oneCodeBuild; or a stop schedule
EBS volumes / snapshotsgp3 $0.0912/GB-mo even when the instance is stopped; snapshots $0.05/GB-mosmall disk; no snapshots
NAT Gateway$0.056/hr (≈ $40.88/mo) + $0.056/GB. The classic runner bill shocknever; no VPC
CloudWatch Logs$0.67/GB ingest beyond 5 GB; retention is forever by default7-day retention
S3no permanent allowance for new accounts; CodeBuild caches write here if enabledno S3 cache
ECR private$0.10/GB-mo after a 500 MB first-year allowanceuse public images
Data transfer$0.1093/GB beyond 100 GB/month outnpm and Docker pulls are inbound (free); fine at our size
CodeBuild reserved or Mac fleetsbill while idle (60-min / 24-hour minimums)on-demand only
Security trials (GuardDuty, Config, Security Hub)free trials that convertdon't enable
GitHub sidethe $0.002/min self-hosted fee was announced for 1 Mar 2026 and postponed, not cancelledsmall at our volume if it returns; watch the changelog

Setup plan ​

  1. Create the account.
    • "Sign up for AWS (advanced)", Mumbai, Digious business details, CERT-In KYC.
    • Choose the Free plan.
    • Root MFA, no root access keys, one admin IAM user.
    • Don't create or join an Organization.
  2. Credits. Complete the Free Tier activities (up to +$100). They double the runway.
  3. Alerts. Zero-spend budget, Free Tier usage alerts, and credit-balance emails.
  4. Connect GitHub. CodeConnections GitHub App ("AWS Connector for GitHub") on digious-platforms/qrsetu.
  5. Runner project.
    • One CodeBuild project named codebuild-qrsetu-style, as a GitHub Actions runner project.
    • Webhook on WORKFLOW_JOB_QUEUED, Ubuntu x86-64 image, general1.medium default.
    • No VPC, 45-min timeout, concurrency 1, 7-day log retention.
  6. Prove it on one job before touching the rest.
    • Point release-gate (Node only, ~1 min) at AWS through the vars.RUNNER_LINUX switch.
    • Read the credit balance after 48 hours.
  7. Move the Linux jobs one workflow at a time, cheapest first: ci → backend-ci → security → parity-native · Android.
    • Compare each against its last GitHub-hosted run.
    • Docker jobs (pgTAP, sonar, semgrep's container:) need CodeBuild's EC2 compute, not Lambda.
  8. Keep on GitHub-hosted:
    • the iOS job (macOS);
    • optionally deploys (deploy-web, deploy-prod), so production credentials and GitHub's environment branch policies stay on GitHub's machines.
  9. Put a date in the calendar for month 5. Decide then:
    • upgrade to Paid (~₹1,250–2,500/month at today's volume), or
    • move the jobs back or elsewhere before the account closes.

Beyond AWS, for completeness ​

GitHub doesn't care whose machine a self-hosted runner is on.

  • Our own Mac mini M4 (16 GB), registered as a runner, is ₹0 permanently.
  • It is also the only ₹0 macOS machine available to us, so it could take the iOS job too.
  • The trade-off: it only works while that machine is on, and it depends on one person's hardware.

It needs the same runs-on switch, so it can sit alongside AWS rather than replace it.

What is out of scope ​

  • CodePipeline, and CodeBuild triggered directly by a GitHub webhook. These replace Actions as the CI definition (gates and deploy rules would move into AWS configuration). The requirement is to keep the current flow, so they are not assessed.
  • SonarQube hosting. The existing sonar job boots SonarQube inside the job; on an 8 GB CodeBuild runner it runs as it does today. SonarQube Cloud's free plan is not an option either way: it caps private code at 50k lines, and our scanned sources are ≈ 198k non-blank lines (our count).

Sources ​

Unverified or conflicting

  • CodeBuild availability on a classic Free-plan account.
  • The Free plan for AWS India accounts.
  • The format() label construction.
  • Whether CodeBuild-runner minutes draw from the 100 always-free minutes.
  • How macOS minutes draw down GitHub's quota after the 1 Jan 2026 price change (10× assumed).
  • Whether Dependabot's own update runs are billed.
  • The INR rate.