Autoscaling: polling and webhooks
Runaway sizes each scale set to demand — the count of busy plus queued jobs — learned through two channels: polling, which always runs, and webhooks, which you can opt into per organization.
Polling — the universal channel
Section titled “Polling — the universal channel”By default Runaway polls GitHub roughly every 30 seconds for each org’s queued and in-progress jobs, and sizes the pool to match. Polling works everywhere with no setup:
- No public exposure. The hub reaches out to GitHub; GitHub never has to reach the hub. A NAT’d homelab hub autoscales out of the box.
- Near-zero rate-limit cost. Requests are ETag-cached, so an idle org costs almost nothing against your GitHub API budget.
For most homelab and small-team workloads, a ~30-second reaction time is fine.
Webhooks — the lower-latency overlay
Section titled “Webhooks — the lower-latency overlay”If you want runners to react faster than the poll interval, you can enable a
per-org workflow_job webhook. When GitHub queues a job it tells the hub
immediately, instead of the hub waiting for its next poll. Webhooks are an
opt-in overlay, not a replacement, and they ask for more from your setup:
- A publicly reachable hub so GitHub can deliver the webhook.
- The
admin:org_hookscope on that org’s PAT so Runaway can create the webhook.
Polling is always the fallback
Section titled “Polling is always the fallback”Webhooks never leave you stranded. When an org has healthy webhook delivery, the autoscaler defers to it; the moment delivery goes quiet or a periodic health check finds the hook broken — deleted, disabled, or failing — polling resumes automatically with no action from you. The two channels feed the same demand calculation, so switching between them changes only the latency, never the behaviour.