Admission Control vs Autoscaling for Inference: The 2026 Buying Guide
You're staring at a production inference cluster that's burning money during off-peak hours and queueing requests during a product demo. Your infrastructure engineer just asked whether you should buy an admission control solution or invest more in autoscaling.
Most people think this is an either/or decision. It's not.
Here's what I tell every team that comes to SIVARO with this exact question: if you're choosing between admission control and autoscaling for inference, you've already missed the point. The real question is which one you need first — and that answer depends entirely on your failure mode.
This guide covers both systems, their overlap, and the honest trade-offs I've seen play out across dozens of production deployments since 2021.
What We're Actually Debating
Admission control is a gatekeeper. It sits in front of your inference endpoints and decides whether a request gets processed now, gets queued, or gets rejected outright. Think of it as a bouncer who knows the venue's capacity and stops letting people in before the fire marshal shows up.
Autoscaling is a resource manager. It watches your traffic patterns and provisions more replicas when demand spikes, then scales down when things calm. It's the venue manager adding more tables when the line gets long.
For LLM inference specifically, the stakes are different from traditional web services. Tokens are expensive. GPU memory is finite. A single 70B parameter model can eat 140GB of VRAM before you serve a single request. Your autoscaler might spin up a new pod in 30 seconds, but loading those weights takes two minutes — and that's if you've pre-cached the model.
That mismatch is where most systems break.
The Autoscaling Lie We Tell Ourselves
Let me be direct: autoscaling for LLM inference is harder than it looks.
The standard Kubernetes HorizontalPodAutoscaler monitors CPU and memory. Those metrics are almost useless for inference workloads. A GPU serving tokens at max throughput shows lower memory pressure than an idle one with weights loaded. CPU utilization on a token-generation machine is a noisy, lagging indicator.
I watched a team at a fintech company (name withheld, but they process real-time fraud detection) deploy a naive CPU-based autoscaler. The replicas stayed at minimum because inferencing is memory-bound, not CPU-bound. Then a batch of high-value transactions hit on a Friday afternoon. Requests queued. SLOs blew past. They were down for 40 minutes before the autoscaler even registered the problem.
The fix was custom metrics. You need to expose GPU utilization, queue depth, and time-to-first-token (TTFT) from your serving layer.
python
# Pseudo-config for a custom autoscaler based on queue depth
from kubernetes import client, config
def get_queue_depth(service_name):
# Query your serving mesh or inference server for pending requests
response = requests.get(f"http://{service_name}:8000/metrics")
return parse_queue_depth(response.text)
def scale_decision(current_replicas, queue_depth):
# Scale out aggressively when queue grows past 50 requests
if queue_depth > 50:
return current_replicas * 2
if queue_depth < 5 and current_replicas > 1:
return current_replicas - 1
return current_replicas
But even with perfect metrics, autoscaling has a physics problem. Load time for a 13B parameter model on A100s runs 30-60 seconds cold. For 70B models with quantization, you're looking at 2-4 minutes before a new replica can serve its first request.
Your autoscaler detects the spike. It provisions a new pod. By the time that pod is ready, the spike is over. You've paid for a replica that never served traffic, and your users still waited.
That's not a scaling problem. That's a systems design problem.
Admission Control Isn't Rate Limiting
The most common misconception I hear: admission control is just throttling requests.
Rate limiting sets a fixed cap. Admission control makes dynamic decisions based on current system state. It asks questions like:
- How many requests are currently in flight?
- What's the average TTFT across the last 60 seconds?
- How much memory is left on the active GPUs?
- What's the P99 execution time for the current model?
An admission controller for LLM inference requests can reject a request when the system is saturated, return a 429 with a Retry-After header, or queue it with a priority class.
I'm seeing more teams run admission control for LLM inference requests as a circuit breaker pattern — protecting the system from cascade failures. If token generation slows down because a related database is degraded, rejecting new requests keeps the system from piling onto an already-wedged experience.
Let me show you what this looks like in practice:
go
// Simplified admission control logic for LLM serving
func CanAdmit(ctx context.Context, req *InferenceRequest) (*AdmissionDecision, error) {
state := GetServingState() // In-memory counters + metrics snapshot
// Reject if we're already over safey threshold
if state.InFlightRequests >= state.MaxConcurrency {
return &AdmissionDecision{
Admit: false,
Reason: "concurrency_limit",
RetryAfter: 2 * time.Second,
}, nil
}
// Reject if TTFT is degrading — protects SLO
if state.P99_TTFT > state.TTFT_SLO * 0.8 {
return &AdmissionDecision{
Admit: false,
Reason: "ttft_degradation",
RetryAfter: 500 * time.Millisecond,
}, nil
}
return &AdmissionDecision{Admit: true}, nil
}
The key insight: admission control prevents overload. Autoscaling handles capacity. They operate on different timescales. Admission control acts in milliseconds. Autoscaling acts in minutes.
Admission Control vs Autoscaling for Inference: The Real Differences
Here's a breakdown based on what I've seen work across production systems in 2025 and 2026.
| Dimension | Admission Control | Autoscaling |
|---|---|---|
| Time to effect | Instant (ms) | Slow (1-5 min) |
| Primary goal | Protect existing capacity | Expand/contract capacity |
| Cost impact | Reduces waste on failed requests | Directly controls infra spend |
| Failure mode | Rejects traffic (availability risk) | Over-provisions (cost risk) |
| Best for | SLO preservation, burst absorption | Predictable traffic patterns |
Where teams get into trouble is treating these as mutually exclusive. They're not. At SIVARO, we typically recommend running admission control as a complement to autoscaling — with autoscaling reacting to sustained admission rejections.
That's the pattern I've seen work best at companies like Anyscale and Databricks — use rejection rates as a scaling signal.
When Autoscaling Alone Is the Right Answer
Let me give you a concrete case. A streaming analytics company — 60K requests per second, mostly short prompts under 200 tokens — came to us in early 2025. They had bursty traffic patterns dictated by their customers' batch jobs. Predictable bursts, 30-minute ramp-up, 2-hour plateau, then a sharp drop.
For them, admission control was the wrong tool. Their peaks were scheduled. Kubernetes' native autoscaling with custom GPU metrics handled it fine. The replication lag didn't hurt because the burst was forecastable.
Their setup looked like this:
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: llm-inference-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: inference-server
minReplicas: 4
maxReplicas: 32
behavior:
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Pods
value: 4
periodSeconds: 30
scaleDown:
stabilizationWindowSeconds: 300
metrics:
- type: External
external:
metric:
name: queue_depth
selector:
matchLabels:
service: inference
target:
type: AverageValue
averageValue: "25"
- type: Resource
resource:
name: nvidia_com_GPU_MEMORY_TOTAL
target:
type: Utilization
averageUtilization: 80
The rule from that experience: if your traffic is scheduled or forecastable, autoscaling wins. You can pre-plan your floor and ceiling. The startup latency gets absorbed by the ramp-up window.
When Admission Control Is Non-Negotiable
The opposite case: a conversational AI company (I'll call them "Convo" — they've since raised a Series B) running a 70B parameter fine-tuned model for customer support.
Their traffic was virally unpredictable. A product launch in Asia pushed 5x their normal traffic with zero warning. Their autoscaler was provisioned correctly — it just couldn't react fast enough. Model loading took 90 seconds minimum due to model sharding across 4 GPUs.
When Convo hit that spike without admission control, the results were catastrophic:
- Previously queued requests timed out after waiting 30+ seconds
- New requests piled onto the already-saturated servers, increasing memory pressure
- GPU OOMs triggered cascading restarts, which made loading slow and expensive
- The entire cluster was in a crash loop for 25 minutes, burning money on restarting pods that never served a single token
Once they added an admission control circuit breaker for LLM serving, things changed. Instead of trying to process every request and failing on all of them, they rejected new requests with a 503 + Retry-After header. The circuit breaker tripped when the queue depth exceeded the throughput capacity for more than 5 seconds.
That rejection bought the autoscaler time to spin up more replicas. And here's the smart part — they configured the autoscaler to treat rejection rate as its primary scale-out signal. Getting 429s at 5% of requests? Autoscale. Sustained? Scale aggressively.
The result: their P99 latency stayed under 2 seconds during the next launch spike. Requests that would have timed out instead got rejected in under 50ms with a clear retry signal. The client libraries handled the retries gracefully. End users experienced brief pauses instead of broken sessions.
The Middle Path: Admission Control as an Autoscaling Signal
There's an interesting architectural pattern emerging. Instead of seeing admission control vs autoscaling for inference as competing tools, integrate them into a single feedback loop.
Here's what that looks like:
- Admission controller tracks a token budget — an estimate of remaining capacity based on current concurrency and memory
- When rejection rate crosses a threshold (say 2% of requests), the controller publishes an event to the autoscaler
- Autoscaler uses that event as a trigger — not a custom metric from the GPU, but a direct signal from the admission layer
- When rejection rate drops below 0.1% for 10 consecutive minutes, autoscaler starts scaling down
This closed-loop system handles both regimes well. Slow, gradual load increases are handled by the autoscaler reacting to traditional metrics. Sharp, unpredictable spikes are handled by rejection first, which buys the slower autoscaler time to catch up.
Helm users building this kind of system are increasingly adopting this pattern with queue-based scaling, but I'm seeing more teams build custom admission controllers that emit Prometheus metrics for exactly this reason.
Here's a concrete implementation:
python
# Metrics exporter for admission control → autoscaling bridge
from prometheus_client import Counter, Gauge, start_http_server
admission_rejections = Counter(
'admission_rejections_total',
'Total requests rejected by admission control',
['reason']
)
active_concurrency = Gauge(
'inference_active_concurrency',
'Current requests in flight'
)
# Export query counts by token length bucket to inform capacity decisions
token_bucket_histogram = Histogram(
'inference_input_tokens',
'Input tokens per request',
buckets=[50, 100, 250, 500, 1000, 2000, 5000]
)
At SIVARO, we've deployed versions of this for video generation startups, real-time voice AI platforms, and financial trading copilots. The pattern holds: admission control for protection, autoscaling for elasticity, and a feedback loop connecting them.
Cost Models: Which One Saves You More?
Let's talk money.
In 2026, an A100 costs roughly $2.50-$4.00 per hour on spot markets. An H100 runs $4-$7. A production cluster running a 70B model with decent redundancy runs 4-16 GPUs minimum. That's $100-$450/hour just in raw GPU cost — before adding KV cache overhead, inference server instances, and orchestration.
Autoscaling saves you money by right-sizing your cluster. If you're running 8 GPUs at 2am with 10% utilization, autoscaling could drop you to 2 GPUs and save $200/hour overnight. Over a month, that's significant.
Admission control saves you money differently — it prevents wasteful load. When a GPU OOMs, you pay for the restart. When requests pile up and crash the process, you pay for recovery time where the GPU isn't serving anyone. When a shared cluster degrades to the point where every request takes 30x longer, you're burning compute on garbage.
From our billing data across clients, I've seen these patterns:
- Autoscaling typically saves 30-50% on GPU costs for workloads with predictable diurnal patterns
- Admission control typically reduces failed request rates from 10% to under 1% — which translates to cloud credits or user trust — plus avoids 5-15% waste on OOM restarts
- Combined, teams report 40-70% cost reduction versus always-on static clusters
The catch: autoscaling's savings only materialize if your traffic actually varies. If you run flat 24/7, autoscaling just adds orchestration complexity without a cost benefit.
What Most People Get Wrong About Kubernetes-Specific Admission Control
The term "admission control" is muddied by Kubernetes' own dynamic admission controller system. Those intercept API server requests and validate/mutate pods before scheduling.
That's important for cluster resource governance — enforcing limits, injecting sidecars, validating GPU requests — but it operates at a completely different layer than the LLM inference request gate I've been describing.
When teams conflate the two, they over-engineer the Kubernetes layer and under-engineer the application layer.
The Kubernetes admission controller can tell you "this pod can't have more than 4 GPUs" — but it can't tell you "this inference request should be rejected because the KV cache on GPU 0 is 90% full." Different problems, different tools, different latencies.
The admission control for LLM inference requests belongs in your serving path — before the model, after the load balancer. Not inside the Kubernetes API server.
Key Features to Compare When You're Evaluating Tools
Let me give you a checklist based on what I've evaluated for clients in 2025-2026.
For admission control tools:
- Serve up your rejection grace period — Can it return a
Retry-Afterheader or does it just drop the connection? - SLO-based policies — Does it let you express "keep P99 under 300ms" and enforce that directly?
- Priority classes — Can you let premium users through while rejecting free-tier during overload? (Paying customers will notice if a startup spike trips your breaker.)
- Model-aware capacity — Does it understand that a 2K-token prompt is more expensive than a 50-token prompt?
For autoscaling tools:
- Custom metric support — Can you feed it GPU utilization, queue depth, or model-specific metrics?
- Scale-down delay — Does it wait long enough after a spike to avoid thrashing?
- Cooldown and stabilization windows — What happens when traffic is oscillating?
- Pre-warming support — Can you keep a spare replica running with the model pre-loaded, so it's ready to serve immediately?
For both:
- Integration with your serving stack — Does it work with vLLM, TensorRT-LLM, or your custom inference server?
- Multi-model support — Can you run different models on the same cluster and treat capacity independently?
- Observability — Can you see rejection reasons, scale events, and cost impact in your existing dashboards?
Which open-source tools should you look at?
- KEDA handles event-driven autoscaling well, including queue-based triggers
- Envoy Gateway with rate limit filters or a custom external auth service for admission control
- Custom Go middleware in your inference gateway that queries Kubernetes metrics
If your stack is on Kubernetes and you're using vLLM or Ray Serve, both have some built-in queue management but neither gives you production-grade admission control out of the box. You'll build it or buy it.
When to Buy vs. When to Build
Let me level with you on this.
Building your own is never simpler than buying. The advantage of building is customization — you can encode your exact business logic into rejection rules.
But the cost of maintaining that code is real. Admission control policies need constant tuning. Your business priorities change. The traffic mix changes. When a model gets fine-tuned and its output latency changes, your thresholds need updating.
Buy if your serving stack is config-heavy (vLLM + FastAPI + standard Kubernetes). Look at managed solutions like the queueing features from your cloud provider or tools like LiteLLM Proxy's budgeting and rate limiting.
Build if you're running at serious scale (lets say >1 billion tokens/day) or if you have unusual capacity constraints that off-the-shelf tools can't encode.
There's a third path — I've seen companies use AI gateway products like Portkey, Helicone, or OpenRouter for admission control when they're consolidating multiple model providers. These add cost per token but eliminate the maintenance overhead. For startups experimenting with models, that's often the right call.
Frequently Asked Questions
Q: Can admission control replace autoscaling?
No. Admission control prevents overload but doesn't add capacity. If you have sustained growth, you need both. Admission control keeps the system alive long enough for autoscaling to do its job.
Q: What's the right default for admission control rejection? — 429 or 503?
It depends on your client. 429 signals you're rate limiting — try again later. 503 signals the server is temporarily unavailable. For LLM inference, 503 with a Retry-After header is more honest — your system isn't enforcing a user-level quota, it's experiencing capacity pressure.
Q: Does admission control handle LLM inference requests differently from traditional services?
Yes. Since GPU memory is the bottleneck, an admission controller for LLM inference needs to track the estimated token count of each request, which can be checked pre-processing with heuristic estimators. That's different from just counting requests or bytes.
Q: How do I integrate admission control right without dropping important customer traffic?
Set different priority classes: premium and batch users get admitted when concurrency is below 80% max. Free tier gets admitted only when below 50%. When saturation crosses the threshold, reject lower-priority requests first. In our experience, 80% is the sweet spot for protection before degradation.
Q: Should I adopt the "burst to paid GPUs" pattern over autoscaling internal capacity?
That's a valid model — use admission control to protect your reserved capacity, and when sustained load exceeds your reserved fleet, automatically route excess to serverless inference providers (like Replicate, Baseten, or cloud "serverless" endpoints). You get instant scaling without the replica startup latency. You eat a higher per-token cost but only for the excess.
Q: How do I check whether admission control or autoscaling is the problem?
Look at the failure symptom:
- High
queue_depth→ too much concurrency → admission control fix - Slow TTFT (time-to-first-token) → capacity shortage → autoscaling fix
- Both? Evaluate whether the autoscaler response time matches your traffic burst duration
Which Should You Start With?
If you're building a new inference system today, I'd start with admission control first. Why?
Because it's cheaper to build and protects you from the worst failure mode: a cascade where the system becomes useless under load. A good admission controller with static capacity works day one. Then layer autoscaling on top — using admission rejections as a primary scale-out signal.
Start conservative: set high rejection thresholds, make sure your clients handle 4xx/5xx gracefully (most SDKs do). Monitor weekly trends. Dial it in.
If you already have a stable infrastructure with elastic capacity and you're seeing cost overruns, start with autoscaling.
The Bottom Line
Admission control and autoscaling solve adjacent problems that, when left unsolved, produce identical symptoms: slow responses, failed requests, and angry customers. But they work at different timescales and protect you against different failures.
I've had teams ask why they should invest in admission control when autoscaling handles their current traffic. My response year after year is consistent: autoscaling is essential infrastructure for cost-sensitive, variable traffic — but it doesn't prevent the death spiral of a saturated GPU cluster. Only admission control does.
Buy both. Run them in a closed loop. Use admission control for protection and rejection rates for scaling decisions.
That's been the winning formula for every high-throughput inference deployment I've worked on at SIVARO and remains what I'd recommend to anyone building production AI systems in 2026. It's the difference between a system that degrades gracefully and one that crashes when you need it most.
Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.