Skip to content

Counting what a customer consumes

A hosted customer consumes resources, and those have to be counted. The kernel does not measure processors: it counts compute credits, a portable unit worth the same on a laptop and on a server.

credits = base + duration_ms // ms_per_credit

Run with the defaults (ms_per_credit = 100, base = 1):

instant request : 1 credit
350 ms request : 4 credits
12 s job : 121 credits

A flat base so instant work still costs something, a duration term so long work costs more. Wall time is a proxy for real cost, not a CPU measurement: the trade-off is deliberate, and it is what makes the counter portable and predictable.

Reads are free

Only writes and jobs are counted. GET, HEAD, OPTIONS cost nothing.

That is not generosity, it is a correction: an admin screen fans out into dozens of read calls, so charging reads turned a compute budget into a request-count cap that plain browsing exhausted. One demo reached 115% of its cap without a single write.

The cap, and what an overrun does

assert_within_compute_quota(engine, period="2099-01", credits_delta=30)

Run on a window at 60 credits used against a cap of 100:

a 30-credit write : allowed
a 50-credit write : refused -> compute quota exceeded for 2099-01: 110 > 100

Over HTTP the refusal is a 402 Payment Required on writes, and reads keep going through.

For the same reason the gate fails open: if the quota table is unreadable or the database hiccups, the request goes through. A billing-infrastructure incident must not take the API down.

No cap is not a cap of zero

with no cap: even a billion credits goes through

The default is uncapped. It is the signed licence that pushes the value (max_compute_credits) into the subsystem at install time: the cap belongs to the contract, not to the code.

Calibrating on your own data

The three numbers are per-tenant parameters (metering.*), so they are tunable without touching code. And the tool recommends them from the durations actually recorded:

$ kewos metering recommend --database-url ...
samples (recorded job runs): 872
median duration: 47 ms p90: 1005 ms
current ms_per_credit=100 request_base=1 job_base=1
recommended ms_per_credit=9 request_base=1 job_base=1

On this instance the median job takes 47 ms: at the default granularity nearly every job costs its base and the duration term says nothing. The recommendation tightens the granularity so the median lands back on target. recommend changes nothing; apply-recommendation persists.

A monthly purge trims windows past the retention horizon, so the counter does not grow forever.