From 233b3e058debf6910359f11b7db791ebe210e556 Mon Sep 17 00:00:00 2001 From: Lior Aronovich Date: Wed, 20 May 2026 08:00:46 -0400 Subject: [PATCH 1/9] docs: Blog post on batch gateway Signed-off-by: Lior Aronovich --- ...able-batch-inference-with-batch-gateway.md | 112 ++++++++++++++++++ blog/authors.yml | 21 ++++ blog/tags.yml | 7 +- static/img/blogs/jooyeonmok.webp | Bin 0 -> 15950 bytes static/img/blogs/lioraronovich.webp | Bin 0 -> 7814 bytes static/img/blogs/raymondzhao.webp | Bin 0 -> 13678 bytes 6 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md create mode 100644 static/img/blogs/jooyeonmok.webp create mode 100644 static/img/blogs/lioraronovich.webp create mode 100644 static/img/blogs/raymondzhao.webp diff --git a/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md b/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md new file mode 100644 index 000000000..514b5356b --- /dev/null +++ b/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md @@ -0,0 +1,112 @@ +--- +title: "Scalable Batch Inference with Batch Gateway" +description: "Batch Gateway brings first-class batch inference capabilities to llm-d, providing an OpenAI-compatible API for submitting, tracking, and managing large-scale batch jobs while coexisting with interactive inference on shared infrastructure." +slug: scalable-batch-inference-with-batch-gateway +date: 2026-05-04T09:00 + +authors: + - lioraronovich + - raymondzhao + - jooyeonmok + +tags: [blog, batch-inference, inference, llm-d] +--- + +# Scalable Batch Inference with Batch Gateway + +As organizations deploy AI applications in production, their inference infrastructure must serve two fundamentally different workloads simultaneously: interactive requests requiring immediate replies, and batch inference jobs that process thousands of requests with a time tolerance of hours for receiving results. Use cases for batch inference include bulk document analysis, embedding generation for large corpora, and model evaluations across large datasets. + +In batch inference, instead of optimizing for low latency on individual requests, the goal is to maximize throughput across a large volume of requests while meeting defined completion time targets. Users can take advantage of differential billing between batch and interactive workloads by shifting non-urgent inference work to batch processing. The result is cost-optimized processing with minimal impact on interactive inference. + +[**Batch Gateway**](https://github.com/llm-d-incubation/batch-gateway) brings first-class batch inference capabilities to llm-d. It provides an OpenAI-compatible API for submitting, tracking, and managing large-scale batch jobs, while coexisting with interactive inference workloads on shared infrastructure. With OpenAI API compatibility, users can migrate existing OpenAI batch scripts with minimal changes. + + + +## The challenge: batch and interactive workloads on shared infrastructure + +Running batch and interactive inference workloads side by side creates a tension that most inference platforms don't address well. Interactive traffic requires low latency and predictable response times. Batch workloads need sustained throughput over extended periods. + +When both compete for the same GPU resources without purpose-built tools, the outcomes are typically poor: + +- **Letting batch workloads degrade interactive performance** is unacceptable for production services. +- **Dedicating separate GPU pools for batch workloads** is expensive and wasteful. +- **Manually throttling batch workloads** is operationally burdensome. + +Batch Gateway is designed to solve this with intelligent flow control between batch and interactive workloads, using downstream system metrics to dynamically adjust the rate of batch requests. Batch Gateway also prioritizes jobs based on their Service Level Objective (SLO) targets, and processes requests within each job concurrently. When submitting a batch job, users specify a requested completion window, and the system prioritizes work to meet these targets. The result is that batch jobs make steady progress toward their SLO without interfering with interactive traffic. + +## How Batch Gateway works + +Batch Gateway is a Kubernetes-native system composed of several components: + + + + +### API Server + +The API server exposes OpenAI-compatible `/v1/batches` and `/v1/files` endpoints, providing the same interface that users and applications already use for batch processing. + +### Data layer + +Batch Gateway uses pluggable storage backends for different functions. Each function is backed by a single plug-in, chosen at deployment time. + +| Function | Available plug-ins | +|----------|-------------------| +| Jobs and files metadata storage | PostgreSQL, Redis | +| Priority queue for jobs | Redis | +| Event channels | Redis | +| Jobs status updates | Redis | +| File storage for input and output files | S3, Filesystem | + +A garbage collector process periodically cleans expired batch jobs and their associated files. + +### Batch Processor + +The batch processor pulls jobs from a priority queue, retrieves the input file, builds execution plans, and dispatches individual inference requests with concurrency control for downstream processing. As inference results come back, the processor writes them to an output file and continuously updates the job's status. The processor also listens for job events such as cancellation, enabling real-time control over in-flight work. In addition, the processor handles recovery from crashes during processing. + +## Integration with llm-d inference components + +Batch Gateway is part of [llm-d](https://github.com/llm-d/llm-d), an open source Kubernetes-native framework for high-performance distributed LLM inference. Batch Gateway integrates with llm-d's components, which means that batch workloads automatically benefit from llm-d's efficient inference capabilities, such as intelligent request routing and KV-cache reuse. + +Batch Gateway is designed to work with the [Flow Control](https://gateway-api-inference-extension.sigs.k8s.io/concepts/flow-control/) component in the [Gateway API Inference Extension](https://github.com/kubernetes-sigs/gateway-api-inference-extension) (GIE) to enable dynamic tuning of batch workload flows as well as SLO-based prioritization. This integration allows the system to: + +- **Classify batch requests as sheddable:** Batch requests are assigned a negative priority, so the inference layer can shed them under saturation while protecting interactive traffic. +- **Order by SLO urgency:** Batch requests carry a deadline header (`x-slo-ttft-ms`) that GIE uses to prioritize jobs closest to their SLO deadline. +- **Enable per-tenant fairness:** The processor sends a fairness header (`x-gateway-inference-fairness-id`) with the tenant identifier, enabling round-robin fairness within the batch priority band. + +In the future, Batch Gateway is planned to support extended integrations with relevant llm-d components, as well as with additional components in the LLM inference ecosystem. + +## Observability, security, and operations + +Batch Gateway is built for production operations out of the box: + +- **Prometheus metrics** enable monitoring of job processing and API handling. +- **OpenTelemetry tracing** enables end-to-end request visibility across components. +- **Health and readiness probes** for Kubernetes-native lifecycle management. +- **Security hardened:** + - TLS / mTLS support for backend connections. + - Authentication and authorization integration. + - Multi-tenancy isolation. + - Security headers, HTTP server hardening, and input validation. + - Pod security: non-root execution, read-only filesystem, all capabilities dropped, seccomp, no privilege escalation. + +## Getting started + +To learn more about Batch Gateway, check out the following resources: + +- To run a local demo using a *kind* cluster, see the [demo resources](https://github.com/llm-d-incubation/batch-gateway/tree/main/scripts/demo) and [prerequisites](https://github.com/llm-d-incubation/batch-gateway/blob/main/docs/guides/development.md#prerequisites). +- To deploy in a Kubernetes cluster using demo settings, see the [demo deployment resources](https://github.com/llm-d-incubation/batch-gateway/blob/main/scripts/dev-deploy). +- For detailed deployment and setup instructions, see the [Kubernetes deployment guide](https://github.com/llm-d-incubation/batch-gateway/blob/main/docs/guides/deploy-k8s.md). +- The project's [documentation](https://github.com/llm-d-incubation/batch-gateway) includes the main readme, [guides](https://github.com/llm-d-incubation/batch-gateway/tree/main/docs/guides), and [design documents](https://github.com/llm-d-incubation/batch-gateway/tree/main/docs/design). + +## Get involved with llm-d + +Batch Gateway is developed in the open as part of the llm-d ecosystem. If you're running LLM inference at scale and need batch processing capabilities, we'd love to have you involved. + +* **Explore the code** -- Browse the [Batch Gateway repo](https://github.com/llm-d-incubation/batch-gateway) and the wider [llm-d organization](https://github.com/llm-d) +* **Join our Slack** -- [Get your invite](/slack) and connect with maintainers and contributors +* **Attend community calls** -- All meetings are open! Add our [public calendar](https://red.ht/llm-d-public-calendar) (Wednesdays 12:30pm ET) and join the conversation +* **Follow project updates** -- Stay current on [Twitter/X](https://twitter.com/_llm_d_), [Bluesky](https://bsky.app/profile/llm-d.ai), and [LinkedIn](https://www.linkedin.com/company/llm-d) +* **Watch demos and recordings** -- Subscribe to the [llm-d YouTube channel](https://www.youtube.com/@llm-d-project) for community call recordings and feature walkthroughs +* **Read the docs** -- Visit our [community page](/docs/community) to find SIGs, contribution guides, and upcoming events diff --git a/blog/authors.yml b/blog/authors.yml index fe147924a..04ab74683 100644 --- a/blog/authors.yml +++ b/blog/authors.yml @@ -198,3 +198,24 @@ abdullahgharaibeh: url: https://github.com/ahg-g image_url: https://avatars.githubusercontent.com/u/40361897?v=4 +lioraronovich: + name: Lior Aronovich + title: Senior Principal Software Engineer, Red Hat + image_url: /img/blogs/lioraronovich.webp + socials: + github: https://github.com/lioraron + +raymondzhao: + name: Raymond Zhao + title: Principal Software Engineer, Red Hat + image_url: /img/blogs/raymondzhao.webp + socials: + github: https://github.com/yizhaodev + +jooyeonmok: + name: Jooyeon Mok + title: Software Engineer, Red Hat + image_url: /img/blogs/jooyeonmok.webp + socials: + github: https://github.com/j-mok-dev + diff --git a/blog/tags.yml b/blog/tags.yml index ffa08769c..4c3bd4335 100644 --- a/blog/tags.yml +++ b/blog/tags.yml @@ -97,4 +97,9 @@ scheduling: inference: label: Inference permalink: /inference - description: LLM inference serving and optimization \ No newline at end of file + description: LLM inference serving and optimization + +batch-inference: + label: Batch Inference + permalink: /batch-inference + description: Batch inference processing for LLM workloads \ No newline at end of file diff --git a/static/img/blogs/jooyeonmok.webp b/static/img/blogs/jooyeonmok.webp new file mode 100644 index 0000000000000000000000000000000000000000..25615808bfa559c57effb2878fbc7b1c2f1d5552 GIT binary patch literal 15950 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 literal 0 HcmV?d00001 diff --git a/static/img/blogs/lioraronovich.webp b/static/img/blogs/lioraronovich.webp new file mode 100644 index 0000000000000000000000000000000000000000..66ecd1e7ec5d75305cc6ce93280746bbe96079d1 GIT binary patch literal 7814 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 Yd2HVXx&t)JM*+Tje`cRxn`VH30Q;-`<^TWy literal 0 HcmV?d00001 diff --git a/static/img/blogs/raymondzhao.webp b/static/img/blogs/raymondzhao.webp new file mode 100644 index 0000000000000000000000000000000000000000..93f25a2f5539d288d6922013409d066aaef32c32 GIT binary patch literal 13678 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 Date: Wed, 10 Jun 2026 16:26:05 -0400 Subject: [PATCH 2/9] chore: update batch-gateway repo links after transfer Update GitHub URLs from llm-d-incubation/batch-gateway to llm-d/llm-d-batch-gateway in the batch gateway blog post. Ref: https://github.com/llm-d/llm-d-batch-gateway/issues/482 Co-Authored-By: Claude Opus 4.6 Signed-off-by: Lior Aronovich --- ...4_scalable-batch-inference-with-batch-gateway.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md b/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md index 514b5356b..804961ef1 100644 --- a/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md +++ b/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md @@ -8,6 +8,7 @@ authors: - lioraronovich - raymondzhao - jooyeonmok + - niliguy tags: [blog, batch-inference, inference, llm-d] --- @@ -18,7 +19,7 @@ As organizations deploy AI applications in production, their inference infrastru In batch inference, instead of optimizing for low latency on individual requests, the goal is to maximize throughput across a large volume of requests while meeting defined completion time targets. Users can take advantage of differential billing between batch and interactive workloads by shifting non-urgent inference work to batch processing. The result is cost-optimized processing with minimal impact on interactive inference. -[**Batch Gateway**](https://github.com/llm-d-incubation/batch-gateway) brings first-class batch inference capabilities to llm-d. It provides an OpenAI-compatible API for submitting, tracking, and managing large-scale batch jobs, while coexisting with interactive inference workloads on shared infrastructure. With OpenAI API compatibility, users can migrate existing OpenAI batch scripts with minimal changes. +[**Batch Gateway**](https://github.com/llm-d/llm-d-batch-gateway) brings first-class batch inference capabilities to llm-d. It provides an OpenAI-compatible API for submitting, tracking, and managing large-scale batch jobs, while coexisting with interactive inference workloads on shared infrastructure. With OpenAI API compatibility, users can migrate existing OpenAI batch scripts with minimal changes. @@ -95,16 +96,16 @@ Batch Gateway is built for production operations out of the box: To learn more about Batch Gateway, check out the following resources: -- To run a local demo using a *kind* cluster, see the [demo resources](https://github.com/llm-d-incubation/batch-gateway/tree/main/scripts/demo) and [prerequisites](https://github.com/llm-d-incubation/batch-gateway/blob/main/docs/guides/development.md#prerequisites). -- To deploy in a Kubernetes cluster using demo settings, see the [demo deployment resources](https://github.com/llm-d-incubation/batch-gateway/blob/main/scripts/dev-deploy). -- For detailed deployment and setup instructions, see the [Kubernetes deployment guide](https://github.com/llm-d-incubation/batch-gateway/blob/main/docs/guides/deploy-k8s.md). -- The project's [documentation](https://github.com/llm-d-incubation/batch-gateway) includes the main readme, [guides](https://github.com/llm-d-incubation/batch-gateway/tree/main/docs/guides), and [design documents](https://github.com/llm-d-incubation/batch-gateway/tree/main/docs/design). +- To run a local demo using a *kind* cluster, see the [demo resources](https://github.com/llm-d/llm-d-batch-gateway/tree/main/scripts/demo) and [prerequisites](https://github.com/llm-d/llm-d-batch-gateway/blob/main/docs/guides/development.md#prerequisites). +- To deploy in a Kubernetes cluster using demo settings, see the [demo deployment resources](https://github.com/llm-d/llm-d-batch-gateway/blob/main/scripts/dev-deploy). +- For detailed deployment and setup instructions, see the [Kubernetes deployment guide](https://github.com/llm-d/llm-d-batch-gateway/blob/main/docs/guides/deploy-k8s.md). +- The project's [documentation](https://github.com/llm-d/llm-d-batch-gateway) includes the main readme, [guides](https://github.com/llm-d/llm-d-batch-gateway/tree/main/docs/guides), and [design documents](https://github.com/llm-d/llm-d-batch-gateway/tree/main/docs/design). ## Get involved with llm-d Batch Gateway is developed in the open as part of the llm-d ecosystem. If you're running LLM inference at scale and need batch processing capabilities, we'd love to have you involved. -* **Explore the code** -- Browse the [Batch Gateway repo](https://github.com/llm-d-incubation/batch-gateway) and the wider [llm-d organization](https://github.com/llm-d) +* **Explore the code** -- Browse the [Batch Gateway repo](https://github.com/llm-d/llm-d-batch-gateway) and the wider [llm-d organization](https://github.com/llm-d) * **Join our Slack** -- [Get your invite](/slack) and connect with maintainers and contributors * **Attend community calls** -- All meetings are open! Add our [public calendar](https://red.ht/llm-d-public-calendar) (Wednesdays 12:30pm ET) and join the conversation * **Follow project updates** -- Stay current on [Twitter/X](https://twitter.com/_llm_d_), [Bluesky](https://bsky.app/profile/llm-d.ai), and [LinkedIn](https://www.linkedin.com/company/llm-d) From 98b907979ce105cab18cd8f5e0ce4d9d49887e34 Mon Sep 17 00:00:00 2001 From: Lior Aronovich Date: Wed, 10 Jun 2026 16:42:32 -0400 Subject: [PATCH 3/9] chore: refresh batch-gateway blog with updated messaging Add background agent use cases, KV-cache eviction challenge, system-prompt hash sorting, and CNCF Sandbox status. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Lior Aronovich --- ...04_scalable-batch-inference-with-batch-gateway.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md b/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md index 804961ef1..f54679b9f 100644 --- a/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md +++ b/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md @@ -15,7 +15,7 @@ tags: [blog, batch-inference, inference, llm-d] # Scalable Batch Inference with Batch Gateway -As organizations deploy AI applications in production, their inference infrastructure must serve two fundamentally different workloads simultaneously: interactive requests requiring immediate replies, and batch inference jobs that process thousands of requests with a time tolerance of hours for receiving results. Use cases for batch inference include bulk document analysis, embedding generation for large corpora, and model evaluations across large datasets. +As organizations deploy AI applications in production, their inference infrastructure must serve two fundamentally different workloads simultaneously: interactive requests requiring immediate replies, and batch inference jobs that process thousands of requests with a time tolerance of hours for receiving results. Use cases for batch inference include autonomous background agents performing multi-step reasoning and deep research, as well as user-initiated workloads like offline evaluations, dataset processing, and embedding generation. In batch inference, instead of optimizing for low latency on individual requests, the goal is to maximize throughput across a large volume of requests while meeting defined completion time targets. Users can take advantage of differential billing between batch and interactive workloads by shifting non-urgent inference work to batch processing. The result is cost-optimized processing with minimal impact on interactive inference. @@ -30,6 +30,7 @@ Running batch and interactive inference workloads side by side creates a tension When both compete for the same GPU resources without purpose-built tools, the outcomes are typically poor: - **Letting batch workloads degrade interactive performance** is unacceptable for production services. +- **Batch requests evict KV-cache entries** needed by interactive workloads, forcing costly prefill reconstruction. - **Dedicating separate GPU pools for batch workloads** is expensive and wasteful. - **Manually throttling batch workloads** is operationally burdensome. @@ -40,9 +41,6 @@ Batch Gateway is designed to solve this with intelligent flow control between ba Batch Gateway is a Kubernetes-native system composed of several components: - ### API Server @@ -60,15 +58,15 @@ Batch Gateway uses pluggable storage backends for different functions. Each func | Jobs status updates | Redis | | File storage for input and output files | S3, Filesystem | -A garbage collector process periodically cleans expired batch jobs and their associated files. +Expired batch jobs and their associated files are periodically cleaned up. ### Batch Processor -The batch processor pulls jobs from a priority queue, retrieves the input file, builds execution plans, and dispatches individual inference requests with concurrency control for downstream processing. As inference results come back, the processor writes them to an output file and continuously updates the job's status. The processor also listens for job events such as cancellation, enabling real-time control over in-flight work. In addition, the processor handles recovery from crashes during processing. +The batch processor pulls jobs from a priority queue, retrieves the input file, builds execution plans, and dispatches individual inference requests with concurrency control for downstream processing. The processor sorts requests by system-prompt hash to maximize prefix cache hits, reducing redundant prefill computation across requests that share the same system prompt. As inference results come back, the processor writes them to an output file and continuously updates the job's status. The processor also listens for job events such as cancellation, enabling real-time control over in-flight work. In addition, the processor handles recovery from crashes during processing. ## Integration with llm-d inference components -Batch Gateway is part of [llm-d](https://github.com/llm-d/llm-d), an open source Kubernetes-native framework for high-performance distributed LLM inference. Batch Gateway integrates with llm-d's components, which means that batch workloads automatically benefit from llm-d's efficient inference capabilities, such as intelligent request routing and KV-cache reuse. +Batch Gateway is part of [llm-d](https://github.com/llm-d/llm-d), a CNCF Sandbox project and open source Kubernetes-native framework for high-performance distributed LLM inference. Batch Gateway integrates with llm-d's components, which means that batch workloads automatically benefit from llm-d's efficient inference capabilities, such as intelligent request routing and KV-cache reuse. Batch Gateway is designed to work with the [Flow Control](https://gateway-api-inference-extension.sigs.k8s.io/concepts/flow-control/) component in the [Gateway API Inference Extension](https://github.com/kubernetes-sigs/gateway-api-inference-extension) (GIE) to enable dynamic tuning of batch workload flows as well as SLO-based prioritization. This integration allows the system to: From 2ffee62398c72923280c4e6115938fc58fc381f0 Mon Sep 17 00:00:00 2001 From: Lior Aronovich Date: Fri, 12 Jun 2026 11:57:11 -0400 Subject: [PATCH 4/9] chore: refine batch-gateway blog content and add architecture diagram Update use cases, simplify challenge section, add GPU utilization and infrastructure capacity framing, and include architecture diagram. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Lior Aronovich --- ...able-batch-inference-with-batch-gateway.md | 18 +++++++++--------- .../img/blog-images/batch-gateway-arch.webp | Bin 0 -> 56432 bytes 2 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 static/img/blog-images/batch-gateway-arch.webp diff --git a/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md b/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md index f54679b9f..74764eec3 100644 --- a/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md +++ b/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md @@ -1,8 +1,8 @@ --- title: "Scalable Batch Inference with Batch Gateway" -description: "Batch Gateway brings first-class batch inference capabilities to llm-d, providing an OpenAI-compatible API for submitting, tracking, and managing large-scale batch jobs while coexisting with interactive inference on shared infrastructure." +description: "Batch Gateway brings first-class batch inference capabilities to llm-d, providing an OpenAI-compatible API for submitting, tracking, and managing large-scale batch jobs, running efficiently alongside interactive inference on shared infrastructure." slug: scalable-batch-inference-with-batch-gateway -date: 2026-05-04T09:00 +date: 2026-06-12T09:00 authors: - lioraronovich @@ -17,30 +17,30 @@ tags: [blog, batch-inference, inference, llm-d] As organizations deploy AI applications in production, their inference infrastructure must serve two fundamentally different workloads simultaneously: interactive requests requiring immediate replies, and batch inference jobs that process thousands of requests with a time tolerance of hours for receiving results. Use cases for batch inference include autonomous background agents performing multi-step reasoning and deep research, as well as user-initiated workloads like offline evaluations, dataset processing, and embedding generation. -In batch inference, instead of optimizing for low latency on individual requests, the goal is to maximize throughput across a large volume of requests while meeting defined completion time targets. Users can take advantage of differential billing between batch and interactive workloads by shifting non-urgent inference work to batch processing. The result is cost-optimized processing with minimal impact on interactive inference. +In batch inference, the goal is to maximize throughput across a large volume of requests while meeting defined completion time targets, without interfering with interactive traffic. Non-urgent inference can fill GPU capacity during periods of lower interactive traffic, increasing infrastructure utilization. Users can also take advantage of differential billing between batch and interactive workloads for cost-optimized processing. -[**Batch Gateway**](https://github.com/llm-d/llm-d-batch-gateway) brings first-class batch inference capabilities to llm-d. It provides an OpenAI-compatible API for submitting, tracking, and managing large-scale batch jobs, while coexisting with interactive inference workloads on shared infrastructure. With OpenAI API compatibility, users can migrate existing OpenAI batch scripts with minimal changes. +[**Batch Gateway**](https://github.com/llm-d/llm-d-batch-gateway) brings first-class batch inference capabilities to llm-d. It provides an OpenAI-compatible API for submitting, tracking, and managing large-scale batch jobs, running efficiently alongside interactive inference workloads on shared infrastructure. With OpenAI API compatibility, users can migrate existing OpenAI batch scripts with minimal changes. ## The challenge: batch and interactive workloads on shared infrastructure -Running batch and interactive inference workloads side by side creates a tension that most inference platforms don't address well. Interactive traffic requires low latency and predictable response times. Batch workloads need sustained throughput over extended periods. - -When both compete for the same GPU resources without purpose-built tools, the outcomes are typically poor: +When batch and interactive inference workloads compete for the same GPU resources without purpose-built tools, the outcomes are typically poor: - **Letting batch workloads degrade interactive performance** is unacceptable for production services. - **Batch requests evict KV-cache entries** needed by interactive workloads, forcing costly prefill reconstruction. - **Dedicating separate GPU pools for batch workloads** is expensive and wasteful. - **Manually throttling batch workloads** is operationally burdensome. -Batch Gateway is designed to solve this with intelligent flow control between batch and interactive workloads, using downstream system metrics to dynamically adjust the rate of batch requests. Batch Gateway also prioritizes jobs based on their Service Level Objective (SLO) targets, and processes requests within each job concurrently. When submitting a batch job, users specify a requested completion window, and the system prioritizes work to meet these targets. The result is that batch jobs make steady progress toward their SLO without interfering with interactive traffic. +Batch Gateway is designed to solve this by dynamically adjusting batch flow based on available infrastructure capacity. Batch Gateway also prioritizes jobs based on their Service Level Objective (SLO) targets, and processes requests within each job concurrently. The result is that batch jobs make steady progress toward their completion targets without interfering with interactive traffic. ## How Batch Gateway works Batch Gateway is a Kubernetes-native system composed of several components: - +
+ Batch Gateway architecture diagram +
### API Server diff --git a/static/img/blog-images/batch-gateway-arch.webp b/static/img/blog-images/batch-gateway-arch.webp new file mode 100644 index 0000000000000000000000000000000000000000..67a00fb671296cccacaa59aa7a2a34b686689e41 GIT binary patch literal 56432 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[k9O1LI@CFT>B6r_HP3V# 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�Bd6r53q;krGGW?-Nvw`e3EIT}l4p5OD7 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 X?8hxNSttMi0}m#B!6YNWR}TOHf=-zl literal 0 HcmV?d00001 From e866f57265b73597677be96a8a947a3e56270e36 Mon Sep 17 00:00:00 2001 From: Lior Aronovich Date: Fri, 12 Jun 2026 13:00:16 -0400 Subject: [PATCH 5/9] chore: streamline blog structure and fix links Consolidate integration and observability sections into challenge section, add Valkey support to data layer table, update getting started links, fix community page path, remove outdated meeting schedule. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Lior Aronovich --- ...able-batch-inference-with-batch-gateway.md | 52 ++++++------------- 1 file changed, 15 insertions(+), 37 deletions(-) diff --git a/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md b/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md index 74764eec3..46fc62e1f 100644 --- a/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md +++ b/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md @@ -34,6 +34,10 @@ When batch and interactive inference workloads compete for the same GPU resource Batch Gateway is designed to solve this by dynamically adjusting batch flow based on available infrastructure capacity. Batch Gateway also prioritizes jobs based on their Service Level Objective (SLO) targets, and processes requests within each job concurrently. The result is that batch jobs make steady progress toward their completion targets without interfering with interactive traffic. +Batch Gateway is production-grade, designed for shared multi-tenant environments where security, reliability, observability, and SLO compliance are essential. + +Batch Gateway is part of [llm-d](https://github.com/llm-d/llm-d), a CNCF Sandbox project and open source Kubernetes-native framework for high-performance distributed LLM inference. Batch Gateway integrates with llm-d's components, which means that batch workloads automatically benefit from llm-d's efficient inference capabilities, such as intelligent request routing, flow-control, and KV-cache reuse. + ## How Batch Gateway works Batch Gateway is a Kubernetes-native system composed of several components: @@ -52,52 +56,26 @@ Batch Gateway uses pluggable storage backends for different functions. Each func | Function | Available plug-ins | |----------|-------------------| -| Jobs and files metadata storage | PostgreSQL, Redis | -| Priority queue for jobs | Redis | -| Event channels | Redis | -| Jobs status updates | Redis | +| Jobs and files metadata storage | PostgreSQL (for production), Redis, Valkey | +| Priority queue for jobs | Redis, Valkey | +| Event channels | Redis, Valkey | +| Jobs status updates | Redis, Valkey | | File storage for input and output files | S3, Filesystem | Expired batch jobs and their associated files are periodically cleaned up. ### Batch Processor -The batch processor pulls jobs from a priority queue, retrieves the input file, builds execution plans, and dispatches individual inference requests with concurrency control for downstream processing. The processor sorts requests by system-prompt hash to maximize prefix cache hits, reducing redundant prefill computation across requests that share the same system prompt. As inference results come back, the processor writes them to an output file and continuously updates the job's status. The processor also listens for job events such as cancellation, enabling real-time control over in-flight work. In addition, the processor handles recovery from crashes during processing. - -## Integration with llm-d inference components - -Batch Gateway is part of [llm-d](https://github.com/llm-d/llm-d), a CNCF Sandbox project and open source Kubernetes-native framework for high-performance distributed LLM inference. Batch Gateway integrates with llm-d's components, which means that batch workloads automatically benefit from llm-d's efficient inference capabilities, such as intelligent request routing and KV-cache reuse. - -Batch Gateway is designed to work with the [Flow Control](https://gateway-api-inference-extension.sigs.k8s.io/concepts/flow-control/) component in the [Gateway API Inference Extension](https://github.com/kubernetes-sigs/gateway-api-inference-extension) (GIE) to enable dynamic tuning of batch workload flows as well as SLO-based prioritization. This integration allows the system to: - -- **Classify batch requests as sheddable:** Batch requests are assigned a negative priority, so the inference layer can shed them under saturation while protecting interactive traffic. -- **Order by SLO urgency:** Batch requests carry a deadline header (`x-slo-ttft-ms`) that GIE uses to prioritize jobs closest to their SLO deadline. -- **Enable per-tenant fairness:** The processor sends a fairness header (`x-gateway-inference-fairness-id`) with the tenant identifier, enabling round-robin fairness within the batch priority band. - -In the future, Batch Gateway is planned to support extended integrations with relevant llm-d components, as well as with additional components in the LLM inference ecosystem. - -## Observability, security, and operations - -Batch Gateway is built for production operations out of the box: - -- **Prometheus metrics** enable monitoring of job processing and API handling. -- **OpenTelemetry tracing** enables end-to-end request visibility across components. -- **Health and readiness probes** for Kubernetes-native lifecycle management. -- **Security hardened:** - - TLS / mTLS support for backend connections. - - Authentication and authorization integration. - - Multi-tenancy isolation. - - Security headers, HTTP server hardening, and input validation. - - Pod security: non-root execution, read-only filesystem, all capabilities dropped, seccomp, no privilege escalation. +The batch processor pulls jobs from a priority queue, retrieves the input files, builds execution plans, and dispatches individual inference requests with concurrency control for downstream processing. The processor sorts requests by system-prompt hash to maximize prefix cache hits, reducing redundant prefill computation across requests that share the same system prompt. As inference results come back, the processor writes them to an output file, and continuously updates the job's status. The processor also listens for job events such as cancellation, enabling real-time control over in-flight work. In addition, the system handles recovery from crashes and failures during processing. ## Getting started To learn more about Batch Gateway, check out the following resources: -- To run a local demo using a *kind* cluster, see the [demo resources](https://github.com/llm-d/llm-d-batch-gateway/tree/main/scripts/demo) and [prerequisites](https://github.com/llm-d/llm-d-batch-gateway/blob/main/docs/guides/development.md#prerequisites). -- To deploy in a Kubernetes cluster using demo settings, see the [demo deployment resources](https://github.com/llm-d/llm-d-batch-gateway/blob/main/scripts/dev-deploy). -- For detailed deployment and setup instructions, see the [Kubernetes deployment guide](https://github.com/llm-d/llm-d-batch-gateway/blob/main/docs/guides/deploy-k8s.md). -- The project's [documentation](https://github.com/llm-d/llm-d-batch-gateway) includes the main readme, [guides](https://github.com/llm-d/llm-d-batch-gateway/tree/main/docs/guides), and [design documents](https://github.com/llm-d/llm-d-batch-gateway/tree/main/docs/design). +- To run a local demo of Batch Gateway using a kind cluster, check out the [demo resources](https://github.com/llm-d/llm-d-batch-gateway/tree/main/examples/poc). +- To deploy Batch Gateway in a Kubernetes cluster using demo settings, see the [demo deployment resources](https://github.com/llm-d/llm-d-batch-gateway/tree/main/examples/deploy-demo). +- For detailed deployment and setup instructions, check out the [guide to deploy on Kubernetes](https://github.com/llm-d/llm-d-batch-gateway/blob/main/docs/guides/deploy-k8s.md). +- The project's documentation includes the [main readme file](https://github.com/llm-d/llm-d-batch-gateway/blob/main/README.md), the [guides](https://github.com/llm-d/llm-d-batch-gateway/tree/main/docs/guides), and [design documents](https://github.com/llm-d/llm-d-batch-gateway/tree/main/docs/design). ## Get involved with llm-d @@ -105,7 +83,7 @@ Batch Gateway is developed in the open as part of the llm-d ecosystem. If you're * **Explore the code** -- Browse the [Batch Gateway repo](https://github.com/llm-d/llm-d-batch-gateway) and the wider [llm-d organization](https://github.com/llm-d) * **Join our Slack** -- [Get your invite](/slack) and connect with maintainers and contributors -* **Attend community calls** -- All meetings are open! Add our [public calendar](https://red.ht/llm-d-public-calendar) (Wednesdays 12:30pm ET) and join the conversation +* **Attend community calls** -- All meetings are open! Add our [public calendar](https://red.ht/llm-d-public-calendar) and join the conversation * **Follow project updates** -- Stay current on [Twitter/X](https://twitter.com/_llm_d_), [Bluesky](https://bsky.app/profile/llm-d.ai), and [LinkedIn](https://www.linkedin.com/company/llm-d) * **Watch demos and recordings** -- Subscribe to the [llm-d YouTube channel](https://www.youtube.com/@llm-d-project) for community call recordings and feature walkthroughs -* **Read the docs** -- Visit our [community page](/docs/community) to find SIGs, contribution guides, and upcoming events +* **Read the docs** -- Visit our [community page](/community) to find SIGs, contribution guides, and upcoming events From a74a3933373cd4fbe06f5c4ac011237e1ff9ee47 Mon Sep 17 00:00:00 2001 From: Lior Aronovich Date: Fri, 12 Jun 2026 13:07:54 -0400 Subject: [PATCH 6/9] chore: rename blog file to match publication date Co-Authored-By: Claude Opus 4.6 Signed-off-by: Lior Aronovich --- ... => 2026-06-12_scalable-batch-inference-with-batch-gateway.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename blog/{2026-05-04_scalable-batch-inference-with-batch-gateway.md => 2026-06-12_scalable-batch-inference-with-batch-gateway.md} (100%) diff --git a/blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md b/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md similarity index 100% rename from blog/2026-05-04_scalable-batch-inference-with-batch-gateway.md rename to blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md From 18a09179ddbce3758450a1969c08fce80aec0af1 Mon Sep 17 00:00:00 2001 From: Lior Aronovich Date: Fri, 12 Jun 2026 13:31:01 -0400 Subject: [PATCH 7/9] chore: widen architecture diagram to full width Co-Authored-By: Claude Opus 4.6 Signed-off-by: Lior Aronovich --- blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md b/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md index 46fc62e1f..7542e63ff 100644 --- a/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md +++ b/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md @@ -43,7 +43,7 @@ Batch Gateway is part of [llm-d](https://github.com/llm-d/llm-d), a CNCF Sandbox Batch Gateway is a Kubernetes-native system composed of several components:
- Batch Gateway architecture diagram + Batch Gateway architecture diagram
### API Server From e5909423779dd843b64fd34403fabc37f30af1ed Mon Sep 17 00:00:00 2001 From: Lior Aronovich Date: Mon, 15 Jun 2026 17:47:46 -0400 Subject: [PATCH 8/9] chore: update blog title and expand prefix cache explanation Rename title to match conference submission framing. Expand prefix cache sorting explanation with eviction prevention mechanism and llm-d routing integration. Split batch processor section into focused paragraphs. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Lior Aronovich --- ...6-12_scalable-batch-inference-with-batch-gateway.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md b/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md index 7542e63ff..b912a77ce 100644 --- a/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md +++ b/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md @@ -1,5 +1,5 @@ --- -title: "Scalable Batch Inference with Batch Gateway" +title: "Efficient Batch and Interactive LLM Inference at Scale with llm-d" description: "Batch Gateway brings first-class batch inference capabilities to llm-d, providing an OpenAI-compatible API for submitting, tracking, and managing large-scale batch jobs, running efficiently alongside interactive inference on shared infrastructure." slug: scalable-batch-inference-with-batch-gateway date: 2026-06-12T09:00 @@ -13,7 +13,7 @@ authors: tags: [blog, batch-inference, inference, llm-d] --- -# Scalable Batch Inference with Batch Gateway +# Efficient Batch and Interactive LLM Inference at Scale with llm-d As organizations deploy AI applications in production, their inference infrastructure must serve two fundamentally different workloads simultaneously: interactive requests requiring immediate replies, and batch inference jobs that process thousands of requests with a time tolerance of hours for receiving results. Use cases for batch inference include autonomous background agents performing multi-step reasoning and deep research, as well as user-initiated workloads like offline evaluations, dataset processing, and embedding generation. @@ -66,7 +66,11 @@ Expired batch jobs and their associated files are periodically cleaned up. ### Batch Processor -The batch processor pulls jobs from a priority queue, retrieves the input files, builds execution plans, and dispatches individual inference requests with concurrency control for downstream processing. The processor sorts requests by system-prompt hash to maximize prefix cache hits, reducing redundant prefill computation across requests that share the same system prompt. As inference results come back, the processor writes them to an output file, and continuously updates the job's status. The processor also listens for job events such as cancellation, enabling real-time control over in-flight work. In addition, the system handles recovery from crashes and failures during processing. +The batch processor pulls jobs from a priority queue, retrieves the input files, builds execution plans, and dispatches individual inference requests with concurrency control for downstream processing. As inference results come back, the processor writes them to an output file, and continuously updates the job's status. + +The processor sorts requests by system-prompt hash so that identical-prefix requests hit the inference engine contiguously, keeping cached prefix blocks hot and avoiding eviction-triggered prefill reconstruction. Combined with llm-d's prefix-cache-aware routing, cache reuse extends across the entire serving pool. + +The processor listens for job events such as cancellation, enabling real-time control over in-flight work. In addition, the system handles recovery from crashes and failures during processing. ## Getting started From 8dd3d9e1c5702610de534e80992f91bb7f552b3d Mon Sep 17 00:00:00 2001 From: Lior Aronovich Date: Mon, 15 Jun 2026 20:52:28 -0400 Subject: [PATCH 9/9] chore: expand flow control description and move concurrency detail Describe adaptive concurrency control and llm-d integration in challenge section. Move concurrent request dispatch detail to batch processor section. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Lior Aronovich --- .../2026-06-12_scalable-batch-inference-with-batch-gateway.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md b/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md index b912a77ce..3a34071f6 100644 --- a/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md +++ b/blog/2026-06-12_scalable-batch-inference-with-batch-gateway.md @@ -32,7 +32,7 @@ When batch and interactive inference workloads compete for the same GPU resource - **Dedicating separate GPU pools for batch workloads** is expensive and wasteful. - **Manually throttling batch workloads** is operationally burdensome. -Batch Gateway is designed to solve this by dynamically adjusting batch flow based on available infrastructure capacity. Batch Gateway also prioritizes jobs based on their Service Level Objective (SLO) targets, and processes requests within each job concurrently. The result is that batch jobs make steady progress toward their completion targets without interfering with interactive traffic. +Batch Gateway is designed to solve this through built-in adaptive concurrency control and integration with llm-d's routing and scheduling components. Together, these mechanisms dynamically adjust batch flow based on available capacity, protect interactive traffic under load, and prioritize jobs based on SLO targets. The result is that batch jobs make steady progress toward their completion targets without interfering with interactive traffic. Batch Gateway is production-grade, designed for shared multi-tenant environments where security, reliability, observability, and SLO compliance are essential. @@ -66,7 +66,7 @@ Expired batch jobs and their associated files are periodically cleaned up. ### Batch Processor -The batch processor pulls jobs from a priority queue, retrieves the input files, builds execution plans, and dispatches individual inference requests with concurrency control for downstream processing. As inference results come back, the processor writes them to an output file, and continuously updates the job's status. +The batch processor pulls jobs from a priority queue, retrieves the input files, builds execution plans, and dispatches individual inference requests concurrently for downstream processing. As inference results come back, the processor writes them to an output file, and continuously updates the job's status. The processor sorts requests by system-prompt hash so that identical-prefix requests hit the inference engine contiguously, keeping cached prefix blocks hot and avoiding eviction-triggered prefill reconstruction. Combined with llm-d's prefix-cache-aware routing, cache reuse extends across the entire serving pool.