Cost Allocation Tags for BYOC Runners

A WarpBuild BYOC stack tags every AWS resource it creates. The default keys, a per-team and per-repository tag scheme, and how to reconcile both bills.

Tag GitHub Actions runner instances at the stack: a WarpBuild BYOC stack applies a documented tag set to every AWS resource it creates and adds any custom tags you define on the stack, so EC2 and EBS spend separates by runner set, by stack, and by GitHub organization in Cost Explorer once you activate those keys. Repository-level allocation comes from the WarpBuild CI billing report, which carries the repository on every job row, and the two views join on runner label plus stack plus date.

Overview

BYOC splits the invoice in two. WarpBuild bills a per-minute fee for the runners it schedules, and your own AWS account bills the EC2 instances, the EBS volumes, and the network and storage those instances touch. Allocation work on BYOC means making both sides separable by the same dimension and then joining them.

BYOC runs on AWS, GCP, and Azure. Custom resource tags are available on AWS today, so everything below is AWS-specific; BYOC runners on AWS for GitHub Actions covers the surrounding setup.

Start from what each side can separate, because the honest answer is that neither side does the whole job alone.

DimensionIn the AWS billIn the WarpBuild reports
GitHub organizationwarpbuild-github-org tagAccount scope
Stack and regionwarpbuild-stack-name, warpbuild-stack-id tagsStack column on every job row
Runner setName, warpbuild-runner-id tagsRunner label column
Runner labelswarpbuild-runner-labels tagRunner label column and filter
TeamCustom stack tag, or the team encoded in the runner set nameRunner label and job name
RepositoryNo tag carries itRepository column and filter
Workflow and job nameNo tag carries itJob name column and filter

Machine-level dollars live in the AWS bill and are grouped by tag. Repository and workflow detail lives in the Reports page and is grouped by the columns on each job row. A chargeback table that has to answer both questions reads from both.

Architecture

Tags are applied where the resources are created. Runner instances are launched just in time when a job is queued and terminated when it ends, so tagging happens on the launch path rather than as a later sweep.

These keys are added by default to every resource a stack creates, per the AWS BYOC configuration guide:

Tag keyValue
warpbuild-managed-bywarpbuild
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, and runner instances are tagged in all cases. Upgrade the stack template from the WarpBuild dashboard if your stack predates 1.3 and the stack resources come back untagged.

Naming conventions are the backstop for anything a tag filter misses, and they matter for cleanup queries as much as for cost.

Resource typeNaming pattern
S3 bucketswarpbuild-*
EC2 instanceswarp-*
EBS volumeswarp-*
Launch templatestmpl-warp-*

Two properties of this tag set drive the scheme in the next section. First, no default key carries the repository, the workflow, or the job name, because the instance is provisioned against a runner set rather than against a repository. Second, custom tags are declared on the stack, so their values are fixed for every resource that stack creates.

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 on 2026-08-13). Activated keys appear in the Cost and Usage Report with a user: prefix.

Configuration

For a shared AWS account, encode the allocation dimension that varies per team in the runner set name and reserve custom stack tags for values that hold across the whole stack.

What you want to allocate byWhere it is setKey it lands in
Team or squadCustom runner set nameName, warpbuild-runner-id, warpbuild-runner-labels
Cost center or business unitCustom tag on the stackYour own key, for example cost-center
EnvironmentCustom tag on the stack, one stack per environmentYour own key, for example env
RegionFixed at stack creationwarpbuild-stack-name
RepositoryReports onlyRepository column, no AWS tag

A runner set named payments-linux-x64-8 registers the GitHub Actions label warp-custom-payments-linux-x64-8, and that same string reaches the AWS bill as the Name tag and the warpbuild-runner-id value. The workflow side is one line per job.

name: build
on: [push]

jobs:
  api-tests:
    runs-on: warp-custom-payments-linux-x64-8
    steps:
      - uses: actions/checkout@v4
      - run: ./scripts/test-api.sh

  web-tests:
    runs-on: warp-custom-web-linux-x64-4
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test

  docs:
    runs-on: warp-ubuntu-latest-x64-4x
    steps:
      - uses: actions/checkout@v4
      - run: ./scripts/build-docs.sh

The first two jobs land on BYOC instances in your account and appear in the AWS bill under their runner set tags. The docs job runs on a WarpBuild hosted runner, so it appears in the WarpBuild reports and never touches your AWS bill. On AWS BYOC the Linux and Windows sets are the ones your tags cover.

Once the keys are active, group by them in Cost Explorer, or query the Cost and Usage Report directly. Tag column naming follows your report version, so check the schema before pasting this in.

SELECT
  resource_tags_user_warpbuild_runner_id AS runner_set,
  line_item_product_code AS service,
  SUM(line_item_unblended_cost) AS cost
FROM cur.aws_costs
WHERE line_item_usage_start_date >= DATE '2026-08-01'
  AND resource_tags_user_warpbuild_managed_by = 'warpbuild'
GROUP BY 1, 2
ORDER BY cost DESC;

Filtering on warpbuild-managed-by first keeps the query scoped to runner infrastructure, and grouping by service separates EC2 instance hours from EBS storage before anyone asks why the disk line moved.

Operations

Reconciliation is a monthly three-step pass, and it works because both sides carry the runner set.

  1. Export the CI billing table from the Reports page filtered to the stack. Every report tab exports CSV containing all rows matching the current filters rather than the visible page, and each row carries repository, job name, runner label, stack, execution time, billed time, and cost.
  2. Run the tag grouping above for the same date range, or group by warpbuild-runner-id in Cost Explorer.
  3. Join on runner label and date. The WarpBuild side gives you the platform fee and the repository split; the AWS side gives you the compute dollars for the same runner sets.

The WarpBuild half of the join is arithmetic you can do before the export. BYOC runners bill at $0.002 per minute, from the pricing page, checked on 2026-08-13.

Runner setJob minutesWarpBuild feeCompute billed by
warp-custom-payments-linux-x64-860,000$120.00Your AWS account
warp-custom-web-linux-x64-435,000$70.00Your AWS account
warp-custom-data-linux-x64-1625,000$50.00Your AWS account
Total120,000$240.00

For comparison against a line with no cloud bill behind it, the hosted warp-ubuntu-latest-x64-4x runner (4 vCPU, 16 GB) bills $0.008 per minute with compute included, from the same pricing page checked on the same date.

Four AWS line types have no matching WarpBuild billed minute, and they are what makes the two totals differ:

  • Instance wall clock time, which includes boot and teardown around the job that WarpBuild bills.
  • EBS volumes for standby disks, which keep billing storage while the VM sits shut down. WarpBuild does not charge for standby disks.
  • Network data processing charges for runners in private subnets, shared across every job in the stack.
  • The stack S3 bucket holding artifact cache, container layer cache, and runner telemetry. The documented recommendation is a 7 day retention lifecycle rule, adjusted to your own policy.

Set a cadence around three events. Re-run tag activation when a new stack is created, since custom stack tags are declared per stack. Re-check the grouping after adding a runner set, since a set named outside your convention lands in an untagged bucket in the report. Re-check after a stack template upgrade, since tagging on stack resources depends on the template version.

Every cost number on this page carries a source link and the date it was checked, and the same rates appear on the pricing page and in the evidence data behind it. Pricing is purely usage based. There is no base subscription fee, no platform fee, and no seat fee, so a per-team runner set costs nothing to create beyond the minutes it runs, and splitting one shared set into five tagged sets changes the report without changing the bill. Signup includes $10 free credits, which is enough to create a stack, run a tagged workload, and see the keys arrive in your own cost report.

For the wider picture, a cost model for BYOC GitHub Actions runners works through the two-line model in full, attributing GitHub Actions cost per repository and team covers the hosted-runner side of the same question, and how do I tag runner resources for cost allocation is the short version of this page.

FAQ

Do the WarpBuild tag keys work in Cost Explorer as soon as the stack is created?

No. AWS requires user-defined tag keys to be activated as cost allocation tags in the Billing console of the payer account, and AWS states that activation can take up to 24 hours. Activated keys appear in the Cost and Usage Report with a user: prefix, so warpbuild-runner-labels reads as user:warpbuild-runner-labels there. Activate the keys before the month you plan to bill against them.

How do I split runner spend by team when every team shares one AWS account and one stack?

Put the team in the runner set name. The runner id becomes the Name tag and lands in warpbuild-runner-id, and the label list lands in warpbuild-runner-labels, so Cost Explorer groups EC2 and EBS spend per runner set once those keys are activated. Custom tags are set on the stack and apply to everything that stack creates, so a custom key that must carry a different value per team needs one stack per team instead.

Why do the AWS costs not match the WarpBuild billed minutes exactly?

The two bills meter different things. WarpBuild bills the job at $0.002 per minute for BYOC runners, while AWS bills instance wall clock time, which includes boot and teardown around the job, plus EBS volumes for standby disks, network data processing charges, and the stack S3 bucket that all runner sets share. Reconcile on the share each runner set holds rather than to the cent.

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.