← Back
Home › Systems › AI and ML infrastructure

llm-api-platform

Sells access to a fixed set of large language models over HTTP, streaming generated tokens back to developers who send prompts.

Claude API, OpenAI API, Gemini API

Open the llm-api-platform pagellm-api-platform Constrained decodingagentic-ai: Force LLM output to match a regex, JSON schema or grammar by masking, at every step, the tokens that would leave the language.›Model routing and cascadesagentic-ai: Send each request to the cheapest model that will answer it well enough, by rules, a learned router, or a cascade that escalates from small to large on low confidence.›Model context protocolagentic-ai: JSON-RPC protocol exposing tools, resources and prompts from servers to LLM clients, with capability negotiationPrompt cachingagentic-ai: Reuse the attention keys/values of a repeated prompt prefix, so an agent's growing context is prefilled once and later turns pay only for the new tokens.›Prompt injection defenseagentic-ai: Treat every untrusted string as data, track where values came from, and make tool calls and rendered output depend on provenance, not on what the model says.›Tool callingagentic-ai: The model emits a structured call (id, name, JSON arguments) instead of prose; your code validates, runs it and returns a result tagged with the same id.›Hdr histogramdata-structures: Log-linear bucketed histograms with bounded relative error for latency percentilesDeterministic simulationtestingdistributed: Run the whole system in one thread under a seeded scheduler with simulated network, disk and clock, so every failure replays from its seed.›Primary-backup replicationdistributed: One node orders all writes and ships them to standbys; the acknowledgement rule (none, one, all) sets what a crash loses, and an external arbiter decides who takes over.›Idempotency keysfinance: Client-chosen unique key per logical operation, stored with a request fingerprint and the final response, so retries replay the first result instead of acting twice.›Usage meteringfinance: Counting tokens/requests per user and key, aggregating for quotas and billing with idempotent eventsProcess supervisionhardware-os: A parent process starts services, reaps their exits and restarts them under a delay and burst-limit policy, then stops them with SIGTERM before SIGKILL.›Continuous batchingml-training: Schedule LLM inference per iteration, not per request; finished sequences leave and new ones join the running batch every step, which keeps the GPU full.›Paged KV cacheml-training: Store each sequence's attention keys/values in fixed-size blocks mapped through a block table, like virtual memory pages; near-zero fragmentation and copy-on-write sharing.›Prefill decode disaggregationml-training: Running prompt prefill and token decode on separate GPU pools with KV-cache transferSpeculative decodingml-training: A cheap draft proposes γ tokens, the big model verifies them in one pass, and rejection sampling keeps the target's exact distribution at 2-3x speed.›Tensor parallelismml-training: Split each layer's weight matrices across GPUs (Megatron-style column then row splits) so one layer's math runs on t devices with one all-reduce per block.›Server-sent eventsnetworking: One long-lived HTTP response carries text events one way; each event may carry an id, so a reconnecting client names its last one and the server resumes.›Coverage-guided fuzzingsecurity: Mutate inputs, run an instrumented target, and keep any input that reaches a new code edge; feedback turns blind guessing into incremental search.›Mutual TLSsecurity: TLS where the client also proves a certificate key, so every connection carries a verified, rotatable machine identity.›Point-in-time recoverystorage: Periodic base backups plus a continuously archived change log let you rebuild the state as of any instant, then branch from there.›Adaptive concurrency limitssystems: AIMD/gradient limits on in-flight requests driven by observed latency, for backpressure and overload protectionAutoscalingsystems: Target-tracking scaler with stabilization windows, cooldowns and hysteresisCircuit breakersystems: Stop calling a failing dependency for a while, probe it with trial calls, and resume on recovery: fail fast instead of piling up timeouts.›Distributed rate limitingsystems: Enforce one rate limit across N servers: a central atomic counter, a limit split per node, or batched token leases, trading exactness against coordination cost.›Distributed tracingsystems: Give each request a 128-bit id, record timed spans linked by parent ids, pass the ids in a header across every hop, and join the spans back into a tree afterwards.›Fair share schedulingsystems: Dominant resource fairness and hierarchical fair-share queuesGraceful drainingsystems: On a termination signal, stop taking new work, finish in-flight work until a deadline, tell clients to reconnect elsewhere, then exit; clients resume from a token.›Priority and preemptionsystems: Priority classes, quota and evicting lower-priority work to admit higherStaged rolloutsystems: Rolling, blue-green and canary rollout with health gates and automatic rollbackWarm pool provisioningsystems: Keep pre-initialized instances ready to cut cold startsByte-pair encoding (BPE)tokenizationmachine-learning: Learn a subword vocabulary by repeatedly merging the most frequent adjacent pair; byte-level BPE encodes any input losslessly with 32k-200k tokens.›Finite state transducersearch-sort: Minimal acyclic FST mapping sorted keys to values; compact term dictionaries with prefix/fuzzy searchCalibrationmachine-learning: Make predicted probabilities match observed frequencies: measure with ECE, fix post hoc with temperature, Platt or isotonic scaling on held-out data.›Embeddingsmachine-learning: A learned table mapping discrete ids to dense vectors: gather forward, sparse scatter-add backward, row-wise optimizers to keep huge tables cheap.›Multi-armed banditsmachine-learning: Choose among K options repeatedly while learning their payoffs: epsilon-greedy, UCB1 and Thompson sampling keep total regret low where a fixed split or a fixed exploration rate pays forever.›OAuth 2 and OpenID Connectsecurity: Delegated authorization (OAuth 2) and login on top of it (OIDC); use authorization code + PKCE for every user-facing client.›JSON Schema validationsecurity: Compile a JSON Schema once, then check every untrusted document against it, within hard size and depth limits, and report failures as JSON Pointers.›Text classificationmachine-learning: Assign one or more labels to a text; climb a ladder from regexes to linear models on n-grams, embeddings, fine-tuned encoders and LLM prompts, only as far as the data and budget demand.›Radix triedata-structures: Compressed prefix tree for path routing, domain matching and prefix lookupsLRU and CLOCKsystems: LRU evicts the least recently used entry via hash map plus linked list; CLOCK approximates it with a reference bit, so hits take no lock.›Json rpcnetworking: JSON-RPC 2.0 requests, notifications and batchingHtml sanitizationsecurity: Allowlist-based HTML sanitizing of untrusted markup+ 47 moreText normalizationmachine-learning: Rewrite messy text into one canonical form for matchers and models, or into spoken words for speech output (and back), keeping a map to the original offsets.›Loss functionsmachine-learning: The scalar a model minimizes: cross-entropy for classes and tokens, MSE or Huber for values, each with a stable form and simple gradient.›AdamWml-training: Adam's per-parameter adaptive steps with weight decay applied directly to the weights; the default optimizer for transformers and LLM pretraining.›Reverse-mode automaticdifferentiationml-training: Record the forward computation on a tape, then sweep it backwards once to get the gradient of a scalar loss for all inputs.›Bayesian rate estimationstatistics: Estimate a conversion or event rate from few observations with a Beta-Binomial or Gamma-Poisson update: two counters, an honest interval, and P(B beats A) directly.›Linear and logistic regressionmachine-learning: Fit a weighted sum of features to a number (least squares) or a probability (logistic); the baseline every model must beat.›Csprngsecurity: OS-backed cryptographically secure random numbers (getrandom), and when a fast PRNG is not enoughJSON Web Token (JWT)security: A signed, URL-safe token carrying claims; the verifier's job is the checklist (pinned algorithm, key by kid, exp, aud, iss), not the format.›+ 24 moreL-BFGSnumerics: Quasi-Newton minimizer that approximates the inverse Hessian from the last m gradient differences via the two-loop recursion; O(m·n) memory and work per step.›LU and Cholesky factorizationnumerics: Factor A = PLU (any square matrix, partial pivoting) or A = LLᵀ (SPD) once in O(n³), then solve each right-hand side in O(n²).›+ 10 more+ 1 more

How it is built

Architecture overview

An LLM API platform sells access to a fixed set of large models over HTTP. A request carries a prompt, sometimes tools, and gets back tokens, usually streamed. Behind that one call sit four very different systems: an edge that authenticates, limits and meters traffic; a router that picks a model and a replica pool; an inference fleet of GPU servers whose cost per token decides the business; and a control plane that decides which models run where, in which tier, with which rollout state. The central difficulty is that GPU capacity is scarce, slow to add, and spent in very uneven units: a request may use 200 tokens or 200,000, and its cost depends on how much of the prompt is already in a cache.

The idea that makes it work is that every layer shares one currency, the token, and one scarce resource, KV-cache memory on a GPU. Rate limits count tokens, billing counts tokens, schedulers pack tokens into batches, caches reuse the key-value state of tokens already computed. Priority, batch and cached traffic are then three ways to sell the same GPU seconds at different prices and different promises. Public documentation of the big providers shows the visible edge of this: token-bucket limits and streamed events at the API (source: Anthropic, Rate limits; Streaming Messages), 5-minute and 1-hour prompt-cache lifetimes, and a batch API at a 50 % discount (source: Anthropic, Prompt caching; Batch processing). The inside is mostly assembled from open serving engines and papers.

Parts:

 client ──TLS──► edge: auth ─► rate/concurrency limits ─► idempotency ─► safety pre-check
                                 │ 429 + retry-after            │ replay stored result
                                 ▼                              ▼
                       router: model, tier, region, prefix-hash ──► cache-affine replica
                                 │                                        │
          ┌──────────────────────┴──────────┐              ┌──────────────┴──────────────┐
          │ prefill pool (compute-bound)    │──KV blocks──►│ decode pool (memory-bound)  │
          │ continuous batch, paged KV,     │              │ continuous batch, spec.     │
          │ prefix cache                    │              │ decoding, TP across GPUs    │
          └─────────────────────────────────┘              └──────────────┬──────────────┘
                                                                          │ tokens (SSE)
 metering log ◄── token counts, cache hits ──── edge ◄── safety post-check ┘
 control plane: model registry, rollout state, limits ──► router, autoscaler, warm pool

How the parts fit together

Edge and admission

The edge must say no cheaply: a rejected request costs microseconds, an accepted one GPU seconds. Three limits stack. A rate limit over tokens per minute, enforced across many edge servers by Distributed rate limiting: the usual choice is a local bucket per node with batched leases from a shared counter, because a central counter per request would add a network hop to every call. Anthropic documents its limits as a token bucket that refills continuously, so capacity is replenished up to a maximum rather than reset on the minute (source: Anthropic, Rate limits). A concurrency limit on in-flight requests, adjusted by Adaptive concurrency limits (no page yet): it watches latency and shrinks the limit when the fleet slows down. A spend or tier limit from the control plane. Anthropic also documents "acceleration" 429s for sharp usage increases, the sign of a limiter that looks at slope, not only level (source: Anthropic, Rate limits).

Clients retry, and a retry of a request that actually completed would charge twice and could run a tool twice. Idempotency keys give the edge a stored result to replay. The cost is a store lookup per request and a retention window; a reused key with a different body must be rejected, not served.

Inside the platform, Mutual TLS gives every hop a verified identity, and a Circuit breaker on each upstream stops a sick pool from piling up waiting requests.

API surface

A reply takes seconds, so the API streams it: Server-sent events carry text deltas over one HTTP response, with periodic keep-alive events so proxies do not close an idle stream. In Anthropic's documented stream, a message is a sequence of message_start, content blocks made of content_block_start, one or more content_block_delta and content_block_stop, then message_delta and message_stop, with ping events interleaved and token counts that are cumulative (source: Anthropic, Streaming Messages). An error can arrive mid-stream, after the 200 status was sent, so clients must treat the stream as the result.

Tool calling is the contract that lets the model request an action: the model emits a structured call with an id, the client or a server-side tool runs it, and the result returns under the same id. Where tools run on the provider's side, the platform becomes an executor and needs sandboxing, per-tool timeouts and Prompt injection defense, because a fetched web page is untrusted text that lands in the model's context. Constrained decoding enforces a JSON schema by masking tokens at each step; it runs inside the engine, but schema compilation is an API-level feature with its own limits. The Model Context Protocol (no page yet) is the open interface through which a platform reaches customer-hosted tools.

Router

The router answers: which model version, which region, which replica. Model choice by the customer is explicit, but behind a model name sit several versions at different rollout stages (Staged rollout, no page yet), and a platform may also offer cheaper cascades (Model routing and cascades). Replica choice is where the money is: Prompt caching only pays if a request lands on a replica that still holds the KV blocks of its prefix. So the router hashes the prompt prefix and prefers the replica (or pool) that served it last, falling back to the least loaded replica when the preferred one is saturated. Documented behaviour at the API matches this: caches have a 5-minute default lifetime that is refreshed on use, an optional 1-hour lifetime, and a lookback of 20 blocks per breakpoint (source: Anthropic, Prompt caching). A cache is a routing property, not a global one.

Inference engine

One replica is a group of GPUs holding one model copy. Tensor parallelism splits each layer across the group (Megatron-LM style: column then row splits with one all-reduce per block, Shoeybi et al. 2019) so a model larger than one GPU's memory runs at the latency of one layer's math. The engine's scheduler uses Continuous batching: at every decoding step, finished sequences leave and waiting ones join, so the batch stays full whatever the request lengths (iteration-level scheduling, Yu et al., Orca, OSDI 2022). The memory for per-sequence attention state is managed as fixed blocks by a Paged KV cache, which removes fragmentation and lets requests that share a prefix share blocks (Kwon et al., PagedAttention, SOSP 2023). Block sharing makes the prompt cache cheap.

Speculative decoding lowers latency per token: a small draft model proposes several tokens and the large model verifies them in one pass, with rejection sampling keeping the output distribution exact (Leviathan et al. 2023). It trades extra compute for latency, so it pays where batches are small.

Prefill (reading the prompt) is compute-bound; decode (generating) is memory-bandwidth-bound. Running both in one batch makes long prompts stall everyone's next token. Prefill/decode disaggregation (no page yet) puts them in separate pools and ships the KV cache between them, so each pool is sized and tuned for its own latency target (DistServe, Zhong et al. 2024; Splitwise, Patel et al. 2024). The contract between the pools is the KV block layout and a transfer fast enough not to cancel the gain.

Capacity and scheduling

GPUs take minutes to start (load weights, compile, warm caches), so Autoscaling (no page yet) needs a signal that leads demand and a Warm-pool provisioning (no page yet) of loaded replicas to absorb a spike. The signal is queue depth or time-to-first-token, not CPU.

Traffic classes are the way to sell spare capacity. Interactive requests have a latency target; batch requests accept delayed completion for a lower price (Anthropic documents a 50 % discount; source: Anthropic, Batch processing); both run on the same fleet. Priority and preemption (no page yet) lets interactive work evict batch work, whose KV blocks are dropped or swapped out and recomputed later. Fair-share scheduling (no page yet) stops one large customer from taking every slot inside a class.

Metering

Billing is exact where limits are approximate. The engine reports input, output, cache-write and cache-read tokens per request; the edge writes one usage event per request with the request id as dedup key, and the Usage metering pipeline aggregates them per customer and period. A retried request must not bill twice, which is why metering reuses the idempotency key and the request id. Cache reads are priced differently from fresh input, so the cached-token split belongs in the event.

Safety hooks

Safety checks sit at three points: classifiers on the incoming prompt, constraints during decoding, and checks on the output stream. They are on the latency path, so they run as small models beside the main one, and an output check on a streamed reply can only cut the stream, not unsend what was shown. Provenance rules from Prompt injection defense keep model-chosen arguments from reaching privileged tools.

Observability and operations

A request crosses edge, router, prefill and decode pools; Distributed tracing joins those spans so that a slow time-to-first-token can be pinned on queueing, prefill or transfer. Latency is recorded in an HDR histogram (no page yet), because percentiles matter more than means and must be merged across servers. Graceful draining is mandatory for streams: on shutdown a replica stops taking new requests and finishes generating, since killing it truncates paying customers' replies. Process supervision restarts crashed engines with backoff.

Control-plane state and verification

Customers, keys, limits and model registry are small, strongly consistent data. A Primary-backup replication of a relational store with Point-in-time recovery is enough; the data plane never waits on it, because each edge caches the entries it needs. The harder part is testing rare failure paths: Deterministic simulation testing for the stateful pieces (limiter leases, idempotency store, metering), and Coverage-guided fuzzing for the parsers of untrusted input (request bodies, schemas, tool results).

Data and control flow

One streamed request:

  1. The client opens TLS and sends the request with an idempotency key. The edge authenticates, charges the token estimate against the rate-limit bucket, checks the concurrency limit, and looks up the idempotency key.
  2. The router resolves the model name to a version and a pool, hashes the prompt prefix and picks a replica that probably holds the prefix.
  3. The engine matches the prefix against its cached blocks, then runs prefill only on the uncached tail. Time here grows with uncached prompt length.
  4. Decode runs inside the continuous batch: one token per step per sequence, with speculative drafts if enabled. Each token goes back through the safety check to the SSE stream.
  5. On completion, the engine reports token counts (input, output, cache read/write); the edge appends one usage event and stores the final response against the idempotency key. Most time and cost are in steps 3 and 4: time-to-first-token is queueing plus prefill, inter-token latency follows the decode batch size.

One capacity change:

  1. The autoscaler sees queue depth or time-to-first-token above target for a window.
  2. It claims replicas from the warm pool, or starts new ones if the pool is empty (weight loading takes minutes).
  3. The router adds a replica only after a health probe passes; its cache is empty, so it gets traffic gradually.
  4. On scale-in, the replica is drained, not killed.

Scaling

Pulled in this order:

  1. Cache hit rate. The cheapest token is one that is not recomputed. Levers: route by prefix, longer cache lifetime, advice to customers to put stable content first.
  2. Batch size and memory. Bigger batches raise tokens per GPU second until KV memory runs out. Levers: paged KV cache, quantized KV, shorter maximum context in cheap tiers.
  3. Latency of the two phases. Levers: speculative decoding, prefill/decode disaggregation when long prompts hurt tail latency, tensor parallelism.
  4. More replicas. Embarrassingly parallel but slow to add: warm pools, then capacity reserved ahead of launches.
  5. Class mix. Batch and low-priority work fills troughs; preemption keeps interactive latency intact.
  6. The edge and control plane scale last: limiter state shards by key, the metering log by customer.

Failure modes

FailureSymptomCauseFix
Cache stampede after a deploycost and latency jump, hit rate dropsnew replicas start cold, router sends prefixes to empty cachesgradual traffic shift, pre-warm common prefixes, keep prefix affinity during rollout
Head-of-line blockingp99 time-to-first-token spikes with long promptsprefill of one huge prompt stalls the shared batchchunked prefill, separate prefill pool, per-class limits
Retry storm429s and overload errors grow, goodput fallsclients retry together; no jitter, no budgetretry-after honoured, jittered backoff, adaptive concurrency limit at the edge
Double chargecustomer billed twice for one callretry after a timeout that actually completed, metering without dedupidempotency key on the request, request id as metering dedup key
Truncated streams on deployreplies cut mid-sentence during rolloutsreplicas killed with requests in flightgraceful draining with a deadline longer than max generation time
KV memory exhaustionrequests evicted or recomputed, tail latency uptoo many long sequences admittedadmission by KV budget, preemption of low-priority sequences
Tool result injectionmodel takes an action nobody asked foruntrusted fetched text treated as instructionsprovenance tracking, policy gate on privileged tools
Bad model version rolloutquality or latency regression for a slice of userswhole fleet switched at oncestaged rollout by percentage, automatic rollback on metric breach

Real implementations

No provider publishes its whole platform; the table lists the open parts that implement the pieces above.

namewhat it isrepolicencenotes
vLLMinference engine with continuous batching, paged KV cache, prefix cachingvllm-project/vllmApache-2.0origin of PagedAttention
SGLanginference engine and serving framework with prefix cachingsgl-project/sglangApache-2.0structured generation support
TensorRT-LLMNVIDIA's optimised inference libraryNVIDIA/TensorRT-LLMApache-2.0GPU-specific kernels
llm-dKubernetes-native distributed inference stackllm-d/llm-dApache-2.0cache-aware routing and disaggregated serving
NVIDIA Dynamodistributed inference framework with disaggregated prefill and decodeai-dynamo/dynamoApache-2.0datacenter-scale serving
MooncakeKV-cache-centric serving architecture (paper and transfer engine)kvcache-ai/Mooncakesee repopaper: arXiv 2407.00079
LiteLLMgateway that unifies many providers behind one API, with routing and budgetsBerriAI/litellmMIT (enterprise directory separate)edge and router pieces for a customer-side gateway
Netflix concurrency-limitsadaptive concurrency limiters for servicesNetflix/concurrency-limitsApache-2.0reference for the edge limiter
HdrHistogramhigh-dynamic-range latency histogramHdrHistogram/HdrHistogramCC0 / BSD-2used for percentile recording
Claude API, OpenAI API, Gemini APIthe hosted platformsClaude rate limits, prompt caching, batchproprietarypublic docs show limits, caching and batch tiers; internals are not published

The alternative: one model for one customer needs none of the router, tiers or edge: run vLLM or SGLang behind an ordinary load balancer.

Sources

  • W. Kwon et al., Efficient Memory Management for Large Language Model Serving with PagedAttention, SOSP 2023. paper
  • G.-I. Yu et al., Orca: A Distributed Serving System for Transformer-Based Generative Models, OSDI 2022. paper
  • Y. Leviathan, M. Kalman, Y. Matias, Fast Inference from Transformers via Speculative Decoding, 2023. paper
  • M. Shoeybi et al., Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism, 2019. paper
  • Y. Zhong et al., DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving, OSDI 2024. paper
  • P. Patel et al., Splitwise: Efficient Generative LLM Inference Using Phase Splitting, ISCA 2024. paper
  • R. Qin et al., Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving, 2024. paper
  • Anthropic API documentation: Rate limits, Streaming Messages, Prompt caching, Batch processing.
  • OpenAI, Batch guide; Google, Gemini API context caching.
  • Stripe, Designing robust and predictable APIs with idempotency. blog

Similar systems

Share the most building blocks with this one.