How it is built
Architecture overview
A cloud control plane is the API through which customers create, change and delete resources: virtual machines, volumes,
networks, addresses. A call such as RunInstances authenticates a signed request, checks permissions and quotas, records the
customer's intent, and then drives a chain of slow, failure-prone steps (choose a host, allocate an address, attach a network
interface, boot) that may take seconds or minutes and that must survive crashes in the middle. The data plane, which moves packets and
disk blocks, does not run through it. The one idea that makes it work is that the API stores intent durably and returns early, and
background machinery makes reality match the intent: every call is safe to retry, every long step is an operation the caller can
poll, and every dependency has a bounded blast radius. This page follows the EC2 API and its AWS documentation, and compares OpenStack Nova, Azure
Resource Manager and Google's API guidelines.
Neighbouring pages: Container orchestrator (the same reconcile idea over pods), Software-defined datacenter network, Durable workflow engine and Multi-tenant SaaS control plane.
Parts:
- API front end — authenticates, authorises and throttles every call — hmac-request-signing (no page yet), Authorization models (RBAC, ABAC, ReBAC), Token bucket, built on Sliding-window counters
- Request semantics — makes calls retry-safe and long calls pollable — Idempotency keys, long-running-operations (no page yet), Exponential backoff with jitter, built on Long polling, Durable job queue
- Resource store and history — the replicated record of resources and what happened to them — Quorum replication, Event sourcing, Tamper-evident audit log, built on Vector clocks, Hinted handoff, Anti-entropy repair, Optimistic concurrency control, Digital signatures (Ed25519), Segmented log
- Orchestration — turns intent into a finished resource across many steps — Desired-state reconciliation, Durable workflow execution, built on Watch notifications, Hierarchical timing wheel
- Placement and addressing — chooses hosts, addresses and virtual-network paths — Bin packing, ip-address-management (no page yet), packet-encapsulation (no page yet), built on Roaring bitmaps, Leases
- Blast-radius control — limits how much one failure or one customer can break — cell-based-architecture (no page yet), shuffle-sharding (no page yet), built on Health checking, Consistent hashing, Deterministic bucketing
client (SDK, signs request) ─► front end: verify signature → authorise → throttle → idempotency lookup
│ accept: write intent (resource record, state=pending) + enqueue
▼ 202 / operation id (or the resource in "pending")
resource store (quorum replicated) ◄── workflow / reconcile loop ──► placement (bin pack) ─► host agent
│ every change is an event ──► audit log (signed batches) ├─► IP address manager (subnet bitmaps)
▼ └─► network mapping service ─► encapsulating dataplane
client polls Describe… / operation (eventually consistent reads) cells: full copy of all of the above, tenants routed by key
How the parts fit together
API front end
Every call is signed. hmac-request-signing (no page yet) means the client builds a canonical form of the request (method, host, headers, body hash),
then computes an HMAC-SHA256 with a key derived from its secret, and the server recomputes it (AWS Signature Version 4, whose string to sign includes a timestamp). The secret never
travels and the signature covers the request, so it cannot be altered in flight. Once the caller is known, Authorization models (RBAC, ABAC, ReBAC)
decide whether this principal may perform this action on this resource: cloud IAM is attribute- and policy-based, evaluated on every call, which is why the policy
store must be quick and highly available. Then throttling: EC2 documents the Token bucket algorithm per account and action, with a bucket
size that allows bursts and a refill rate for the steady state; calls over the limit get RequestLimitExceeded. Actions that change many resources also have a
separate resource-token bucket: for RunInstances the documentation gives 1,000 tokens refilled at two per second. Counting windows
(Sliding-window counters) are the cheaper alternative for coarse limits. The front end is stateless, so it scales by adding hosts, but
limits and idempotency records must be shared state.
Request semantics
Clients time out, so every mutating call must be safe to repeat. Idempotency keys are EC2's client token: a unique string of up to 64
ASCII characters sent with RunInstances and similar actions; a retry with the same token and parameters succeeds without doing the work again, and a retry
with the same token and different parameters fails with IdempotentParameterMismatch. Some actions (such as TerminateInstances) are idempotent by default.
AWS's Builders' Library describes the same contract (a caller-provided client request identifier, with the created resource labelled by it). The server should record the token in the same transaction as the intent, or a crash between the two reintroduces the duplicate (this page's reading).
long-running-operations (no page yet) are the contract for calls that cannot finish inside a request. Google's API guidelines (AIP-151) say a slow method returns
a google.longrunning.Operation instead of the final result, which the client polls or waits on; Azure Resource Manager returns 201 or 202 and a status URL in an
Azure-AsyncOperation header, with Retry-After. EC2 takes a third route: the instance enters the pending state at once and the client polls Describe. In all three,
reads are eventually consistent (EC2's documentation says a new resource is "eventually visible" and advises polling with exponential backoff), so a client that
creates then immediately describes must expect a not-found. Waiting uses Long polling where offered, and retries use Exponential backoff with jitter
on both sides so that a recovering service is not hit by every client at once. The accepted intent is queued on a Durable job queue.
Resource store and history
Quorum replication stores resource records without a single leader: write to W of N replicas, read from R, with R + W > N so reads see the last write; Vector clocks, Hinted handoff and Anti-entropy repair deal with divergence and temporary failures (the Dynamo design). A control plane often prefers a smaller, consistent store: Nova keeps its state in a SQL database, and AWS describes Physalia, a transactional key-value store that is highly available only for the keys each client needs, built as the configuration master for EBS and designed for cloud control planes. Whichever is chosen, concurrent updaters use Optimistic concurrency control: a version number checked on write.
Event sourcing keeps the history, not just the state: each resource is a stream of events (created, attached, resized, terminated) from which the current view is derived. The Azure architecture guidance names auditability and historical reconstruction as its benefits, and notes that a state-only store without a separate audit log loses history. The Tamper-evident audit log turns the events into evidence: AWS CloudTrail can hash each log file with SHA-256, write an hourly digest file signed with RSA, and include the previous digest's signature in the next so deletion or alteration breaks the chain (Digital signatures, Segmented log).
Orchestration
Desired-state reconciliation keeps the intent true over time: a record says "instance i-1 should be running on subnet s"; a controller compares it with the host's actual state and acts, again and again, so a crashed controller or a missed event only delays convergence. Nova shows the plumbing: REST API servers write the database, send RPC over a message queue to a scheduler, a conductor (which mediates database access and coordinates builds and resizes) and the compute service on each host. Watch notifications tell controllers what changed.
Creation is not a single state change but a sequence: reserve capacity, allocate an address, create an interface, start the host agent, record the result. Durable workflow execution runs such sequences as code whose progress is logged, so after a crash it resumes at the next step instead of repeating or abandoning the earlier ones; failed steps are retried with backoff and completed ones are compensated on rollback. Timers (waiting 30 s before the next check, timing out a step) are cheap with a Hierarchical timing wheel. The two ideas complement each other: workflows for the multi-step "do this once" path, reconciliation for "keep this true". See Durable workflow engine.
Placement and addressing
Bin packing picks the host. Nova's filter scheduler asks its Placement service, which tracks each host's inventory and usage, for candidates, then filters and weighs them. Microsoft's Protean paper describes the Azure equivalent: one instance serves an availability zone of 10,000 to 100,000 machines, keeps policy (a rule-based allocation agent) apart from mechanism, and uses multi-layer caching to answer in milliseconds. The contract with orchestration is that placement returns a reservation, not a promise: capacity may have been taken meanwhile, so the workflow retries on a conflict.
ip-address-management (no page yet) hands out addresses from subnets. EC2 documents that in every subnet the first four addresses and the last are reserved, which shows the shape of the problem: carve CIDR blocks without overlap, allocate and free single addresses fast, and never hand one out twice. A bitmap per subnet (Roaring bitmaps when sparse) and an atomic claim, guarded by a lease while the address is in transit, cover it. OpenStack Neutron exposes IPAM as a pluggable driver interface.
packet-encapsulation (no page yet) is what makes a customer's private network private on shared hardware. The host wraps each guest packet in an outer header addressed to the host that runs the destination guest, so customer addresses can overlap. Geneve (RFC 8926) is one standard for this; Google's Andromeda paper describes a control plane that can program connectivity for tens of thousands of VMs in seconds over a host dataplane. The control plane owns the mapping from virtual address to physical host; the dataplane only looks it up. See Software-defined datacenter network.
Blast-radius control
cell-based-architecture (no page yet) partitions the whole control plane into independent copies, each serving a slice of accounts or resources, with a thin router in front that keeps the partition key (AWS Well-Architected guidance). A bad deploy or an overloaded store hurts one cell. Nova calls the same idea "cells" for sharding a deployment. Health checking decides when a cell or host is out, and Consistent hashing and Deterministic bucketing assign keys and ramp changes stably. shuffle-sharding (no page yet) goes further for shared fleets: each customer gets a random small subset of workers, so a customer who sends poisonous requests exhausts only its own subset; with eight workers and two per customer there are 28 distinct shards, and AWS gives Route 53's 2,048 virtual name servers and shards of four as 730 billion. Cells fit whole-stack isolation and need a router, shuffle sharding fits shared pools and needs retrying clients. The Builders' Library "static stability" article defines the control plane as the machinery for changing resources and the data plane as what they do day to day; the design rule that follows is that running resources should not depend on the control plane.
Data and control flow
Launching an instance:
- The SDK signs
RunInstanceswith a client token; the front end verifies the signature, authorises the principal, and takes one request token and many resource tokens. - The idempotency record for the token is looked up; a repeat returns the earlier result.
- The resource records are written in state
pending, with the intent event, and a workflow is started; the call returns. - The workflow asks placement for a host, claims an address, creates the interface and tells the host agent to boot; each step is logged before the next.
- The mapping service publishes the virtual-address-to-host entry so the dataplane can encapsulate traffic to the new instance.
- The record moves to
running; the event goes to the audit log; the client'sDescribepoll now returns it.
A retried call after a timeout: the client waits with jittered backoff, resends the same token, and receives the original result or the in-flight resource; no second instance is created.
A host failure: the health check marks the host down; the reconcile loop sees fewer instances than desired and starts the workflow again elsewhere, where policy allows.
Scaling
- API request rate. Levers: stateless front ends, per-action throttles, shed load early, cache authorisation and policy.
- Store size and write rate. Levers: partition by account or resource id, quorum tuning, move hot partitions, read replicas for
Describe. - Workflow count and placement. Levers: more workers, timer wheels, per-zone placement with cached inventory and reservation retry.
- Network programming. Levers: push only the mappings a host needs, gateways for rare flows, batched updates.
- Blast radius as the customer base grows. Levers: more and smaller cells, shuffle shards for shared services, staged deployment cell by cell.
Failure modes
| Failure | Symptom | Cause | Fix |
|---|---|---|---|
| Duplicate resources | two instances for one call | retry without a token, or token recorded after the work | client token stored atomically with the intent |
| Not-found right after create | Describe fails for a moment | eventually consistent read | retry with backoff, read from the leader when needed |
| Retry storm | recovery keeps failing | all clients retry at once | jittered backoff, throttle with a clear error, shed load |
| Half-created resource | an address or interface with no instance | crash between workflow steps | durable workflow with compensation, reconcile sweeper |
| Placement conflict | launch fails after capacity was "found" | two requests chose the same host | reservation with retry, optimistic versioning |
| Address collision | two guests with one IP | racy allocation or stale lease | atomic claim, leases, audit of the allocation table |
| Cell-wide outage | all customers in one cell fail | bad deploy or shared dependency | staged rollout cell by cell, no cross-cell calls |
| Poisonous request | one customer's calls break a shared fleet | shared worker pool | shuffle sharding, per-account limits |
| Control plane down | cannot create, but existing instances run | control-plane dependency in the data path | static stability: data plane keeps last known state |
Real implementations
| name | what it is | repo | licence | notes |
|---|---|---|---|---|
| Amazon EC2 API | the reference: signed requests, client tokens, token-bucket throttling | EC2 developer guide | — | closed, documented |
| OpenStack Nova | compute API, scheduler, conductor, cells | openstack/nova | Apache-2.0 (LICENSE) | architecture |
| OpenStack Neutron | virtual networks, pluggable IPAM | openstack/neutron | Apache-2.0 (LICENSE) | IPAM |
| Apache CloudStack | open-source cloud orchestration | apache/cloudstack | Apache-2.0 (LICENSE) | |
| Azure Resource Manager | async operations with status URLs | docs | — | closed, documented |
| Google API guidelines | long-running operations and request ids | AIP-151 | — | design rules, not code |
| Temporal | durable workflow engine usable for provisioning steps | temporalio/temporal | MIT (LICENSE) | |
| Physalia | AWS cell-oriented control-plane store (paper) | NSDI 2020 | — | closed, described |
The alternative: one synchronous call that does everything inside the request is simple and fine for a few resources that start in under a second; it fails once steps take minutes, a step can fail halfway, or callers retry, which is why every large cloud uses intent plus operations.
Sources
- AWS EC2 developer guide: request throttling, idempotency, eventual consistency, instance states, signing requests (SigV4), VPC subnet sizing, CloudTrail log file integrity.
- AWS Builders' Library: Making retries safe with idempotent APIs, Timeouts, retries and backoff with jitter, Static stability using Availability Zones, Workload isolation using shuffle-sharding.
- AWS Well-Architected, Reducing the Scope of Impact with Cell-Based Architecture.
- M. Brooker, T. Chen, F. Ping, Millions of Tiny Databases, NSDI 2020. paper
- O. Hadary et al., Protean: VM Allocation Service at Scale, OSDI 2020. paper
- M. Dalton et al., Andromeda: Performance, Isolation, and Velocity at Scale in Cloud Network Virtualization, NSDI 2018. paper
- G. DeCandia et al., Dynamo: Amazon's Highly Available Key-value Store, SOSP 2007. paper
- J. Gross et al., Geneve: Generic Network Virtualization Encapsulation, RFC 8926. RFC
- Google API Improvement Proposals: AIP-151 long-running operations, AIP-155 request identification.
- Microsoft: Azure async operations, Event Sourcing pattern.
- OpenStack Nova: architecture, scheduling.