How Do I Tag Runner Resources for Cost Allocation?
A BYOC stack tags every resource it creates, and those default keys plus custom stack tags make GitHub Actions runner spend separable in your own cloud bill.
Answer
Tag them at the stack. A BYOC stack applies a documented set of tags to every resource it creates, accepts custom tags that are added alongside them, and follows fixed naming patterns, so runner spend separates in your own cloud bill once you activate those keys as cost allocation tags.
The AWS BYOC configuration docs list both the default keys and the naming conventions. These keys land on every resource a stack creates.
| Key | Value |
|---|---|
warpbuild-managed-by | warpbuild |
Name | {runner-id} |
warpbuild-github-org | {github-org} |
warpbuild-runner-labels | {runner-label1}, {runner-label2}, ... |
warpbuild-runner-id | {runner-id} |
warpbuild-stack-id | {stack-id} |
warpbuild-stack-name | {stack-name} |
WarpBuild also adds a managed-by: warpbuild tag to provisioned resources, which doubles as a key for AWS IAM tag-based access control. On stack resources that tagging starts at CloudFormation template version 1.3 in create mode; runner instances are tagged in all cases.
Names are the backstop for anything a tag filter misses.
| Resource type | Naming pattern |
|---|---|
| S3 buckets | warpbuild-* |
| EC2 instances | warp-* |
| EBS volumes | warp-* |
| Launch templates | tmpl-warp-* |
One step happens outside WarpBuild. AWS requires user-defined tag keys to be activated as cost allocation tags in the Billing console before they appear in cost reports, and states that activation can take up to 24 hours (AWS cost allocation tags, checked 2026-08-13). Activated keys show up in the Cost and Usage Report with a user: prefix, so warpbuild-runner-labels becomes user:warpbuild-runner-labels there.
BYOC runs on AWS, GCP, and Azure. Custom resource tags are available on AWS today, and the GCP and Azure BYOC configuration docs list resource tagging under coming soon, so plan cloud-side attribution on those two around project and subscription boundaries for now (feature matrix, checked 2026-08-13).
Detail
What varies per instance and what varies per stack
Custom tags are a stack-level setting, so their values are identical on every resource that stack creates. The keys that change per job are the default ones: Name, warpbuild-runner-id, and warpbuild-runner-labels. That split decides the whole scheme. A dimension that changes inside one stack has to ride on the runner configuration; a dimension that needs its own tag key and value needs its own stack.
warpbuild-runner-labels holds a comma-joined list, so a runner configuration carrying three labels produces one tag value with three tokens in it, and grouping in Cost Explorer treats that string as a single value. Keep one label per custom runner if you intend to group on this key.
A tag scheme that survives a shared account
| Dimension | Where it comes from | How you read it |
|---|---|---|
| Team | Team name inside the custom runner name, for example warp-custom-platform-use1-8x | Group EC2 and EBS on warpbuild-runner-labels or Name |
| Cost center | Custom tag on the stack, for example cost-center: platform | Group on cost-center, one stack per cost center |
| Region and environment | Stack, since region is fixed at creation | Group on warpbuild-stack-name |
| Runner class | Instance size in the runner name, for example -8x versus -16x | Group on warpbuild-runner-labels |
| Repository | Not present in the cloud tags | Read the repository column in the WarpBuild CI billing report |
The last row is the one that catches teams out. A runner instance is created before GitHub assigns it a job, so no cloud tag on that instance can carry the repository the job came from. Per-repository allocation has two routes. Give a repository its own custom runner and the label becomes the proxy key, or take the repository split from the reports, where every CI billing row carries repository, job name, runner label, stack, execution time, and billed time.
Cache storage is the exception, because the stack bucket lays objects out by repository: <bucket_name>/<org_id>/artifact_cache/<vcs_org>/<vcs_repo>/<vcs_ref>/<version>/<key>. Per-repository storage attribution comes from prefix reporting on that bucket rather than from a tag. A 7-day lifecycle policy is the documented recommendation, and it caps how large that line gets before you split it.
Reconciling the WarpBuild bill against the cloud bill
Run the two sides on the same date range. On the WarpBuild side, filter the CI tab of the Billing report by stack and export the CSV, which contains every row matching the current filters rather than the visible page. On the cloud side, filter Cost Explorer on warpbuild-stack-name for the same stack.
Take one stack that billed 150,000 runner minutes in a month. BYOC runners cost $0.002 per minute for Linux and $0.002 per minute for Windows (pricing page, checked 2026-08-13).
| Line | Billed by | How to find it | Amount |
|---|---|---|---|
| Runner minutes | WarpBuild | Billing report, CI tab, filtered by stack | 150,000 x $0.002 = $300 |
| EC2 instance hours | Your cloud account | warpbuild-stack-name in Cost Explorer | Your instance rates |
| EBS volumes | Your cloud account | Same tag, or warp-* names | Your volume rates |
| Standby disk volumes | Your cloud account | Same tag, no matching billed minute | Your volume rates |
| NAT gateway and S3 | Your cloud account | Stack resources, shared across jobs | Your rates |
Three lines will not match one to one, and knowing which ones saves the argument with finance. Standby disk VMs are billable for about 90 seconds at boot, after which the VM stops and the network disk keeps billing, and WarpBuild does not charge for standby disks at all. NAT gateway processing and bucket storage serve every job in the stack, so they are allocated by share rather than measured per job. Instance time and billed job time diverge by the boot and teardown window around each job.
macOS never appears in the cloud bill. MacOS runs on WarpBuild-hosted capacity, so those minutes stay on the WarpBuild invoice only.
Pricing is purely usage based. There is no base subscription fee, no platform fee, and no seat fee, which keeps the WarpBuild side of the reconciliation to billed minutes multiplied by the per-minute rate. Signup includes $10 free credits, enough to run a tagged stack against one repository and check that both reports line up before the first invoice. The full walkthrough is on the AWS BYOC page, and cost allocation tags for BYOC runners covers the console steps key by key.
Related Questions
Which tags does a BYOC stack apply by default?
Every resource a stack creates carries warpbuild-managed-by, Name set to the runner id, warpbuild-github-org, warpbuild-runner-labels, warpbuild-runner-id, warpbuild-stack-id, and warpbuild-stack-name. WarpBuild also adds managed-by: warpbuild, usable as a key for IAM tag-based access control. Custom tags set on the stack are added to everything the stack creates, per the AWS BYOC configuration docs.
How do I split runner spend by team in one shared AWS account?
Encode the team in the custom runner name, since the runner id becomes the Name tag and the label list becomes warpbuild-runner-labels on each instance. Activate that key as a cost allocation tag and Cost Explorer groups EC2 and EBS spend by runner label. Custom tag values are fixed per stack, so a tag key that must carry a per-team value needs one stack per team. The cost attribution guide pairs this with the report-side keys.
Why does my cloud bill not match the WarpBuild billed minutes?
Three lines have no matching billed minute. Standby disk VMs are billable for about 90 seconds at boot and the network disk keeps billing while the VM sits shut down, and WarpBuild does not charge for standby disks. NAT gateway processing and the stack bucket are shared across all jobs. Instance hours run on wall clock while WarpBuild bills the job, so boot and teardown sit outside the runner minutes. The BYOC cost model works the whole month through with those lines named.
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.