Model Pricing Configuration#
Overview#
Langfuse stores model pricing in PostgreSQL via Prisma using three related tables: Model, Price, and PricingTier . The system supports two pricing modes:
- Flat pricing — legacy
inputPrice/outputPrice/totalPricedecimal fields directly on theModelrecord. - Tiered pricing — condition-based
PricingTierrecords linked to granularPriceentries perusageType(added in November 2025).
Models with projectId = null are system-wide defaults; models scoped to a project via projectId override them for that project . Default models are shipped via Prisma migrations, not a seed file.
Database Schema#
Three Prisma models make up the pricing layer . The Model → PricingTier → Price hierarchy means every price is attached to a tier, even flat/legacy prices (which are backfilled into a default tier).
| Table | Key Fields | Notes |
|---|---|---|
models | modelName, matchPattern, startDate, inputPrice, outputPrice, totalPrice, unit, tokenizerId, tokenizerConfig | matchPattern is a regex used to resolve model names at ingestion time. unit is one of TOKENS, CHARACTERS, MILLISECONDS, SECONDS, REQUESTS, or IMAGES. |
pricing_tiers | modelId, name, isDefault, priority, conditions (JSONB) | conditions stores an array of match rules. Unique on (modelId, priority) and (modelId, name). |
prices | modelId, pricingTierId, usageType, price (Decimal), projectId | Unique on (modelId, usageType, pricingTierId). projectId allows per-project price overrides. |
All three tables cascade-delete on parent removal .
Usage Types#
The usageType field on Price is a free-form string matched exactly against keys in the ingested usage_details map. Supported values across providers include:
usageType | Description |
|---|---|
input | Standard input tokens |
output | Standard output tokens |
total | Total token cost (when not split) |
input_cached_tokens | Cached input tokens (OpenAI) |
input_cache_creation | Anthropic cache creation (default TTL) |
input_cache_creation_5m | Anthropic 5-min TTL cache creation |
input_cache_creation_1h | Anthropic 1-hour TTL cache creation |
input_cache_read | Bedrock cache read tokens |
input_cache_write | Bedrock cache write tokens |
output_reasoning_tokens | OpenAI o1/o3 reasoning tokens |
accepted_prediction_tokens | OpenAI accepted prediction tokens |
rejected_prediction_tokens | OpenAI rejected prediction tokens |
⚠️ Exact-match gotcha: Cost calculation matches
usageTypeby strict string equality againstusage_detailskeys . If the provider SDK emits a raw key (e.g.,cache_read_input_tokens) that doesn't match the pricing entry key (input_cached_tokens), that bucket is silently priced at zero. This caused a known undercount for GPT-5.6 Sol/Terra/Luna models .
Tiered Pricing Mechanism#
Each PricingTier holds a conditions JSONB array. Each condition has the shape :
{ usageDetailPattern: string, operator: "gt"|"gte"|"lt"|"lte"|"eq"|"neq", value: number, caseSensitive: boolean }
At cost calculation time, matchPricingTier() :
- Iterates non-default tiers in ascending
priorityorder. - For each tier, compiles
usageDetailPatternas a regex, sums all matchingusage_detailskeys, and evaluates the operator+threshold (AND logic across conditions). - Returns the first matching tier; falls back to the
isDefault = truetier if none match.
Each winning tier owns a set of Price records — one per usageType. calculateUsageCosts() then multiplies price × units for each key .
User override: if any provided_cost_details key is set on the observation, automatic cost calculation is bypassed entirely .
Management APIs and Entry Points#
Public REST API#
GET /api/public/models— list all models (system + project-scoped) with their pricing tiers.POST /api/public/models— create a custom model with flat or tiered pricing.GET /DELETE /api/public/models/[modelId](source) — fetch or delete a specific model.
Internal tRPC Router#
web/src/server/api/routers/models.ts exposes upsert, getById, getAll, delete, and testMatch procedures. upsert deletes existing pricing tiers before writing new ones — i.e., tier updates are full replacements .
Default Model Definitions#
System-default models are added exclusively via Prisma migrations in packages/shared/prisma/migrations/. Notable migration milestones:
20241024100928_add_prices_table— introduced thepricestable.20251127105316_add_pricing_tiers— addedpricing_tierstable; backfilled existing prices into default tiers.20250711105322_prices_add_project_id— enabled per-project custom pricing.20240913095558_models_add_openai_o1— added o1 reasoning models (no tokenizer config because reasoning output cannot be locally tokenized).
Model Matching#
findModel() resolves an incoming model name string against matchPattern regexes. Results are cached in Redis and local memory to minimize DB round-trips during high-throughput ingestion.