Updating and Deleting a BYOC Stack

Apply WarpBuild BYOC stack and cloud connection updates in order, drain in-flight GitHub Actions jobs first, and verify what a delete leaves in your account.

Overview

WarpBuild may require changes to cloud connections or stacks to support new features, and those changes show up in the dashboard as updates to apply (BYOC documentation). Applying one issues a CloudFormation changeset against the connection or the stack inside your own cloud account, which is how a stack picks up a newer template version while keeping its runners, its bucket, and its history.

Three stack properties are fixed at creation: the stack name, the object storage bucket, and the region (AWS BYOC configuration guide). A change to any of the three is a delete and a rebuild, and deletes run in dependency order: custom runner configurations first, then the stack, then the cloud connection.

What you want to changePath
Pick up a newer CloudFormation template versionApply the stack update from the dashboard
Grant permissions a new WarpBuild feature needsApply the cloud connection update
Instance types, disk size, spot setting, IMDSv2, instance profileEdit the custom runner configuration; the stack is untouched
Rules on a security group you supplied in import modeEdit it in your own account; the stack attaches the group you selected
Stack nameDelete and rebuild
Object storage bucketDelete and rebuild
RegionBuild a second stack in the new region

The last row is the one that surprises teams mid-migration. Region is a stack property, so a move to a closer region is a new stack with its own bucket and its own runner configurations, which is also how a fleet ends up spanning several regions on purpose.

BYOC runs on AWS, GCP, and Azure. The dependency rules above come from the shared BYOC documentation and hold on all three clouds. The naming, tagging, and template version details below are the AWS ones, so on GCP and Azure check the equivalent instances, disks, images, and storage in the project or subscription you connected.

Architecture

A connected AWS account carries two CloudFormation stacks, and they version separately.

The connection stack creates the IAM role warpbuild-<integration-id>, whose permissions are grouped into named policy contexts: FineGrainedEC2Permissions, SpotServiceLinkedRolePermissions, NetworkPermissions, StoragePermissions, and CloudFormationPermissions. The last context is the one that lets WarpBuild raise changeset requests against connection and stack upgrades in create mode. Updates to this role are required when a new feature needs a permission the role does not hold yet.

The WarpBuild stack holds the region, the VPC and subnets, the security group attached to every runner instance, and the object storage bucket used for the artifact cache, the container layer cache, and runner telemetry. Its template version is what a stack update moves.

Template versionDocumented change
Before 1.3Runner instances are tagged, stack resources in create mode are not
1.3Stack resources in create mode carry the WarpBuild tag set; runners are tagged in all cases
Before 1.4Public subnet runners may hit ECR authentication failures, seen as ecr login timeouts
1.4VPC endpoints are configured for ECR operations from both public and private subnet runners

Those two rows are the common reasons to apply an update rather than to rebuild. A registry login that times out only on public subnet runners is a template version symptom, and the documented fix is upgrading the stack to template v1.4 from the dashboard (AWS BYOC configuration guide).

Create mode and import mode differ in what the changeset can reach. In create mode CloudFormation provisioned the VPC, the subnets, and the security group, so they move with the template. In import mode you supplied those objects and they stay under your control, so the update changes the WarpBuild stack record and the resources WarpBuild created inside it.

Configuration

Applying an update

  1. Read what the dashboard is offering, and check whether it targets the cloud connection or the stack. A connection update usually means new IAM permissions; a stack update usually means a new template version.
  2. Pick a window against your busiest runner set rather than against wall clock time. A nightly batch runner set and a pull request runner set have different quiet hours.
  3. Drain the runner sets you care about, using the sequence in the next section.
  4. Apply the update. The changeset runs against the connection or the stack in your account under the warpbuild-<integration-id> role.
  5. Re-check any permission customization you made. The two documented customization approaches are editing the CloudFormation template on the AWS redirect page before applying it, and editing the role after it is created, so read the role once the changeset completes and confirm your edits are still what you intend.
  6. Run one workflow per affected runner set and watch the Set up job step complete.

Deleting in dependency order

WarpBuild enforces the order, so the dashboard tells you what is blocking before it refuses a delete.

  1. Delete the custom runner configurations that reference the stack. Nothing on the WarpBuild side blocks this step, which is why the drain belongs here.
  2. Delete the stack. The confirmation lists the custom runner configurations that depend on it, and the stack cannot be deleted until those are gone.
  3. Delete the cloud connection if you are disconnecting the account. The confirmation lists the stacks that depend on it, and the connection cannot be deleted until those are gone.

Step 3 is optional and usually skipped. Keep the connection when another stack still runs on it, or when you are rebuilding in a new region under the same account. The answer on deleting a BYOC stack walks the same chain from the delete side.

Operations

Draining in-flight jobs

Each GitHub Actions job runs on a distinct, freshly provisioned instance that is terminated when the job completes, with no shared state between jobs (BYOC security hardening). There is no long-lived agent to unregister, so the drain window is the duration of the longest job on that runner set, and the fleet turns over on its own once new work stops arriving. The creation side of that cycle is covered in how BYOC runners are created and destroyed.

Repoint the labels you want to protect for the length of the window:

.github/workflows/test.yml
jobs:
  unit:
    # During the update window, swap the BYOC label for a hosted one:
    # runs-on: warp-custom-linux-x64-8x
    runs-on: warp-ubuntu-latest-x64-8x
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test

Then confirm the runner set is empty before you apply:

gh run list --status in_progress --limit 100 \
  --json databaseId,workflowName,createdAt

Two details decide whether a drain is clean. Scheduled workflows on release branches can still carry an old label days after main is updated, so search the organization for warp-custom- rather than reading the default branch alone. And a job that queues against a label with no runner behind it waits rather than failing, until GitHub cancels it at 24 hours (GitHub Actions limits, checked on 2026-08-13).

Verifying after an update

Run one workflow per affected runner set. On public subnet runners, watch the registry login step, since that is the step the v1.4 endpoint change addresses. Confirm the dashboard no longer lists a pending update for the connection or the stack.

Verifying after a delete

The dashboard stops listing the objects once they are deleted, so verify against your own account. Filter by tag where the console allows it, since every resource the stack creates carries warpbuild-stack-id and warpbuild-stack-name alongside warpbuild-managed-by, warpbuild-github-org, warpbuild-runner-id, and warpbuild-runner-labels.

aws ec2 describe-instances \
  --filters "Name=tag:warpbuild-stack-id,Values=<stack-id>" \
  --query "Reservations[].Instances[].[InstanceId,State.Name]" \
  --output table
ResourceHow to find it
EC2 runner instances and EBS volumesName pattern warp-*
Launch templatesName pattern tmpl-warp-*
Object storage bucketName pattern warpbuild-*
Connection IAM rolewarpbuild-<integration-id>
Custom images and their snapshotsImages built for custom VM image runners

The tag filter and the name patterns are both worth running on an older fleet. Stack resources in create mode are tagged from template version 1.3 onward, so a stack that was never updated past 1.2 leaves resources that the tag query misses and the name pattern finds. That is the same version history the update flow exists to close.

Deleting a stack stops the WarpBuild meter for its runners. BYOC carries a WarpBuild fee of $0.002 per runner minute for Linux runners and $0.002 per runner minute for Windows runners (pricing page, checked on 2026-08-13), while your own cloud account bills the compute, storage, and data transfer at your rates.

Jobs on hosted warp- labels keep running through a BYOC stack update, which is what makes the label swap above a workable drain. The full AWS setup, quota, and cost picture is on the BYOC runners on AWS page.

FAQ

What does applying a BYOC stack update actually do?

It issues a CloudFormation changeset against the cloud connection or the stack in your own account, which is how a stack picks up a newer template version without being rebuilt. WarpBuild may require these changes to cloud connections or stacks to support new features, and they appear in the dashboard as updates to apply.

Can an update change the stack region or the object storage bucket?

No. The stack name, the object storage bucket, and the region are fixed at creation, so a change to any of the three means deleting the stack and building a new one. Everything else, including template versions and new IAM permissions, arrives through an update.

Do in-flight GitHub Actions jobs need to finish before I apply an update?

Plan for it. Each job runs on a distinct, freshly provisioned instance that is terminated when the job completes, so the drain window is the duration of the longest job on that runner set. Repoint the runs-on labels you want to protect, let the running jobs finish, then apply.

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.