Jev Cost and Latency: Real Pricing Math and Budgets
Judgment work is high-volume by nature — every comment, every ticket, every chunk — so the per-call price and the per-call latency compound fast. The good news: Jev’s economics are built for exactly this shape of workload. This guide walks through the pricing math at the publicly listed rate, compares it structurally with general LLM calls, and gives you latency budgets and batching patterns for the two most common high-volume uses: moderation and reranking.
TL;DR: At the listed rate of about $0.0462 per 1M input tokens (third-party listing data — confirm on the OpenRouter model page), a million short judgment calls cost tens of dollars, dominated by input tokens because outputs are tiny structured objects. Against a general chat model doing the same job with prose answers, the saving is structural, not marginal. For latency, budget per-call time, run independent calls concurrently, and batch reranking work.
The pricing math
The reference price for this guide is $0.0462 per 1M input tokens, as listed by third-party trackers for Jev on OpenRouter at the time of writing. That number will move — always confirm current pricing on the OpenRouter model page before you commit a budget.
| Workload | Prompt size | Calls / month | Input tokens / month | Approx. input cost |
|---|---|---|---|---|
| Comment moderation, small site | ~200 tokens | 100,000 | 20M | ~$0.92 |
| Comment moderation, large site | ~200 tokens | 5,000,000 | 1,000M | ~$46 |
| RAG chunk reranking (10 chunks/query) | ~150 tokens/chunk | 500,000 queries | 750M | ~$35 |
| Support ticket triage | ~400 tokens | 200,000 | 80M | ~$3.70 |
Reading the table: at these rates, input-side cost is rarely the constraint — a busy moderation pipeline lands in the tens of dollars per month. Two caveats keep the math honest. First, output tokens are also billed (at the rate shown on the model page); Jev’s structured short answers keep that line small, which is precisely the structural advantage over prose answers. Second, these are third-party listing figures; the official TypeSafe AI channel’s pricing is documented separately — check typesafe.ai.
The structural comparison with a chat model
The same judgment asked of a general chat model differs in kind, not just in degree:
| Cost driver | General LLM | Jev |
|---|---|---|
| Input tokens | Your question plus the item | Same — the dominant cost for both |
| Output tokens | A sentence or paragraph per call | A tiny structured object (example fixture shape) |
| Parsing failures | Retries, defensive code, occasional human cleanup | Rare — the answer space is bounded |
| Escalation handling | Often improvised | Built-in: confidence + unclear route low-certainty items out |
The output line is where chat models bleed on judgment tasks: you pay generation prices for prose that distills to one bit or one number. With Jev the answer arrives as a short structured object — {"answer":"yes","confidence":0.97,"rationale":"..."} is the example fixture shape — so the generation cost per decision shrinks to near the floor.
Latency: budgeting and patterns
A single Jev call behaves like any OpenAI-compatible chat call: network round trip plus model time. What matters is the shape of your workload:
- Single gate checks (one call per event): budget for the p95, not the mean, and decide what the fallback is when the call is slow — queue, skip, or default-deny.
- Reranking pipelines (N calls per query): never serialize. The ten chunks of a RAG query are independent judgments; fire them concurrently and the wall time is one call, not ten.
- n8n and workflow tools: keep the HTTP timeout generous (30s) and make the node idempotent so a timeout retry does not double-judge.
A concurrent reranking sketch in Python:
import concurrent.futures, json, os, requests
def judge_chunk(chunk: str) -> dict:
# Confirm the exact model slug on the OpenRouter model page
resp = requests.post(
"https://openrouter.ai/api/v1/chat/completions",
headers={"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}"},
json={
"model": "typesafe/jev-1.13",
"messages": [{"role": "user", "content": f"Scoring question (1-10): how relevant is this chunk to the query? Chunk: \"{chunk}\""}],
},
timeout=30,
)
return json.loads(resp.json()["choices"][0]["message"]["content"])
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as pool:
scores = list(pool.map(judge_chunk, chunks))
Each element of scores is an example fixture — the response shape shown is illustrative and official field names should be confirmed in the official documentation. Sort your chunks by the returned answer once the pool completes.
Budgeting checklist
- Measure your real prompt size — it is almost always larger than you think; multiply calls by measured tokens, not guessed ones.
- Price both sides: input at the listed rate, output at the model page’s current rate.
- Add the escalation cost: at an 0.8 confidence threshold, some share of calls becomes human work — that line item usually dwarfs the token bill.
- Re-check prices quarterly; listing rates move.
The RAG chunk rerank batch case applies this math end to end, and the channel comparison guide notes where official-channel pricing may differ from marketplace listings.
Token billing in detail: three price tiers
Most API pricing pages list one input rate and one output rate, but OpenAI-compatible providers including OpenRouter typically expose a third line: cache-hit tokens, billed at a fraction of the standard input rate. The three-tier structure looks like this:
| Token type | Example rate | When it applies |
|---|---|---|
| Input (standard) | $0.0462 / 1M | First time a prompt prefix is seen |
| Output | ~$0.18 / 1M (verify on model page) | Every generated response token |
| Cache-hit input | ~$0.0046 / 1M (~10× cheaper) | When the provider’s KV cache covers the prefix |
For Jev, the output is structurally short — a 20–40 token JSON object rather than prose — so the output line is rarely the budget concern. Input dominates. At a 200-token prompt and $0.0462/1M, each call costs about $0.0000092. Run 5 million calls per month and the input bill lands near $46. That arithmetic is the starting point; layering in cache hits cuts it further when your prompts share a long system-prompt prefix.
To see what you are paying per token type, log the usage field on every response:
resp = client.chat.completions.create(...)
usage = resp.usage
print(usage.prompt_tokens, usage.completion_tokens,
getattr(usage, "prompt_tokens_details", {}))
prompt_tokens_details (where the provider returns it) breaks down cached vs uncached input tokens. Tracking this ratio weekly tells you whether your prompt structure is cache-friendly. See making your first API call for the basic request shape before adding instrumentation.
Latency broken down: time to first token and total time
Latency has two components that matter differently depending on the use case.
Time to first token (TTFT) is the pause before the model starts sending output — driven by network round trip, queue depth on the provider side, and the model’s prefill time on the prompt. For a short 200-token Jev prompt, TTFT typically lands in the 200–600 ms range under normal load, rising to 1–2 s during congested periods.
Total time to completion is TTFT plus generation time. Because Jev’s output is short (20–40 tokens), generation adds 50–150 ms at most, so total latency is almost entirely TTFT.
Streaming changes perceived experience even when it does not change total time. If you open a streaming connection, your application receives the first JSON tokens within TTFT and can begin partial processing — or simply dismiss a spinner — before the full object arrives. For synchronous pipeline steps (a rerank gating a database lookup) streaming offers no practical benefit; for UI surfaces it cuts perceived wait by several hundred milliseconds.
To measure both components:
import time, requests
start = time.perf_counter()
resp = requests.post(url, headers=headers, json=payload, stream=True)
first_chunk_time = None
chunks = []
for chunk in resp.iter_content(chunk_size=None):
if first_chunk_time is None:
first_chunk_time = time.perf_counter() - start
chunks.append(chunk)
total_time = time.perf_counter() - start
print(f"TTFT: {first_chunk_time*1000:.0f}ms Total: {total_time*1000:.0f}ms")
Record both metrics per request in your observability store; the gap between p50 and p95 TTFT is your headroom for SLA-setting.
Cutting costs 30–50% with batching and off-peak windows
Two levers reliably reduce per-call cost without touching your prompt structure.
Batch endpoints — where the provider offers them — accept a list of requests in one HTTP call and process them with higher throughput efficiency. If you call Jev through a provider that exposes a dedicated batch API (or through TypeSafe AI’s official channel), batching 50–200 requests into one call can cut effective per-call cost by 30–50% compared to individual async calls at the same volume. Check the provider’s batch pricing page; the discount is usually stated explicitly.
Off-peak windows apply on providers that offer time-based pricing tiers. Traffic on LLM inference providers drops overnight in US time zones; some providers pass that saving on as a discount of 25–40% on requests submitted between 22:00 and 06:00 UTC. For workloads that are not latency-sensitive — nightly content moderation sweeps, daily report generation, bulk reranking of archived documents — scheduling jobs in this window is the lowest-effort cost reduction available.
A practical pattern for non-urgent batch jobs:
import schedule, time
def run_nightly_rerank():
# runs at 02:00 UTC, inside the off-peak window
results = process_batch(pending_items)
store_results(results)
schedule.every().day.at("02:00").do(run_nightly_rerank)
while True:
schedule.run_pending()
time.sleep(60)
Combine both levers — batching during off-peak — and a moderation pipeline’s effective rate can drop from $46/month to under $25 without any prompt changes. For API access configuration, see getting your API key.
Prompt caching: the consistency gain and when it expires
Prompt caching keeps a computed key-value representation of a prompt prefix alive on the provider’s infrastructure so that subsequent requests sharing that prefix skip the full prefill computation. The benefit is twofold: cache-hit tokens are billed at roughly 10% of the standard input rate, and TTFT drops because the model jumps past the cached portion.
The consistency gain is less obvious but equally important. A long shared system prompt — your scoring rubric, your moderation policy text, your product taxonomy — is processed identically every time it hits from cache. There is no token-by-token re-encoding variation. That makes the prefix semantically stable across calls, which reduces subtle output variance caused by floating-point non-determinism during prefill.
Cache entries expire based on inactivity, not a wall-clock schedule. The exact TTL varies by provider — OpenRouter does not publish a guaranteed TTL — but typical values are 5–30 minutes of inactivity. Practical consequence: if your batches run 40 minutes apart, the second batch pays full input price. Keep batches tight, or send a small keep-alive request if your provider supports it.
Cache invalidation triggers whenever any token in the cached prefix changes, including whitespace. A common mistake is appending a timestamp or request ID inside the system prompt text. Move dynamic content to the user turn:
# wrong: breaks cache on every call
system = f"Moderation policy v2. Request ID: {req_id}"
# right: static system prompt stays cached
system = "Moderation policy v2."
user = f"Request ID: {req_id}\nContent: {content}"
See confidence scoring and fallback routing for patterns that combine stable system prompts with per-request user content.
Why fewer calls at a higher model cost often wins
When a model produces a wrong answer, the instinct is to retry at a lower temperature or route to a cheaper fallback for simple cases. Both strategies feel like cost control, but they frequently cost more in aggregate.
Retry loops compound cost without improving success rate predictably. If a model fails on a class of inputs, a second call is likely to fail the same way. Three retries at $0.0000092 each cost $0.0000276 per input — and you still have no answer. A single call to a model one tier up that handles the hard case reliably costs roughly $0.00005. More expensive per call, but zero retries means fewer total billed tokens and a definitive result.
Routing overhead adds hidden cost. A two-model architecture (cheap for easy, expensive for hard) requires a classification step to decide which model to use. That classification call itself costs tokens. If 20% of your traffic is “hard” and each routing classification costs $0.000002, the routing tax on a million calls is $2 — not catastrophic, but it erodes the saving from the cheaper model.
Practical threshold: if your p90 success rate on the primary model is below 85%, reprice a single-model upgrade before building a retry or routing layer. Run a two-week A/B comparing total tokens billed, not per-call price:
# instrument total token spend, not just per-call price
def call_with_retry(payload, max_retries=3):
total_tokens = 0
for attempt in range(max_retries):
resp = client.chat.completions.create(**payload)
total_tokens += resp.usage.total_tokens
result = parse_response(resp)
if result is not None:
return result, total_tokens
return None, total_tokens # still failed after retries
See troubleshooting guide for diagnosing consistent failure patterns before reaching for retries.
Monitoring cost and latency in production: p50, p95, and cost per request
Intuitions about latency and cost break down at scale. A mean latency of 400 ms can coexist with a p95 of 3,200 ms if a small fraction of calls hit a slow path — and that p95 is what determines whether downstream SLAs are met. Similarly, an average per-request cost can mask a class of long prompts that account for 40% of the monthly bill.
The minimum instrumentation worth adding to any production Jev integration:
| Metric | How to record | Why it matters |
|---|---|---|
| TTFT (ms) | Stream response; timestamp first chunk | SLA-setting, user experience |
| Total latency (ms) | Timestamp request start and response complete | End-to-end budget |
| Prompt tokens | resp.usage.prompt_tokens | Cost prediction |
| Completion tokens | resp.usage.completion_tokens | Near-constant for Jev |
| Cost per request | tokens × per-token rate | Budget dashboard |
| p50 / p95 latency | Aggregate over 1-hour windows | Headroom and alert thresholds |
A minimal logging hook:
def log_jev_call(resp, elapsed_ms: float):
tokens_in = resp.usage.prompt_tokens
tokens_out = resp.usage.completion_tokens
cost = (tokens_in * 0.0462 + tokens_out * 0.18) / 1_000_000
print(json.dumps({
"latency_ms": elapsed_ms,
"tokens_in": tokens_in,
"tokens_out": tokens_out,
"cost_usd": round(cost, 8),
}))
Pipe this to any time-series store (Datadog, Grafana, or a CSV) and compute p50/p95 latency plus daily cost per 1,000 requests. Alert when p95 latency exceeds 3× your p50 baseline — that ratio signals a provider issue or a runaway prompt-length class. For channel-level pricing differences that affect cost accounting, see API channel comparison.
This guide applies to Jev 1.13.