TutorialCost Optimization

LLM Batch API: Async Jobs, Retries, and Cost Planning

Run an embedding batch through DeltaLLM: upload JSONL, track progress, and download results. Learn what async processing saves and what it does not discount.

DeltaLLM Team April 5, 2026Updated October 10, 2026 9 min read
Short answer: DeltaLLM's batch API turns a JSONL file into a tracked async job with retries and downloadable results. Use it for embeddings and, on versions that support it, non-streaming chat completions. Queuing work does not automatically reduce the model provider's token price.

Start with a small job before submitting a whole knowledge base. This walkthrough embeds two sample documents, checks item-level results, and shows how to assess cost without assuming a provider discount.

Gateway batch jobs and provider batch pricing are different

MechanismWhat it changesWhat to verify
Gateway async queueWhen work runs; progress, retry, and result handlingWorker capacity, completion time, failures, and storage cost
Embedding micro-batchingCombines eligible inputs into fewer upstream requestsProvider support and measured throughput; token rates may stay unchanged
Lower-cost modelProvider charges for the selected modelOutput quality and, for embeddings, dimensions and retrieval quality
Provider-native async batchMay use the provider's separate batch pricingWhether the gateway actually submits to that provider's native batch service

The current DeltaLLM batch documentation describes an internal worker queue. It does not use provider-native async chat batch APIs in this release. Do not assume a provider's advertised batch discount applies to jobs submitted here.

See the batch API and production setup reference for your installed version. Older releases may support embeddings only; chat batches require a version with non-streaming chat support.

Run a two-document embedding batch

1. Prepare the gateway

Complete the Docker setup, then configure an embedding deployment named text-embedding-3-small. The starter chat deployment alone is not enough. Create an application key with access to the embedding target and enough budget for the job.

Enable batching in your existing config.yaml and restart the gateway. Ensure the batch worker is enabled for your deployment. This single-instance evaluation uses local storage; use the production reference when separating API and worker instances.

terminal
general_settings:
  embeddings_batch_enabled: true

Set DELTALLM_API_KEY to the scoped key. The single-instance Compose address is http://localhost:4002. The curl steps below use jq to read JSON response IDs.

2. Create and upload the JSONL input

Save these two lines as input.jsonl, or download the sample input. Keep the custom_id unique so each result can be matched back to its source document.

terminal
{"custom_id":"support-refunds","method":"POST","url":"/v1/embeddings","body":{"model":"text-embedding-3-small","input":"Refund requests are reviewed within two working days."}}
{"custom_id":"support-delivery","method":"POST","url":"/v1/embeddings","body":{"model":"text-embedding-3-small","input":"Customers can track a delivery using the order reference."}}
terminal
export DELTALLM_BASE_URL=http://localhost:4002

FILE_ID=$(curl --fail-with-body -sS "$DELTALLM_BASE_URL/v1/files" \
  -H "Authorization: Bearer $DELTALLM_API_KEY" \
  -F "purpose=batch" -F "[email protected]" | jq -er '.id')
printf 'Input file: %s\n' "$FILE_ID"

3. Submit the job

terminal
BATCH_ID=$(curl --fail-with-body -sS "$DELTALLM_BASE_URL/v1/batches" \
  -H "Authorization: Bearer $DELTALLM_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --arg id "$FILE_ID" '{
    input_file_id: $id,
    endpoint: "/v1/embeddings",
    completion_window: "24h"
  }')" | jq -er '.id')
printf 'Batch: %s\n' "$BATCH_ID"

Use the supported 24h completion-window value. It is an API setting, not a promise that every job succeeds within that time.

4. Inspect progress and download both result files

terminal
curl --fail-with-body -sS "$DELTALLM_BASE_URL/v1/batches/$BATCH_ID" \
  -H "Authorization: Bearer $DELTALLM_API_KEY" | jq .

Poll with a delay while the job is active. Check status, request_counts, output_file_id, and error_file_id. Download the output file when available and inspect the error file too: a completed job can contain failed items. Match records by custom_id rather than relying on line order.

For a complete client that polls with a time limit and downloads both files, use the Python embedding batch example. It uses requests; install it with python -m pip install requests, then run python embedding-batch.py input.jsonl.

DeltaLLM Batch Jobs page showing completed demo jobs, progress, teams, and cost
Inspect job progress, ownership, and cost in Batch Jobs. Model labels, costs, and durations are demo data, not benchmark results.

Estimate savings with explicit assumptions

Suppose a workload uses 10 million input tokens. An existing embedding model costs an illustrative $0.10 per million tokens and a suitable alternative costs $0.04. These are arithmetic assumptions, not current provider prices or measured DeltaLLM savings.

terminal
Existing model: 10 million tokens × $0.10 / million = $1.00
Alternative:    10 million tokens × $0.04 / million = $0.40
Difference:     $1.00 − $0.40 = $0.60, or 60%

Same model and same token rate in an async queue:
10 million tokens × $0.10 / million = $1.00 before extra costs

The 60% comes from the assumed model price difference, not the queue. Include retries, gateway compute, storage, and any output-token charges for chat workloads. Changing an embedding model may require re-indexing and retrieval-quality testing.

For an actual comparison, process the same document set with the same chunking and model settings. Record billed tokens, failed items, retry count, elapsed time, and worker cost. Report cost per successfully processed document alongside quality, rather than comparing only nominal token prices.

The broader cost-management guide covers budgets and routing. A budget controls spend; it does not itself make each request cheaper.

Before scaling beyond the example

  • Protect interactive capacity: bound worker concurrency and tune model-capacity allocation before sharing a provider with live chat traffic.
  • Keep policies consistent: batch execution rechecks access and budgets. Permanent policy failures are not fixed by retrying.
  • Use shared storage: separate workers and API replicas need shared artifact storage, such as S3-compatible storage, and distributed coordination.
  • Handle partial success: inspect failed items and resubmit only the intended failures. Avoid replaying the entire successful job.

For chat batches, change the endpoint and each JSONL request body to /v1/chat/completions, use a permitted chat target, and omit streaming. Current documentation excludes MCP tools in chat batch requests. Do not mix embedding and chat endpoints in one job.

Use async jobs when results can wait and you need reliable progress and result handling. Start with the setup guide, then check the production batch reference before increasing volume.

Try DeltaLLM

Set up DeltaLLM on Railway for a small test, or explore a related guide before you deploy.

Railway sets up DeltaLLM, PostgreSQL, and Redis. Requires a Railway account and gateway/admin credentials; add an AI provider to make requests. Hosting may incur charges.

Prefer another deployment option? Read the setup guide.