Quota Cost Registry

GitHub's REST API allows 5,000 requests per hour per user (shared across all tokens belonging to the same user). This page documents how many REST calls each workflow consumes per run, the minimum quota required before a workflow should start, and how the quota management system uses this data.

GraphQL counts as 1 call regardless of how many repos are queried. raw.githubusercontent.com fetches are exempt entirely.


How quota is managed

Three mechanisms work together:

MechanismWhereWhat it does
quota-reserve.shRuns every 30 minCancels queued low-priority runs when remaining < RESERVE_FLOOR (default: 1000). Uses min_quota per workflow to also cancel runs that couldn't succeed with current quota even if they started.
budget_check()Inside each script loopStops processing mid-run when time budget is exhausted. Prevents a single run from consuming all quota in one shot.
workflow_min_quota()Pre-flight stepsReturns the min_quota for a workflow from config/workflow-quota-costs.yml. Workflows can use this to skip themselves when quota is too low.

The single source of truth for costs is config/workflow-quota-costs.yml.


Cost table

Costs are estimated from code audit (Phase 1). Phase 2 will replace these with observed p50/p95 values from actual run measurements.

min_quota = minimum REST calls required before this workflow should be allowed to start.

Tier 1 — Critical (never cancelled)

Workflowmin_quotaLowMidHighNotes
Rotate Secret Token5051020Token validation + secret update
Queue Manager5051530Queued run list + cancel calls
Quota Reserve101515rate_limit check (exempt) + cancels
Rate-Limit Re-trigger5052050Failed run scan + dispatch calls
Token Health Monitor5051020Token validation only
CI502510ShellCheck + lint, minimal API
Pre-Flush Prep100103060PR list + check-run queries

Tier 2 — High

Workflowmin_quotaLowMidHighNotes
Mirror Interested-Deving-1896 → OSP50020802002 GraphQL + 1 REST/repo (check-runs, gated)
Mirror OSP → GitLab300520501 GraphQL for repo list; GitLab calls exempt
Sync Registered Imports200515301 GraphQL prefetch; REST only for new repos
Sync All Forks500502005001 GraphQL + 1 REST merge-upstream per fork
Full Chain Flush10001004001000Orchestrates chain — cost is additive
Add Mirror Repo200103060Repo creation + webhook + dispatch

Tier 3 — Medium

Workflowmin_quotaLowMidHighNotes
Update READMEs30050150300Tree fetch + file reads/writes per repo
Create Missing READMEs2002080200Same as Update READMEs, subset of repos
Inject Built-with-Ona Badges200530801 GraphQL (repo list + README); REST only on write
Reconcile Org References30010601501 GraphQL repo list; pushedAt from cache
Check OSP-Bound CI Status300501503004 REST/repo (check-runs not in GraphQL)
Rebase PRs10052050PR list + rebase trigger
Sync btrfs-devel Branches10052050Branch sync per tracked branch
Sync pieroproietti Forks1001040100merge-upstream per fork branch
Setup OSP Mirror Workflows20020802001 GraphQL + workflow/secrets per repo (not in GraphQL)
Upstream PRs from OSP + OOC2002080200PR creation/update per diverged repo
Upstream Direct Commits from OSP + OOC2002080200Commit compare + PR creation
Sync to GitLab10052050GitHub reads; GitLab writes exempt
Sync to GitLab Variant10052050Same as Sync to GitLab
Sync from GitLab10052050GitLab reads + GitHub writes
Notification Poller501515Single notifications call + optional dispatch

Tier 4 — Low (cancelled first)

Workflowmin_quotaLowMidHighNotes
Translate READMEs1001040100File read + write per README
LTS README Standardisation1001040100File read + write per LTS repo
Generate OSP Dependency Graph1002060150README + package.json reads per repo
Upstream Workflow Proposal5052050Workflow file reads + PR creation
Update Infrastructure Dependencies5051530Dependabot config + PR creation
Mirror Artifacts20010501502 GraphQL; release asset downloads exempt
Mirror Releases20010501502 GraphQL + 1 REST releases list per repo
Cleanup Stale Branches20010602001 GraphQL + 1 REST compare per branch
OTA Discover1001040100Fork list + config reads per fork
OTA Self-Update5051530Config read + PR creation
Mirror Orgs1002060150Repo list + description reads per org
Resolve CI Failures1001040100Failed run list + job details + file writes

Daily quota budget

At 5,000 calls/hour reset, the effective daily budget depends on how many resets are consumed cleanly vs. drained by backlog. With the schedule reductions applied (June 2026), the expected daily workflow run count dropped by ~172 runs/day.

CategoryBeforeAfter
quota-reserve runs/day14448
queue-manager runs/day9648
notify-poller runs/day126
rate-limit-rerun runs/day126
mirror-artifacts runs/day63
mirror-osp-to-gitlab runs/day63
sync-pieroproietti-forks runs/day63
sync-to-gitlab-variant runs/day63

REST → GraphQL conversion log

Scripts converted from per-repo REST loops to batched GraphQL calls:

ScriptSavings/runRuns/daySaved/day
sync-registered-imports.sh~1004~400
mirror-osp-to-gitlab.sh~23~6
reconcile-org-refs.sh~1006~600
inject-badges.sh~503~150
cleanup-branches.sh~2001~200
mirror-releases.sh~504~200
mirror-artifacts.sh~503~150
ota-discover.sh~501~50
mirror-orgs.sh~601~60
setup-osp-mirrors.sh~1004~400
Total~2,216/day

Phase 2: observed cost tracking (planned)

Phase 2 will add lightweight instrumentation to measure actual REST consumption per run:

  1. scripts/includes/quota-instrument.sh — records remaining_before and remaining_after as workflow step summary annotations
  2. update-quota-costs.yml — weekly workflow that reads the last 30 run summaries via GraphQL, computes p50/p95 per workflow, and commits updated values back to config/workflow-quota-costs.yml with basis: observed

Once Phase 2 is active, the tables above will show observed values alongside the code-audit estimates, and quota-reserve.sh will automatically use the more accurate figures.