From c382cb406c116d59df5a21160b3caa8b60a2422a Mon Sep 17 00:00:00 2001 From: Jose Szychowski Date: Wed, 12 Aug 2026 19:19:30 -0300 Subject: [PATCH] docs: add design proposal and documentation for per-second compute usage billing --- .../per-second-usage-billing/README.md | 337 ++++++++++++++++++ .../architecture-context.png | Bin 0 -> 41966 bytes .../architecture-context.puml | 21 ++ 3 files changed, 358 insertions(+) create mode 100644 docs/enhancements/per-second-usage-billing/README.md create mode 100644 docs/enhancements/per-second-usage-billing/architecture-context.png create mode 100644 docs/enhancements/per-second-usage-billing/architecture-context.puml diff --git a/docs/enhancements/per-second-usage-billing/README.md b/docs/enhancements/per-second-usage-billing/README.md new file mode 100644 index 00000000..4eafb7ea --- /dev/null +++ b/docs/enhancements/per-second-usage-billing/README.md @@ -0,0 +1,337 @@ +--- +status: draft +stage: alpha +latest-milestone: "v0.x" +--- + +# Per-Second Usage Billing for Compute + +- [Summary](#summary) +- [Motivation](#motivation) + - [Goals](#goals) + - [Non-Goals](#non-goals) +- [Proposal](#proposal) + - [Where Compute Fits](#where-compute-fits) + - [User Stories](#user-stories) + - [How It Works](#how-it-works) + - [Risks and Mitigations](#risks-and-mitigations) +- [Design Details](#design-details) + - [The Instance Controller Is the Metering Point](#the-instance-controller-is-the-metering-point) + - [What It Tracks per Instance](#what-it-tracks-per-instance) + - [How the Running Time Becomes Usage](#how-the-running-time-becomes-usage) + - [Downtime and Crash Recovery](#downtime-and-crash-recovery) +- [Drawbacks](#drawbacks) +- [Alternatives](#alternatives) +- [Production Readiness Review Questionnaire](#production-readiness-review-questionnaire) + - [Feature Enablement and Rollback](#feature-enablement-and-rollback) + - [Monitoring Requirements](#monitoring-requirements) + - [Dependencies](#dependencies) + - [Scalability](#scalability) + - [Troubleshooting](#troubleshooting) +- [Implementation History](#implementation-history) +- [Infrastructure Needed](#infrastructure-needed) + +## Summary + +Today, projects are not billed for the compute they use. This enhancement makes +Compute **meter and hand off exact, per-second usage** — how many vCPUs and how +much memory each customer's workloads actually consumed — to the platform +billing pipeline. Customers get billed for what they truly run, **only while +they are running**, and nothing else. + +Compute's job here is narrow and precise: **know how long an instance actually +ran** and report that accurately. It does not set prices, decide who owes what, +or generate invoices — those already live in the platform billing stack. Compute +measures; the billing platform prices and invoices. + +## Motivation + +Compute currently gives every customer a fixed pool of resources and enforces +limits against it (see [quota enforcement](../quota-enforcement/README.md)), but +nothing records how much of that pool a customer actually used. That means: + +- **Customers who run little pay the same as those who run a lot.** Consumption + is invisible, so usage can't factor into fair, consumption-based billing. +- **There is no accurate, auditable number** beyond a reservation — no count of + hours used, no basis for usage-based pricing, no way for a customer to see + their real footprint. + +Billing against actual, per-second consumption fixes both. It gives the platform +an accurate, trusted measure of what each project used, for the exact time it +used it — and it gives customers a bill that reflects reality, not a ceiling. + +### Goals + +- Compute records, for each project, the **actual running time** of its compute + workloads, counted per second. +- That running time is broken out by resource — **vCPUs** and **memory** — so the + billing platform can price them (possibly differently) later. +- **Customers are billed only for time they actually ran** — nothing accrues + while a workload is stopped, and suspension stops accrual entirely. +- The usage Compute reports is **exact and trustworthy**: no double-counting on + retries, no gaps on faults, and it survives operator and controller restarts. +- The meter definitions Compute emits match what the billing platform expects, + so usage lands cleanly instead of being rejected. +- Compute's contribution is **hand-off only**. It measures and reports; pricing + and invoicing stay in the billing platform. + +### Non-Goals + +- **Pricing, rate cards, or invoices.** Compute does not decide what a vCPU-hour + costs or bill anyone. It produces usage; the platform turns that into money. +- **Metering things Compute doesn't run.** Billing is for **running** instances + only — while one is available and running. Reserved-but-idle capacity is not + billed through this mechanism. +- **Per-second bookkeeping on the wire.** Billing is per-second in *denomination + and accuracy*, but events are batched, so usage is not a billion little events. + This keeps the pipeline efficient while billing stays exact. +- **Replacing capacity reservation / quota.** Quota enforcement keeps limiting + what a project *may* run; this enhancement measures what it *did* run. Both + coexist. +- **Attributing usage to a billing account.** Compute reports which **project** + used the resources; mapping project → account (and organizing it by the right + customer) is the billing platform's job. + +## Proposal + +### Where Compute Fits + +Compute runs customer workloads and knows, moment to moment, what is actually +running. It turns that into usage records and hands them to the platform's +billing pipeline, which meters them against price and sends the result to +billing: + +![How Compute's usage reaches the billing pipeline](./architecture-context.png) + +### User Stories + +**Consumption-based billing.** A customer runs a small workload for a few hours +and a large one for a week. Their invoice reflects each: measured vCPU and +memory for exactly the time each instance ran — no more, no less. + +**Stop means stop.** A customer stops a workload on Friday night. Saturday +onwards accrues nothing. When they start it again Monday, billing resumes from +that point — there is no charge for the gap. + +**Suspended costs nothing.** A customer's project is suspended. Instances stop +running, so they stop costing anything, the moment that happens. Billing +resumes only if (and when) the instance actually runs again. + +**An operator trusts the number.** Whether an event is retried, a controller +restarts, or write hiccups occur, the usage that lands is the same quantity it +should be — never double-counted, never silently dropped. + +### How It Works + +**Only running instances bill.** An instance accrues usage while it is running +and stops accruing the moment it leaves the running state (stopped, terminated, +or suspended). Usage is therefore a measure of *actual uptime*, not potential. + +**Per second, batched.** An instance's running time is accounted for in seconds, +but recorded in intervals. Any workload that has been running continuously for +the reporting interval reports its accumulated seconds in one record — e.g. a +workload that ran for five minutes reports 300 seconds (times its resource +size) in one event, not 300 separate events. + +**What gets recorded, per project:** + +- **CPU** — vCPU-seconds: how many vCPUs the instances ran, for how long. +- **Memory** — memory byte-seconds: how much memory the instances used, for how + long. + +**When a workload stops**, the final partial interval is reported up to the +moment it stopped, so the exact time it ran is captured. + +The sequence an instance follows over its life: + +```mermaid +stateDiagram-v2 + [*] --> Running: Instance starts + Running --> Running: Usage accrues while running + Running --> Stopped: Instance stops + Stopped --> Running: Instance restarts + Stopped --> [*]: Terminated + Running --> [*]: Circle = no accrual when not running +``` + +Nothing about this changes how customers run their workloads. They create, +start, stop, and delete instances exactly as today; measuring usage is +invisible to them. + +## Design Details + +### The Instance Controller Is the Metering Point + +Compute already has a component — the **Instance Controller** — that shepherds +every instance through its life: when it starts, when it becomes available, +when it stops, and when it's removed. Only it sees, centrally, that an +instance is actually **running**. Because it already knows this, it is the +natural and only place to record "how long did this instance run." There is no +separate metering service or per-runtime timers; the controller simply adds +usage accounting wherever it already observes an instance changing state. + +### What It Tracks per Instance + +For each instance, the controller remembers two things across its lifetime: + +- **When the current running stretch began** — the moment the instance became + available/running, so the clock can start without it having to be observed + every single second. +- **How far usage has already been reported** — so that on the next report it + only covers new time, never re-counts what was already handed off. + +This bookkeeping belongs to the instance and persists with it, so it survives +the controller itself restarting — metering doesn't lose its place when a +process is recycled. (If the instance is created or its state is reset, the +tracking starts fresh from that point.) + +> [!NOTE] +> This tracking is **persisted with the instance** (in the cluster's API +> storage), not held in the controller's memory — so the controller restarting +> or going down never loses it. + +### How the Running Time Becomes Usage + +On any of the transitions the controller already handles, it turns the tracked +running time into usage: + +- **While running**, it reports in intervals: what has accumulated since the + last report is handed off as one record (CPU + memory for that window). +- **When the instance stops, terminates, or suspends**, it reports the final + partial interval up to the moment of the transition, then stops — so the + exact runtime is captured and nothing accrues once it's no longer running. + +A signed-off report hand-off that fails is retried for the **same window**, so +no double-count on a retry. The controller therefore never has to be exact at +any single instant — it just needs to be exact about *when the running state +changed*, which it already observes. + +### Downtime and Crash Recovery + +The metering bookkeeping is stored with the instance itself, not in the +controller's memory, so an outage does **not** erase running time: + +- **Controller restarts (or is down briefly).** Instances keep running; on + restart the controller reads back each instance's markers and bills from the + last successfully-reported point forward to now. The downtime is recovered + and billed — nothing is missed, it is simply billed late. +- **Controller is down for a long stretch.** Running time keeps accumulating and + is all billed on recovery. Correct, but a larger single catch-up window and a + longer unbilled lag while it is down. + +Two genuinely bounded limits apply: + +- **The instance is deleted while the controller is down.** Its markers are + deleted with it, losing the unreported window — bounded to at most one + reporting interval (default five minutes), because normal operation flushes + at least that often. +- **A crash between handing usage to the pipeline and recording that it was + handed off.** On restart that window is re-reported; whether it double-counts + depends on the pipeline deduplicating by event *content* (quantity) rather + than only by event *identity* — a check the billing platform must honor. + +### Risks and Mitigations + +- **Usage events are rejected because the meter isn't registered/declared.** + Compute's meter definitions and the billing platform's expectations must agree + one-for-one. Mitigation: Compute ships the declarations and emits consistently + against them; a mismatch surfaces loudly in monitoring (see + [Monitoring Requirements](#monitoring-requirements)) rather than silently + underbilling. +- **A transient write failure could, naively, double-count or drop usage.** + Mitigation: recording is designed so a retry produces the *same* usage for the + same interval, and a crash loses at most a bounded, small window. The reported + number stays trustworthy. +- **Operators can't tell whether usage is flowing.** Mitigation: dedicated + signals surface usage being emitted and usage being rejected/errored, so "is + billing working?" is answerable at a glance. +- **This depends on the platform billing pipeline existing and being wired.** + Compute's side can be developed, gated, and tested independently, and only + begins reporting once enabled and pointed at the pipeline. + +## Drawbacks + +- **The platform's first dependency on the billing pipeline for compute.** Until + it's proven, Compute's usage telemetry is new infrastructure carrying the + billing path. This is mitigated by shipping behind a feature gate and + monitoring hand-off closely before broad enablement. +- **Billing is exact, which means it's transactional in nature.** Accurate + per-second usage is more operational care than a flat capacity charge — but + it's exactly what fair, consumption-based billing requires. + +## Alternatives + +- **Bill against reserved capacity (instances *could* run), not actual usage.** + Rejected. It's the status quo's implicit model and doesn't reward efficiency + or reflect real consumption; a customer who never starts a workload would + still be capped-and-charged as if they had. Billing actual usage is the + differential this enhancement exists to provide. +- **Emit a record every single second.** Rejected. Per-second accuracy does not + need per-second events, which would impose unreasonable volume and pipeline + load for no additional billing fidelity (the batching in + [How It Works](#how-it-works) is exact). +- **Have each runtime separately report and reconcile usage.** Rejected in favor + of a single, authoritative metering point in Compute, so all runtimes report + consistently through one path and there is one number to trust. + +## Production Readiness Review Questionnaire + +> Trimmed to the subsections relevant at alpha, following the precedent of other +> compute enhancements. Beta-targeted subsections (rollout/upgrade/rollback +> planning) are deferred. + +### Feature Enablement and Rollback + +- [x] Feature gate + - Usage emission ships behind a feature gate, **off by default**, and is only + enabled once configured and pointed at the billing pipeline. A deployment + that hasn't opted in emits nothing. + - Enabling/disabling takes effect on restart with the changed configuration; + no control-plane downtime. + - Rollback is turning the feature off — usage emission stops; no existing + behavior is affected. + +### Monitoring Requirements + +- [x] Other (dedicated usage/billing telemetry) + - Signals distinguish usage being **emitted** (successfully handed off) from + usage **errored/rejected** (not reaching the pipeline). A rising rejection + rate with flat emission is the "billing may be silently broken" alarm — + especially the case where events are rejected for an undeclared meter. + +### Dependencies + +- The **platform billing pipeline** and the **meter/resource-type definitions** + it fans out from Compute. Usage is only billable if Compute's declared meters + and the pipeline's expectations agree, and events actually reach the pipeline. + If the pipeline is unreachable, emission blocks and surfaces the error (no + silent underbilling). + +### Scalability + +- Usage volume is bounded by the **number of running instances** times the + reporting interval — not by per-second count. A large fleet adds proportionally + more records, but each instance stays a small, infrequent contributor, so the + load scales linearly and manageably with fleet size rather than with wall-clock + seconds. + +### Troubleshooting + +- **"No usage is landing."** Confirm emission is enabled and configured, and that + the pipeline is reachable. If events are being rejected, check that Compute's + declared meters are present and registered on the platform side. +- **"Usage for X looks wrong."** Confirm the instance actually ran for the window + in question (stopped/suspended time is not billable), and consult the + emission/rejection signals to rule out a hand-off problem. + +## Implementation History + +- **Proposed here.** Initial capability and hand-off design. + +## Infrastructure Needed + +- The **platform billing pipeline** must be available and wired to accept + Compute's usage records, and Compute's meter/resource-type declarations must be + registered on the platform side (just-in-time as emission is enabled). +- No new customer-facing surface: measuring usage requires no customer behavior + change. diff --git a/docs/enhancements/per-second-usage-billing/architecture-context.png b/docs/enhancements/per-second-usage-billing/architecture-context.png new file mode 100644 index 0000000000000000000000000000000000000000..9064030a8152621150fc3b5b73d7df97924414bb GIT binary patch literal 41966 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 Pz(*T)2l`&^-t+$gzpbUv literal 0 HcmV?d00001 diff --git a/docs/enhancements/per-second-usage-billing/architecture-context.puml b/docs/enhancements/per-second-usage-billing/architecture-context.puml new file mode 100644 index 00000000..761f5841 --- /dev/null +++ b/docs/enhancements/per-second-usage-billing/architecture-context.puml @@ -0,0 +1,21 @@ +@startuml architecture-context +!$NEW_C4_STYLE = 1 +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml +!include https://raw.githubusercontent.com/datum-cloud/enhancements/main/enhancements/datum-theme.puml + +Person(customer, "Customer", "Runs compute workloads; billed for what they use") + +System(billing, "Billing Platform", "Turns measured usage into invoices") + +System_Boundary(compute, "Compute") { + Container(instances, "Instances", "Virtual machines / workloads running on behalf of the customer") + Container(controller, "Instance Controller", "Knows when an instance is running and records how long it ran", "Measures vCPU + memory usage per project") +} + +Rel_U(customer, compute, "Runs workloads") +Rel_D(instances, controller, "Is observed while running") +Rel_R(controller, billing, "Reports measured usage") +Rel_U(billing, customer, "Invoices based on usage") + +SHOW_LEGEND() +@enduml