Usually not.
Self-host GitHub Actions runners when a workflow needs hardware, policy, or runtime control that a managed runner can't provide. If the goal is faster jobs, lower cost, more capacity, or access to private infrastructure, use GitHub Actions runners managed by Depot instead.
The runners are up to 3x faster than GitHub-hosted runners, with cache transfers up to 1000 MiB/s and no concurrency limit. Every job gets a fresh, single-tenant virtual machine that's destroyed when the job finishes. Depot operates the capacity, images, runner registration, updates, monitoring, and cleanup.
That's the part teams underestimate. Installing the GitHub runner application is easy. Operating a secure runner platform isn't.
Self-hosting is an infrastructure product
A self-hosted runner is any machine your team operates and registers with GitHub Actions. It can be a server under a desk, a virtual machine in a cloud account, an autoscaling group, or a pod created by Actions Runner Controller.
The first runner takes minutes to configure. A production runner fleet needs much more:
- Capacity that starts quickly enough to avoid queues and scales far enough to absorb pull request bursts
- Fresh machine images with the operating system, GitHub runner application, and build tools kept current
- Job isolation so one workflow can't read files, credentials, or processes left by another
- Cleanup for stopped jobs, failed machines, stale registrations, and partial provisioning
- Central logs and metrics that survive after an ephemeral machine is destroyed
- Network controls, secret boundaries, and access rules for every repository using the fleet
- Capacity planning across Linux x64, Linux Arm, Windows, macOS, GPUs, and larger machine sizes
- An on-call path when GitHub is waiting for a runner that your platform failed to create
GitHub requires self-hosted runner software to stay current. If automatic updates are disabled, GitHub says the runner must be updated within 30 days of a new release, and critical security updates can prevent jobs from being queued until the runner is updated. Ephemeral runner logs also need to be forwarded to external storage before the machine is removed. Those are two small parts of the system, but they show why the monthly cloud bill isn't the full cost.
The real comparison is managed runner spend versus compute, idle capacity, engineering time, security work, and operational ownership together.
Choose how much of CI you want to own
"Hosted versus self-hosted" hides two separate decisions: who runs the compute, and who runs the CI control plane.
| Model | Workflow and control plane | Runner lifecycle | Best fit |
|---|---|---|---|
| GitHub-hosted runners | GitHub | GitHub | Default setup with no runner changes |
| Depot GitHub Actions runners | GitHub | Depot | Keep GitHub Actions while changing compute, cache, and capacity |
| Depot CI | Depot | Depot | Remove the GitHub Actions control-plane dependency too |
| Self-hosted runners or ARC | GitHub | Your team | Own hardware, networking, images, scaling, and isolation |
| Self-operated CI platform | Your team | Your team | Full control is itself a product requirement |
A managed runner changes the machine underneath a GitHub Actions job. GitHub still receives the event, schedules the workflow, registers the runner, and dispatches the job. This is the smallest migration and keeps the GitHub UI and checks.
A managed CI platform changes the control plane as well. Depot CI runs compatible GitHub Actions YAML on Depot's own orchestrator and compute, with local execution, targeted retries, cancellation, logs, metrics, diagnosis, and SSH available through an API and CLI.
Self-hosting is the far end of the ownership spectrum. Choose it when controlling the runner fleet is a requirement, not merely because the default hosted option is slow.
Long-lived runners are the dangerous shortcut
A long-lived runner reuses the same machine for multiple jobs. It's tempting because caches and installed tools stay on disk. It also means files, processes, credentials, and machine changes can survive into the next job.
GitHub warns that self-hosted runners can be persistently compromised by untrusted workflow code. GitHub says they should almost never be used for public repositories. The risk also exists in private and internal repositories when someone who can open a pull request can cause code to run on the machine.
Public fork pull requests shouldn't run on a long-lived self-hosted runner. Neither should unreviewed code share a runner host or Kubernetes cluster with production workloads that it can reach.
Use one ephemeral runner per job. Give it the minimum token, secret, and network access required. Destroy its compute and disk after the job. Keep reusable state in a cache designed for sharing rather than treating yesterday's workspace as today's cache.
This is Depot's default model. A webhook starts a fresh single-tenant runner for one job, then Depot terminates it when the job finishes. The cache persists separately and is scoped by repository.
Autoscaling with Actions Runner Controller
Actions Runner Controller is GitHub's recommended Kubernetes solution for autoscaling self-hosted runners. ARC creates runner scale sets, adds ephemeral runners as jobs arrive, and scales them down when demand falls.
ARC is the right foundation when Kubernetes is already a core platform primitive and operating CI compute is an intentional responsibility for the platform team.
It doesn't turn self-hosting into a managed service. Your team still owns cluster capacity, runner images, controller upgrades, networking, security boundaries, logs, metrics, and regional failover. GitHub specifically recommends isolating runner workloads from production workloads because Actions jobs execute arbitrary code.
Running a second production platform to avoid paying for managed runners rarely saves money. ARC makes sense when the control itself is the requirement.
Private network access without self-hosting
Needing an internal database, package registry, secret manager, or API doesn't automatically mean the runner must be self-hosted.
Depot GitHub Actions runners can access private resources through:
- Tailscale, with each runner joining the tailnet as an ephemeral node
- Cloudflare WARP and identity-based Zero Trust policies
- VPC peering for private AWS resources
- Dedicated infrastructure with static outbound IP addresses
- Depot Managed, where the Depot data plane and cache run in an isolated sub-account inside your AWS organization
Depot can also apply egress filters that allow or deny outbound connections by hostname, IP address, or CIDR on Linux runners.
These options preserve managed runner lifecycle and isolation while giving jobs controlled access to private systems. For many teams, that's the actual requirement behind a request to self-host.
Cases where self-hosting is justified
Self-hosting is reasonable when the workload requires something a managed runner can't supply:
- Proprietary hardware, lab equipment, or devices physically attached to the runner
- A specific GPU, accelerator, kernel, hypervisor, or operating system configuration
- An air-gapped or on-premises runtime that can't connect through an approved private networking path
- Software licensing bound to a specific physical host
- A policy that requires your team to operate every layer of the runner platform
Check whether a custom Depot GitHub Actions runner image, dedicated infrastructure, VPC peering, or Depot Managed satisfies the requirement before building a fleet. Those options cover many compliance and runtime-control cases without handing the runner platform back to your team.
If none of them fits, self-host. Build ephemeral runners from the start. Treat the fleet like production infrastructure, isolate it from production workloads, and include the engineers operating it in the cost calculation.
Before committing to the fleet, run a 30-day comparison that includes peak pull request traffic, upgrades, failed provisioning, image maintenance, incident response, and idle capacity. A proof of concept with one warm VM measures the job. It doesn't measure the runner platform your team will have to operate.
Switching to Depot
Moving an existing GitHub Actions job to Depot is usually a one line runner-label change:
jobs:
test:
- runs-on: ubuntu-24.04
+ runs-on: depot-ubuntu-24.04The workflow, Marketplace actions, secrets, pull request checks, and GitHub interface stay the same. The job moves to a managed runner fleet without turning runner operations into another platform your team has to own.