Skip to content
CCAF Preparation

Task Statement 4.5·Domain 420% of exam

Batch Processing Strategies

Design efficient batch processing strategies

Jump to practice →

Official Exam Guide Objectives

Task 4.5: Design efficient batch processing strategies

Knowledge of

  • The Message Batches API: 50% cost savings, up to 24-hour processing window, no guaranteed latency SLA
  • Batch processing is appropriate for non-blocking, latency-tolerant workloads (overnight reports, weekly audits, nightly test generation) and inappropriate for blocking workflows (pre-merge checks)
  • The batch API does not support multi-turn tool calling within a single request (cannot execute tools mid-request and return results)
  • custom_id fields for correlating batch request/response pairs

Skills in

  • Matching API approach to workflow latency requirements: synchronous API for blocking pre-merge checks, batch API for overnight/weekly analysis
  • Calculating batch submission frequency based on SLA constraints (e.g., 4-hour windows to guarantee 30-hour SLA with 24-hour batch processing)
  • Handling batch failures: resubmitting only failed documents (identified by custom_id) with appropriate modifications (e.g., chunking documents that exceeded context limits)
  • Using prompt refinement on a sample set before batch-processing large volumes to maximize first-pass success rates and reduce iterative resubmission costs

What You Need to Know

The Message Batches API buys throughput at a discount, subject to constraints that are not negotiable. The examinable skill is recognising which workloads fit inside those constraints and which cannot.

Message Batches API: The Facts

Five properties define what the API will and will not do, and none of them is tunable:

  • 50% cost savings compared to synchronous API calls
  • Up to 24-hour processing window — completion may take minutes, and may take the full day
  • No guaranteed latency SLA — there is no timeframe you are entitled to rely on
  • No multi-turn tool calling within a single batch request — a tool cannot be executed part-way through and its result fed back in to continue
  • custom_id fields for correlating request/response pairs — every request carries its own identifier, which is how a response is matched back to what produced it

The Matching Rule

This is the single most tested concept from this task statement:

Synchronous API: anything where completion is being waited on. A pre-merge check in CI/CD, review feedback a developer is sitting in front of, any step that holds up work until it returns.

Batch API: anything consumed on someone else's schedule. Overnight technical debt reports, weekly audit summaries, test generation that runs while nobody is working, bulk document extraction.

Question 11 in the sample set puts this as a proposal to move everything onto batch and capture the saving across the board. The answer that scores keeps the blocking workflows synchronous and moves only the latency-tolerant ones — the saving is real, and it does not apply to work that blocks a person.

// Synchronous — developer is waiting for this
const preMergeReview = await client.messages.create({
  model: "claude-sonnet-5",
  max_tokens: 4096,
  messages: [{ role: "user", content: prDiffContent }]
});

// Batch — results consumed tomorrow morning
const batchRequest = await client.messages.batches.create({
  requests: technicalDebtDocuments.map((doc, i) => ({
    custom_id: `debt-report-${i}`,
    params: {
      model: "claude-sonnet-5",
      max_tokens: 4096,
      messages: [{ role: "user", content: doc }]
    }
  }))
});

SLA Calculation

Scheduling batch work means treating the 24-hour window as spent before you begin. Given an organisational commitment to deliver a report within 30 hours:

  • Everything must be submitted at least 24 hours before the deadline, because that is the longest processing may take
  • Subtracting that from the 30-hour commitment leaves 6 hours, and that remainder is the entire allowance for gathering requests, validating them, and absorbing anything that goes wrong operationally
  • Submitting every 4-6 hours inside that window keeps a batch permanently in flight, so no single submission failure consumes the whole margin

Items may give you the SLA and ask for the submission cadence, which is this calculation run backwards.

Batch Failure Handling

Not every document in a batch comes back successfully. The correct failure handling pattern has three steps:

1. Identify failures by custom_id. The identifier attached to each request is what makes a failure attributable — read the results and collect the identifiers that errored.

2. Resubmit only failures with modifications. Resending everything pays a second time for the requests that already worked. Modify what failed, typically by:

  • Splitting documents that ran past the context limit into pieces that fit
  • Cutting back the extraction prompt where a document's structure was unusual enough to confuse it
  • Supplying few-shot examples drawn from the specific layout that failed

3. Refine prompts on a sample set BEFORE batch processing. The step that pays best happens before submission: prove the prompt against a representative sample of 5-10 documents spanning the formats and edge cases the batch contains, and most of the failures never occur.

// Parse batch results and identify failures. results() streams a .jsonl
// file, so iterate it — there is no array to .filter().
const failedIds: string[] = [];
for await (const entry of await client.messages.batches.results(batchId)) {
  if (entry.result.type === "errored") failedIds.push(entry.custom_id);
}

// Resubmit only failures with modifications
const retryRequests = failedIds.map(id => {
  const originalDoc = documentsById[id];
  return {
    custom_id: `${id}-retry-1`,
    params: {
      model: "claude-sonnet-5",
      max_tokens: 8192,  // increased for oversized docs
      messages: [{
        role: "user",
        content: chunkIfNeeded(originalDoc)
      }]
    }
  };
});

Multi-Turn Tool Calling Limitation

A single batch request cannot carry a multi-turn tool exchange. Specifically, it will not let you:

  • Define tools and have the model call them mid-request
  • Process tool results and continue the conversation within the same batch item
  • Run agentic loops within a single batch request

Anything requiring a tool to run part-way through belongs on the synchronous API, and this is tested directly: a scenario describing batch work that needs to call an external service during processing is describing a workflow the batch API cannot express, whatever its latency tolerance.

Prompt Optimisation Before Batch Submission

The economics favour work done before submission rather than after:

  1. Sample set testing: pull 5-10 documents that between them cover the formats, document types and awkward cases the full batch contains
  2. Iterate on the sample: work the prompts, examples and schema against those until accuracy on the sample holds up
  3. Submit the full batch: the proven prompt carries a materially higher first-pass rate into the volume run
  4. Handle failures: send back only what errored, each with the modification its failure calls for

The arithmetic is stark on volume. Across 1,000 documents, a 90% first-pass rate leaves 100 to resubmit. A 60% rate leaves 400 — four times the resubmission volume, and the batch processing cost of those retries on top.

Deep Dive

Cost, timing, and why "best-effort" is not a promise

The 50% discount is unconditional: "The Batches API offers significant cost savings. All usage is charged at 50% of the standard API prices." Timing is a range, not a target: "This approach is well-suited to tasks that do not require immediate responses, with most batches finishing in less than 1 hour," but "the system processes each batch as fast as possible... processing may be slowed down based on current demand and your request volume. In that case, you may see more requests expiring after 24 hours." Design for the 24-hour worst case, not the sub-1-hour common case. Because batches routinely run longer than 5 minutes, the docs also recommend the 1-hour prompt-cache TTL (instead of the default 5-minute one) "for better cache hit rates when processing batches with shared context."

Sourceplatform.claude.com › batch-processingfetched 2026-07-30

Hard size limits and the custom_id contract

A single Message Batch is capped at "100,000 Message requests or 256 MB in size, whichever is reached first" — exceeding the size cap returns a 413 request_too_large error. Every request needs a custom_id matching ^[a-zA-Z0-9_-]{1,64}$ (1-64 alphanumeric characters, hyphens, underscores). That ID exists for one reason: "Batch results can be returned in any order, and may not match the ordering of requests when the batch was created... To correctly match results with their corresponding requests, always use the custom_id field." Never assume position-based matching.

Sourceplatform.claude.com › batch-processingfetched 2026-07-30

Batch lifecycle: statuses, polling, and cancellation

A created batch "begins processing immediately" and "can take up to 24 hours to complete." Its processing_status is one of three values — in_progress, canceling, or ended — starting at in_progress and moving to ended "once all the requests in the batch have finished processing, and results are ready." The docs recommend "a polling loop that checks the batch status periodically until processing has ended." request_counts tallies every request by status; all requests "start as processing and move to one of the other statuses only once processing of the entire batch ends," and the counts always sum to the batch total. Canceling a batch moves it to canceling and then to a final ended state that "may contain partial results for requests that were processed before cancellation."

Sources: https://platform.claude.com/docs/en/api/creating-message-batches (statuses and request_counts) · https://platform.claude.com/docs/en/build-with-claude/batch-processing (the polling loop and cancellation behaviour) (fetched 2026-07-30)

Four result types — and which ones cost you nothing

Once a batch ends, every request resolves to exactly one of four result types: succeeded, errored, canceled, or expired. Only succeeded is billed. The other three explicitly are not: errored requests ("invalid requests and internal server errors") are not billed; canceled requests ("user canceled the batch before this request could be sent to the model") are not billed; expired requests ("batch reached its 24-hour expiration before this request could be sent to the model") are not billed. A stalled or oversubscribed batch does not silently cost you for work that never ran.

Sourceplatform.claude.com › batch-processingfetched 2026-07-30

Retrieving results: streaming .jsonl, and a 29-day clock from creation

Results live at a results_url that is "specified only once processing ends," pointing to a .jsonl file. "Results in the file are not guaranteed to be in the same order as requests" — the same custom_id rule applies here too. Because result files can be large, "it's recommended to stream results back rather than download them all at once." The retrieval window is generous but finite: "Batch results are available for 29 days after creation. After that, you may still view the Batch, but its results will no longer be available for download" — and critically, that clock runs from the batch's creation, not from when processing ended, so a batch that sat queued for most of a day still expires 29 days after created_at.

Sourceplatform.claude.com › batch-processingfetched 2026-07-30

What a batch request can and cannot contain

"Almost any request you can make to the Messages API can be included in a batch," including vision, tool use (including all server tools), system messages, multi-turn conversations, extended thinking, and most beta features — and because each request is processed independently, you can freely mix request types within one batch. Two things are explicitly rejected with a validation error if included: stream: true ("Batch results come back as a single file, not a stream") and the stateful Threads parameters store / previous_thread_event_id ("Threads are stateful; batch requests are not"). Validation itself is asynchronous — "validation errors are returned when processing of the entire batch has ended," not at submission time — which is why the docs recommend you "dry run a single request shape with the Messages API" before batching thousands of them.

Sourceplatform.claude.com › batch-processingfetched 2026-07-30

Current state — the multi-turn tool-calling limitation, precisely

Sourceplatform.claude.com › batch-processingfetched 2026-07-30

Quick Reference

ItemValue / rule
Cost discount50% of standard API prices, unconditionally
Typical processing timeUnder 1 hour for most batches
Maximum processing window24 hours (hard)
Latency guaranteeNone — best-effort, slower under high demand
Batch size limit100,000 requests OR 256 MB, whichever first
Oversized batch error413 request_too_large
custom_id format^[a-zA-Z0-9_-]{1,64}$, 1-64 characters
Result matching ruleAlways match by custom_id — results are NOT in request order
processing_status valuesin_progresscancelingended
Four result typessucceeded, errored, canceled, expired
Billed result typessucceeded only — the other three are free
Results file.jsonl at results_url, populated only once ended
Results retrieval window29 days from created_at (not ended_at)
Download recommendationStream results, don't bulk-download
Rejected batch paramsstream: true; Threads store / previous_thread_event_id
Param validation timingAsynchronous — errors surface only after the batch ends
Pre-submission checkDry-run one request against the synchronous Messages API
Prompt caching tipUse the 1-hour cache TTL for batches (they often exceed 5 minutes)
Server tools in a batchRun their full agentic loop inside the batch worker
Client tool / turn continuation in a batchNOT possible mid-request — pause_turn requires a new follow-up request
Blocking workflows (pre-merge checks)Synchronous API
Latency-tolerant workflows (overnight reports)Batch API
30-hour SLA calculationFinal batch in ≥24h before the deadline (the max processing window); the remaining 6h is buffer — submit every 4–6h so one is always in flight

Exam Traps

Practice Scenario

Your team wants to reduce API costs for automated analysis. You have two workflows: (1) a blocking pre-merge check that must complete before developers merge, and (2) a technical debt report generated overnight for review the next morning. Your manager proposes switching both to the Message Batches API for 50% cost savings. How should you evaluate this proposal?

Build Exercise

Design a Batch Processing Strategy

Difficulty: Intermediate (2/4)

45 minutes

  1. List 5 workflows in a hypothetical organisation and categorise each as blocking (synchronous) or latency-tolerant (batch-eligible) with justification

Why: The matching rule between synchronous and batch API is the most tested concept in this task statement. The exam presents a scenario where a manager proposes switching everything to batch for cost savings, and you must identify which workflows cannot tolerate the 24-hour processing window.

You should see: A table with 5 workflows, each clearly categorised with justification. Blocking workflows have someone or something waiting for the result. Batch-eligible workflows consume results later with no real-time dependency.

  1. Define a batch submission for 20 documents using the Message Batches API format with unique custom_id fields for each document

Why: custom_id fields are the mechanism for correlating request-response pairs in batch results. Without unique identifiers, you cannot determine which documents succeeded or failed, making failure handling impossible.

You should see: A valid batch request object with 20 entries, each containing a unique custom_id, model specification, max_tokens, and a messages array with the document content.

  1. Implement failure handling: parse batch results, identify failures by custom_id, and construct a retry batch containing only failed documents with increased max_tokens

Why: Resubmitting only failures with targeted modifications is the correct batch failure pattern. Resubmitting the entire batch wastes cost on already-successful documents. The exam tests that you understand custom_id correlation and targeted retry.

You should see: A failure handler that filters results by error status, extracts the custom_id values of failures, looks up the original documents, and creates a retry batch with modifications like increased max_tokens or chunked content.

  1. Calculate the batch submission frequency needed to guarantee a 30-hour SLA given the 24-hour maximum processing window

Why: SLA calculation with the 24-hour batch processing window is a direct exam test point. You must work backwards from the SLA deadline to determine when to submit, accounting for the maximum processing time plus a safety margin.

You should see: A calculation showing: 30-hour SLA minus 24-hour maximum processing window equals 6 hours of buffer. Submission must occur at least 30 hours before the deadline, with batches submitted every 4-6 hours to guarantee the SLA with margin.

  1. Create a 5-document sample set and refine extraction prompts iteratively before submitting the full batch of 20 documents

Why: Prompt refinement on a sample set before batch submission is the most cost-effective batch processing strategy. A 90% first-pass success rate means 2 retries on 20 documents. A 60% first-pass rate means 8 retries, four times the resubmission cost.

You should see: A sample set covering the range of document types and edge cases, 2-3 prompt iterations improving accuracy on the sample, and then the full batch submission achieving a high first-pass success rate.

Sources


Appendix A — Build Exercise Step Hints

Progressive hints revealed by the "Stuck? Get a nudge" control on each step.

Step 1. List 5 workflows in a hypothetical organisation and categorise each as blocking (synchronous) or latency-tolerant (batch-eligible) with justification

Why: The matching rule between synchronous and batch API is the most tested concept in this task statement. The exam presents a scenario where a manager proposes switching everything to batch for cost savings, and you must identify which workflows cannot tolerate the 24-hour processing window.

You should see: A table with 5 workflows, each clearly categorised with justification. Blocking workflows have someone or something waiting for the result. Batch-eligible workflows consume results later with no real-time dependency.

Stuck? Get a nudge

Step 2. Define a batch submission for 20 documents using the Message Batches API format with unique custom_id fields for each document

Why: custom_id fields are the mechanism for correlating request-response pairs in batch results. Without unique identifiers, you cannot determine which documents succeeded or failed, making failure handling impossible.

You should see: A valid batch request object with 20 entries, each containing a unique custom_id, model specification, max_tokens, and a messages array with the document content.

Stuck? Get a nudge

Step 3. Implement failure handling: parse batch results, identify failures by custom_id, and construct a retry batch containing only failed documents with increased max_tokens

Why: Resubmitting only failures with targeted modifications is the correct batch failure pattern. Resubmitting the entire batch wastes cost on already-successful documents. The exam tests that you understand custom_id correlation and targeted retry.

You should see: A failure handler that filters results by error status, extracts the custom_id values of failures, looks up the original documents, and creates a retry batch with modifications like increased max_tokens or chunked content.

Stuck? Get a nudge

Step 4. Calculate the batch submission frequency needed to guarantee a 30-hour SLA given the 24-hour maximum processing window

Why: SLA calculation with the 24-hour batch processing window is a direct exam test point. You must work backwards from the SLA deadline to determine when to submit, accounting for the maximum processing time plus a safety margin.

You should see: A calculation showing: 30-hour SLA minus 24-hour maximum processing window equals 6 hours of buffer. Submission must occur at least 30 hours before the deadline, with batches submitted every 4-6 hours to guarantee the SLA with margin.

Stuck? Get a nudge

Step 5. Create a 5-document sample set and refine extraction prompts iteratively before submitting the full batch of 20 documents

Why: Prompt refinement on a sample set before batch submission is the most cost-effective batch processing strategy. A 90% first-pass success rate means 2 retries on 20 documents. A 60% first-pass rate means 8 retries, four times the resubmission cost.

You should see: A sample set covering the range of document types and edge cases, 2-3 prompt iterations improving accuracy on the sample, and then the full batch submission achieving a high first-pass success rate.

Stuck? Get a nudge

Appendix B — Interactive Study Prompts

Two prompts to paste into Claude. B1 drills the judgement the exam actually measures; B3 reviews the code you wrote for the Build Exercise above. The exam simulator between them is the interactive quiz on this page.

B1. Concept Check — Discrimination Drill

Prompt — paste into Claude

You are examining me for the Claude Certified Architect – Foundations (CCAR-F) exam, Domain 4: Prompt Engineering & Structured Output (20% of the exam), Task Statement 4.5: Batch Processing Strategies. Use British English throughout.

What this exam actually measures. Not one item on the official exam asks what something is. Every item drops you into a production system that is already misbehaving, offers four defensible engineering responses, and asks which is best. The skill being tested is proportionality: fix the root cause with the cheapest instrument that gives the guarantee the situation demands. So do not quiz me on definitions. Make me choose between options that are both defensible, then attack whatever I chose.

How to run this session.

  • One question at a time. Stop and wait. Never answer your own question, and never move on until I have committed.
  • Never reveal which option is right before I commit to one.
  • Do not praise me. A correct answer earns "Yes" and the next question. If I am right for the wrong reason, say so — that is the failure that costs marks on exam day.
  • When I am wrong, quote the exact phrase in my answer that gave it away, correct it in one sentence, and move on. One correction at a time.
  • If I write something fluent but empty, name it: "That is a restatement, not a reason."
  • Set every scenario inside one of the exam's production contexts: Structured Data Extraction (pulling fields out of unstructured documents, validating them against a JSON schema, handling edge cases, feeding a downstream system) or Claude Code for Continuous Integration (automated review on pull requests, generated tests and PR feedback, with false positives to keep down).

Session plan — about twelve questions.

Round 1 — Anchor (1 question). One concrete question to check I have actually read the material. If I cannot answer it, stop the session and tell me to read the lesson before continuing.

Round 2 — Discrimination (5 questions). Each one: describe a symptom in one of the contexts above, with a number or a log observation in it. Offer exactly two responses, both defensible. Ask me to pick one and justify it in a single sentence. Then argue the case for the option I rejected as strongly as you can, and ask whether I am holding or changing my answer. Only after I answer that, tell me which is right and why the other one is the more tempting trap.

Round 3 — Proportionality (2 questions). Take one symptom and run it twice with different stakes: once where the cost of an error is a wasted re-extraction or a noisy comment on a pull request, once where it is a payment issued against a mis-extracted total or a security defect merged to main. The right answer must change between the two. If I answer the same way both times without noticing the stakes moved, that is the finding — tell me.

Round 4 — Code review (3 questions). Present a colleague's confident proposal containing one of the trap errors listed below, written the way a teammate would write it in a pull request. Ask me what is wrong with it. Do not signal that anything is wrong.

Round 5 — Verdict. Rate me green, amber or red on each concept below. Name the single weakness most likely to cost me marks, and give me one specific next action: a section of this lesson to re-read, or a step of the Build Exercise to redo. If I am not ready for this task statement, say so plainly.

Concepts in scope

  1. The Message Batches API's fixed terms — reached at client.messages.batches.*, charged at 50% of standard prices, with a processing window of up to 24 hours and no guaranteed latency. Each request carries a custom_id, and that identifier is the only correct way to match a result back to its request.
  2. The matching rule — anything with a person or a merge blocked on the answer stays on the synchronous Messages API. Overnight reports, weekly audits, nightly test generation and bulk document extraction go to batch.
  3. Scheduling against an SLA — design against the 24-hour ceiling rather than the sub-hour common case. A 30-hour SLA leaves six hours of buffer, so the last batch must go in at least a full processing window before the deadline, with submissions repeating every four to six hours so one is always in flight.
  4. Failure handling — read the results, collect the identifiers that failed, and resubmit only those with a targeted change: chunking an oversized document, raising the token ceiling, adding a format-specific example. Never resubmit the whole batch.
  5. Refine before you submit — iterate the prompt on a five to ten document sample covering the real range of formats and edge cases, because first-pass success rate is what determines resubmission cost at volume.
  6. The multi-turn tool-calling limit — a batch request cannot execute a client-defined tool, take its result and keep reasoning within the same turn. A workflow that needs that belongs on the synchronous API.

Trap errors to plant in Round 4

  • Moving every workflow to batch for the 50% saving, including the pre-merge check a developer is waiting on.
  • Designing a schedule around how quickly batches usually finish, when there is no latency guarantee to design around.
  • Putting a workflow that has to call a tool and use its result mid-processing into a batch request.
  • Matching results to requests by their position in the results file rather than by identifier, when results can come back in any order.

Stay inside the material above. If I raise something outside it, tell me it is out of scope for this task statement and return to the drill. Begin with Round 1.

B2. Exam Simulator

Exam simulator

Question 1 of 11

Scenario · Claude Code for Continuous Integration

Your CI account is over budget. Two workflows dominate the spend: a pre-merge review developers wait on before they can merge, and a technical debt report generated overnight and read at standup. Your manager wants both moved onto the Message Batches API for the 50% saving. How should you evaluate this?

B3. Build Coach — Code Review

The Build Exercise and its hint ladder are already on this page. This prompt is for the one thing the page cannot do: review the code you actually wrote.

Prompt — paste into Claude

You are a staff engineer reviewing my implementation of a build exercise for the Claude Certified Architect – Foundations exam, Domain 4, Task Statement 4.5: Batch Processing Strategies. Use British English throughout.

I am building a batch processing strategy: a set of organisational workflows sorted by whether anything is blocked on the result, a batch submission whose requests each carry a unique identifier, a failure handler that resubmits only what failed and only with a targeted change, a submission schedule derived backwards from an SLA against the 24-hour processing ceiling, and a prompt refined on a representative sample before the full volume goes in.

It has to satisfy all of the following:

  • Every workflow is classified as blocking or latency-tolerant with a justification that names who or what is waiting for the result.
  • The submission goes through client.messages.batches.*, and every request carries a unique custom_id alongside its model, token ceiling and messages.
  • The failure handler reads the results, collects the identifiers that failed, looks up the originals, and builds a retry containing only those — with a modification that addresses why they failed.
  • The schedule is worked backwards from the deadline against the 24-hour maximum, showing the buffer and the resulting submission interval.
  • The sample set covers the real range of formats and edge cases rather than the easy documents, and the prompt is iterated on it before the full batch is submitted.

How to review.

  • Ask me to paste my code, my workflow classification and my SLA working. If I have not pasted them, ask for them and nothing else. Do not write the implementation for me, do not offer a reference solution, and do not fill in a step I have skipped.
  • Work through the criteria above in order. For each one, quote the line of my code or my working that satisfies it, or say plainly that nothing does.
  • Then hunt for the failure modes below. Each is a real production bug, not a style preference.
  • Rank everything you find: (1) would fail in production, (2) would lose marks on the exam, (3) style. Give me the first item under (1) and then stop — wait for my fix before giving me the next one.
  • If my code satisfies everything, do not congratulate me. Change the requirements — half the batch comes back expired rather than errored, and the report is due in nine hours — and make me handle it.
  • If I ask you to just write it for me, refuse once and give me the smallest nudge that would unblock me instead.

Failure modes to probe

  • Results matched to documents by their order in the file rather than by custom_id, which passes in testing and silently misattributes in production.
  • A schedule built on how fast batches usually finish, so one slow day breaks the SLA the design was supposed to guarantee.
  • The retry reusing the original identifiers, leaving the two runs indistinguishable in the results.
  • A failed document resubmitted unchanged, so it fails the same way and costs another cycle.
  • A workflow filed as latency-tolerant while something downstream blocks on it, or a batch request that needs a client tool to run mid-processing.

Start by asking me for my code.