Data Plane
A data plane is the set of components that carry the actual workload, while the control plane beside it decides what should exist and schedules work onto them.
A data plane is the set of components that carry the actual workload: the machines, processes, and network paths that work passes through on its way to a result. The control plane sits beside it and decides what should exist and where work should go, without carrying the work itself.
The split describes responsibility rather than hardware. Two processes on one machine can belong to different planes, and a single plane can span several accounts, regions, and providers.
Definition
A component belongs to the data plane when it sits on the path of the work. Remove it and work already in flight stops. Remove a control plane component and existing work continues on whatever was already placed, until something needs to change.
Three properties follow from that position.
It scales with volume. Data plane capacity is sized against how much work arrives: requests per second, packets per second, or, in a build system, concurrent jobs. Control plane capacity is sized against the rate of change, which is usually smaller by orders of magnitude. A fleet running 500 concurrent jobs needs 500 machines and one scheduler.
Its failures are immediate. A data plane outage stops work that is running. A control plane outage stops new decisions while placed work continues, a property AWS describes as static stability. Systems are usually designed so the data plane keeps serving through a control plane outage.
It holds the workload's own material. Source code, secrets, intermediate files, and build outputs all pass through the data plane, so a question about where those things live is a question about where the data plane runs. The control plane holds descriptions instead: identifiers, labels, sizes, timestamps, and the record of what should exist.
| Dimension | Control plane | Data plane |
|---|---|---|
| Job | Decides what should exist and issues instructions | Executes the work and moves the bytes |
| Sized against | Rate of change, such as decisions per minute | Volume of work, such as concurrent jobs |
| Effect of an outage | New changes stall, placed work continues | Work in flight stops |
| Holds | Identifiers, labels, configuration, desired state | The workload's inputs, secrets, and outputs |
| Usual placement | Central, operated once for many workloads | Wherever the work has to run |
The vocabulary comes from network routing. Inside a router, the control plane runs the routing protocols that build the forwarding table, and the data plane, also called the forwarding plane, moves packets according to that table at line rate. Kubernetes reuses the same division: the API server and the scheduler decide which node should run a pod, and the kubelet with the container runtime on that node runs it.
Where the boundary is drawn
The boundary is a design choice, and the same system can be cut at different points. A managed database can place query execution and storage in one account while the provisioning and upgrade logic runs elsewhere. A build platform can place the queue watcher and the machine lifecycle logic outside a customer account while every compiler process runs inside it.
Two questions settle where the line falls for any given system. Which components would a running workload notice the loss of within seconds, and which components does the workload's data physically pass through. Everything answering yes to either question is data plane.
Why placement is a data plane question
Because the data plane carries the work, the decisions that follow from placement attach to it: which region the machines sit in, which account owns them, which network they join, and which quotas they consume. A team can therefore adopt scheduling operated by someone else while keeping execution on machines it controls, and the reverse arrangement is equally possible.
Example
GitHub Actions splits along this line by default. GitHub holds the queue, evaluates workflow triggers, and matches the labels in runs-on against online runners, which is control plane work. The runner machine performs the steps, which is data plane work.
name: build
on:
push:
branches: [main]
jobs:
package:
runs-on: [self-hosted, linux, x64]
steps:
- uses: actions/checkout@v4
- run: make build
- run: make package
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/The runs-on line is where the boundary appears in the file. Everything above it describes a decision made outside the machine. Everything below it happens on the machine that claims the job.
Now place that runner on an instance inside a cloud account you own, with the scheduling loop running outside the account. One job then reads like this:
| Step | Where it happens | Plane |
|---|---|---|
A push creates a workflow run and queues the package job | GitHub | Control plane |
| A scheduler sees the queued job and calls the cloud API for a machine | Outside the account | Control plane |
| The instance boots in the account's VPC and registers with GitHub | Inside the account | Data plane |
actions/checkout clones the repository onto the instance disk | Inside the account | Data plane |
make build compiles and writes to the instance disk and the cache bucket | Inside the account | Data plane |
| Step logs and the job conclusion stream back to GitHub | Across the boundary | Both |
| The instance is terminated after the job finishes | Inside the account | Data plane |
The source tree, the compiler, the secrets exposed to the step environment, and the produced artifact stay on the instance. What crosses the boundary is the instruction to create a machine, the log stream, and the conclusion of the job. The runner agent opens an outbound connection and waits for work, so the machine needs no inbound path for any of this to function.
One documented arrangement of that shape places a VPC with public and private subnets, a security group attached to every runner instance, an object storage bucket for caches and logs, and per-job instances inside the account, while the scheduling loop stays outside it. The resource graph is drawn in the BYOC AWS architecture reference, and the three setup steps for a cloud account are listed in the bring-your-own-cloud documentation.
Sizing follows the plane it belongs to. Because data plane capacity tracks concurrent work, the account quotas that matter are the ones counted per job: instance count, attached volumes, and one elastic IP for each concurrently running job, plus three for the NAT gateways in three availability zones. The AWS guide in that same documentation lists them per stack. The scheduler outside the account needs none of those numbers to grow, because its work grows with the number of decisions rather than the number of machines.
Related Terms
- Control plane, the side that decides what should exist: the scheduling and reconciliation half of the split, and why its outages look different.
- GitHub Actions runners inside your own AWS account: how a runner data plane is placed in an AWS account you own, including the IAM surface the scheduler uses.
- What gets created in your cloud account: the resource list, naming convention, and tags that make the data plane identifiable in a shared account.
- Bring-your-own-cloud documentation: connecting a cloud account, creating a stack, and configuring the runners that execute jobs.
- WarpBuild pricing: per minute rates by runner type.
FAQ
What is a data plane?
A data plane is the set of components that carry the actual workload: the machines, processes, and network paths the work passes through on its way to a result. A component belongs to the data plane when removing it stops work that is already in flight.
What is the difference between a control plane and a data plane?
The control plane decides what should exist and issues instructions. The data plane executes. Control plane capacity is sized against the rate of change, data plane capacity against the volume of work, and an outage on each side looks different: losing the control plane stalls new decisions while running work continues, and losing the data plane stops the work itself.
Where is the data plane in a GitHub Actions workflow?
The runner is the data plane. GitHub queues the job and matches the labels in runs-on, and the runner machine performs the checkout, compiles the code, holds the secrets in the step environment, and writes the artifacts. The runs-on line is where the boundary between the two planes appears in the workflow file.
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.