All the URLs the server exposes and what each one does.
Startup (the lifespan hook)
Modal-style cold start: every expensive thing happens once, before any request lands.
Tokenizer
Stateless. Same tokenizer instance shared across every request.
Streaming (SSE)
Tokens go to the client as soon as the model produces them. No waiting for the whole response.
Load simulator
A built-in multi-user traffic generator. Lives in simulator_prompts.py; control endpoints are on the server.
Knob
What it does
num_users
How many virtual users to run in parallel.
weighted prompt buckets
Mix of short, medium, long prompts in realistic ratios.
per-user RNG seed
Each user picks prompts from its own deterministic stream so runs are reproducible.
jittered think-time
Random pause between a user's turns, so requests don't all arrive in lockstep.
session_id per user
Each user has a stable session ID so the cache + fairness layers see real session boundaries.
Why this exists: the engine is built for many concurrent users with mixed prompt lengths. Single-request curl tests don't exercise the scheduler, the backpressure gates, or the fairness policy. The simulator does. External Locust testing comes next.
Metrics tracker
metrics.py. Pull-based, lives in process memory, surfaced through /scheduler/stats.
Metric
Meaning
TTFT
Time-to-first-token. How long the user waits before they see anything.
TPOT
Time-per-output-token. The streaming smoothness metric.
throughput
Tokens per second across the whole engine, plus requests per second.
sliding window
60 seconds by default. Old samples are pruned on every snapshot read.
percentiles
p50, p95, p99 — what tail latency looks like, not just the average.
Prometheus /metrics (Phase 8, shipped). Pull-based exposition at /metrics (prometheus_metrics.py): counters (requests by outcome, tokens, prefill chunks), histograms (TTFT/TPOT/latency + HTTP duration from the timing middleware), gauges (active batch, queue/prefilling depth, KV pressure — refreshed from the scheduler at scrape time). Completions/rejections/chunks are observed through the existing MetricsTracker, so the scheduler gains no direct Prometheus coupling. Aggregate — no session_id label: session_id is unbounded → a per-session label would explode Prometheus cardinality; per-session detail stays in /scheduler/stats (JSON, pull-on-demand). Only low-cardinality labels (outcome, HTTP method/endpoint/status). Config + dashboard in monitoring/.
Structured logs + timing middleware.LOG_FORMAT=json (default text) switches stdlib logging to one JSON object per line (logging_config.py); logger.info(..., extra={...}) fields merge in. A FastAPI middleware times every HTTP request → the inference_http_request_duration_seconds histogram (labeled by the matched route template, not the raw path) + a structured log line.
Dashboard
src/inference_server/static/index.html. A single-page UI that polls the stats endpoints.
Top: live cache hit rate, used/free blocks, eviction count.