Batch APICost OptimizationLLM API

LLM Batch API Guide: Millions of Tokens at Half Price (2026)

1 min read

You have a job that runs 5,000 requests a night, takes two hours, and nobody looks at the output until morning. And you’re paying realtime prices for it — because somewhere along the way, “the API” became “the synchronous API,” and the batch endpoint with the 50% discount never made it into the architecture.

That’s the most common cost leak in 2026 LLM budgets: delay-tolerant work paying realtime rates. Every major provider now discounts asynchronous workloads by roughly 50% — the LLM batch API market standardized on half price — OpenAI’s batch API with its ~24-hour completion window, Anthropic’s Message Batches with a ~1-hour window, Gemini’s batch tier, and DeepSeek folding the same idea into its peak/off-peak pricing. The money is sitting on the table, and this guide is about picking it up: what the batch APIs are, the provider-by-provider matrix, a workflow you can copy, the batch-vs-realtime decision rule, and the combination math that stacks batch savings with caching and routing.

What the Batch API Is

Takeaway: batch = submit now, collect later, pay half — every major provider standardized on the same shape.

The mechanism is consistent everywhere: you submit a file of requests (JSONL), the provider queues them, processes them when capacity allows, and you collect results when the batch completes. No streaming, no interactive latency — the discount is the compensation for flexibility.

The 2026 provider matrix:

ProviderDiscountCompletion windowNotes
OpenAI~50%~24 hoursthe reference implementation
Anthropic~50%~1 hourfastest window of the four
Gemini~50%flexible tierbatch maps to the Flex inference tier
DeepSeekoff-peak pricingpeak/off-peak windowsthe same idea via the clock, effective August 2026

The cross-provider comparison tracks the details; the pattern is identical — if you can wait, you pay half.

Why Batch Processing Saves Real Money

Takeaway: 50% off the largest line item in your bill is a pricing decision, not an optimization.

The math is deliberately boring. Say your monthly bill is $1,000 and 60% of it is delay-tolerant work (evals, indexing, enrichment, nightly generation). Moving that $600 to batch: $300 saved per month, $3,600 a year, zero quality change. The output tokens are identical; the only difference is when they arrive.

Two caveats keep the math honest:

  1. The discount applies at the provider level, not the platform level. A unified endpoint bills what the underlying provider bills — batch rates pass through as batch rates. Our cost-optimization playbook covers the full lever stack; batch is the lever with the least engineering cost.
  2. Batch is not free. It’s half price. The other half still benefits from caching and routing — which is the stacking math in section five below.

How to Build a Batch Workflow

Takeaway: the workflow is four pieces — submission, idempotency, collection, recovery — and the recovery piece is the one everyone skips.

The skeleton, provider-agnostic in shape — the request format follows the chat completions endpoint docs:

import json
from openai import OpenAI

client = OpenAI()  # point at your provider or unified endpoint

# 1. Build the JSONL request file
with open("batch.jsonl", "w") as f:
    for i, task in enumerate(tasks):
        f.write(json.dumps({
            "custom_id": f"task-{i}",          # idempotency key — never omit
            "method": "POST",
            "url": "/v1/chat/completions",
            "body": {"model": "gpt-4o-mini", "messages": task["messages"]},
        }) + "\n")

# 2. Submit once — the custom_id makes retries safe
batch = client.batches.create(input_file=upload(batch_path), endpoint="/v1/chat/completions")

# 3. Poll or webhook until complete, then map results back by custom_id
# 4. Recover: failed rows get re-queued into the NEXT batch, not re-run inline

Four rules that keep this production-grade:

  1. custom_id is your contract. Idempotency is what makes retries safe; without it, a network blip during submission duplicates work and doubles the bill.
  2. Collect by ID, not by order. Batch results arrive in arbitrary order; map custom_id back to your records or you’ll write the join wrong twice.
  3. Webhooks beat polling at scale. A completion callback replaces the “check every 5 minutes” loop; the error codes reference tells you which failures are retryable.
  4. Recovery is a queue, not a hack. Failed rows go back into the next batch cycle. The teams that re-run failures inline are the teams that discover batch’s rate limits the hard way.

How to Choose: Batch vs Realtime

Takeaway: the decision is one question — can this work wait? — with two explicit exceptions where the answer is always no.

The decision rule, stated bluntly:

  • Can the work wait an hour? Batch it.
  • Can it wait a day? Batch it at the provider with the cheapest window fit.
  • Is a user waiting? Never batch.
  • Is it an agent loop? Never batch.

The second exception deserves emphasis: agent loops look like batch candidates on token volume alone, but their requests are causally chained — each call depends on the last — which makes them interactive by construction. The voice-agent and support-chatbot architectures in this series are interactive for the same reason. Batch is for parallelizable work with a deadline, and that’s a smaller set than most teams think — which makes the 50% all the more valuable where it does apply.

How to Stack Savings: Batch × Caching × Routing

Takeaway: batch, caching, and routing multiply — a batch job that reuses cached prefixes on a budget model costs a fraction of the naive version.

The three levers don’t overlap, which is exactly why they stack:

  1. Batch — 50% off the base rate for delay-tolerant work.
  2. Prompt caching — cached input prefixes at ~0.1×, and batch jobs are ideal caching workloads: the same templates run thousands of times, so byte-stable prefixes hit almost every time. The caching guide has the mechanics; the batch synergy is the multiplier.
  3. Routing — the model tier for the batch is a routing decision: evals on a frontier model because you’re measuring the frontier; enrichment on a budget model because nobody reads it. The production optimization docs cover the routing mechanics.

A worked stack: a nightly enrichment job at 10M tokens. Base rate on a mid-tier model: $30. Batch: $15. Same job with stable prefixes hitting cache at 0.1× on the input side (say 80% of tokens are cached): roughly $4-6. Same job, same output quality, one routing config and one stable prompt template later. The quickstart gets the pipeline wired up in minutes; the multiplier is the part that compounds.

Common Mistakes That Inflate Your Bill

Takeaway: four ways to undo the discount — each one silently converts 50% back into 100%.

  1. Evaluating on failed rows. Run your eval on the batch’s completed rows only; failed rows are a data-quality problem, and including them produces a fake score you’ll optimize against. The CI-style eval discipline from this series’ testing guide shows the pattern.
  2. Letting results expire. Batch results have retention windows; a job that finishes while you’re on vacation and expires before collection is a full-price job with no output. Wire collection to the completion event, not to your calendar.
  3. Ignoring batch-specific rate limits. Batch quotas are separate from realtime quotas — teams that assume the same limits discover their own ceiling mid-batch.
  4. Skipping idempotency. No custom_id, no safe retry, no recovery path — the most expensive four characters you can omit.

FAQ

How much do batch APIs actually save?

About 50% on OpenAI, Anthropic, and Gemini batch tiers, with DeepSeek’s peak/off-peak scheme as the clock-based equivalent. The savings are per-token, so they scale with your delay-tolerant volume — the largest line item in most bills.

How long does a batch take to complete?

OpenAI’s window is ~24 hours, Anthropic’s ~1 hour, Gemini’s is tied to its Flex tier, and DeepSeek’s off-peak windows are defined by the clock. Pick the provider whose window fits your deadline; the discount is the same.

Can I run evals in batch mode?

Yes — evals are the canonical batch workload. Run them on completed rows only, keep the prompt template byte-stable for cache hits, and gate CI on the completed-batch score.

Does batch work with prompt caching?

Exceptionally well — batch jobs repeat the same templates thousands of times, which is the ideal caching profile. Stable prefixes + batch = the discount stacking in this guide.

Which workloads should never be batched?

Anything a user waits on, and anything causally chained — agent loops and interactive voice/chat are realtime by construction. The batch decision is “can it wait,” not “is it big.”

Do unified endpoints pass through batch discounts?

Yes — batch rates are provider rates, and the endpoint bills what the provider bills, with the discount intact. The endpoint’s job is one key and one dashboard; the 50% is the provider’s, and it flows through.

Summary

The 2026 LLM batch API landscape is remarkably standardized: roughly 50% off on every major provider, with completion windows as the only real differentiator. The play is mechanical — find the delay-tolerant share of your workload, move it to batch, keep the prefixes stable, route the model tier by task — and the combination of batch, caching, and routing routinely lands 60-80% below the naive bill. The discount is sitting on the table; the question is only whether your architecture picks it up.

Take the delay-tolerant 60% of your bill and halve it. Get your TokSpan API key — $5 free to spend on your first batch — and let per-job costs show you the savings.