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:

  1. Derive the access bucketfree, freemium, or paid — from the offer’s pricing model and its typed limitations. The bucket is computed, never chosen by hand.
  2. Shadow-price the free allowance into a dollar value: what would this cost at a reference market rate?
  3. 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.

OriginMeaningRule
RAWObserved from an official source.Carries a proof URL. Never derived.
CALCProduced by the pipeline from RAW inputs via a documented formula.Never hand-entered. Recomputed on every build.
PARAMA 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.

BucketRule
freeA 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.
freemiumA 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}.
paidNo 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:

ClassExamplesEffect on bucket
barriercard required, minimum balance, eligibility gateMoves a free path into freemium.
finitetime-limited, one-time finite poolMoves a free path into freemium.
qualitythrottled, sleeps when idle, feature-limited, non-commercial, attributionStays in the bucket as a caveat; never moves it.
renewablerenewable quota, rate limitNormal, 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:

BucketWhat the shadow value is used asWhat it catches
freeAn absolute $/month of free capacity.”This tier is $25/mo of inference, free.”
freemiumThe 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.
paidshadow_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.

RatingMetric rankedUnit
OverallShadow value ($/mo for renewable tiers; one-time $ for credits).$
VolumeEffective free tokens per month, T_eff.tokens/mo
Artificial AnalysisArtificial Analysis score of the best free model.index
ThroughputFree-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:

CategoryResourceReference priceSource
StorageObject storage$0.023 / GB-monthAWS S3 Standard
StorageEgress$0.09 / GBAWS first-tier data transfer out
Serverless functionsInvocations$0.20 / 1M requestsAWS Lambda
Serverless functionsCompute$0.0000166667 / GB-secondAWS Lambda (x86)
App platformsvCPU compute$0.05 / vCPU-hourGoogle Cloud Run
App platformsMemory$0.005 / GiB-hourGoogle Cloud Run
App platformsBandwidth$0.09 / GBAWS first-tier egress
DatabasesDB storage$0.30 / GB-monthManaged Postgres (Supabase/Neon class)
DatabasesReads$0.001 / 1M rows readCloudflare D1
DatabasesWrites$1.00 / 1M rows writtenCloudflare D1
SchedulersScheduled runs$0.20 / 1M invocationsAWS Lambda (a cron run ≈ an invocation)
SchedulersCompute$0.05 / vCPU-hourGoogle Cloud Run
WorkspacesSeat$12.00 / seat-monthTypical team-SaaS seat (mid-market)
Agent deploymentAgent runs$0.20 / 1M runsAWS Lambda proxy
Domains.com / year$13.00 / domain-yearTypical 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.