Environments
Use RunsOn environments to isolate stacks, runtime permissions, GitHub App boundaries, networks, and regions.
RunsOn environments are stack and runtime isolation boundaries. They are not GitHub Actions environments, and they do not replace GitHub environment protection rules. A RunsOn environment decides which RunsOn stack should pick up a job, which GitHub App boundary is used, and which AWS IAM and network configuration the runner gets.
The default environment is production. If a Flex job omits an env label, it targets that default.
Usage
Flex
In Flex, a workflow selects the stack environment directly from the runs-on label:
jobs: build: runs-on: runs-on=${{ github.run_id }}/runner=2cpu-linux-x64/env=stagingFleet
In Fleet, the generated runner label includes the stack environment and approved fleet:
jobs: build: runs-on: runs-on/fleet=linux-small/env=productionSee Flex job labels and Fleet runner groups for the product-specific controls.
When to use multiple environments
Use separate RunsOn environments when the blast radius should be different — production deployments vs ordinary CI, public vs private repositories, workloads with different IAM policies, runners in different VPCs / accounts / regions, or temporary branch-isolated stacks. Each Flex environment is backed by a separate RunsOn stack and private GitHub App, so a different set of repositories can be allowed per environment with separate AWS permissions.
Common patterns:
- Single stack — keep
productiononly. Enough for most teams. - Production plus CI — separate deployment workflows from normal pull-request CI.
- Multi-region — one environment per region, targeted with Flex
env+regionlabels, or with separate Fleet deployments. - Branch isolation — a temporary environment for a risky branch migration, removed once the branch lands.
How it works
Each Flex stack is deployed with an Environment stack parameter. The default is production. Workflows opt into a non-default environment by adding the env label — only the matching stack picks up the job, and all other stacks ignore it.
In Fleet, the equivalent isolation lives in the runner fleet itself. The runner fleet emits the runs-on/fleet=<name>/env=<environment> label that workflows target directly — see the example in Usage. Workflow authors don’t author the env value; it comes from the runner fleet’s Terraform configuration and the Fleet runner groups. Put separate isolation requirements into separate runner fleets, runner groups, or Fleet deployments, depending on whether the boundary is GitHub access, AWS capacity, IAM, or networking.
Flex vs Fleet
Same isolation goal, opposite ownership: Flex environments are workflow-driven, Fleet environments are baked into the runner fleet.
| Aspect | Flex | Fleet |
|---|---|---|
| Where defined | Environment stack parameter | Runner fleet + Fleet GitHub boundary |
| How a workflow opts in | env=<name> label on runs-on | Target a fleet label that already carries env |
| Default value | production if env is omitted | Fleet emits its own label; no workflow default |
| Per-job override | ✓ | — (workflow can’t change the fleet’s env) |
| Typical boundary use | One stack per blast-radius / region | Separate runner fleets, groups, or deployments |
Considerations
Each RunsOn stack incurs a cost (AWS resources + regular stack upgrades), so create as few as possible. The majority of clients only run one stack.
For exact Flex syntax, see job labels. For Fleet boundaries, see Fleet runner groups and Fleet networking and IAM.