Batch APIs — the 50% Discount as Industry Standard
Every major provider ships an async batch API with a 50% discount and a 24-hour turnaround window. OpenAI, Anthropic, Google, and most inference platforms (Fireworks batch tier, Together batch) follow the same pattern. Stack batch with prompt caching and an overnight pipeline whose shared prefix dominates the input can fall to roughly 10% of its synchronous-uncached cost; the three workloads in this lesson land between 17% and 41%. The rule is simple: if it isn't interactive, it belongs on batch. Content generation, document classification, data extraction, report generation, bulk labeling, catalog tagging: anything that tolerates 24-hour latency is money left on the table until it moves. The 2026 production pattern is to triage every new LLM workload into three lanes: interactive (synchronous with caching), semi-interactive (async queue with fallback), and batch (overnight, cached input stacked). Workloads that pretend to be interactive but tolerate minutes of latency waste most of their spend.
Learning Objectives
- Name the three provider batch APIs (OpenAI, Anthropic, Google) and the common 50% discount + 24h turnaround guarantees.
- Compute the cost for stacking batch + cached-input on an overnight classification workload and compare to synchronous-uncached baseline.
- Triage a workload into interactive / semi-interactive / batch and justify the lane.
- Name the two traps: partial interactivity (user expects faster than 24h) and output-schema drift (batch file format differs per provider).
The Problem
Your team ships a nightly report generation pipeline. 50,000 documents: summarize each, cluster the summaries, draft an executive brief. Run synchronously, it takes 4 hours and costs about $1,050 a night (the price comes from this lesson's script, with a 4,000-token shared prefix, 2,000 tokens per document and 200 output tokens). Then you hear about batch APIs.
Batch gets you 50% off. You also turn on prompt caching for the system prompt, which is shared across all 50k calls. Stacked, the bill drops to about $255 a night, 24.3% of baseline, roughly a quarter. Same pipeline, three config changes.
Batch is the cheapest lever in the LLM cost toolkit that nobody pulls. The reason is mostly organizational. Teams think "real-time" when the actual SLA is "by morning." This lesson is about not leaving about three quarters of the bill on the table.
The Concept
The three batch APIs
OpenAI Batch API. You upload a JSONL file with a list of requests. The promised turnaround is 24 hours, though in practice it is often 2-8 hours. You get 50% off input and output tokens, served through the /v1/batches endpoint. Cache-eligible inputs also get cached-input pricing on top.
Anthropic Message Batches. Also a JSONL upload, also 24 hours, also 50% off. It supports cache_control: cache writes are explicit, and reads happen automatically within the batch.
Google Vertex AI Batch Prediction. Input comes from BigQuery or GCS. The discount for Gemini is similar at 50%, and it plugs into Vertex pipelines.
Asynchronous, not slow
Batch means "I promise to return within 24 hours." It does not mean "this will take 24 hours." A typical P50 is 2-6 hours. The provider schedules your batch in off-peak windows when GPU inventory is underused.
Stack with caching
Take a 50k-document summarization with the same 4K-token system prompt:
- Synchronous uncached: 50000 × ($input × 4000 + $output × 200) at full rates.
- Synchronous cached: the system prompt is cached after the first write, and the remaining 49999 calls get 10x cheaper input.
- Batch cached: everything above, plus a 50% discount on both read and write.
Batch plus cache can land near 10% of the synchronous uncached bill when the shared prefix dominates the input. Any overnight workload with a shared system prompt should at least price this out.
Workload triage
Interactive. The user waits for the response and TTFT matters. Use a synchronous call with prompt caching. You cannot batch this.
Semi-interactive. The user submits a task and checks back in minutes. Use an async queue with fallback to sync when batch isn't available. Moderate-volume RAG indexing is a good example.
Batch. The user expects results "by morning" or "next hour": content pipelines, classification at scale, offline analysis. Always batch, and always stack caching on top.
The common mistake is calling everything interactive because the pipeline is in production. Production is not a latency spec. The SLA is.
The partial-interactivity trap
Some features look interactive but tolerate 5-10 minutes. Take a nightly customer health report with a "refresh" button. The user clicks refresh and a 10-minute wait is fine, but the team ships it synchronously. 50 concurrent refreshes then cost about 10x what a batched report delivered by email would.
Ask this: "What does 24 hours mean for this user?" If the answer is "they wouldn't notice," batch it.
The output-schema trap
Batch file formats differ per provider:
- OpenAI: JSONL, one request per line.
- Anthropic: JSONL, one message per line, with the response format embedded.
- Vertex: a BigQuery table or GCS prefix with TFRecord.
A single batch client across providers means adapter code for each one. Gateways that advertise multi-provider batch (Portkey, and some LiteLLM tiers) still thin-wrap the raw format.
Numbers you should remember
- Batch discount across providers: 50% flat on input and output.
- Turnaround SLA: 24 hours guaranteed, 2-6 hours typical P50.
- Stacked batch + cached input: roughly 10% of sync uncached cost.
- Triage rule: if 24h latency is acceptable, always batch.
Use It
code/main.py computes costs across sync, sync+cache, batch, and batch+cache for three workloads, starting with the 50k-document one. It reports each configuration in dollars and as a percent of the sync baseline.
Ship It
This lesson produces outputs/skill-batch-triager.md. Given workload characteristics, it triages the workload into interactive, semi-interactive, or batch and estimates the savings.
I'd run main.py before trusting the 10% figure, because the script doesn't reproduce it. Its 50k-document case, with a 4,000-token prefix, 2,000 tokens per document, and 200 output tokens, comes out at $1050.00 sync and $255.01 batch + cache, which is 24.3% of baseline. The classification case lands at 17.1% and the heavy-per-document report case at 41.3%. Only the shared prefix gets cached, so the per-document input and the output tokens keep paying full rate, and the stack gets close to 10% only when that prefix dominates the bill.
The prices in the script are hardcoded constants: $3.00 per million input tokens, $15.00 output, $0.30 cached input, and a cache write at 1.25x input. They are not any one provider's current price list, and the batch discount is a flat 0.50 multiplier over the whole cached bill. Cache expiry isn't modeled either. The constant is named CACHE_WRITE_5MIN, but the sync+cache function charges one write and then reads at the cached rate for every later document, with no refresh.
So I'd treat the printed percentages as shape, not forecast. Before moving a pipeline, I'd swap in my own prices and token counts and check the result against one real billed run. Exercise 1 asks for a 100k-document case the script doesn't include, which means adding a run(...) call to main().
Exercises
- Run
code/main.py. For a 100k-doc pipeline with 3K-token system prompt and 500-token output, compute the savings of full stack (batch + cache) vs sync baseline. - Pick three features in a real product you know. Triage each into interactive/semi/batch.
- A user complains their report took 3 hours. Was that a batch mis-triage or a legitimate interactive? Write the decision criterion.
- Your batch API return SLA is 24h but P99 is 20 hours. How do you communicate this to the user: what is the downstream system behavior on the edge case?
- Compute break-even: at what shared-prefix length does batch + cache become cheaper than running overnight on your own reserved GPU?
Key Terms
| Term | What people say | What it actually means |
|---|---|---|
| Batch API | "async discount" | 50% off with 24h turnaround |
| JSONL | "batch format" | One JSON request per line; OpenAI/Anthropic standard |
| Message Batches | "Anthropic batch" | Anthropic's batch API product name |
| Batch prediction | "Vertex batch" | Vertex AI's batch API product |
| Turnaround SLA | "24h promise" | Guarantee, not typical; typical is 2-6h |
| Workload triage | "interactivity decision" | Interactive / semi / batch routing decision |
| Output schema | "response format" | Per-provider JSONL layout; not portable |
| Stacked discount | "batch + cache" | 17-41% of the uncached sync bill in this lesson's runs; near 10% only when the shared prefix dominates |
Further Reading
- OpenAI Batch API: JSONL format and
/v1/batchessemantics. - Anthropic Message Batches: batch format and
cache_controlinteraction. - Vertex AI Batch Prediction: Gemini batch semantics.
- Finout: OpenAI vs Anthropic API Pricing 2026
- Zen Van Riel: LLM API Cost Comparison 2026