ux
Gpu Economics For Self Hosted Code Models Production: practical systems guide
Technical field guide on gpu economics for self hosted code models production playbook for teams building dependable AI coding workflows.
Running code models on your own GPUs sounds expensive until you calculate what you're already paying per-seat SaaS subscriptions multiplied by team size. A 50-person engineering org spending $20–40/dev/month on AI coding tools is burning $12k–24k annually—enough to lease serious inference hardware that you control, audit, and tune to your stack.
The hard part isn't justifying the CapEx. It's designing a system that delivers sub-500ms p95 latency, handles bursty traffic from dozens of concurrent devs, and doesn't melt down when three people simultaneously ask for refactors during standup. This guide walks through the actual deployment decisions—GPU selection, batching strategy, model sizing, and the operational primitives that keep self-hosted inference production-grade.
Why latency matters more than throughput
Code completion dies if it takes two seconds. Developers will disable the tool, ignore suggestions, or context-switch to Slack while waiting. Your target is **p95 < 500ms from keypress to first token**, which means the model must start generating within ~300ms after the request hits your inference server.
Throughput—tokens per second across all requests—matters for cost modeling, but latency is the product constraint. A single A100 (80GB) can serve 8–12 concurrent developers with small models (7B–13B parameters) if you batch aggressively and keep the KV cache hot. Scale beyond that and you need either more GPUs or a request router that spreads load across instances.
The trap: optimizing for throughput first by running massive batch sizes. This tanks latency for individual requests because the GPU churns through a 32-request batch before returning a single token. Start with batch size 1–4 and tune upward only when you've validated latency under realistic traffic patterns.
Model size vs. hardware: the 7B / 13B / 34B tiers
**7B models** (e.g., CodeLlama-7B, DeepSeek-Coder-7B) fit comfortably in 16GB VRAM with room for KV cache. They run on consumer RTX 4090s or datacenter L4s. Quality is good enough for autocomplete and simple refactors but struggles with multi-file context or nuanced logic.
**13B–15B models** are the sweet spot for self-hosted production. They need 24–32GB VRAM depending on quantization (FP16 vs. int8). An RTX 6000 Ada (48GB) or A10G (24GB) handles one instance; an A100 (80GB) can run two with separate processes. Noticeably better at following instructions and handling 4k+ token contexts.
**34B+ models** require 48GB+ even with int8 quantization. You're looking at A100 80GB or H100 territory. The quality jump is real—better at architecture-level reasoning, understanding framework idioms—but inference is 2–3× slower per token. Reserve these for asynchronous tasks (PR review, test generation) where 1–2 second latency is acceptable.
Goatfied's agent loop runs smaller models for the **plan** and **edit** steps (latency-critical) and reserves larger models for the **validate** step, where we're checking diffs against compile/lint/test gates and can tolerate a second of inference time.
Batching and KV cache: the operational knobs
Modern inference servers (vLLM, TensorRT-LLM, text-generation-inference) support **continuous batching**: new requests join in-flight batches dynamically instead of waiting for the entire batch to finish. This is non-negotiable. Static batching destroys tail latency.
The KV cache stores attention keys/values from previous tokens so the model doesn't recompute context on every new token. A 4k context with 13B FP16 model eats ~2GB VRAM per request. With 48GB total, you can fit ~8 concurrent 4k-context requests plus the model weights. Monitor cache evictions—if you're thrashing, either reduce max context length or add more VRAM.
**PagedAttention** (from vLLM) reduces memory fragmentation by splitting the KV cache into fixed-size blocks. This lets you pack more concurrent requests into the same VRAM footprint. In practice, it increases effective batch size by 20–40% without changing hardware.
Tune `max_num_seqs` (concurrent requests) and `max_model_len` (context window) together. Start conservative: `max_num_seqs=8`, `max_model_len=4096`. Measure p95 latency and VRAM usage under load, then bump `max_num_seqs` until latency degrades or you hit OOM.
Traffic patterns and request routing
Code completion traffic is **spiky**. Mornings after standup, right before lunch, late afternoon before commits. You'll see 2–3 concurrent requests for hours, then suddenly 15 simultaneous autocomplete + 3 longer context fills when everyone's heads-down.
A single GPU instance can't absorb that variance without either overprovisioning (wasting idle capacity) or queueing requests (blowing latency). You need a **request router** that tracks per-instance load and directs new requests to the least-busy GPU. NGINX with custom Lua scripts works; so does a simple Python FastAPI proxy that polls inference servers for queue depth.
Autoscaling is hard because model startup takes 30–60 seconds (loading weights, warming up KV cache). Kubernetes HPA based on request queue length is too slow. Better: keep 2–3 instances warm during business hours and scale up at known traffic peaks (9am, 1pm). Use preemptible instances for overflow capacity if your cloud provider supports GPU preemption with reasonable SLAs.
Cost modeling: TCO vs. per-seat SaaS
An A100 80GB on AWS p4d.24xlarge costs ~$32/hour (~$23k/month for 24×7). That's absurd for a single team. Instead:
- **Self-hosted on-prem**: Buy RTX 6000 Ada ($6800) or A10G ($2500 used). One-time CapEx, 3-year depreciation. For a 20-person team, ~$340/dev over 3 years.
- **Reserved instances**: GCP A100 40GB reserved 1-year is ~$7k/month. 40 devs = $175/dev/month, higher than SaaS but you own the data and model weights.
- **Spot/preemptible**: AWS g5.12xlarge (4× A10G) spot averages $3–5/hour. Good for dev/staging; too risky for production without robust failover.
The break-even is usually 15–25 developers depending on SaaS pricing and whether you're already running on-prem infra. Below that, SaaS is cheaper. Above, self-hosted wins if you can staff the ops overhead.
Operational primitives: metrics, fallback, updates
**Metrics that matter**: p50/p95/p99 latency, requests per second, VRAM utilization, KV cache hit rate, token throughput. If p95 > 500ms, users notice. If VRAM util > 90%, you're about to OOM. Prometheus + Grafana with alerts on latency SLO violations.
**Fallback**: Keep API keys for a managed provider (OpenAI, Anthropic) as a hot standby. If your inference cluster is down or saturated, route overflow to the API. Costs spike but the tool stays usable. Goatfied's managed offering does this automatically; self-hosted users wire it into their router.
**Model updates**: Treat model weights like container images. Test new versions in a canary environment (5% traffic), validate latency and quality on real traffic, then roll out. Regression in code quality is subtle—bad suggestions don't crash, they just frustrate users. Pair quantitative metrics (acceptance rate, tokens generated) with qualitative feedback from a few trusted devs.
Related reading
- [Goatfied vs Cursor vs GitHub Copilot: a benchmark across 50 real PR tasks](/blog/goatfied-vs-cursor-vs-github-copilot-benchmark-50-pr-tasks)
- [The Goatfied agent loop: how we ship code that actually compiles first try](/blog/goatfied-agent-loop-compiles-first-try)
