Skip to content

Batch Processing API: Scaling for High Volume

Overview

Batch APIs process multiple requests asynchronously at 50% discount.

Perfect for agents analyzing reports, generating content, or processing data.


When to Use Batch

Batch vs Real-Time Tradeoff

Factor Real-Time API Batch API
Latency 1-10 seconds Hours to days
Cost Full price 50% discount
Volume Single requests Bulk processing
Use Case Chat, live Reports, analysis

Claude Batch API

Submitting Batch Requests

from anthropic import Anthropic
import json

class BatchProcessing:
    def __init__(self):
        self.client = Anthropic()

    def create_batch_request(self, requests: list[dict]):
        """Submit multiple requests as batch"""

        # Format requests for batch
        batch_requests = []

        for i, request in enumerate(requests):
            batch_requests.append({
                "custom_id": f"request_{i}",
                "params": {
                    "model": "claude-3-5-sonnet-20241022",
                    "max_tokens": 1024,
                    "messages": [
                        {"role": "user", "content": request["prompt"]}
                    ]
                }
            })

        # Submit batch
        batch = self.client.messages.batches.create(
            requests=batch_requests
        )

        return batch.id

    def check_batch_status(self, batch_id: str):
        """Check if batch completed"""

        batch = self.client.messages.batches.retrieve(batch_id)

        return {
            "status": batch.processing_status,
            "succeeded": batch.request_counts.succeeded,
            "failed": batch.request_counts.errored,
            "pending": batch.request_counts.processing
        }

    def get_batch_results(self, batch_id: str):
        """Retrieve results after completion"""

        batch = self.client.messages.batches.retrieve(batch_id)

        if batch.processing_status != "completed":
            return None  # Not done yet

        results = {}

        for result in batch.results:
            results[result.custom_id] = {
                "output": result.result.message.content[0].text,
                "usage": result.result.usage
            }

        return results

Use Cases for Batch

Case 1: Report Generation

class BatchReportGeneration:
    """Generate reports for 1000 products"""

    def generate_reports_batch(self, products: list[dict]):
        """Batch generate product reports"""

        requests = []

        for product in products:
            requests.append({
                "prompt": f"""Generate marketing report for:
                Product: {product['name']}
                Category: {product['category']}
                Price: ${product['price']}

                Include: Overview, target market, positioning"""
            })

        # Submit batch
        batch_id = self.create_batch_request(requests)

        # Wait for completion (async)
        # Check status in background

        return batch_id

Case 2: Content Moderation

class BatchModeration:
    """Moderate 10k user comments"""

    def moderate_comments_batch(self, comments: list[str]):
        """Batch moderate comments"""

        requests = []

        for i, comment in enumerate(comments):
            requests.append({
                "prompt": f"""Moderate this comment:
                "{comment}"

                Response: [APPROVED|FLAGGED|REMOVED]
                Reason: [brief explanation]"""
            })

        return self.create_batch_request(requests)

Cost Math

Savings Calculation

10,000 requests @ 500 tokens each

REAL-TIME API:
  Cost per request: 500 × $3/1M = $0.0015
  Total: 10,000 × $0.0015 = $15.00

BATCH API:
  Cost per request: 500 × $1.50/1M = $0.00075
  Total: 10,000 × $0.00075 = $7.50

SAVINGS: 50% ($7.50)

Monthly at 1M requests:
  Real-time: $3,000
  Batch: $1,500
  Annual savings: $18,000!

Polling for Results

Checking Batch Status

import time

class BatchPolling:
    def __init__(self):
        self.client = Anthropic()

    def wait_for_batch_completion(self, batch_id: str, check_interval=30):
        """Poll until batch completes"""

        while True:
            batch = self.client.messages.batches.retrieve(batch_id)

            status = batch.processing_status

            print(f"Status: {status}")
            print(f"  Succeeded: {batch.request_counts.succeeded}")
            print(f"  Failed: {batch.request_counts.errored}")
            print(f"  Processing: {batch.request_counts.processing}")

            if status == "completed":
                return batch

            # Wait before next check
            time.sleep(check_interval)

3 Warnings ⚠️

Warning 1: Latency Mismatch

# ❌ WRONG
# Use batch for real-time needs
batch_id = submit_batch(requests)
result = get_batch_results(batch_id)  # Wait hours!

# User waiting for response!

# ✅ RIGHT
# Use batch only for async work
batch_id = submit_batch(reports)
# Process in background
notify_user_when_done(batch_id)

Warning 2: No Retries

# ❌ WRONG
# Assume all requests succeed
batch = submit_batch(requests)
results = get_results(batch)
# Some failed!

# ✅ RIGHT
# Track failures and retry
batch = submit_batch(requests)
results = get_results(batch)

failed = [r for r in results if r["failed"]]
if failed:
    resubmit_batch(failed)

Warning 3: Cost of Mistakes

# ❌ WRONG
# Submit 1M+ requests carelessly
# Realize mistakes after submission

# ✅ RIGHT
# Validate before batch submit
validate_requests(sample)  # Test first
if valid:
    submit_batch(requests)

Last Updated: August 9, 2026