Roadmap¶
This page is about what GitHub Actions Gateway (GAG) does not do yet. For what it does today, see Features for every shipped capability, with a link to the doc that explains it, and Why GAG? for the capability-by-capability comparison against Actions Runner Controller (ARC).
GAG is generally available and installable from the GitHub Container Registry (GHCR); the releases page names the current version. It is Apache-2.0, vendor-neutral, and built for one outcome: real operators running multi-tenant self-hosted runners in real clusters. There is no paid tier and no commercial roadmap, so the plan below is about capability and adoption, not revenue.
It is a direction-of-travel snapshot, not a dated commitment. Priorities move with what adopters actually hit first, so the surest way to influence what comes next is to open an issue describing your setup. Every open item, in priority order, is in the working backlog.
In progress / near-term¶
Committed to a named release. Every item here blocks a release tag, and nothing else appears in this section: work waiting on demand, on an unbuilt prerequisite, or on hardware sits under Exploring / longer-term with the signal that revives it. The pill beside each title names the release it blocks, read from the backlog rather than typed here, so it cannot outlive the commitment.
-
Bind each runner set to a GitHub runner group 1.5 The runner group is GitHub's own control over which repositories may target a runner set, and GAG does not set it today, so every scale set registers into the installation's default group. Kubernetes-side isolation is unaffected; what is unbounded is which repositories can send work to a tenant.
-
Job duration and pod-creation latency on the default tier 1.5 Both series are emitted on the classic tier only, so on the scale-set tier that every new tenant runs, two Service Level Objectives, an alert, four recording rules, and panels in both shipped dashboards have no data. Until it lands, expect those panels to read empty.
-
Multi-label runner sets for
runs-onarrays 1.5 A runner set takes exactly one label today, so a workflow targetingruns-on: [linux, gpu]needs one edit per target to move here from Actions Runner Controller (ARC). That is the one gap breaking the otherwise zero-edit migration. -
Detect the runner version a tenant's worker image ships 1.5 The version GAG reports to GitHub is the pinned default, whatever
spec.workerImageholds, and the too-old warning fires on the classic tier only. GitHub raises its enforced minimum on 2026-09-25, so a stale image fails with no prior signal. -
Persistent and shared worker storage 1.6 Workers are storage-less by design and nothing validates a
ReadWriteManyvolume mounted into one, so the stance is undocumented rather than decided.ReadWriteManyis how jobs share files, and it is what ARC'scontainerMode: kubernetesdepends on, so it also matters to anyone migrating off that mode. Validation and a reference architecture come before any API. -
A non-privileged path for
container:andservices:steps 1.6 ARC runs these as separate pods on a shared volume undercontainerMode: kubernetes. One worker pod per job means the path here is Docker-in-Docker, unprivileged only under Kata. Sequenced behind theReadWriteManyvalidation above, which it depends on; documenting Kata Docker-in-Docker as the permanent answer is a valid outcome.
Exploring / longer-term¶
Directions we expect to pursue as demand and validated evidence accumulate. These are intentionally unscheduled. Each waits on a real operator need, a measured limit, or a gating release before it becomes scheduled work. The first entry is the exception: a firm commitment, waiting only on the release that carries it.
-
Retiring
v1alpha1,v2alpha1, and the classic acquisition protocol Committed, but not yet started.v1.3.0is the one-release-ahead announcement;v2.0.0is the named release that removes all three together, sincev2beta1is already ScaleSet-only. Gated on thev2GA API being validated, not on a date. -
Validate GHES against a real appliance Both GitHub Enterprise Server (GHES) capabilities ship marked untested against real hardware: the appliance-addressing path and the private-CA bundle. They are believed correct and unproven, which is not the same thing. Waits on access to an appliance.
-
CI for untrusted pull requests on Kata workers Kata workers are validated for trusted CI only: the micro-VM bounds the guest kernel, the runner's egress stays permissive. Untrusted PRs need an in-cluster pull-through registry mirror plus egress scoped to it, GitHub, and DNS. Waits on an operator's ask, then a measurement.
-
Opt-in auto-retry for flaky jobs A job the cluster disrupts already re-runs itself; a flaky failure does not. Same machinery, opted in per runner set with its own budget so a broken test cannot loop. Waits on detection, which needs a real job outcome.
-
Controller horizontal scaling / high availability. The per-tenant controller runs one replica by design: the session registry is in-memory, and HA comes from GitHub redelivering an unacquired job. Distributed session state would enable multi-replica HA if a single controller becomes a measured bottleneck.
- Bring-your-own proxy TLS certificate
Supply the proxy's certificate from your managed PKI or Vault instead of the
self-signed default the Gateway Manager Controller (GMC) issues.
(The autoscaler half has shipped:
managedAutoscaling: falsehands the pool to KEDA, VPA, or a custom HorizontalPodAutoscaler.) - First-class GPU runner support
Priority tiers and the
NodeSharesizing profile already carry the GPU cases, but GPU Operator / Node Feature Discovery awareness, andnodeSelector/ toleration /RuntimeClassconventions that make a GPU runner set feel native, wait on a concrete GPU workload to design against. - Multi-node GPU jobs One job needing several co-scheduled workers in one NVLink or InfiniBand domain is a different problem from one job needing one GPU: capacity is advertised to GitHub as a single integer, and a gang requirement is a placement predicate rather than a count. Waits on a real multi-node workload, and would interact with a batch scheduler such as Kueue or Volcano.
- A worker cache backend
actions/cachealready works. What is missing is a cache inside the cluster, to cut egress cost and restore latency. Docker layer caching has no home either way, because workers are storage-less by design. It waits on a security review of cross-job cache isolation: a shared cache between tenants is an obvious exfiltration path. - A warm worker pool An opt-in pool of idle pods per runner set, for teams that still hit pod-schedule latency after image pre-pull and caching.
- gVisor validation The
runtimeClassNamepath is validated end-to-end with Kata; gVisor is documented but unproven on a real cluster. It waits on an operator who wants lightweight syscall filtering for compute-only, non-Docker-in-Docker jobs, since Kata already covers the DinD case. - SPIFFE / SPIRE workload identity A keyless, SPIRE-backed signer slots behind the existing signer interface alongside the deferred cloud-KMS providers, for operators who want no GitHub App private key anywhere.
- An Operator Lifecycle Manager bundle. Helm-only is the deliberate install stance; an OperatorHub catalog entry waits on OpenShift demand.
- A published benchmark and case study. Real GitHub-at-scale numbers behind the cost model, which needs a funded scale run rather than a local cluster.
The last four are opt-in additions to the per-tenant proxy, shelved together because none has demand recorded against it. A coherent theme is not a release.
-
Proxy-side audit logging A structured line per accepted CONNECT: tenant, host and port, bytes each way, duration. The proxy emits counters only today, so per-tenant egress is reconstructable just from cluster flow logs. Off by default.
-
Per-tenant proxy rate limiting A token bucket at the proxy, so one looping tenant is slowed before it reaches GitHub's ceiling; today the only feedback is a 429 and Actions Gateway Controller (AGC) backoff. Per-pod state, since global limits would need a shared backend.
-
TLS on the in-cluster proxy hop The CONNECT target is cleartext between the AGC or workers and the proxy, readable by an eBPF tap, though the tunnelled payload stays TLS to GitHub. Mount a cert-manager certificate and move to an
https://proxy URL. -
A dedicated proxy pool per runner group One pool per gateway today, so a bandwidth-heavy group can saturate a co-tenant's. Give an opted-in group its own Deployment, Service, and autoscaler. Largest of the four; needs a plan doc before code.
How priorities are set¶
GAG's success metric is external operators running it and telling us what breaks, not stars or downloads. That feedback drives the ordering above far more than any internal plan. If something here is in your way, or missing entirely, open an issue. That is the fastest way to move it up.
The page above is the adopter-facing summary. The day-to-day ordering behind it
is the working backlog: every
open item, filterable by label, status, and size. It tracks the unreleased
main branch, so it is published only on the dev version of this site and
carries no commitment: rows are added, reordered, and deleted as work lands.