2.2 Message Batches API & Asynchronous Workloads
Key Takeaways
- The Message Batches API provides a 50% discount on all token types (input, output, cache write, and cache read); most batches finish in under an hour and any request not processed within 24 hours expires unbilled.
- Each request inside a batch requires a unique custom_id of 1 to 64 alphanumeric, hyphen, or underscore characters, which developers must use to correlate results because lines in the output JSONL file are non-deterministic in order.
- A batch is limited to 100,000 Message requests or 256 MB, whichever is reached first, and batch requests draw on a rate-limit pool separate from synchronous interactive traffic.
- Error boundaries operate at individual item granularity: failures (validation, rate limit, timeout) are reported per custom_id without aborting the broader batch execution.
- Canceling a batch halts pending items while allowing currently running requests to complete and yield downloadable partial results.
2.2 Message Batches API & Asynchronous Workloads
Core Concept: The Anthropic Message Batches API provides an asynchronous, high-throughput execution channel engineered for bulk, non-interactive workloads. By decoupling requests from real-time synchronous serving constraints, the Batches API provides a flat 50% discount across all token modalities (input, output, cache creation, and cache read) with most batches finishing in under 1 hour and a hard 24-hour expiration.
Architectural Purpose of the Message Batches API
Modern enterprise AI architectures frequently require processing massive volumes of data where immediate sub-second responses are unnecessary. Running millions of tokens through standard synchronous endpoints (POST /v1/messages) introduces significant architectural friction:
- Connection Fragility: Synchronous HTTP connections held open across long generation windows risk timeout errors, dropped sockets, and transient network disconnects.
- Rate Limit Contention: High-volume batch jobs (such as re-indexing document embeddings, evaluating historical conversations, or running overnight classification pipelines) compete directly with user-facing interactive traffic for requests-per-minute (RPM) and tokens-per-minute (TPM) quotas.
- Economic Inefficiency: Paying standard retail token pricing for background tasks that could easily execute during off-peak inference windows wastes organizational budget.
The Message Batches API solves these challenges by providing a dedicated asynchronous ingestion and execution pipeline. In exchange for relaxing the latency guarantee - most batches finish within an hour, and any request not sent to the model within 24 hours expires - Anthropic cuts all token costs in half—including inputs, outputs, prompt cache writes, and prompt cache reads. Furthermore, batches execute against dedicated asynchronous capacity pools, shielding interactive production services from rate limit exhaustion.
Synchronous vs. Asynchronous Decision Matrix
Selecting between the standard Messages API (with or without streaming) and the Message Batches API is a foundational architectural decision:
| Evaluation Dimension | Standard Messages API (Synchronous) | Message Batches API (Asynchronous) |
|---|---|---|
| Turnaround Latency | Immediate (sub-second to seconds); streaming TTFT < 1s | Asynchronous; most batches under 1 hour, hard 24-hour expiration |
| Pricing Structure | 100% standard retail token pricing | 50% discount on all input, output, and cached tokens |
| Connection Model | Persistent client-server connection (HTTP request/response or SSE) | Asynchronous: Submit -> Poll/Webhook -> Download JSONL |
| Concurrency & Quotas | Shared real-time RPM / TPM rate limits | Separate asynchronous capacity; up to 100,000 requests or 256 MB per batch |
| Error Isolation | Request-level; single connection failure drops the call | Per-request boundary; individual item failure does not halt batch |
| Prompt Caching Support | Fully supported | Fully supported; 50% discount stacks with cache savings |
| Ideal Workloads | Interactive chat, coding assistants, low-latency agent loops | Evals, document classification, synthetic data, overnight backfills |
Batch Request Lifecycle & Operations
The Message Batches API follows a decoupled lifecycle consisting of submission, background processing, monitoring, and result retrieval.
1. Creating a Batch (POST /v1/messages/batches)
Batches are initialized by posting a collection of message requests. Each individual item in the requests list requires two primary attributes:
custom_id: A developer-assigned unique string (1 to 64 characters; alphanumeric, underscores, and hyphens) used to correlate responses back to original records.params: A standard Messages API payload object specifyingmodel,max_tokens,messages, and optional configurations likesystem,tools,temperature, orcache_control.
import anthropic
client = anthropic.Anthropic()
batch = client.messages.batches.create(
requests=[
{
"custom_id": f"doc-classification-{idx}",
"params": {
"model": "claude-sonnet-5",
"max_tokens": 256,
"system": [
{
"type": "text",
"text": "Classify the sentiment and category of the provided legal filing.",
"cache_control": {"type": "ephemeral"} # Caching works in batches!
}
],
"messages": [
{"role": "user", "content": document_text}
]
}
}
for idx, document_text in enumerate(corpus_documents)
]
)
print(f"Batch created with ID: {batch.id}, Status: {batch.processing_status}")
2. Batch Lifecycle States
A batch transitions through distinct states recorded in processing_status:
in_progress: The batch has been validated and queued. Requests are executing concurrently across worker pools.canceling: A cancellation command has been submitted viaPOST /v1/messages/batches/{batch_id}/cancel. Workers are terminating un-started tasks while allowing running tasks to finish.ended: Terminal state. All requests in the batch have reached completion (succeeded,errored,canceled, orexpired).
3. Monitoring Batch Progress
Clients query batch state via GET /v1/messages/batches/{batch_id}. The response provides fine-grained counters in the request_counts object:
{
"id": "msgbatch_01ABCxyz...",
"type": "message_batch",
"processing_status": "ended",
"request_counts": {
"processing": 0,
"succeeded": 9982,
"errored": 18,
"canceled": 0,
"expired": 0
},
"created_at": "2026-09-10T02:00:00Z",
"ended_at": "2026-09-10T02:45:12Z",
"results_url": "https://anthropic-batches.s3.amazonaws.com/results_01ABCxyz.jsonl?AWSAccessKeyId=..."
}
Result Processing & Result Correlation via custom_id
Once a batch enters the ended state, results are available for download as a newline-delimited JSON (JSONL) file.
The Non-Deterministic Ordering Rule
A fundamental architectural characteristic of the Batches API is that results in the JSONL output file are NOT emitted in the original submission order. Because Anthropic's distributed scheduler processes requests asynchronously across thousands of parallel worker nodes, shorter prompts or faster completions may finish ahead of earlier submissions.
Developers must correlate results using custom_id rather than array indexing.
JSONL Schema Structure
Each line in the downloaded JSONL file contains an independent JSON object encapsulating the result of a single custom_id:
{"custom_id": "doc-classification-0", "result": {"type": "succeeded", "message": {"id": "msg_01...", "type": "message", "role": "assistant", "content": [{"type": "text", "text": "Category: Regulatory Compliance. Sentiment: Neutral."}], "model": "claude-sonnet-5", "stop_reason": "end_turn", "usage": {"input_tokens": 1520, "output_tokens": 18, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 1450}}}}
{"custom_id": "doc-classification-1", "result": {"type": "errored", "error": {"type": "invalid_request_error", "message": "max_tokens: 256 is smaller than minimum required"}}}
{"custom_id": "doc-classification-2", "result": {"type": "canceled"}}
{"custom_id": "doc-classification-3", "result": {"type": "expired"}}
Result Status Types & Error Boundaries
The result.type field reflects one of four outcomes:
"succeeded": The request completed normally. The object contains the standard Anthropicmessageobject with fullcontent,usage, and token metrics."errored": The individual request failed (e.g., malformed payload, invalid schema, or content filter trigger). It contains anerrorobject with standard error codes."canceled": The batch was canceled by the client before this specific request began processing."expired": The batch reached its 24-hour expiration before this request was sent to the model. You are billed for neitherexpirednorerroredrequests.
Granular Error Isolation
In synchronous API calls, a batch of requests orchestrated via client-side threads can fail unpredictably if connection drops or rate limits hit. In the Batches API, error boundaries are isolated to the individual request. If 18 out of 10,000 requests in a batch contain an invalid parameter, those 18 requests emit "errored" lines in the JSONL output, while the remaining 9,982 requests process to "succeeded" status without interruption.
Quotas, Limits, and Cancellation Semantics
Architectural Limits
- Maximum Requests per Batch: 100,000 Message requests.
- Maximum Batch Payload Size: 256 MB. A batch is capped by whichever of the two ceilings it reaches first, so work beyond either bound must be partitioned across batches.
- Result Retention Window: Results files remain accessible via
results_urlfor 29 days after the batch enters theendedstate. After 29 days, the results file is purged. - Processing Window: Most batches complete in under 1 hour. Results become available once every request finishes or after 24 hours, whichever comes first; any request still unprocessed at 24 hours expires and is not billed. Actual speed depends on cluster load and queue depth.
Cancellation Semantics
A batch in the in_progress state can be canceled at any time by issuing:
POST /v1/messages/batches/{batch_id}/cancel
Understanding cancellation behavior is a common exam topic:
- The batch immediately transitions from
in_progresstocanceling. - Any individual requests that are currently executing in worker memory will run to completion and be recorded as
"succeeded"(or"errored"). - Requests that are still queued and have not yet started execution are halted and recorded as
"canceled". - Once all active requests finalize, the batch transitions to
ended. - Developers can still download the partial results file via
results_urlto retrieve all requests that succeeded before the cancellation completed.
Combining Prompt Caching with Message Batches
A powerful production optimization pattern is compounding Prompt Caching with the Message Batches API. Because prompt caching operates inside batch processing:
- The 50% batch discount applies to all token types, including
cache_creation_input_tokensandcache_read_input_tokens. - For Claude Sonnet 5:
- Synchronous base input: $2.00 / MTok
- Batch base input (50% off): $1.00 / MTok
- Synchronous cache read (0.1x): $0.20 / MTok
- Batch cache read (50% of 0.1x): $0.10 / MTok!
When evaluating large document corpuses against a static instruction set using batching and prompt caching together, developers achieve an astonishing 95% total cost reduction compared to standard synchronous un-cached execution ($0.10 vs $2.00 per MTok).
What pricing discount and turnaround Service Level Agreement (SLA) govern requests submitted through the Message Batches API?
When retrieving results from an ended batch via the downloadable JSONL output file, how must client applications map completion outputs back to their original requests?
How does the Message Batches API handle individual request errors and batch cancellation requests?