11 min čteníJohnny UnarJohnny Unar

Účtujte compute, zabijte pricing per request

Účtování per request trestá automatizaci a odměňuje plýtvání. Měřte compute a ekonomika vašeho SaaS se přestane chovat jako bug.

pricing per request je lenost

Pricing per request přežívá jen proto, že se snadno vysvětluje, snadno měří a snadno se napojí do Stripe. Ne proto, že by to byl rozumný model ve chvíli, kdy zákazníci začnou stavět seriózní automatizaci. Prvních sto requestů vypadá neškodně. Pak někdo napojí vaše API na queue consumer, ERP sync job nebo smyčku s LLM agentem, která retryuje každou rozbitou odpověď, a z faktury je najednou support ticket se screenshoty a v kopii sedí právníci. Tenhle pattern jsem viděl u systémů na zpracování dokumentů i v AI workflow. Jednotka hodnoty pro zákazníka skoro vůbec nesouvisela s počtem requestů, ale účtovalo se právě podle requestů, protože billing tým dodělal až nakonec a sáhl po nejrychlejší metrice.

Tahle volba vede ke špatnému produktu. Zákazníci nezačnou optimalizovat lepší výsledek, ale menší počet callů. To je tlačí do obřích batch requestů, přerostlých payloadů, ošklivého client-side cachování a křehké orchestrace napsané čistě kvůli tomu, aby obešli billing. Vy mezitím tratíte na vlastní efektivitě. Když snížíte latenci na polovinu, osekáte CPU čas o 40 % nebo přesunete endpoint z GPU boxu na levný CPU pool, náklady jdou dolů, ale revenue se podle toho nepohne. To je postavené na hlavu.

Compute je čistší jednotka. Když job spálí 2,4 CPU-sekundy, účtujte 2,4 CPU-sekundy. Když embedding run spotřebuje 180k input tokenů a 12k output tokenů, měřte přímo tohle. Když OCR pipeline zabere GPU na 900 milisekund a pak ještě 4 sekundy workeru při parsování tabulek, rozdělte metriku na GPU-sekundy a worker-sekundy. Zákazníci si pořád umí spočítat odhad, vy pořád umíte nacenit produkt jednoduše a faktura konečně odpovídá reálné spotřebě prostředků, ne nějaké náhodné HTTP události.

U AI produktů je to ještě důležitější, protože jeden request může znamenat úplně něco jiného. Krátký prompt proti gpt-4o-mini a extrakce z dvousetstránkového PDF přes vision model jsou technicky vzato oba jeden request. Brát je jako ekvivalent je nesmysl.

vyberte metriky, které sedí na náklady

Nepotřebujete doktorát z cloud ekonomiky. Stačí jedno pravidlo: účtovaná jednotka má těsně korelovat s vašimi infrastrukturními náklady a zároveň musí být dost čitelná na to, aby se v ní zákazník vyznal. U Django appky, která posílá joby přes Celery na Kubernetes, to obvykle znamená CPU-sekundy, worker-sekundy u memory-heavy workloadů, pokud vás limituje RAM, GPU-sekundy tam, kde dávají smysl, storage v GB za měsíc a tokeny, pokud přeprodáváte usage třetích modelů. Počet účtovaných dimenzí držte při zemi, protože každá další metrika je další zátěž pro support.

Praktické schéma pro AI pipeline na dokumenty může vypadat takhle. API ingress zdarma. Queueing zdarma. Každý job se účtuje podle worker runtime zaokrouhleného na 100 ms, GPU runtime zaokrouhleného na 100 ms, model tokenů podle skutečné spotřeby a storage dokumentů po 30denním okně, které je v ceně. Levná extrakce textu z PDF může spolknout 0,8 worker-sekundy a žádné GPU. Naskenovaná faktura s detekcí tabulek může sežrat 1,2 GPU-sekundy, 3,6 worker-sekundy a k tomu 24k model tokenů na klasifikaci a post-processing. To se mapuje přímo na náklady.

Pricing tiers jsou pak přímočaré. Starter: 3 600 worker-sekund a 250k tokenů měsíčně v ceně. Growth: 36 000 worker-sekund, 5M tokenů, nižší sazba za overage. Scale: committed spend, vlastní concurrency capy, reserved GPU pool. Důležité je, že kvóty odrážejí rozpočet na prostředky, ne náhodný počet callů. Zákazníci, kteří píšou efektivní prompty, deduplikují práci a zastaví retry stormy, mají být zvýhodnění. Přesně tak to má být.

Nemám trpělivost s vendory, kteří schovávají hnusnou nákladovou strukturu za kredity bez pevného převodu. Ten převod prostě zveřejněte. Když už jste na kreditech závislí, napište, že 1 worker-hour je 3 600 kreditů. Ještě lepší je kredity úplně vyhodit a ukazovat na každé faktuře syrové jednotky. Lidi čísla zvládnou.

měření bez hádání

Na instrumentaci se týmy typicky zaseknou víc, než je nutné. První den fakt nepotřebujete bespoke event pipeline. Začněte s OpenTelemetry na traces a metrics, Prometheem na scraping a jednou append-only usage tabulkou v PostgreSQL, kam budete zapisovat finalizované účtovatelné události. Traces vám pomůžou rozpočítat náklady napříč request chainem, Prometheus ukáže agregované chování a usage tabulka bude billing source of truth, protože faktury se nemají opírat o scrape interval po 15 sekundách.

Pro Python služby jsou opentelemetry-sdk==1.25.0, opentelemetry-instrumentation-django==0.46b0, opentelemetry-instrumentation-celery==0.46b0 a prometheus-client==0.20.0 úplně v pohodě start. Přidejte middleware, který do aktivního span zapíše account_id, job_id a plan_code. V Celery zachyťte task_prerun a task_postrun, spočítejte wall time a pak uložte účtovatelné worker-sekundy až po dokončení tasku, aby retry omylem nedvojpočítaly nedokončenou práci.

Úplně normální schema vypadá takhle:

sql
1create table usage_events (
2 id bigserial primary key,
3 account_id bigint not null,
4 job_id uuid,
5 meter_code text not null,
6 quantity numeric(18,6) not null,
7 unit text not null,
8 occurred_at timestamptz not null,
9 idempotency_key text not null unique,
10 metadata jsonb not null default '{}'::jsonb
11);
12create index idx_usage_events_account_time on usage_events(account_id, occurred_at);

A odpovídající sada Prometheus metrik může být až nudně obyčejná, což je přesně to, co chcete:

python
1from prometheus_client import Counter, Histogram
2
3worker_seconds = Counter(
4 "billable_worker_seconds_total",
5 "Finalized billable worker runtime",
6 ["account_id", "plan_code"]
7)
8
9gpu_seconds = Counter(
10 "billable_gpu_seconds_total",
11 "Finalized billable GPU runtime",
12 ["account_id", "model"]
13)
14
15task_duration = Histogram(
16 "task_duration_seconds",
17 "Task runtime",
18 ["task_name"],
19 buckets=(0.1, 0.25, 0.5, 1, 2, 5, 10, 30, 60)
20)

Dvě tvrdá pravidla. Každá usage událost potřebuje idempotency key, protože billing bugy způsobené duplicitními consumery jsou trapné a drahé. Druhé pravidlo: usage finalizujte na hranici, kde je práce hotová a jde jednoznačně přiřadit. Když se později pokusíte dopočítat faktury z logů, skončíte u vysvětlování chybějící položky větou retention expired in Loki. To je věta, kterou žádný zákazník nemá nikdy slyšet.

pricing, který se dá předvídat

Foundeři často slyší „compute-based pricing“ a okamžitě postaví pricing page, kterou může mít rád jen procurement analytik: šest metrík, dvacet poznámek pod čarou a kalkulačka, na kterou potřebujete další kalkulačku. Takhle ne. Uvnitř firmy klidně měřte s maximální přesností. Navenek to zabalte do dvou nebo tří konceptů, kterým zákazníci už teď rozumí.

Model, který mám rád, jsou kvóty v ceně plus explicitní overage. Když třeba prodáváte AI backoffice tool postavený na Next.js, Django, PostgreSQL a worker fleetě za queue, může veřejný plán říkat: 10 000 dokumentů měsíčně v ceně, až 50 worker-hours a 2M model tokenů, overage za 0,12 € za worker-minutu a 1,80 € za milion tokenů. Pod kapotou jsou dokumenty jen reporting lens, billing se pořád vypořádává podle worker času a tokenů. PM dostane metriku hodnoty, o které může mluvit, finance dostane metriku nákladů, která se nerozjíždí.

U produktů, které hodně stojí na API, dobře funguje i jiný model: měsíční platform fee plus usage buckets. Třeba 499 € zahrnuje 20 000 worker-sekund a 1M tokenů, potom jedou overage lineárně. Linearita je důležitá. Zákazníci nesnáší cliffy. Volume discount dává smysl na úrovni accountu nebo přes committed use, ale sleva má vycházet z predikovatelnosti, kterou získáte pro capacity planning, ne z nějakého pricing divadla.

Ukazujte usage skoro v reálném čase. Každý seriózní produkt by měl mít billing page s grafem rozpadnutým podle metrík, denními součty, month-to-date odhadem faktury a hlavními cost drivery. Když jeden tenant propálí polovinu měsíčního rozpočtu, protože background sync loop mlátí do endpointu každé 3 sekundy, dashboard to má ukázat dřív, než to skončí v support inboxu. Takové portály jsme ve Steezr pro klienty stavěli, schválně na nudném stacku: PostgreSQL materialized views pro denní rollupy, Django admin action na úpravy, HTMX na rychlé filtrování, žádný přepálený billing microservice cirkus. Nudné systémy přežijí billing month close.

jak migrovat stávající zákazníky

Migrace z pricingu per request chce politický cit, protože zákazník slyší „změna ceny“ a automaticky si řekne, že jste jen našli nový způsob, jak mu naúčtovat víc. Když to uděláte blbě, bude mít pravdu. Čistá cesta je dual metering aspoň po dobu jednoho celého billing cyklu, ideálně dvou. Dál účtujte podle starého modelu, ale paralelně zapisujte compute usage. Každému zákazníkovi pak pošlete shadow invoice, kde bude srovnání staré a nové faktury a normálně lidsky vysvětlený rozdíl.

Chcete věty typu: „Vaše usage za březen byla 1,8M requestů, včetně retry loopu z jedné integrační úlohy. Při compute billingu byste platili za 14,2 worker-hours a 320k tokenů, celkem 184 € místo 690 €.“ Tohle buduje důvěru, protože zákazník na první pohled vidí, že starý model byl hloupý. Některé accounty pod compute billingem zaplatí víc, hlavně ty, které posílají drobné requesty ve vysoké frekvenci a vás skoro nic nestojí. Dejte jim přechodový kredit nebo 90denní strop na sazbu. Cíl je srovnat incentivy, ne zapálit revenue.

Provozní pravidlo je jednoduché: přidejte verzovaný pricing engine. Nikdy nepřepisujte historickou rating logiku. pricing_version=v1_request a pricing_version=v2_compute musí existovat v kódu i v invoice záznamech. Když se finance zeptají, proč se invoice INV-2025-03-104 liší od INV-2025-04-021 při stejném chování zákazníka, potřebujete lepší odpověď než „změnili jsme to“. Stačí malá Python funkce:

python
1def rate_event(event, pricing_version):
2 if pricing_version == "v1_request":
3 return Decimal("0.0004") if event.meter_code == "api_request" else Decimal("0")
4 if pricing_version == "v2_compute":
5 rates = {
6 "worker_second": Decimal("0.0020"),
7 "gpu_second": Decimal("0.0180"),
8 "token_1m": Decimal("1.80"),
9 }
10 return rates[event.meter_code] * event.quantity
11 raise ValueError(f"unknown pricing version: {pricing_version}")

Ještě jedna věc: ošklivé detaily komunikujte dřív, než se z nich stanou drby. Jasně popište rounding policy, minimální účtovací krok, jak řešíte retry, jak řešíte failed joby a co se děje při outage u providera. Když failed OpenAI call vrátí 429 Rate limit reached for gpt-4o-mini a vy retrynete třikrát, rozhodněte se, jestli jsou ty tokeny jako pass-through billable, a napište to do dokumentace. Nedůvěra v billing roste přesně tam, kde je nejasno.

kde se to láme

Compute billing není magie a existují případy, kdy per request pořád dává smysl. Když máte těsné rozložení nákladů na endpoint, requesty jsou homogenní a zákazníky primárně zajímají počty transakcí, protože tak měří svůj business volume, účtování per request může být úplně v pohodě. Webhook relay s malými payloady a stabilním časem zpracování nepotřebuje GPU-sekundy ani token ledger. Používejte úsudek.

Problém nastává ve chvíli, kdy si tým vymyslí falešnou přesnost. Účtovat přesné CPU cykly uvnitř hlučného multi-tenant container setupu zní chytře jen do momentu, kdy Linux scheduling jitter a contention na pozadí udělají z čísel něco, co nejde rozumně vysvětlit. Wall-clock worker-sekundy se chápou mnohem líp. Totéž platí pro paměť. Nevymýšlejte „GB-milisekundy“, pokud paměť opravdu není váš hlavní cost driver a dokážete to měření obhájit. Většina týmů má držet model dostatečně hrubý a dostatečně přesný, ne akademicky čistý.

Jinak se mění i ochrana proti abuse. U pricingu per request je spam drahý pro zákazníka. U compute billingu může být spam levný, když request failne hned. Budete potřebovat poctivé rate limity, queue kvóty a concurrency capy. V NGINX to může být klidně tak prosté jako limit_req_zone $binary_remote_addr zone=api:10m rate=20r/s;, a na aplikační vrstvě pak vynucovat tenant-level limity na souběžné joby podle plánu. Billing a admission control spolupracují. Jedno nenahrazuje druhé.

Hlavní pointa je jednoduchá: pricing má odměňovat efektivní software na obou stranách API. Billing per request dělá pravý opak ve chvíli, kdy zákazníci hodně automatizují. Compute-based billing tohle opravuje, vaše náklady sledují skutečné usage, zákazníci přestanou stavět bizarní workaroundy jen kvůli nižšímu počtu callů a produktová rozhodnutí se dělají snáz, protože účtovací jednotka konečně odpovídá času na mašinách, který opravdu platíte.

Johnny Unar

Napsal/a

Johnny Unar

Chcete s námi spolupracovat?

Účtování per request trestá automatizaci a odměňuje plýtvání. Měřte compute a ekonomika vašeho SaaS se přestane chovat jako bug.