Control Plane

A control plane is the component that decides what should exist and issues the instructions that create it, while the workload runs elsewhere on the data plane.

A control plane is the part of a system that decides what should exist and issues the instructions that make it exist, without carrying the workload traffic itself. The components that carry the work are the data plane, and separating the two is what lets a scheduling failure and a workload failure be different events.

The term comes from network equipment and now describes any system where placement decisions are kept apart from execution.

Definition

A control plane holds three things: a description of desired state, a view of actual state, and an authenticated path to an API that can change actual state. It runs one loop: read what should exist, read what does exist, and issue calls until the two agree. Nothing in that loop requires the control plane to touch the payload.

QuestionControl planeData plane
What it holdsdesired state, configuration, credentials, metadatathe workload itself: processes, packets, build output
What it doesdecides, schedules, reconciles, retriesexecutes, forwards, stores
What it talks toprovider APIs, queues, its own databasethe workload's own dependencies
What stops when it stopsnew placements, scaling, cleanupeverything currently running
What it scales withthe number of objects under managementthe amount of work

Two familiar systems show the split clearly.

A router computes routing tables from protocols such as BGP or OSPF in its control plane, and its forwarding path moves packets according to the tables already installed. Restarting the routing process does not drop traffic that the installed tables already know how to forward.

Kubernetes places the API server, the scheduler, and the controller manager on the control plane side, and the kubelet plus a container runtime on each node on the workload side (Kubernetes cluster components, checked on 2026-08-13). The scheduler decides which node runs a pod. The kubelet on that node starts the container and keeps it running. Pods that are already running survive an API server outage, while a pod that needs a new node stays pending.

The direction of the connection matters as much as the division of duties. A control plane usually initiates its connections outward: it calls a cloud provider API, a source control API, or a queue, and it accepts no inbound connections from the machines it manages. Machines dial out too, to register themselves and to report status. The practical result is that a control plane needs credentials rather than network reachability, and the addresses it dials from are a small stable set that a network team can put in a firewall rule.

That asymmetry sets the trust boundary. A control plane is trusted to create, size, and destroy capacity, which is significant authority, while the data flowing through the workload can stay outside its reach entirely. Reviewing such a system means asking two separate questions: what the control plane is permitted to do, and what it is able to read.

Example

In GitHub Actions, a runner platform's control plane is the component that watches for queued jobs and creates machines to serve them, while the build runs on a machine somewhere else. The workflow file names no plane at all. It names labels:

name: build
on:
  push:
    branches: [main]

jobs:
  compile:
    runs-on: [self-hosted, linux, x64]
    steps:
      - uses: actions/checkout@v4
      - run: make build

When that push lands, the following happens in order, and the two planes take alternating turns:

StepWhich planeWhat happens
1controlThe platform observes a queued job carrying the labels self-hosted, linux, and x64.
2controlIt compares queue depth against machines already running and decides one more is needed.
3controlIt calls the cloud provider API with a granted role and launches an instance.
4dataThe instance boots, starts the runner agent, and registers with GitHub under those labels.
5dataThe agent claims the job, checks out the repository, runs make build, and streams logs to GitHub.
6controlAfter the job reports its conclusion, the platform terminates the instance and records the minutes used.

Steps 1 through 3 and step 6 involve no repository content. Steps 4 and 5 carry all of it: the checkout, the compiler output, any cache the build reads or writes, and the log lines. The control plane sees a job identifier, a label set, a machine size, and lifecycle timestamps.

The split is visible during a partial failure. Once the agent has claimed the job in step 4, that build finishes even if the control plane is unreachable, because the agent holds its own connection to GitHub and reports there directly. What breaks is step 2 for the next push: the job sits in the queue showing "Waiting for a runner to pick up this job" and produces no logs. GitHub cancels a job that has waited 24 hours for a self-hosted runner (GitHub Actions limits, checked on 2026-08-13), so a stalled placement surfaces as a cancellation a day later rather than as an immediate error.

The same split decides where data lives when the machines run inside a customer's own cloud account. The instances, the disks, the caches, and the artifacts sit in that account, and the component that launches them sits outside it and reaches in through a granted role. The AWS BYOC architecture reference draws the resource graph for that arrangement, and the runner security documentation covers the isolation model applied to each machine.

FAQ

What is a control plane in simple terms?

A control plane is the part of a system that decides what should exist and issues the instructions that make it exist. It holds a description of desired state, watches actual state, and calls an API to close the gap. The workload traffic travels somewhere else, so the control plane can be unavailable while the work it already placed keeps running.

What is the difference between a control plane and a data plane?

The control plane decides and instructs. The data plane executes and carries. In a router the control plane computes routing tables while the forwarding path moves packets. In Kubernetes the scheduler decides which node runs a pod while the kubelet and container runtime run it. The two planes fail independently, which is why a scheduling outage and a workload outage are separate events.

What happens to running work when a control plane goes down?

Work that has already been placed usually continues, because the machine executing it holds its own connection to whatever it reports to. What stops is anything that needs a new decision: new placements, scaling up, and cleanup of finished capacity. The visible symptom is a queue that grows while everything already running finishes normally.

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.