runnerhut
Answers
Direct answers to the questions engineers ask about CI.
Billing and cost21
Am I billed when a GitHub Actions job fails?Yes. You are billed for the minutes consumed up to the point of failure, not for a successful outcome.Are GitHub Actions free for open source?Yes, on GitHub-hosted standard runners for public repositories, with no minute charge.Are GitHub Actions free for private repositories?No. Private repositories get a monthly included-minutes allowance by plan, then bill per minute.Do I pay a seat fee for managed runners?On runnerhut, no. Billing is per compute minute with no per-developer charge.Do I pay for queue time?No. Billing starts when your first step executes, not when the job is queued.Do I pay for both the runner and the remote Docker builder?Yes, but the builder is billed only for the seconds it is actively building.How is a cancelled job billed?You pay for the minutes elapsed before cancellation, rounded to the billing increment.Is there a minimum billing increment?runnerhut bills per second with a one-minute minimum per job.How much do managed GitHub Actions runners cost?runnerhut Linux x64 runners start at $0.004 per minute, roughly half GitHub's list price for the equivalent size.What is the cheapest runner size?The smallest size that keeps your job on its critical path — usually 2 or 4 vCPU for lint and unit tests.Is arm64 cheaper than x64?Yes. runnerhut arm64 runners are priced about 20% below the equivalent x64 size.Is it cheaper to run fewer, larger runners?Only if your workload actually parallelises. Otherwise you pay more per minute for cores that sit idle.Can I set a spending limit?Yes. runnerhut supports hard budget caps per organisation and per repository.What happens when free credits run out?Jobs stop being scheduled until you add a payment method or raise the cap.How do I estimate my GitHub Actions bill?Multiply monthly minutes per OS by the per-minute rate for that OS, then add storage for artifacts and cache.How do I forecast runner spend?Take trailing 90-day minutes per workflow, apply your merge-rate growth, and add headroom for matrix changes.Why is my GitHub Actions bill so high?Usually one of four things: macOS minutes, matrix explosion, no concurrency cancellation, or oversized runners.Do public repositories pay for managed runners?On GitHub-hosted standard runners, no. On managed providers including runnerhut, yes — but open-source programmes are available.What does Actions cache storage cost?GitHub includes 10 GB per repository at no charge and evicts beyond that. runnerhut cache is unlimited and included.How is snapshot storage billed?Per gigabyte-month for the retained snapshot, separate from the compute minutes.Can I run more concurrent jobs than my GitHub plan allows?Yes. Managed runner concurrency is set by your runner provider, not by your GitHub plan's hosted-runner limits.
Performance10
Why are GitHub Actions slow?Most commonly: shared vCPU, cold caches, network-attached disk, and queue time before the job even starts.How fast do runners start after a job is queued?runnerhut runners start in about three seconds from a warm pool.Do I need to change my workflow?No. Change the runs-on label and leave everything else as it is.How do I choose a runner size?Start one size above your current runner, then check CPU utilization and stop when the curve flattens.Why do my jobs queue behind each other?You have hit a concurrency limit — either your plan's, your runner group's, or a concurrency group in the workflow.Why do my Python tests run slower in CI than locally?pytest is serial by default, and your laptop has faster single-core performance and a warm filesystem cache.Why is npm install slow in CI?node_modules writes tens of thousands of small files, and network-attached CI disk handles that badly.Why does the Gradle daemon start every run?Each CI job is a fresh machine, so there is no daemon to reuse — and without the configuration cache Gradle re-evaluates the whole build.Why does my job show high I/O wait?The workload is disk-bound — usually dependency installation, container layer extraction or a database in a service container.How many jobs can run at once?It depends on your plan for GitHub-hosted runners, and on your configured concurrency for managed runners.
Caching38
Why does Cargo rebuild everything?Your cache key changes on every run, or target/ is not cached at all.Why is cache restore slow?GitHub throttles cache bandwidth, so a multi-gigabyte cache can take minutes to restore.How do I write a good cache key?Hash exactly the files that determine the cached content — usually the lockfile — and nothing else.What are restore-keys?Ordered prefixes tried when the exact cache key misses, so a partial match can still be restored.Why does my cache miss every run?The key includes something that changes every run — commonly github.sha or a timestamp.How long do caches last?GitHub evicts caches unused for 7 days, or sooner if the repository exceeds 10 GB.How do I clear a cache?Delete it from the repository's Actions cache page, or via the REST API or gh CLI.Do caches carry across branches?A branch can read caches from itself and from its base branch, but not from unrelated branches.Can I share a cache between workflows?On GitHub-hosted runners, only within the same repository and branch scope. runnerhut caches are shared across workflows in the organisation.What is the GitHub Actions cache size limit?10 GB per repository, after which least-recently-used entries are evicted.How do I cache node_modules?Cache ~/.npm keyed on package-lock.json, or restore node_modules directly if your install is deterministic.How do I cache pip dependencies?Cache ~/.cache/pip keyed on requirements.txt, or cache the whole virtualenv for a bigger win.How do I cache Go modules?Cache ~/go/pkg/mod and ~/.cache/go-build keyed on go.sum.How do I cache Cargo dependencies?Cache ~/.cargo/registry, ~/.cargo/git and target/ keyed on Cargo.lock.How do I cache Maven dependencies?Cache ~/.m2/repository keyed on a hash of every pom.xml.How do I cache Gradle builds?Cache ~/.gradle/caches and ~/.gradle/wrapper, and enable the build and configuration caches.How do I cache Bundler gems?Cache vendor/bundle keyed on Gemfile.lock so native extensions are compiled once.How do I cache Composer dependencies?Cache ~/.composer/cache keyed on composer.lock.How do I cache CocoaPods?Cache Pods/ and ~/Library/Caches/CocoaPods keyed on Podfile.lock.How do I cache Swift Package Manager dependencies?Cache .build and ~/Library/Caches/org.swift.swiftpm keyed on Package.resolved.How do I cache Yarn Berry?Cache .yarn/cache and .yarn/install-state.gz keyed on yarn.lock.How do I cache uv or Poetry environments?Cache ~/.cache/uv or ~/.cache/pypoetry keyed on the lockfile, plus the .venv directory.How do I cache Playwright browsers?Cache ~/.cache/ms-playwright keyed on the Playwright version from your lockfile.How do I cache Docker layers?Use a remote builder that keeps the cache locally, or export to a registry with cache-to and cache-from.Does caching work inside a container job?Yes, but paths inside the container differ from paths on the host, so cache keys must reference container paths.Do caches work across architectures?No. Compiled artefacts for x64 are not valid on arm64, so architecture must be part of the key.Do caches work on Windows runners?Yes, but path separators and case sensitivity differ, so keys and paths need Windows-specific handling.How do I keep a Docker layer cache between pull requests?Use a persistent remote builder — its cache is not scoped to a branch.Can I cache a built image rather than rebuilding?Yes — push it to a registry tagged by content hash and pull it when the inputs are unchanged.Can I keep a database warm between jobs?Not with service containers, which are destroyed with the job. Load a pre-migrated schema dump instead.Can I keep Xcode DerivedData between runs?Yes. Persist ~/Library/Developer/Xcode/DerivedData — it is the biggest single win for iOS CI.Do snapshot runners replace actions/cache?They can. A snapshot restores the whole machine state, so the install step disappears rather than getting faster.What carries over in a snapshot?The entire filesystem at snapshot time — installed packages, built extensions, toolchain directories and warm page cache.How do I invalidate a snapshot?Key it on your lockfile hash so a dependency change automatically triggers a rebuild.How long do snapshots last?14 days by default on runnerhut, then rebuilt on next use.Can I snapshot on a feature branch?Yes, and branch snapshots are isolated from each other.What are snapshot runners?Runners that boot from a filesystem image captured after your dependencies were installed, so install is skipped entirely.Do snapshots work on macOS runners?Yes, and they are especially valuable there because CocoaPods and DerivedData are both slow to rebuild.
arm6412
Can GitHub Actions run arm64?Yes. GitHub offers arm64 runners on paid plans, and managed providers including runnerhut offer them on all plans.Can I build arm64 images on an x64 runner?Yes, with QEMU — but it is 5–40× slower than building natively.What changes when moving from x64 to arm64?Native modules, Python wheels, and any x86 assembly need aarch64 support. Most mainstream dependencies now have it.Can I run arm64 and x64 jobs in the same workflow?Yes. Use a matrix with a different runner label per architecture.Do arm64 runners support buildx?Yes, and on native arm64 hardware buildx produces arm64 images with no emulation.Can I run 32-bit ARM builds on arm64 runners?Yes, via cross-compilation with an armhf toolchain, or with multilib support where available.How do I run arm64 integration tests?Run the whole job on a native arm64 runner, including any service containers, which must have arm64 images.What arm64 runner sizes are available?runnerhut offers 2 to 64 vCPU arm64 runners on Ubuntu 22.04 and 24.04.Do arm64 runners use a different work directory?No. The paths match the x64 images, so workflows port without change.How do I build a Rust binary for multiple targets?Use a matrix with one native runner per target, rather than cross-compiling everything on one machine.Can GitHub Actions build multi-arch images?Yes — either with QEMU on one runner, or natively on per-architecture runners and merged into a manifest list.Is QEMU or native arm64 faster?Native, by a factor of 5 to 40 depending on how much the build compiles.
macOS and iOS15
Do GitHub Actions runners support macOS?Yes, both GitHub-hosted and managed providers offer macOS runners on Apple silicon.Can I build iOS apps without a Mac runner?No. Xcode only runs on macOS, so an iOS build requires a macOS runner.Is Xcode preinstalled on macOS runners?Yes. runnerhut images ship several Xcode versions with matching command line tools.How do I select an Xcode version?Run sudo xcode-select -s /Applications/Xcode_16.4.app before your build steps.What Xcode versions are available?runnerhut macOS 15 images carry Xcode 16.0, 16.2 and 16.4; macOS 14 images carry 15.2 and 15.4.What macOS versions are supported?runnerhut offers macOS 14 and macOS 15 images on Apple silicon.Does GitHub Actions support Apple silicon?Yes. Both GitHub-hosted and managed macOS runners now run on Apple silicon.How much disk do macOS runners have?runnerhut macOS runners provide 250 GB to 1 TB of NVMe depending on size.Which simulator runtimes ship on macOS runners?iOS 17.5 through 18.4, plus watchOS, tvOS and visionOS runtimes.Can I use Docker on macOS runners?Only via a Linux VM, which is slow. Run Docker workloads on Linux runners instead.Can I run macOS runners in the EU?Yes. runnerhut operates macOS capacity in EU regions for data residency requirements.Can I run Android and iOS builds in one workflow?Yes — use a matrix with a macOS runner for iOS and a Linux runner for Android.How do I speed up repeated Xcode builds?Persist DerivedData between runs and pin the Xcode version.How do I run iOS tests in parallel?Shard by test target or test class across several simulators on one large macOS runner.How do I notarise a macOS app in CI?Use notarytool with an App Store Connect API key stored as a secret.
Windows11
Can GitHub Actions run Windows builds?Yes. Windows Server runners are available both from GitHub and from managed providers.Can I run Windows Server 2022 builds?Yes. runnerhut offers Windows Server 2022 and 2025 images.Which Windows versions are supported?Windows Server 2022 and Windows Server 2025.Is Visual Studio preinstalled?Yes. Build Tools for 2022 and 2025 ship with the C++, .NET desktop, ASP.NET and UWP workloads.How do I install extra Windows SDK components?Use vs_installer.exe modify with --add and the component ID.Why are Windows runners slower to start?Windows boots more slowly and Defender scans everything the checkout writes.Can I run Docker on Windows runners?Yes, for Windows containers. Linux containers require nested virtualization.Do Windows runners support nested virtualization?On runnerhut, yes on Windows Server 2025 images and sizes that expose Hyper-V.What is the smallest Windows runner size?4 vCPU. Smaller sizes spend too much of the job on OS overhead to be useful.Can I run tests in parallel on Windows?Yes. dotnet test --parallel and MSBuild -m both use multiple cores.How do I run PowerShell scripts?Set shell: pwsh on the step for PowerShell Core, or shell: powershell for Windows PowerShell 5.1.
Docker17
How do I reduce image pull time?Use a registry pull-through cache in the same network as the runner.How do I reset a Docker builder cache?Run docker buildx prune on the builder, or recreate the builder instance.Do remote builders support multi-platform builds?Yes. runnerhut runs separate amd64 and arm64 builders and merges the results.How do I push a manifest list?Build each architecture by digest, then combine them with docker buildx imagetools create.Why is my Docker build slow?Cold layer cache, cache transferred over the network, or arm64 built under emulation.Why does Docker build run out of disk?GitHub-hosted runners have around 14 GB free, which large images and their layer cache exhaust quickly.Why does a base image update invalidate everything?Every layer after FROM depends on the base image digest, so a new base invalidates all of them.What is the difference between cache-from and cache-to?cache-from imports an existing layer cache; cache-to exports the cache produced by this build.Do I need buildx?For multi-platform builds, cache mounts or remote builders, yes. For a simple single-arch build, no.What is a remote Docker builder?A persistent BuildKit instance your job attaches to, which keeps the layer cache on its own disk.How is a remote builder billed?Per second of active build time, separately from the runner minutes.Can two jobs share one builder?Yes. Matrix legs and separate workflows can attach to the same builder and share its cache.How do I build and push in one step?Use docker/build-push-action with push: true.How do I use Docker Bake?Define targets in docker-bake.hcl and run docker buildx bake in a step.How do I authenticate to a private registry?Use docker/login-action with a token, or OIDC for cloud registries.Can I run Docker Compose?Yes. Compose v2 is preinstalled; use docker compose up -d --wait so steps do not race startup.Can I use Podman instead of Docker?Yes. Podman is available and is largely CLI-compatible with Docker.
Security19
Are snapshot runners safe for public repositories?Only if snapshots are taken from trusted branches and never from fork pull requests.How do I generate an SBOM?Enable buildx's sbom: true output, or run syft against the built image.How do I attach build provenance?Use actions/attest-build-provenance, or buildx's provenance: true attestation.How do I pass secrets into a Docker build?Use BuildKit build secrets with --secret, never ARG or ENV.Are GitHub Actions runners secure?GitHub-hosted and reputable managed runners are ephemeral single-use VMs, which is the right isolation model.Do runners store my source code?Only for the duration of the job. runnerhut destroys the VM and wipes its disk when the job ends.Can the runner platform see my secrets?Secrets are decrypted in the runner's memory to be used, so any runner platform technically could.How do I set GITHUB_TOKEN permissions?Add a permissions block at workflow or job level and grant only the scopes needed.How do I authenticate to AWS with OIDC?Configure GitHub as an OIDC provider in IAM and use aws-actions/configure-aws-credentials with a role.Do managed runners change my GitHub permissions?No. Jobs run with the same GITHUB_TOKEN and the same permissions as on GitHub-hosted runners.Can I restrict which repositories use my runners?Yes, with runner groups scoped to specific organisations or repositories.Is runnerhut SOC 2 compliant?runnerhut maintains SOC 2 Type 2, with the report available under NDA.Where is my build data stored?In the region you select. Compute, cache, logs and metrics are all pinned to the same region.Can I keep builds in the EU only?Yes. EU-only deployments pin compute, cache, logs and metrics to EU regions.Can I restrict outbound traffic?Yes. Egress policies default-deny and allow only the destinations you list.How do I audit runner configuration changes?The audit log records actor, timestamp, source IP and before/after values for every configuration change.Where do managed runners physically run?In the provider's data centres, or in your own cloud account under BYOC.What happens to runner disks after a job?On runnerhut they are cryptographically wiped and the VM destroyed.Do runners keep state between jobs?Ephemeral runners do not. Persistent self-hosted runners do, which is a security risk on public repositories.
Bring your own cloud18
Can runners access my private network?Yes, via BYOC runners in your VPC or a mesh network such as Tailscale.Can runners run in my own cloud account?Yes. BYOC deploys runners into your AWS, GCP or Azure account while the control plane stays managed.What does runnerhut create in my cloud account?An autoscaling group, a cache bucket, a registry pull-through cache, a scoped IAM role and a VPC endpoint.What AWS permissions does BYOC need?Permissions to manage its own autoscaling group, its cache bucket and its instance role — nothing broader.Can I use my own VPC?Yes. You supply the VPC and subnet IDs and runners are placed there.Can BYOC runners reach internal services?Yes — that is the main reason to use BYOC. They sit inside your network with normal routing.Do BYOC runners need a NAT gateway?They need outbound internet for image and package pulls, which usually means a NAT gateway.Can BYOC runners run in a private subnet?Yes, and they should. Outbound access goes through NAT or VPC endpoints.Can I attach an IAM role to a BYOC runner?Yes, via an instance profile — so jobs get credentials without any stored secret.Does BYOC work with IMDSv2?Yes, and IMDSv2 is enforced by default.Can I run BYOC in multiple regions?Yes. Deploy the module per region and label runners by region.Does BYOC support custom images?Yes. Supply your own AMI or machine image with your tooling baked in.Does BYOC support Windows?Yes on AWS and Azure. GCP Windows support is more limited.Does BYOC support GCP local SSD?Yes, on machine families that offer it.How does BYOC billing work?You pay your cloud provider for compute and network, and runnerhut a reduced control-plane fee.How do I tag BYOC resources?Set cost allocation tags in the Terraform module; they propagate to every created resource.How do I delete a BYOC stack?Drain the runners, then terraform destroy the module.Can I control egress on BYOC runners?Yes, with security groups, NACLs and runnerhut egress policy together.
Workflows30
How many jobs can a matrix fan out to?GitHub caps a single matrix at 256 jobs per workflow run.How do I reproduce a CI failure locally?Match the runner image, then SSH into a live runner if the failure only appears in CI.Can I SSH into a runner?Yes. runnerhut supports opening a debug session on a running job with an authorised SSH key.Can I mix GitHub-hosted and managed runners?Yes. runs-on is per job, so different jobs in one workflow can use different providers.How do I change the runner?Edit the runs-on value for the job. Nothing else needs to change.How do I run a job only when files change?Use paths or paths-ignore on the trigger, or a change-detection action for finer control.How do I run a workflow manually?Add a workflow_dispatch trigger, optionally with typed inputs.How do I run jobs on a schedule?Use the schedule trigger with cron syntax, in UTC.How do I cancel superseded runs?Set a concurrency group keyed on the ref with cancel-in-progress: true.How do I limit a workflow to one run at a time?Use a fixed concurrency group name with cancel-in-progress: false.What happens when two workflows share a concurrency group?They serialise — the second waits or cancels the first depending on cancel-in-progress.How do I set a job timeout?Add timeout-minutes to the job. The default is six hours.How do I retry a failed step?Use a retry action, or wrap the command in a shell retry loop.How do I reuse a workflow across repositories?Publish a reusable workflow and call it with workflow_call.How do I write a composite action?Create action.yml with runs.using: composite and a steps list.How do I use matrix include and exclude?include adds or extends combinations; exclude removes them from the generated product.How do I skip CI on a commit?Add [skip ci] to the commit message.How do I write a job summary?Append Markdown to $GITHUB_STEP_SUMMARY.How do I run a database in CI?Declare it as a service container with a healthcheck.How do I publish a package?Use OIDC trusted publishing where the registry supports it, otherwise a scoped token in an environment secret.How do I share data between jobs?Upload an artifact in one job and download it in the next, or use job outputs for small values.How do I stop a slow workflow blocking deploys?Split required checks from advisory ones and only mark the fast, reliable jobs as required.How do I run browser tests headless?Use the headless flag for your runner, or xvfb-run for tools that require a display.How do I run Go race detector tests?Run go test -race. Expect roughly 2–10× slower execution and higher memory use.What is the difference between a job and a step?A job runs on one runner and contains steps; steps run sequentially in the same workspace.What is the difference between GitHub-hosted and self-hosted runners?GitHub-hosted are managed, ephemeral and billed per minute. Self-hosted are yours to operate, on your hardware.Which operating systems can GitHub Actions run?Linux, Windows and macOS, on x64 and arm64 depending on the provider.How long are artifacts kept?90 days by default, configurable per repository or per upload down to one day.How do I debug a failed job?Enable step debug logging, add a job summary, or open an SSH session on the runner.How do I run a job only on pull requests?Use the pull_request trigger, and an if condition for finer control such as skipping drafts.
Observability19
How do I see cost per workflow?The runnerhut dashboard breaks spend down by workflow, job, label and repository.How do I see cost per runner label?Filter the usage dashboard by label to see minutes and spend per runner type.How do I detect an undersized runner?Sustained CPU near 100%, memory pressure, or swap activity through the job.How do I find the slowest step in a workflow?Sort steps by duration in the run view, or use the runnerhut timeline which shows queue, setup and step time separately.How do I find which workflow got slower?Compare p95 duration per workflow month over month in the analytics dashboard.How do I measure cache hit rate?The runnerhut dashboard reports hit rate, restore time and size per cache key.How do I export job data?Use the runnerhut API or the GitHub Actions REST API and write the results to CSV.Can an AI agent query my CI metrics?Yes, through the runnerhut MCP server, which exposes builds, durations, failures and costs as tools.Can AI agents trigger CI jobs?Yes, through the API or by pushing branches, like any other actor.What metrics does the API expose?Queue time, duration percentiles, cache hit rate, CPU and memory utilization, and cost per job, label and workflow.How do I see CPU and memory usage for a job?runnerhut records per-job utilization automatically and shows it on the run page.Can I alert on out-of-memory jobs?Yes. Alert on OOM kills or on memory utilization crossing a threshold.How do I produce a weekly CI health report?Schedule a workflow that queries the metrics API and posts p95 duration, cache hit rate, flake rate and spend.Why did my job get killed with exit code 137?That is an OOM kill — the process exceeded available memory.Why did my job run out of disk?GitHub-hosted runners have roughly 14 GB free; Docker layers and node_modules exhaust that quickly.Do runners have large disks?GitHub-hosted runners have about 14 GB free. runnerhut runners provide 150 GB to 2 TB of local NVMe.Do runner groups limit concurrency?They can. A group can carry its own concurrency ceiling independent of your account limit.What GitHub API rate limits affect CI?GITHUB_TOKEN is limited per repository per hour; workflows making many API calls can exhaust it.Why do my jobs hit network timeouts?Usually registry rate limiting, a NAT gateway bottleneck, or an egress policy silently dropping traffic.