Solution Patterns & Playbooks

Document Summarization Pipeline: End-to-End Reference Design

Summarizing ten documents is a prompt. Summarizing a hundred thousand is a pipeline — with chunking, batching, and a schema the rest of your systems can trust.

Claude 3P 101 · Updated July 2026 · Unofficial guide

High-volume summarization is one of the most common first production workloads for Claude, and the reference design is stable: split documents into model-sized pieces, summarize each piece ("map"), then summarize the summaries ("reduce"). The interesting decisions are where you split, how you keep costs down, and how you make the output machine-readable. Everything below uses documented Claude capabilities; the glue — queues, retries, storage — is standard engineering practice you own.

Step 1: Decide whether you need to chunk at all

Current Claude models carry large context windows — 1M tokens on most current models, 200K on Haiku 4.5 — so many "long" documents fit in a single request. PDFs are supported directly as document blocks (up to 600 pages per request on a 1M-context model), with each page costing roughly 1,500–3,000 text tokens plus image tokens, since pages are processed both as extracted text and as images. If a document fits, skip map-reduce: one well-structured request produces a more coherent summary than stitched fragments.

When you do send long inputs, follow Anthropic's long-context guidance: put the document content at the top of the prompt and your instructions at the end (placing queries at the end can improve response quality by up to 30%), and wrap multiple documents in <document> tags with <source> subtags so the model can keep them apart.

Step 2: Map-reduce for what doesn't fit

For documents beyond the window — or when you want per-section summaries anyway — chunk on natural boundaries (sections, chapters, filings) rather than fixed byte counts, so no fact is cut in half. Each map call takes one chunk plus a fixed instruction template; the reduce call takes all map outputs plus a template asking for a consolidated summary. Keep the instruction templates identical across calls: a stable prompt prefix is what makes prompt caching work, since caching is a strict prefix match and cache reads bill at 0.1x the base input price. See RAG chunking strategies for the chunking trade-offs in depth.

Step 3: Run the volume through batch processing

Map calls are independent, which makes them ideal batch work. On the first-party Claude API and Claude Platform on AWS, Anthropic's Message Batches API accepts up to 100,000 requests or 256 MB per batch, charges 50% of standard prices, and usually finishes in under an hour (requests unfinished at 24 hours expire unbilled; results stay downloadable for 29 days). Each request carries a custom_id you choose — use your document/chunk ID so results rejoin your pipeline deterministically. Because batches can take longer than five minutes, use the 1-hour prompt-cache TTL on shared context instead of the default 5-minute one.

Platform note: Anthropic's Message Batches API is available on the Claude API and Claude Platform on AWS, but not on Amazon Bedrock, Google Vertex AI, or Microsoft Foundry. Bedrock and Vertex AI have their own cloud-native batch inference mechanisms for Claude (S3-based on Bedrock; BigQuery/GCS-based on Vertex at 50% batch pricing) — different APIs, same idea. Design your pipeline so the "submit N jobs" layer is swappable.

Step 4: Make the output a schema, not prose

Downstream systems want fields, not paragraphs. Structured outputs (output_config with a JSON schema, objects set additionalProperties: false) guarantee the response parses, so your reduce step and your database never see free-form text where a field should be. Structured outputs are generally available on the Claude API, Claude Platform on AWS, Bedrock, and Vertex AI, and in beta on Foundry.

from anthropic import AnthropicVertex

client = AnthropicVertex(project_id="my-project", region="global")
schema = {"type": "object", "additionalProperties": False,
          "properties": {"summary": {"type": "string"},
                         "topics": {"type": "array", "items": {"type": "string"}}},
          "required": ["summary", "topics"]}
msg = client.messages.create(
    model="claude-sonnet-5", max_tokens=1024,
    output_config={"format": {"type": "json_schema", "schema": schema}},
    messages=[{"role": "user", "content": f"<document>{chunk}</document>\nSummarize."}])

Model choice and operational guardrails

A common split: Haiku 4.5 ($1/$5 per million tokens) for map calls, where each chunk is self-contained, and Sonnet 5 or Opus 4.8 for the reduce call, where synthesis quality matters most. Combined with batch pricing, the map phase often ends up costing pennies per document. Operationally: treat 429 and 5xx errors as retryable with backoff (the official SDKs already retry them), check for stop_reason: "max_tokens" on truncated summaries and re-run with a higher limit, and validate every structured output against your schema before it enters storage — a refusal returns HTTP 200 with stop_reason: "refusal" and may not match the schema.

Where to go next

Compare the per-platform gaps in the feature gaps article, or continue to the extraction-to-database pattern for pipelines that pull fields rather than summaries. The feature matrix shows batch availability at a glance.

Sources