Running BYOC Runners in Several Regions

Run BYOC GitHub Actions runners in more than one region with one WarpBuild stack per region, per-region runner labels, in-region caches, and transfer costs.

Overview

A BYOC fleet spans several regions by creating one WarpBuild stack per region and one or more custom runners inside each stack. Workflows then select a region by selecting a runner label, because every custom runner belongs to exactly one stack and every stack is pinned to one region of your cloud account.

BYOC runs on AWS, GCP, and Azure, and the region choice is yours in every case, since the instances run in your account. The BYOC documentation describes the three setup steps that this page repeats per region: connect the cloud account once, create a stack in a region, then create the custom runners that workflows address.

Three properties of a stack are fixed at creation and drive the whole design: the stack name, the object storage location, and the region. There is no rename and no region change afterwards, so a second region is always a second stack rather than an edit to the first one.

This page covers what a region owns, how labels map to regions, when a second region is the wrong answer for a residency requirement, and what crossing a region boundary costs.

Architecture

One cloud connection can serve many stacks. The connection creates the IAM role or service account WarpBuild uses, and each stack it then creates is a group of infrastructure components in a specific region: a VPC, subnets, and an object storage bucket. Adding a region adds a stack and reuses the connection.

LayerScopeFixed after creation
Cloud connection (IAM role or service account)One per cloud accountNo, permissions can be updated
Stack (VPC, subnets, object storage bucket)One per regionName, bucket location, and region are fixed
Custom runner (instance types, disk, IP configuration)One or more per stackNo, the configuration is editable
Workflow label (warp-custom-<runner-name>)One per custom runnerFollows the runner name
Artifact cache, layer cache, logsThe stack bucket, in the stack regionRegion follows the stack
WarpBuild fee$0.002 per runner minute in every regionSame rate in every region

The bucket is the part people underestimate. It holds the artifact cache, the container image layer cache, runner telemetry, and other workflow artifacts, and the AWS configuration guide requires it to sit in the same region as the stack. Two regions therefore run two cache namespaces, and a job that lands in the second region reads and writes there.

Regions are also separate capacity domains. Instance type availability, vCPU quotas, EBS volume capacity, and free IP addresses per subnet are all per region, so a fleet that works in one region can queue in another purely on quota. Fallback instance types are the documented answer to a capacity gap, and they operate within the runner and its region rather than shifting a job across regions.

The WarpBuild control plane stays outside your regions in every configuration. It watches the GitHub Actions job queue and calls your cloud API to launch and terminate instances. Adding a region does not add a control plane.

Configuration

Encode the region in names. The documented convention is to name a stack with the product and region information, for example twitch-use1 and alexa-use2, and the same convention on custom runners makes the workflow label self-describing.

StackCloud regionCustom runnerWorkflow label
payments-use1us-east-1linux-x64-8x-use1warp-custom-linux-x64-8x-use1
payments-euw1eu-west-1linux-x64-8x-euw1warp-custom-linux-x64-8x-euw1
payments-euw1eu-west-1windows-x64-8x-euw1warp-custom-windows-x64-8x-euw1

A workflow then routes jobs by label. The matrix below runs the build in one region and fans the integration suite across both, with the region held next to the label so the mapping stays readable in the run log:

.github/workflows/build.yml
name: build

on:
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: warp-custom-linux-x64-8x-use1
    steps:
      - uses: actions/checkout@v4
      - run: make build

  integration:
    strategy:
      fail-fast: false
      matrix:
        include:
          - region: us-east-1
            runner: warp-custom-linux-x64-8x-use1
          - region: eu-west-1
            runner: warp-custom-linux-x64-8x-euw1
    runs-on: ${{ matrix.runner }}
    steps:
      - uses: actions/checkout@v4
      - run: make integration-test REGION=${{ matrix.region }}

Each region needs its own network prerequisites. The documented recommendation is three public and three private subnets across availability zones, with at least 250 addresses per subnet for concurrent runners, plus a security group that blocks all inbound traffic and allows outbound traffic to WarpBuild, the GitHub API, and your package registries. Import mode, which places runners in a VPC you already operate, is supported on AWS.

Platform coverage is the same in every region you stand up. On BYOC the WarpBuild fee covers Linux runners on AWS, GCP, and Azure and Windows runners on AWS and Azure.

Operations

Residency comes first, region count second. A team that has to keep build data in one place is better served by one region than by two. Every extra region is another VPC, another bucket holding source-derived artifacts and logs, and another set of console evidence an auditor reads. US and EU are the regions WarpBuild names publicly for hosted capacity, and on BYOC the placement is enforced by your own cloud account boundary in the region you selected. If the requirement is that build data stays in the EU, run the EU stack alone and keep the US stack out of the fleet; the trade is worked through in EU data residency for GitHub Actions runners and US data residency for GitHub Actions runners.

Crossing a region boundary is billed by your cloud provider. A runner in one region pulling a container image or a build artifact from a store in another region moves that data across the boundary, and your cloud account pays the transfer. The BYOC documentation puts outbound transfer from a runner with static IPs at roughly $0.45 per GB in data egress rates, adds a per-GB data processing fee at a similar rate, and lists inter-region transfer as a third charge on the same setup (BYOC documentation, checked on 2026-08-13). Runners without static IPs launch in public subnets, where the documentation reports no transfer charge on ingress and usually minimal egress for GitHub Actions workloads. The practical rule is to keep each region self-contained: the stack bucket in the region, as the AWS configuration guide requires, and the container registry a job pulls from in the same region as the runner that pulls it. On the enterprise tier, runners pull large images and artifacts from ECR, S3, and similar stores with zero egress cost to you, whether those runners live in your cloud or ours; see zero egress on the WarpBuild enterprise tier.

The WarpBuild bill does not change shape. The fee is $0.002 per BYOC runner minute in every region (pricing, checked on 2026-08-13), and your cloud account bills the compute, storage, and transfer at your own rates.

Run stack updates per region. WarpBuild occasionally requires changes to cloud connections or stacks to support new features, and they arrive as updates to apply on each stack. Deletion runs in dependency order: custom runners first, then the stack that owns them, then the cloud connection. Two regions means two of those sequences, which is the recurring operational cost of the second region.

For the single-region setup this page builds on, start with BYOC runners on AWS for GitHub Actions. For the short version of the question, see can I run BYOC in more than one region.

FAQ

Can one custom runner cover two regions?

No. A custom runner belongs to one WarpBuild stack, and a stack is created in one region of your cloud account. Two regions means two stacks, two custom runners, and two workflow labels.

Can I move a stack to a different region later?

No. The stack name, the object storage location, and the region are fixed at creation. The migration path is to create a second stack in the new region, create custom runners inside it, and switch the runs-on labels in your workflows.

Does a cache built in one region serve jobs in another?

No. Each stack has its own object storage bucket in its own region, and that bucket holds the artifact cache, the container image layer cache, logs, and other workflow artifacts. A job that moves to a second region starts against that region's cache.

Start with $10 in free credits

Change the runner label in your workflow and keep the rest of your GitHub Actions setup. Runner time is billed per minute.