What is Model Serving?
Why a serialized weight checkpoint on disk is not an inference service, and the complete journey from user request to tensor core prediction.
During model training, the primary objective is maximizing parameter convergence across large offline datasets using heavy backward passes, gradient calculations, and optimizer state updates. Latency is irrelevant; throughput across days or weeks is what matters.
Model Serving flips this operational paradigm completely upside down. In production serving, the backward pass is permanently discarded. The objective is to expose the frozen model weights as a high-concurrency, sub-second API endpoint that must perform hardware memory management, tensor serialization, dynamic batch scheduling, and low-latency forward passes across heterogeneous hardware.
Trained Checkpoint
Weights stored on disk (e.g. .safetensors, ONNX, or TensorRT plan). Completely inert; cannot accept HTTP traffic, schedule concurrent requests, or allocate GPU memory dynamically.
Model Server Runtime
High-performance runtime (NVIDIA Triton, vLLM, KServe) that loads weights into GPU VRAM, binds CUDA streams, manages input queues, and executes compiled tensor kernels.
API & Business Backend
Application gateway (FastAPI/Node) handling user authentication, rate limiting, database writes, prompt composition, and calling the model server via high-speed internal gRPC.
Inference Request Journey & Tensor Core Trace
Trace an inference request through each architectural layer. Select a model architecture and step through the pipeline to inspect latency and data transformations.
Client POST Request
Client SDK submits text document chunk to be embedded for downstream vector database similarity search.
Model Server vs Application Server
Architecting the strict boundary between business logic and GPU tensor computation to prevent resource starvation.
A fatal anti-pattern in modern AI development is treating a web backend (like FastAPI or Express) as the model execution engine. In this anti-pattern, a developer loads PyTorch weights into memory inside a route handler:
When a Python web framework directly executes deep learning models:
- Python Global Interpreter Lock (GIL): Heavy CPU pre-processing or tensor copying completely freezes the asynchronous event loop, blocking all incoming HTTP requests.
- Zero Dynamic Batching: Each web request executes a single forward pass (batch size 1), leaving 85% to 95% of GPU tensor cores completely idle.
- Forked Memory Multiplier: Scaling the web server with 4 workers clones model weights 4 times, triggering immediate Out-Of-Memory (Exit 137) crashes.
| Operational Dimension | Application Server (FastAPI / Node / Go) | Model Server (Triton / vLLM / TensorRT) |
|---|---|---|
| Primary Responsibilities | User Auth, JWT validation, Business Rules, DB CRUD, Stripe Billing, Rate Limiting | CUDA stream binding, dynamic batching, VRAM allocation, KV cache indexing, kernel execution |
| Concurrency Model | Asynchronous I/O event loops, thousands of concurrent open TCP sockets | Threadpools pinned to hardware accelerators; batch-scheduled execution queues |
| Communication Protocol | Public HTTPS (Port 443), REST JSON, WebSockets | Internal VPC high-speed gRPC (binary protobuf) or shared memory (IPC) |
| Scaling Metric | CPU utilization, open HTTP connection count, network I/O | GPU Tensor Core utilization, VRAM usage, queue wait latency (p99) |
| Scaling Velocity | Sub-second (100β300ms container boot) | Slow cold starts (15β90s to download weights & warm CUDA kernels) |
Architectural Layer Classifier (βChoose the Right Layerβ)
Production AI engineering demands strict separation of concerns. Assign each production task to the correct architectural tier.
Model Loading & Serving Lifecycle
Understanding the boot sequence, VRAM memory allocation, kernel compilation, and warm-up requirements before accepting live traffic.
Unlike a lightweight web server that binds to a port in 50 milliseconds, a high-performance model server undergoes a rigorous, multi-stage initialization lifecycle:
config.pbtxtAllocate HBM2Compile KernelsWarm CachesAccept TrafficModel Startup & VRAM Allocation Simulator
Simulate model server startup across different parameter counts, quantizations, and GPU hardware to test cold starts and Out-Of-Memory risks.
0.5B (Small Embedding/ViT) to 70B (Llama-3-70B).
Bytes/param: FP32 (4B), FP16 (2B), INT8 (1B), FP8 (1B).
Triton `instance_group: count` (multiplies model weight footprint!).
Startup VRAM Allocation Calculation
STARTUP VERIFIED (READY)β Simulation Result: Successfully allocated! Model server consumes 16.3 GB with 7.8 GB of VRAM headroom remaining for dynamic request batching.
Inference Request Flow & Latency Deconstruction
Deconstructing end-to-end inference latency into its mathematical components to pinpoint bottlenecks.
When an inference endpoint fails to meet its Service Level Objective (e.g. p99 < 50ms), inexperienced engineers frequently assume the model itself is too slow and attempt to prune or quantize weights. In reality, the GPU forward pass is often only 20% to 40% of the total elapsed latency.
Latency_total = T_network + T_queue + T_preprocess + T_batch_wait + T_gpu_compute + T_postprocess + T_serialization
Every millisecond spent waiting in the incoming HTTP socket buffer, tokenizing on a single CPU core, or serializing tensors to JSON directly increases client latency.
name: "bge_large"
platform: "onnxruntime_onnx"
max_batch_size: 32
input [
{
name: "input_ids"
data_type: TYPE_INT64
dims: [ -1 ]
},
{
name: "attention_mask"
data_type: TYPE_INT64
dims: [ -1 ]
}
]
output [
{
name: "sentence_embedding"
data_type: TYPE_FP32
dims: [ 1024 ]
}
]
# Enable Dynamic Batching with 5ms maximum queue window
dynamic_batching {
max_queue_delay_microseconds: 5000
preferred_batch_size: [ 8, 16, 32 ]
}
# Pin 1 model instance to GPU 0
instance_group [
{
count: 1
kind: KIND_GPU
gpus: [ 0 ]
}
]Concurrency & Request Scheduling
What happens when 100 users hit a single GPU simultaneously, understanding queue saturation curves, and Little's Law.
Unlike a CPU that context-switches across hundreds of threads via preemptive multitasking, a GPU is a massive streaming multiprocessor (SM) array designed for uniform, data-parallel tensor operations. If 50 independent clients hit an un-scheduled model server at the same instant, the server must choose: serialize requests sequentially, allocate parallel CUDA streams, or aggregate them into dynamic batches.
Little's Law in Model Serving
Little's Law dictates: L = Ξ» Γ W, where L is the number of requests inside the model server, Ξ» is incoming request arrival rate (RPS), and W is total inference latency. If arrival rate exceeds execution throughput, L accumulates in the request queue, driving latency to infinity.
Triton Model Instances
NVIDIA Triton allows declaring instance_group [ { count: 2, kind: KIND_GPU } ]. This spawns two distinct runtime execution engines on the same physical GPU, allowing parallel CUDA kernel dispatches when models do not fully saturate all SM cores.
Concurrency & Saturation Curve Simulator
Observe how increasing concurrent users impacts queue backlog, mean latency, tail latency (p95), and GPU core saturation.
Simultaneous in-flight requests.
Raw GPU execution duration per batch.
Parallel CUDA execution streams.
Live Concurrency & Queue Simulation
WARNING: QUEUE SATURATION (HIGH p95)π‘ Observation: With 20 concurrent requests and 1 instance(s), the queue incurs 267 ms of delay. Tail p95 latency is 410 ms. Notice that doubling concurrency without adding model instances or dynamic batching does not double throughputβit merely balloons the request queue!
Batching & Dynamic Batching
Why GPUs crave batching for arithmetic intensity, and how server-side dynamic batching achieves 10x throughput gains.
A modern GPU has thousands of floating-point ALUs (e.g. 14,000+ CUDA cores on an H100). When processing an inference request with batch_size = 1, the GPU spends the vast majority of its clock cycles waiting for model weights to be fetched from High Bandwidth Memory (HBM) across the memory bus. The compute units are starved of math.
By grouping multiple requests into a batch, the same model weights loaded once into local SRAM can be applied across 16 or 32 input vectors simultaneously. This shifts the operation from memory-bandwidth-bound matrix-vector multiplication (GEMV) to compute-bound matrix-matrix multiplication (GEMM), boosting arithmetic intensity.
Client must wait & bundleTriton collects independent reqsDynamic Batching Lab (NVIDIA Triton Mechanics)
Tune `max_batch_size` and `max_queue_delay_microseconds` to find the sweet spot between low latency and maximum hardware throughput.
Dynamic Batching Performance Trade-Off
β‘ The Core Trade-off: Executing batch size 1 took 13 ms on GPU (only slightly longer than a single request at 13.3ms!). The server yielded 77 requests/sec (1.0x efficiency gain) at the cost of an extra 3 ms queue delay for early-arriving requests.
Latency vs Throughput & Tail Latency (p99)
Why average latency lies, and how microservice fan-out turns a 1% p99 tail delay into widespread outage.
In model serving, Latency and Throughput are opposing engineering forces:
| Metric | Definition | Optimization Target | Typical Workload |
|---|---|---|---|
| Latency (ms) | Time elapsed between client request and final response | Minimize batch size, zero queue delay, fast tensor cores | Real-time voice AI, interactive autocomplete, robotics |
| Throughput (RPS) | Total inference operations processed per second across the cluster | Maximize batch size, pipeline parallelism, high utilization | Document indexing, offline batch scoring, vector ingestion |
Consider a modern Agentic RAG workflow where answering one customer query requires: 1 guardrail classifier + 3 embedding lookups + 1 reranker + 1 LLM completion = 6 model inferences.
If each model server has a 99% success rate under 100ms (1% p99 tail delay): The probability that the user experiences the slow p99 delay is:1 - (0.99)^6 = 1 - 0.941 = 5.9% of all users!
In complex multi-model pipelines, tail latency compounds geometrically. A stable p99 SLA is far more critical than an impressive average latency.
GPU Memory Architecture & KV Cache Sizing
Deconstructing GPU VRAM into weights, activations, and Key-Value (KV) cache for Large Language Models.
When serving Large Language Models (LLMs), memory calculation is fundamentally different from traditional deep learning models. In traditional vision or embedding models, memory is static ($Weights + Peak Activations$).
In autoregressive generative models, each generated token must attend to all previous tokens in the conversation. To avoid re-computing self-attention matrices on every single step, the intermediate Key and Value activation vectors are cached in GPU VRAM: the KV Cache.
KV_Cache_Bytes = 2 Γ Num_Layers Γ Hidden_Dimension Γ Sequence_Length Γ Batch_Size Γ Precision_Bytes
For a 7B model (32 layers, hidden dim 4096, FP16 = 2 bytes): Each token stored in KV Cache requires 524,288 bytes (~0.5 MB)! If 64 users stream 4,000-token conversations simultaneously, the KV Cache alone demands 64 Γ 4,000 Γ 0.5 MB = 128 GB VRAM, exceeding a full 80GB H100!
GPU VRAM & KV Cache Capacity Planner
Calculate exact VRAM footprints for weights, activations, and dynamic KV Cache to determine maximum concurrent streaming capacity.
VRAM Allocation on 80GB GPU Cluster
STABLE CAPACITYβ Optimal Sizing: System can safely host up to 32 simultaneous users streaming at 4096 tokens before exhausting KV cache memory.
Modern Model Serving Systems
Objective comparison of enterprise inference engines: NVIDIA Triton, vLLM, KServe, and framework-native runtimes.
Selecting an inference server is an architectural decision based on the mathematical characteristics of your model. There is no universal winner: an engine optimized for generative autoregressive tokens (like vLLM) is useless for low-latency XGBoost fraud scoring, while an enterprise multi-framework engine (like NVIDIA Triton) is the gold standard for heterogeneous multi-model pipelines.
| Serving System | Core Architecture & Engines | Key Innovations | Primary Use Case |
|---|---|---|---|
| NVIDIA Triton Inference Server | C++ core; TensorRT, ONNX Runtime, PyTorch (LibTorch), OpenVINO, Python backends | Server-side dynamic batching, concurrent model instances on single GPU, ensemble pipelines (BLS), HTTP/gRPC v2 Data Plane | Heterogeneous enterprise pipelines (Vision + Audio + Tabular + Embeddings) on NVIDIA hardware |
| vLLM | Python / C++ CUDA core; PyTorch, FlashAttention-2, FlashInfer | PagedAttention virtual memory KV cache, continuous batching (iteration-level scheduling), chunked prefill, speculative decoding, multi-GPU tensor parallel | High-throughput Large Language Model (LLM) serving with massive concurrent user sessions |
| KServe | Kubernetes CRD controller; Knative, Istio, Triton / TorchServe / vLLM runtimes | Standardized v2 Data Plane inference protocol, scale-to-zero serverless autoscaling, canary rollouts, multi-model storage agents | Kubernetes-native enterprise microservices across multi-cloud clusters |
| Framework-Native (TorchServe / FastAPI) | Python process wrapping PyTorch / ONNX C++ library | Simplicity, rapid local prototyping, direct access to raw Python libraries | Low-volume internal tools, offline development, non-latency-critical prototypes |
Serving Different Model Architectures
Why vision, tabular, embedding, and generative LLM models demand radically different serving configurations.
Tabular & Decision Trees (XGBoost / LightGBM)
Tabular models have almost zero compute complexity compared to neural nets. Compiling to ONNX Runtime or Treelite C-trees on CPU delivers sub-millisecond (0.2β0.8ms) inference at 10,000+ RPS. GPUs add PCIe bus latency overhead and should be avoided here.
Computer Vision (ResNet / YOLO / ViT)
Images have fixed tensor dimensions (e.g. [3, 224, 224]). They compile exceptionally well to NVIDIA TensorRT engines with static or bounded dynamic batch sizes, delivering 5x to 10x throughput boosts on cost-effective GPUs like NVIDIA T4 or L4.
Dense Text Embeddings (BGE / E5)
Transformer encoders (BERT-style) have variable sequence lengths. NVIDIA Triton with dynamic batching and padding grouping enables embedding 500+ document chunks per second on a single GPU instance for real-time RAG ingestion.
Generative Autoregressive LLMs (Llama / Mistral)
LLMs generate tokens sequentially. Traditional static batching causes head-of-line blocking (fast requests waiting for slow ones). They require continuous iteration-level batching (vLLM) where requests join and leave the active batch dynamically at each generated token.
Streaming Inference for Generative AI
Architecting low-latency token streaming: measuring Time-to-First-Token (TTFT), Inter-Token Latency (ITL), and Chunked Prefill.
In generative chat applications, generating a complete 400-word response can take 6 to 10 seconds. If a user is forced to stare at a blank spinner for 8 seconds, they perceive the application as frozen. By streaming tokens progressively as they are decoded, perceived latency drops from 8,000ms to sub-100ms.
1. Time to First Token (TTFT)
Governed by the Prefill Phase. The model processes the entire prompt context (e.g. 500 tokens) in a single parallel forward pass. TTFT measures the time from client submission to the first byte emitted over the HTTP stream.
2. Inter-Token Latency (ITL)
Governed by the Decode Phase. The model generates one token at a time autoregressively. ITL measures the time between consecutive emitted tokens (typically 15ms to 35ms on modern GPUs, equivalent to 30β60 tokens/sec).
Historically, a massive 16,000-token prompt arriving during ongoing generation would monopolize the GPU for 500ms, causing active streaming users to experience a noticeable stutter. Chunked Prefill breaks large prompts into smaller chunks (e.g. 512 tokens) and co-schedules them alongside decode iterations, eliminating decode starvation.
Production Model Serving Optimization
The six core engineering levers for optimizing throughput, latency, and hardware utilization.
1. Graph Compilation
Compile models using TensorRT or TorchInductor. Fuses multiple consecutive operations (e.g. Conv + BatchNorm + ReLU) into a single CUDA kernel, eliminating intermediate VRAM roundtrips.
2. Weight Quantization
Convert 16-bit floats (FP16) to FP8 (native Hopper/Ada support) or 4-bit AWQ / GPTQ. Cuts weight VRAM in half and doubles memory bandwidth throughput with negligible perplexity degradation.
3. CUDA Graphs
Captures a sequence of CUDA kernel launches on the CPU and replays them with a single driver call, removing CPU-to-GPU launch overhead for fixed-shape forward passes.
4. Speculative Decoding
A tiny draft model (e.g. 1B) guesses 4 tokens ahead; the main 70B model verifies all 4 in a single parallel forward pass, boosting decode speed by 2x to 3x.
5. Model Warm-Up
Run dummy forward passes during pod startup to trigger JIT kernel compilation and allocate memory pools before marking the container ready in Kubernetes.
6. Dynamic Batch Tuning
Profile latency vs batch size curves using Triton Perf Analyzer to identify the hardware saturation knee point.
Model Serving Failure Scenarios & Debugging
Diagnosing production model server crashes, VRAM OOM errors, and engine starvation under real traffic.
Production Model Server Debugger & Triage
Inspect crash logs and metrics from production model servers, determine the root cause, and verify the correct infrastructure remediation.
Capstone Mini-Project: Production Model Serving Plan
Complete architectural blueprint for an enterprise multi-model serving stack: NVIDIA Triton for embeddings and vLLM for generative chat.
Review the production-grade Kubernetes manifest below. It demonstrates how modern AI engineering teams deploy dedicated model serving pods: decoupling the FastAPI application gateway from internal Triton and vLLM inference engines over private cluster DNS, with strict GPU resource limits, readiness probes, and model warm-up procedures.
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-llama3-serving
namespace: ai-inference
spec:
replicas: 2
selector:
matchLabels:
app: vllm-llama3
template:
metadata:
labels:
app: vllm-llama3
spec:
containers:
- name: vllm-engine
image: vllm/vllm-openai:v0.6.2
args: [
"--model", "meta-llama/Meta-Llama-3-8B-Instruct",
"--tensor-parallel-size", "1",
"--gpu-memory-utilization", "0.92",
"--max-model-len", "8192",
"--enable-chunked-prefill",
"--max-num-batched-tokens", "2048",
"--dtype", "bfloat16"
]
env:
- name: HUGGING_FACE_HUB_TOKEN
valueFrom:
secretKeyRef:
name: hf-secret
key: token
resources:
limits:
nvidia.com/gpu: "1"
memory: "32Gi"
cpu: "8"
requests:
nvidia.com/gpu: "1"
memory: "16Gi"
cpu: "4"
ports:
- containerPort: 8000
name: http-inference
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 45
periodSeconds: 10
timeoutSeconds: 5
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 60
periodSeconds: 15
---
apiVersion: v1
kind: Service
metadata:
name: vllm-internal-svc
namespace: ai-inference
spec:
selector:
app: vllm-llama3
ports:
- port: 8000
targetPort: 8000
name: httpReal-World Production Incident Post-Mortems
Eight field-tested production failure scenarios from real model serving deployments with root-cause diagnostics and copyable remediations.
#1: CUDA Out-Of-Memory Crash Under Dynamic Batch Surge
criticalModel server container terminated abruptly with Exit Code 137 / 'RuntimeError: CUDA out of memory' when a traffic spike of 80 concurrent users arrived.
Dynamic batching was configured with `max_batch_size: 64`, but peak activation memory at batch size 64 exceeded remaining GPU VRAM after loading model weights.
Benchmark peak activation memory across batch sizes. Cap `max_batch_size` to 32 and configure Triton dynamic batcher memory allocation limits.
# Triton config.pbtxt correction
max_batch_size: 32
dynamic_batching {
max_queue_delay_microseconds: 5000
preferred_batch_size: [ 8, 16, 32 ]
}
# Allocate dedicated pinned memory pool for input/output tensors
instance_group [
{
count: 1
kind: KIND_GPU
gpus: [ 0 ]
}
]#2: Python Preprocessing Lock Freezing Async Event Loop
highFastAPI inference gateway p99 latency skyrocketed from 25ms to 1,800ms when processing multi-page text documents, even though GPU utilization was only 18%.
Heavy regex tokenization and PDF text extraction were executed synchronously inside the `async def predict()` handler, blocking Python's single-threaded asyncio event loop.
Offload CPU-bound tokenization and image resizing to `asyncio.to_thread()` or run preprocessing in a dedicated C++ / Rust Triton pipeline (BLS - Business Logic Scripting).
# Anti-pattern: Blocking async event loop
# tokens = heavy_tokenizer.encode(payload.text)
# Production Fix: Offload CPU-bound preprocessors to worker threadpool
import asyncio
@app.post("/v1/predict")
async def predict(payload: InferencePayload):
# Offload CPU-bound tokenization to thread pool
tokens = await asyncio.to_thread(heavy_tokenizer.encode, payload.text)
# Non-blocking async client dispatch to Triton / vLLM gRPC
result = await triton_grpc_client.infer(model_name="bge_large", inputs=tokens)
return {"embedding": result}#3: vLLM KV Cache Starvation Under Long Context Requests
criticalvLLM engine threw HTTP 503 'Engine queue is full' and began preempting active user generations, causing stuttered responses and dropped tokens.
`gpu_memory_utilization` was set to 0.70 (leaving only 5GB for KV cache), while multiple concurrent requests submitted 8,000-token prompts, exhausting all physical KV blocks.
Tune `gpu_memory_utilization` to 0.92, enable chunked prefill (`--enable-chunked-prefill`), and set `--max-model-len` to realistic production bounds.
# vLLM Production Launch Arguments
python3 -m vllm.entrypoints.openai.api_server \
--model mistralai/Mistral-7B-Instruct-v0.3 \
--tensor-parallel-size 1 \
--gpu-memory-utilization 0.92 \
--max-model-len 8192 \
--enable-chunked-prefill \
--max-num-batched-tokens 2048 \
--swap-space 4#4: First-Request Latency Stall (Cold Start & Unwarmed Engine)
highEvery time an autoscaled GPU pod spun up, the very first user request took 18.4 seconds to respond, violating the 500ms p99 SLA.
TensorRT-LLM and PyTorch lazy-initialize CUDA kernels, memory allocators, and graph captures on the first forward pass rather than during container boot.
Implement a formal model warm-up script in the startup probe that passes dummy tensors through the network before reporting readiness (`/v2/health/ready`).
# production_warmup.py (Executed in Lifespan / Startup Probe)
import numpy as np
async def warmup_model(client, model_name: str, batch_size: int = 1):
print("[WARMUP] Emitting dummy forward pass to warm CUDA kernels...")
dummy_input = np.zeros((batch_size, 512), dtype=np.int64)
# Run 3 passes to trigger full CUDA graph capture
for i in range(3):
_ = await client.infer(model_name=model_name, inputs={"input_ids": dummy_input})
print("[WARMUP] CUDA context initialized and kernels compiled. Ready for traffic.")#5: Unbounded Dynamic Batch Queue Causing p99 Tail Latency Blowup
highAverage latency was 45ms, but p99 tail latency breached 2,500ms during peak lunch traffic hours.
`max_queue_delay_microseconds` was configured to 50,000Β΅s (50ms) with an infinite FIFO request queue. Under load, queued requests piled up behind slow forward passes.
Reduce `max_queue_delay_microseconds` to 5,000Β΅s (5ms) and configure Triton queue priority policies with explicit timeouts.
# Triton config.pbtxt tuning for bounded tail latency
dynamic_batching {
max_queue_delay_microseconds: 5000 # Cap queue wait to 5ms
preferred_batch_size: [ 4, 8, 16 ]
default_queue_policy {
max_queue_size: 128 # Reject requests above 128 with HTTP 429/503
timeout_action: REJECT
default_timeout_microseconds: 200000 # Drop if queued > 200ms
}
}#6: TensorRT Engine Architecture Mismatch on Cloud Migration
criticalModel server failed to boot on a new AWS instance with error: 'Internal: The engine plan file is not compatible with this device'.
TensorRT engines are strictly compiled for a specific GPU Compute Capability (e.g. sm_80 for A100). The deployment team migrated the image to an AWS G5 instance (A10G, sm_86) without re-building the engine.
Store model source checkpoints (ONNX or PyTorch weights) in artifact storage and compile TensorRT plans dynamically during CI/CD build matrix or on instance startup.
# Check GPU Compute Capability before loading TensorRT engine
python3 -c "import torch; print(f'CUDA Device: {torch.cuda.get_device_name(0)}, SM: {torch.cuda.get_device_capability(0)}')"
# Build TensorRT engine specifically for the host architecture
trtexec --onnx=model.onnx \
--saveEngine=model_sm86.engine \
--fp16 \
--minShapes=input:1x3x224x224 \
--optShapes=input:16x3x224x224 \
--maxShapes=input:32x3x224x224#7: Reverse Proxy Dropping Long-Running gRPC Streaming Tokens
mediumUsers requesting long code generation (over 1,000 tokens) saw token streams suddenly terminate midway through generation without error messages.
The ingress Nginx reverse proxy had a default `grpc_read_timeout 60s`. When token generation exceeded 60 seconds, Nginx closed the gRPC stream with `RST_STREAM`.
Configure reverse proxy gRPC read/send timeouts to 300s and disable buffer caching for streaming inference connections.
# Nginx ingress configuration for vLLM / Triton gRPC streaming
location /v1/chat/completions {
grpc_pass grpc://vllm_upstream;
grpc_read_timeout 300s;
grpc_send_timeout 300s;
grpc_buffer_size 4k;
# Disable buffering for low-latency token streaming
grpc_socket_keepalive on;
proxy_buffering off;
}#8: Database Connection Pool Starvation in Model Pre-check
highInference server pods reported healthy, but 40% of user prediction requests failed with HTTP 500 'Connection pool exhausted'.
The prediction handler opened an asynchronous database connection to check customer rate limits for every incoming token chunk instead of doing an in-memory Redis token check.
Separate inference authentication and rate checks into a Redis token-bucket filter at the API gateway layer before dispatching to the model server.
# API Gateway Layer: Check rate limits using in-memory Redis
async def check_inference_quota(user_id: str, redis_client) -> bool:
key = f"rate_limit:{user_id}"
tokens = await redis_client.incr(key)
if tokens == 1:
await redis_client.expire(key, 60)
if tokens > 200:
return False # HTTP 429 Too Many Requests
return TrueWhat You Should Know Now & Knowledge Assessment
Validate your understanding of high-throughput model serving with our 12-point competency checklist and 8-question scenario quiz.
Production Model Serving Competency Checklist
max_queue_delay_microseconds and max_batch_size boost GPU throughput by 10x.Production Model Serving Assessment
Evaluate your mastery of inference engines, dynamic batching trade-offs, KV cache planning, and tail latency mitigation.