Back to blog
Tutorial·10 min read·1855 words

How to Cut AI API Costs by 50%+ with Batch Processing: A Complete Developer Tutorial

If you're running AI features in production, API costs can quickly become your biggest line item. One of the most effective — and most underused — ways to sl...

How to Cut AI API Costs by 50%+ with Batch Processing: A Complete Developer Tutorial — illustration

How to Cut AI API Costs by 50%+ with Batch Processing: A Complete Developer Tutorial

If you're running AI features in production, API costs can quickly become your biggest line item. One of the most effective — and most underused — ways to slash that bill is batch processing: submitting requests in bulk instead of one at a time.

Most major AI API providers now offer batch endpoints that give you 50% off standard prices in exchange for a simple trade-off: your results arrive in minutes or hours instead of instantly. For workloads that don't need real-time responses, this is essentially free money.

In this tutorial, you'll learn how batch APIs work, when to use them, and how to build a production-ready batch pipeline with automatic retry, error handling, and cost tracking — using the Qubax AI API as the example platform.

What Are Batch APIs and Why Are They 50% Cheaper?

Batch APIs exist because of how inference infrastructure works. Real-time requests must be served immediately, which forces providers to keep expensive GPU capacity idle in reserve for traffic spikes. Batch requests, by contrast, can be scheduled during lulls — nights, weekends, off-peak hours — when that same GPU capacity would otherwise sit unused.

Providers pass those savings to you. A 50% discount is the industry standard:

  • OpenAI Batch API: 50% discount, results within 24 hours
  • Anthropic Message Batches API: 50% discount, results within 24 hours
  • Google Gemini Batch API: 50% discount on batch mode
  • Qubax AI: batch discounts across hundreds of models on the model catalog

The discount applies to every token — input and output. If you're spending $2,000/month on real-time API calls that could be batched, that's $12,000/year in savings.

When to Batch (and When Not To)

Batch processing shines for workloads where a delay of minutes-to-hours is acceptable:

Great candidates:

  • Document summarization and analysis
  • Product catalog enrichment and classification
  • Content moderation backfills
  • E-commerce product description generation
  • Embedding generation for search/RAG
  • Code migration and refactoring analysis
  • Log analysis and anomaly labeling
  • Review/rating sentiment analysis
  • Weekly report generation
  • Any nightly cron job

Poor candidates:

  • Interactive chat (user is waiting)
  • Real-time autocomplete
  • Live agents that need tool call responses
  • Trading or alerting systems

A simple heuristic: if a user is watching a spinner, don't batch. If nobody's waiting, batch.

How Batch APIs Work: The Core Pattern

All batch APIs follow the same lifecycle:

code
1. Prepare a JSONL file with your requests (each line = one request)
2. Upload the file
3. Create a batch job referencing the file
4. Poll until the batch completes (or use a webhook)
5. Download results as a JSONL file
6. Handle errors for failed individual requests

The key mental model: a batch is a container of up to tens of thousands of individual requests, each processed and billed independently at the discounted rate.

Tutorial: Building a Batch Pipeline

Let's build a realistic example: a product review sentiment analysis pipeline that processes 50,000 reviews. We'll use Python with the OpenAI-compatible interface that Qubax and most providers support.

Prerequisites

bash
pip install httpx

Step 1: Prepare the Batch Input File

Every request in the batch needs a unique custom_id so you can match results back to your source data:

python
import json

def build_batch_file(reviews: list[dict], model: str) -> list[str]:
    """Convert product reviews into batch request format."""
    lines = []
    for review in reviews:
        request = {
            "custom_id": f"review-{review['id']}",
            "method": "POST",
            "url": "/v1/chat/completions",
            "body": {
                "model": model,
                "messages": [
                    {
                        "role": "system",
                        "content": "You are a sentiment analyzer. Respond ONLY with valid JSON: {\"sentiment\": \"positive\"|\"negative\"|\"neutral\", \"score\": 0-100}"
                    },
                    {
                        "role": "user",
                        "content": f"Product: {review['product_name']}\nReview: {review['text']}"
                    }
                ],
                "temperature": 0,
                "max_tokens": 50
            }
        }
        lines.append(json.dumps(request))
    return lines

# Write JSONL file
reviews = [...]  # your 50,000 reviews
with open("batch_input.jsonl", "w") as f:
    f.write("\n".join(build_batch_file(reviews, model="gpt-5.6-luna")))

Step 2: Upload and Create the Batch

python
import httpx

API_BASE = "https://api.qubax.ai/v1"
API_KEY = "your-api-key"
headers = {"Authorization": f"Bearer {API_KEY}"}

# Upload the input file
with open("batch_input.jsonl", "rb") as f:
    upload = httpx.post(
        f"{API_BASE}/files",
        headers=headers,
        files={"file": ("batch_input.jsonl", f, "application/jsonl")},
        data={"purpose": "batch"}
    )
file_id = upload.json()["id"]

# Create the batch job
batch = httpx.post(
    f"{API_BASE}/batches",
    headers=headers,
    json={"input_file_id": file_id, "endpoint": "/v1/chat/completions", "completion_window": "24h"}
)
batch_id = batch.json()["id"]
print(f"Batch created: {batch_id}")

Step 3: Poll for Completion

python
import time

def wait_for_batch(batch_id: str, poll_interval: int = 60) -> dict:
    while True:
        resp = httpx.get(f"{API_BASE}/batches/{batch_id}", headers=headers)
        data = resp.json()
        status = data["status"]
        counts = data.get("request_counts", {})
        print(f"Status: {status} | completed: {counts.get('completed', 0)}/{counts.get('total', '?')}")
        
        if status in ("completed", "failed", "expired"):
            return data
        time.sleep(poll_interval)

result = wait_for_batch(batch_id)

Pro tip: If your provider supports batch completion webhooks, use them instead of polling — it's more reliable and avoids wasted API calls.

Step 4: Download and Process Results

python
def process_results(result: dict):
    # Download the output file
    output = httpx.get(
        f"{API_BASE}/files/{result['output_file_id']}/content",
        headers=headers
    )
    
    for line in output.text.splitlines():
        record = json.loads(line)
        custom_id = record["custom_id"]
        
        if record["status"] == "completed":
            content = record["response"]["body"]["choices"][0]["message"]["content"]
            sentiment = json.loads(content)  # our sentiment JSON
            save_to_db(custom_id, sentiment)
        else:
            log_failure(custom_id, record.get("error"))

<br clear="all">

Realistic Cost Comparison: Real-Time vs Batch

Let's run the numbers on our 50,000-review example. Assume average 300 input tokens and 50 output tokens per review. Using real prices from the Qubax model catalog (August 2026):

GPT-5.6 Luna (list: $0.20/M input, $1.20/M output):

  • Tokens: 15M input, 2.5M output
  • Real-time cost: 15 × $0.20 + 2.5 × $1.20 = $9.00
  • Batch (50% off): $4.50 — saving $4.50

That's cheap either way. Now scale to the model that matters:

Claude Opus 4.8 (list: $5.00/M input, $25.00/M output):

  • Tokens: 15M input, 2.5M output
  • Real-time cost: 15 × $5.00 + 2.5 × $25.00 = $137.50
  • Batch (50% off): $68.75 — saving $68.75 per run

Run that monthly and you're saving $825/year on a single pipeline. Stack pipelines and models, and batch processing routinely saves teams thousands per month.

Beyond the 50%: Four More Batch-Friendly Optimizations

Batch discounts stack with other techniques for compound savings:

1. Right-Size the Model

Don't use a flagship model for sentiment classification. A cheap model like GPT-5.6 Luna ($0.03/M input on Qubax) handles it fine. Route by task complexity — the Qubax model catalog makes it easy to compare pricing across 300+ models.

2. Cache Repeated Prompts

If many requests share the same long system prompt, prompt caching can cut input token costs by up to 90% on the cached portion. Batch files and prompt caching work together.

3. Trim Output Tokens

Output tokens are 3–25× more expensive than input tokens. Constrain max_tokens, ask for JSON only, and use stop sequences. Halving output length halves the most expensive part of your bill.

4. De-duplicate Before Batching

Run a hash of each input payload before adding it to the batch. If you've seen identical input+model+params before, reuse the cached result. Backfills often contain 10–30% duplicate content.

Production Checklist for Batch Pipelines

Before shipping your batch pipeline to production, make sure you have:

  • [x] Idempotency: store custom_id → result mapping so re-runs don't double-process
  • [x] Partial failure handling: a batch can complete with some requests failed; retry only failures, not the whole batch
  • [x] Monitoring: alert if a batch stays in validating/in_progress beyond your SLA (e.g., 26h for a 24h window)
  • [x] Budget caps: hard limits on tokens/month per pipeline so a bug can't 3am-page you with a $5,000 bill
  • [x] PII scrubbing: batch files can persist on provider infrastructure for up to 30 days; scrub sensitive fields before upload
  • [x] Schema validation: validate model JSON responses (e.g., with zod/pydantic) before writing to your DB

Common Pitfalls (and How to Avoid Them)

Pitfall 1: Forgetting `max_tokens` on cheap models. Small models can ramble. Without max_tokens, a $4 batch becomes $12.

Pitfall 2: Batching interactive traffic. Users notice a 24-hour delay. Audit your queues: anything user-facing shouldn't be in a batch file.

P3: Assuming provider consistency. Error formats differ. Normalize errors into your own retry taxonomy: transient (retry), schema (fix prompt), content policy (route to another model).

Pitfall 4: One giant batch for everything. A 50,000-request batch that fails validation wastes a day. Split into chunks of 5,000–10,000 requests for faster feedback and partial progress.

Pitfall 5: Ignoring rate limits on result processing. Downloading and processing 50,000 results can hammer your own DB. Backpressure matters on the consumer side too.

Conclusion

Batch processing is the highest-ROI cost optimization available for AI workloads that don't need real-time responses: a flat 50% discount on every token, for a few hours of integration work. Combined with model right-sizing, prompt caching, and output trimming, teams routinely cut their AI bills by 60–80% without changing output quality.

Start by auditing your current API usage: which calls have nobody waiting on them? Those are your first batch candidates. Build the pipeline once, and the savings repeat every month.

To explore batch pricing across hundreds of models — including GPT-5.6, Claude Opus 4.8, Gemini 3.1 Pro, and DeepSeek — visit Qubax AI or read the API documentation.

FAQ

What is an AI batch API?

A batch API lets you submit thousands of AI requests in a single file for bulk processing, instead of making individual real-time API calls. In exchange for accepting delayed results (typically within 24 hours), providers give you a 50% discount on all tokens.

How much can I save with batch processing?

50% off every token is the standard discount. A workload spending $1,000/month on batchable calls saves $500/month ($6,000/year). Combined with model right-sizing and prompt caching, total savings of 60–80% are common.

How long do batch jobs take?

Most providers complete batches within 24 hours, though many finish much faster during off-peak times. Some batches complete in under an hour. Poll your batch status or use a completion webhook to know exactly when results are ready.

Can I mix different models in one batch?

Typically no — each batch references a single endpoint and model. To use multiple models, create separate batches per model. Some platforms like Qubax let you manage all of them from one place with unified billing.

What happens if some requests in a batch fail?

Individual request failures don't fail the whole batch. Each request is processed independently; failed ones are listed in the batch's error file with per-request error details. You retry only the failed custom_ids, not the entire batch.

Is batch processing worth it for small volumes?

For fewer than ~100 requests/day, the integration effort may outweigh savings. But if those requests use expensive models (e.g., Claude Opus 4.8 at $25/M output tokens), even small volumes can justify batching — 100 long analyses a month can mean $50+ in monthly savings.

Where can I find current batch pricing for all models?

Check the Qubax AI model catalog for up-to-date pricing on 300+ models, and the documentation for batch API specifics.

💎

Try Gemini on Qubax

Google AI models on Qubax. Up to 94% off.

View pricing

Article tags

#batch API#AI API costs#developer tutorial#cost optimization
Share:Post on XTelegramLinkedInYHacker NewsReddit
Qubax AI

Qubax AI

AI Models at up to 99% off · Pay with crypto

Reading about Gemini? Access it — plus 340+ other models — through one API. Google AI models on Qubax. Up to 94% off.

Related articles