Skip to content

Jev Practices & Patterns

Batch decisions and backfills: reprocessing a corpus

Reprocessing a corpus is a different workload from serving one request. How to batch, fan out, and backfill decisions without blowing the budget.
Published
Category
Jev Practices & Patterns
Resources cited
11
Reading time
6 min
Tags#operations#batching#backfills#cost

A backfill is a data pipeline with a model in the middle. The corpus is fixed, the questions are known, and the output is a table of probabilities. That makes it much easier than online serving, and much easier to get subtly wrong, because a bad batch can rewrite months of decisions before anyone notices.

The discipline is the same one you would apply to a warehouse migration: define the unit of work, measure the cost, version every input, checkpoint, and validate on a sample before running the whole thing.

The unit is a request, not a row

The natural mental model is one row per decision. The billing model does not work that way. Jev bills input tokens, and the state is sent once per request, not once per question. So the efficient unit is one request per item with all the questions that item needs.

The parallel questions cookbook makes the gap concrete. It ran 13 questions over a 54,000-character document: one batched call cost $0.000497 and took 0.27 s; 13 single-question calls cost $0.006090 and 2.71 s. The answers were the same across five repeats. That is 12.2x cheaper and 10x faster, and the saving is the shared state.

For a backfill, this changes the shape of the job. You are not running one model call per row. You are running one call per row with a question set, and the question set should cover every branch the downstream logic might take. The speculative fan-out pattern is the design for that: ask the category plus the four judgments the branch might need, then ignore what the branch does not use.

Measure the fixed overhead

The fan-out benchmark measured 2,976 requests totaling $0.156 and found about 261 input tokens of fixed overhead on every request. At eight questions, median input-token savings were 76% on a tiny control state, 77% on a small state, 84% on a medium state, and 86% on a large state.

That 261-token floor is the reason very small items should be grouped carefully. If each item is a one-line record and you send one request per record, overhead can dominate the bill. If each item is a long document, overhead is noise and the state is the whole cost.

The benchmark also found that 1,000 questions succeeded in one call, and that context window limits bracketed 32,768 content tokens and 65,536 total. Those are empirical limits from an independent run, not a vendor guarantee. The models page states a 64k context covering 32k of state plus the longest question, which is consistent but not a promise.

For a backfill, estimate before you run. Count the tokens in a representative item and question set, multiply by the number of items, and compare that to the per-item cost you are replacing. The benchmark's full run sent about 2 million input tokens in roughly 15 minutes for about $0.09 at the published $0.042 per million input tokens. A corpus of 100,000 items is a different conversation.

Chunk by context, not by file

The tempting chunk is the file. The right chunk is the unit a question can judge. A 200-page PDF split at arbitrary page boundaries produces states that are individually incomplete and collectively redundant. A document split at section boundaries, with only the relevant section passed to the question, produces smaller states and better answers.

The jaggedness notes add a specific warning: counting is unreliable and error grows with size. Do not ask one question for the total number of items in a long document. Ask one Noul per item and sum in code. That changes the batch design from one request per document to one request per document with a question per item, which is exactly the fan-out shape the billing model rewards.

The API reference caps Choice at 255 options and Score at 2 to 10 levels. If a backfill has a candidate set larger than 255, pre-filter in code or run multiple passes. Do not compress the options into a free-text label and hope the model returns the one you meant.

Version the job, not just the model

A backfill is only reproducible if you can name every input: the model version, the question text, the criteria, the threshold, the pre-processing code, and the state assembly. Pinning jev-1.13.0 is necessary but not sufficient. A question wording change can move answers more than a model patch.

jev-workbench is a useful reference for the versioning discipline. Publishing a judgment function freezes the config and model version, requires a successful preview of exactly that config, and never changes under a caller. Grants pin a client token to specific function versions, so a new publish does not silently upgrade anyone. Whether or not you use the tool, copy the rule: a backfill runs against an immutable function version, not against whatever is live.

The Jev harness shows the same idea inside an agent. Its context picker asks 22 yes/no questions in one call, one per runbook section, and its gate classifies a tool call as read, additive, modify, or destroy. Every decision is logged with its numbers. That log is what makes a replay possible after a bad run.

Checkpoint and make retries idempotent

Backfills fail in the middle. A 429, a malformed state, a single record that exceeds the context, a process restart: any of these can leave the corpus half-processed. The job needs a durable record of which items completed and which did not.

Use the item id as an idempotency key and write the result before advancing the checkpoint. The LLM cost optimizer does this with SQLite WAL, atomic reservations, durable audit leases, and idempotency keys, and it permits at most two attempts. That is a reasonable default for a backfill: retry once for a transient error, then quarantine the item for inspection rather than looping.

The API reference says to retry only 429 and 529, with exponential backoff. A 422 is a caller error; retrying it wastes time and hides the bad record. Classify the error before deciding whether the checkpoint advances.

Validate on a stratified sample

Do not run the full corpus to discover that the question set is wrong. Run a stratified sample first: a few items from each source, language, document length, and label. Compare the batch output to a hand-labelled subset, and inspect the disagreements rather than only the accuracy number.

The workflow evals code is a usable harness for this. It runs four workflows (150 invoice cases, 204 customer-service cases, 111 agent traces, and 240 security incidents) against typesafe:jev-1.13.0 or another provider, with inputs and labels from Hugging Face. It is Apache-2.0, needs Python 3.13 or newer, and its README is explicit that the workflow code is assumed correct: it compares models, it does not re-check the questions.

The published workflow evals report 67.8% average accuracy at $0.0004 per case across those workflows. That is a vendor-run number with reference labels from two frontier models. It is useful as a prior, not as a substitute for your own sample.

If the sample looks good, run the full corpus in shards and keep the sample results as a regression baseline. The statistical power article explains how many labelled cases you need before a difference is meaningful; the one request, many questions article explains why batching is the default. The reproducibility article is the checklist for the version fields.

A backfill is finished when you can rerun it and get the same table. That requires more than a saved model id. It requires a frozen question set, a checkpointed corpus, an idempotent writer, and a sample you trust.

From the Jev directory

The resources behind this article.

A 13-question regulatory briefing that shows batching every question into one call is 12.2x cheaper and 10x faster with no change in answers.
Jev CookbooksDocs#official#cookbook#batching
Official
Ask everything the system might need in one request, then let code throw away what it does not use. The ticket-triage example sends a category plus four speculative questions in parallel.
Jev Practices & PatternsDocs#official#patterns#batching
Official
0GitHub stars
Reproducible billing and stability measurement of Jev's fan-out behavior across 2,976 requests to jev-1.13-20260917: asking N questions in one call bills the state once, with raw data, exact invoice checks and a batched-versus-single answer comparison.
Jev Benchmarks & Evaluations#community#benchmarking#billing
The model card for jev-1.13.0: $42 per billion input tokens with free output, a 64k context, 250k tokens per second, and how to list the models your account can call.
Jev Guides & ArticlesDocs#official#docs#models
Official
A maintained list of jev-1.13's known failure modes, literal reading, unreliable counting, dates as text, indirection, context rot, and contradictory criteria, each with a guardrail.
Jev Practices & PatternsDocs#official#docs#evaluation
Official
The raw HTTP contract behind every SDK: POST a state plus typed noul, choice, and score questions to /v1/systemone, and get one answer per question, with error codes and retry guidance.
Jev Guides & ArticlesDocs#official#docs#api
Official
3GitHub stars
Local service for authoring versioned judgment functions on TypeSafe Jev in a browser, then publishing one immutable version that both your backend calls over HTTP and your coding agents call over MCP, using a scoped client token.
Jev Agents & MCP#community#jevbest#catalog-import
9GitHub stars
An agent harness where Pi runs the loop, Gemini does the work, and Jev makes the small decisions: which model tier to use, which runbook sections to load, whether a tool call may run on a real Postgres database, and whether the report holds up.
Jev Agents & MCP#community#python#agents
Fixture-first LLM router that picks the lowest expected-cost qualified route, verifies output before release, and records cost provenance with idempotency keys.
Jev Tools & CLIs#community#github
18GitHub stars
The code behind evals.typesafe.ai. It runs four published workflows against Jev and other providers and scores them on reference labels.
Jev Benchmarks & Evaluations#official#evaluation#python
Published evaluations of four automation workflows, security incidents, agent trace observability, invoice processing, and customer service, comparing Jev and frontier LLMs as structured workflows versus single prompts.
Jev Practices & PatternsDocs#official#benchmarks#evaluation
Official
Back to all articles

Related Jev articles

Repeated decisions are common. How to cache, deduplicate, and invalidate without serving stale policy or hiding a distribution change.
Jev Practices & Patterns#operations#caching#deduplication
Read article
Jev bills input tokens and gives output away, and questions in one call run in parallel. Why the state is where the money is, and how to size a request before you ship it.
Jev Practices & Patterns#pricing#cost#api
Read article

From the Jev AI model community

Posts from builders shipping with Jev right now.

Follow @typesafeai