liveBook · Manning

Batching

As explained in Building Reliable AI Systems

Temporarily grouping incoming application requests to manage concurrency and reduce processing overhead.

Batching groups incoming LLM requests briefly before dispatching them. When traffic surges, an application can use a queue to control concurrency and smooth demand instead of starting every request immediately. The trade-off is a short wait while requests collect; under heavy load, throughput and overall response times can improve. section 9.2.2

Choose the batching mechanism to match the workload:

  • For interactive traffic, queue requests in the application. Drain up to a target batch size on a repeating interval, then dispatch their model calls concurrently. Each query remains a separate Chat Completion call; this does not bundle multiple prompts into one endpoint request. section 9.2.2
  • For large jobs that can wait, use the OpenAI Batch API instead. It processes offline-style API work at lower cost but with longer turnaround; the illustrated submission specifies a 24-hour completion window. The two approaches can coexist. section 9.2.2

Holiday-sale customer support

An online store’s support chatbot receives bursts of product, refund, and policy questions during a sale. An asyncio.Queue holds each query with its callback and streaming preference. A background processor takes up to two requests per cycle, creates a task for each, awaits them together, and then sleeps for one second. The request handler separately chooses a model and either streams a reply or retrieves a cached answer. Batching manages the burst; semantic caching and model fallback address repeated questions and expensive calls. section 9.2.5 section 9.2.5

async def batch_processor(batch_size: int = 2, interval: float = 1.0):
    """
    Periodically collects up to batch_size requests from request_queue,
    processes them in one go, then sleeps 'interval' seconds before repeating.
    This reduces overhead spikes when many users query at once.
    """
    while True:
        batch = []
        try:
            while len(batch) < batch_size:
                item = request_queue.get_nowait()
                batch.append(item)
        except asyncio.QueueEmpty:
            pass

        if batch:
            tasks = []
            for r in batch:
                tasks.append(asyncio.create_task(handle_request(r)))
            await asyncio.gather(*tasks)

        await asyncio.sleep(interval)

The processor shows the operational boundary: drain a limited number of queued items, launch one task per item, await the group, and pause before checking again. section 9.2.5

How Building Reliable AI Systems covers it

How deep it goes
Works through an asyncio queue and periodic processor, while distinguishing separate per-query calls from offline Batch API jobs.
Examples
Uses an asyncio queue, a two-request customer-support processor, and a Batch API submission with a 24-hour completion window.
What it assumes
Assumes Python and API familiarity; illustrates asynchronous queue handling rather than teaching those foundations from zero.
What you can do after
Build it from scratch: queue interactive requests, dispatch bounded groups, and choose offline processing when longer turnaround is acceptable.
How it connects
Connects batching to token streaming, semantic caching, multimodel fallback, and rate limiting.

Also explained in

Compare how 15 books explain batching →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Building Reliable AI Systems. The section links point to the parts of the book it draws on.