How ratings are computed
Every offer in the Volksdroid catalog is rated by a single, deterministic value model. The model answers one question a builder actually has: what is this free tier worth, in dollars, compared with everything else in its class? No number is hand-set. Each rating is computed by a script from observed inputs and a fixed set of reference prices, and recomputed on every build.
This document is the on-site mirror of the implemented spec. The authoritative
sources are docs/value-model.md, the scoring scripts in scripts/, and the
reference prices in src/data/reference-prices.ts.
1. The shape of the model
The pipeline runs the same three steps for every offer:
- Derive the access bucket —
free,freemium, orpaid— from the offer’s pricing model and its typed limitations. The bucket is computed, never chosen by hand. - Shadow-price the free allowance into a dollar value: what would this cost at a reference market rate?
- Rank the value against every other offer in the same bucket and category, and turn that rank into a 1–10 score by percentile.
You always compare like with like: free against free, freemium against freemium, paid against paid — never one global number across buckets.
2. Where every number comes from: RAW, CALC, PARAM
Every value in the system carries exactly one origin, and the three are kept physically separate.
| Origin | Meaning | Rule |
|---|---|---|
| RAW | Observed from an official source. | Carries a proof URL. Never derived. |
| CALC | Produced by the pipeline from RAW inputs via a documented formula. | Never hand-entered. Recomputed on every build. |
| PARAM | A global methodology constant (e.g. a reference price). | Defined once, applied uniformly. |
A CALC number cannot exist without its RAW inputs — the pipeline simply will not emit a score for an offer whose underlying quantities are missing. This is what keeps the ratings honest: there is no score floating free of the data behind it.
The * marker. Anywhere a CALC value is shown — on a card, in a table, in this
documentation — it carries a trailing asterisk, read as “computed, not observed.”
RAW values render plain and link to their proof. So value* $25/mo means the
dollar figure was computed; 7.5M tokens/mo (no star) means it was read off the
provider’s own page.
3. The three access buckets, and how the bucket is derived
The bucket answers: “Can literally anyone use this for free, indefinitely?” It is
derived from the pricingModel field plus the offer’s typed limitations by one
function, deriveBucket.
| Bucket | Rule |
|---|---|
| free | A perpetual free path with no up-front gate and no expiry: pricingModel ∈ {free_forever, open_source_selfhost}, with no barrier-class and no finite-class limitation. |
| freemium | A free path exists but carries a string: any barrier limitation (card, eligibility, minimum balance) or any finite limitation (one-time credit, trial, time-limited) or pricingModel ∈ {freemium, finite_credit, trial, byok, student, startup}. |
| paid | No usable free path. |
The mechanism is the limitation class. Every typed limitation belongs to one of
four classes (defined in src/data/generosity.ts), and the class — not the
limitation’s wording — decides what happens to the bucket:
| Class | Examples | Effect on bucket |
|---|---|---|
| barrier | card required, minimum balance, eligibility gate | Moves a free path into freemium. |
| finite | time-limited, one-time finite pool | Moves a free path into freemium. |
| quality | throttled, sleeps when idle, feature-limited, non-commercial, attribution | Stays in the bucket as a caveat; never moves it. |
| renewable | renewable quota, rate limit | Normal, expected; no bucket effect. |
So a tier that is genuinely free but throttled and non-commercial is still free —
those are quality-class caveats, not gates. A tier that needs a card on file, or
hands you a one-time credit, is freemium even if the allowance is large. Trial
and one-time credit always land in freemium. The full taxonomy, with every type’s
class and icon, is in
Free-tier conditions & limitations.
4. Shadow pricing: turning a free allowance into dollars
One engine powers every rating. It prices a free allowance at a reference market rate:
value = Σ ( free_quantity × reference_unit_price ) (one term per metered resource)
The dollar is the only unit comparable across categories, so the same engine is combined three ways depending on the bucket:
| Bucket | What the shadow value is used as | What it catches |
|---|---|---|
| free | An absolute $/month of free capacity. | ”This tier is $25/mo of inference, free.” |
| freemium | The allowance de-inflated to the reference rate. | Inflated vendor claims — a “$30 credit” priced at the vendor’s own rate is worth less at the market rate. |
| paid | shadow_value ÷ offered_price — a value-for-money ratio. | ”This $X plan includes $Y of capacity → ×N value.” |
For LLM providers the reference market is OpenRouter per-model prices, so model quality is baked into the price (frontier tokens are worth more). For every other infrastructure category the reference is a fixed per-unit rack rate, listed in section 8.
5. The 1–10 score is a percentile
A dollar value is meaningful only relative to the field. The model converts value into a 1–10 score by percentile rank within the cohort (same bucket, same category):
score = 1 + 9 · ( b / (n − 1) ) (b = offers this one beats on the metric,
n = number of offers in the cohort)
Read plainly: line up every comparable offer by the metric. An offer that beats
none scores 1; one that beats all n − 1 others scores 10; one exactly in the
middle scores 5.5. The b / (n − 1) fraction is just “what share of the field did
this offer beat.” Because the score is a rank, the catalog never clumps at the top —
the full 1–10 range is always used.
6. The four LLM ratings
LLM providers carry four percentile ratings. They use the identical formula above; they differ only in which metric is ranked. The cohort for each is the set of free + freemium LLM providers that have the relevant metric.
| Rating | Metric ranked | Unit |
|---|---|---|
| Overall | Shadow value ($/mo for renewable tiers; one-time $ for credits). | $ |
| Volume | Effective free tokens per month, T_eff. | tokens/mo |
| Artificial Analysis | Artificial Analysis score of the best free model. | index |
| Throughput | Free-tier tokens per minute. | tokens/min |
The Overall rating is the headline score shown on the card; the other three are the breakdown behind it.
Computing the inputs
The dollar value for an LLM tier needs two computed quantities: effective capacity
T_eff and a reference price ref_price.
Reference price. Look up the provider’s best_free_model on OpenRouter and take
a blend weighted toward input tokens (a chat request is roughly 75% prompt, 25%
completion):
ref_price = 0.75 · P_in + 0.25 · P_out (P_in, P_out = OpenRouter $/M tokens
of the best free model)
OpenRouter’s :free promo variants are skipped — pricing a model at $0 would make
its tokens worth nothing — so the real market rate is always used.
Effective capacity T_eff is the narrowest monthly token bottleneck. Only
published token ceilings are converted to tokens per month; request caps remain
request-rate/request-volume signals and are not priced as token capacity:
C_cap = free_tokens_per_month
C_tpm = tokens_per_minute × 43 200
C_tpd = tokens_per_day × 30
T_eff = MIN( the C_* whose RAW inputs exist )
For a renewable tier the value is then:
value = T_eff × ref_price
For a credit tier the credit is the ceiling, not the rate. The capacity is the credit divided by the vendor’s own price, and the value is de-inflated to the reference rate:
T_credit = credit_usd / vendor_price
value = credit_usd × ( ref_price / vendor_price ) (de-inflated to OpenRouter)
Worked example — Google Gemini (free, renewable)
Using the verified frontmatter of the Google Gemini entry:
- RAW:
free_tokens_per_month = 7,500,000,requests_per_day = 250,tokens_per_minute = 250,000,best_free_model = Gemini 3.5 Flash(Artificial Analysis 50). - OpenRouter price of Gemini 3.5 Flash:
P_in = $1.50/M,P_out = $9.00/M.
Reference price:
ref_price = 0.75 · P_in + 0.25 · P_out
= 0.75 · 1.50 + 0.25 · 9.00
= 3.375 ($/M tokens)*
Effective capacity — the explicit monthly cap is the binding bottleneck:
T_eff = MIN( C_cap, C_tpm, C_rpd )
= MIN( 7 500 000, 250 000·43 200, 250·1000·30 )
= MIN( 7 500 000, 10 800 000 000, 7 500 000 )
= 7 500 000 (tokens/mo)*
Value:
value = T_eff × ref_price
= ( 7 500 000 / 1 000 000 ) × 3.375
= 25.31 ($/mo)*
The four ratings (the “beaten” counts b and cohort sizes n are the live
computed values):
Overall score = 1 + 9 · ( b / (n − 1) ) (value $25.31/mo)
= 1 + 9 · ( 27 / 47 ) (b = 27, n = 48)
= 6.2*
Volume score = 1 + 9 · ( 14 / 35 ) (T_eff 7.5M tok/mo; b = 14, n = 36)
= 4.6*
Artificial Analysis score = 1 + 9 · ( 18 / 47 ) (Artificial Analysis 50; b = 18, n = 48)
= 4.4*
Throughput score = 1 + 9 · ( 7 / 12 ) (250K tok/min; b = 7, n = 13)
= 6.2*
The headline Overall score is 6.2.
Worked example — Baseten (freemium, one-time credit)
A credit tier shows the de-inflation step. From the Baseten entry:
- RAW:
credit_amount_usd = 30,vendor_price_in = $1.50/M,vendor_price_out = $4.50/M,best_free_model = GLM 5.2. - OpenRouter reference price of GLM 5.2:
ref_price = $1.925/M.
vendor_price = 0.75 · 1.50 + 0.25 · 4.50
= 2.25 ($/M tokens)
value = credit_usd × ( ref_price / vendor_price )
= 30 × ( 1.925 / 2.25 )
= 25.67 ($ one-time, de-inflated)*
The vendor’s “$30 of credit” is worth $25.67 once re-priced at the market rate — the de-inflation strips out the vendor’s own list-price inflation. Within the freemium “one-time credits” cohort this earns an Overall score of 6.4.
7. Freemium sub-tops
Freemium offers are not all comparable on one axis: a $10k one-time startup credit and a small renewable-but-student-gated tier are different things. Freemium is therefore split into sub-tops by condition type, and the percentile is computed within each sub-top:
- credits — one-time credit pools (ranked by de-inflated dollar value).
- programs — eligibility programs (
student,startup). - renewable — everything else freemium (e.g. card-gated renewable tiers).
Free has a single ranking per category; paid is ranked by the value-for-money ratio.
8. Reference prices for non-LLM categories
Outside LLMs, the same value = Σ(quantity × price) engine is used, but the
per-unit price is a fixed market rack rate (PARAM) rather than an OpenRouter
lookup. These are defined with sources in src/data/reference-prices.ts:
| Category | Resource | Reference price | Source |
|---|---|---|---|
| Storage | Object storage | $0.023 / GB-month | AWS S3 Standard |
| Storage | Egress | $0.09 / GB | AWS first-tier data transfer out |
| Serverless functions | Invocations | $0.20 / 1M requests | AWS Lambda |
| Serverless functions | Compute | $0.0000166667 / GB-second | AWS Lambda (x86) |
| App platforms | vCPU compute | $0.05 / vCPU-hour | Google Cloud Run |
| App platforms | Memory | $0.005 / GiB-hour | Google Cloud Run |
| App platforms | Bandwidth | $0.09 / GB | AWS first-tier egress |
| Databases | DB storage | $0.30 / GB-month | Managed Postgres (Supabase/Neon class) |
| Databases | Reads | $0.001 / 1M rows read | Cloudflare D1 |
| Databases | Writes | $1.00 / 1M rows written | Cloudflare D1 |
| Schedulers | Scheduled runs | $0.20 / 1M invocations | AWS Lambda (a cron run ≈ an invocation) |
| Schedulers | Compute | $0.05 / vCPU-hour | Google Cloud Run |
| Workspaces | Seat | $12.00 / seat-month | Typical team-SaaS seat (mid-market) |
| Agent deployment | Agent runs | $0.20 / 1M runs | AWS Lambda proxy |
| Domains | .com / year | $13.00 / domain-year | Typical retail .com (Namecheap/GoDaddy list) |
These prices are deliberately mainstream rack rates, so the value means “what this would cost at a typical market rate,” not the cheapest possible price.
The three non-LLM value forms
free / freemium-renewable value = Σ ( free_quantity × reference_unit_price ) ($/mo)
paid value = allowance_value ÷ offered_price (×, value-for-money)
domains value = max( 0, reference_retail − offered_price ) ($/yr saved)
A free serverless tier of, say, 1M invocations plus a slice of GB-seconds is summed
term by term into a monthly dollar figure. A paid entry is rated by how much
allowance value its price buys — the ratio, not the absolute, so a cheap plan with a
fat allowance ranks above an expensive one. Domains are special: the price is
the metric, so they are rated by yearly savings against a reference retail .com
price of $13/year.
Each non-LLM value, like the LLM value, is then percentile-ranked within its
{bucket, category} cohort by the same score = 1 + 9·(b/(n−1)) mechanic.
9. The commercial-use rule
Whether a free tier may be used commercially is a hard fact a builder needs at a
glance, so it is always surfaced as a mandatory badge — green when commercial
use is allowed, red when it is forbidden — never left implicit. A
non-commercial restriction is a quality-class limitation (no_commercial_use): it
does not move the offer out of its bucket, but it is always shown. An offer can
be genuinely free and non-commercial; the badge makes sure you know which.
10. What a rating is and is not
- It rates the free offer, not the product. A great paid product can have a stingy free tier (low score), and vice versa.
- It is not a substitute for reading the limitations. Two offers can share a score for very different reasons; the typed limitations tell you which constraints apply to your use case.
- It is not static. Reference prices and provider numbers change; every CALC value is recomputed from RAW inputs on each build, and RAW inputs are refreshed as providers update their pages.
Where the numbers live
Each offer’s markdown frontmatter carries a managed valueModel block written by
the scoring scripts, with raw, quantities/calc, and the derived bucket. Every
field under calc is a CALC value and renders with a *. The rubric metadata — the
limitation taxonomy and the reference prices — lives in code at
src/data/generosity.ts and src/data/reference-prices.ts as the single source of
truth shared by the scripts, the catalog UI, and this document.