Skip to main content

Batching and throughput

The defaults work for most connectors. Reach for these knobs when a crawl is timing out, running too slowly, or overwhelming your source.

KnobWhereDefaultReach for it when…
connector.batch_sizeConnector attribute1000Batches time out — lower it.
max_batch_bytesPushUploader argument5 MiBRarely. This tracks the API payload limit.
upload_timeout_msConnectorOptionsclient defaultLarge batches hit timeouts.
upload_max_workersConnectorOptions5Many small batches over a high-latency link.

Find the bottleneck first

Before tuning anything, look at where time is going. The SDK times fetch, transform, and upload separately:

connector.index_data(mode=IndexingMode.FULL)
print(connector.observability.get_metrics_summary())
Dominant stageLikely fix
data_fetchSource API is slow or rate-limited. Tune rate limiting, reduce N+1 detail calls, or use a streaming connector to overlap work.
data_transformExpensive work in transform() — HTML parsing, regex, per-document network calls. Move network calls into the data client.
data_uploadTune the knobs below.

Tuning upload concurrency when 90% of wall-clock is data_fetch accomplishes nothing. See Observability.

Batch size

Batches close on whichever limit hits first: batch_size documents or max_batch_bytes serialized bytes.

connector = WikiConnector(name="wiki", data_client=client)
connector.batch_size = 250

Lower batch_size when your documents are large. A connector indexing full page bodies will hit the 5 MiB byte cap long before 1000 documents, so the count limit is doing nothing and you're paying serialization cost to discover that each time. Setting batch_size closer to what actually fits makes batching cheaper and upload sizes more predictable.

Raising batch_size above 1000 is rarely useful — the byte cap almost always binds first.

Timeouts

A batch that exceeds the request timeout fails and retries the whole batch, which is expensive. If you see timeouts, do one of:

# Give large batches longer.
connector.index_data(options=ConnectorOptions(upload_timeout_ms=120_000))

# Or make the batches smaller.
connector.batch_size = 250

Smaller batches are usually the better answer. They fail cheaper, retry faster, and give more granular progress in logs.

Concurrency

upload_max_workers controls how many middle pages upload at once:

connector.index_data(options=ConnectorOptions(upload_max_workers=10))

The first and last pages are always sequential — the first opens the upload session, the last closes it and triggers stale-document deletion.

Concurrency helps when you're latency-bound: many small batches, each spending most of its time waiting on the network. It doesn't help when you're bandwidth-bound or when the source is the bottleneck. Set it to 1 to serialize uploads while debugging.

Memory

For in-memory connectors, peak memory holds every source record and every transformed document simultaneously. If a full crawl gets OOM-killed, the fix isn't a smaller batch size — batching happens after transform. Switch to a streaming connector, which transforms and uploads one batch at a time and keeps memory bounded regardless of total document count.