oxllm is a minimalist, ultra-low-footprint adaptive routing LLM gateway written in Rust. It exposes an OpenAI-compatible interface, proxying requests to a tiered fallback pool of free-tier LLM providers with automatic rate-limit detection, circuit breakers, signal-based configuration reloading, and lightweight asynchronous OTel metrics/traces.
Based on our interactive design alignment and expert reviews, we have locked down the following production-grade technical refinements:
- TOML Native Configurations (Security & Stability):
- We will use the native
tomlcrate instead of the deprecatedserde_yaml(or vulnerability-proneserde_yml). TOML supports clean inline comments, plays natively with Cargo, and avoids unsafe parsing landscapes. config.tomlwill act as the single source of truth for providers, virtual models, and endpoints.
- We will use the native
- Backpressure-Safe Telemetry (OOM Prevention):
- To prevent memory leaks or kernel panics in memory-constrained environments (like OpenWrt), telemetry will use a bounded channel (
tokio::sync::mpsc::channel(1024)) and a non-blockingtry_sendstrategy. - If the
otelitecollector is down, the buffer will gracefully drop metrics/traces rather than caching infinitely in RAM.
- To prevent memory leaks or kernel panics in memory-constrained environments (like OpenWrt), telemetry will use a bounded channel (
- Axum 0.8 Dependency & Route Syntax:
- Axum 0.8 heavily feature-gates common core elements. We will explicitly opt-in to needed features:
axum = { version = "0.8", features = ["http1", "json", "matched-path"] }
- Routes will strictly use Axum 0.8's new explicit token path matching syntax (e.g.,
{param}instead of legacy:param).
- Axum 0.8 heavily feature-gates common core elements. We will explicitly opt-in to needed features:
- Adaptive Circuit Breaker with Strict
HalfOpen(Thundering Herd Defense):- To prevent thundering herds of concurrent requests from multiplying failure counts and permanently locking up a cooled-down provider, we enforce a strict
HalfOpenstate with a single-concurrent-probe lock. - The
probe_in_flightflag is represented as anArc<AtomicBool>insideProviderState. - When selecting a
HalfOpenprovider, we perform a lock-free atomiccompare_exchange(fromfalsetotruewithOrdering::SeqCst) under a fastRwLock::readlock. This allows other concurrent requests to instantly bypass the provider and cascade to the fallback pool without holding a write lock during the long HTTP call!
- To prevent thundering herds of concurrent requests from multiplying failure counts and permanently locking up a cooled-down provider, we enforce a strict
- Standard OTel Integration & W3C Trace Propagation:
- Telemetry uses standard
opentelemetry(0.28),opentelemetry_sdk(0.28), andopentelemetry-otlp(0.28) crates with thehttp-jsonandreqwest-rustlsfeatures. - W3C Trace Context Propagation: We will extract incoming
traceparentheaders, participate as a middle/child span in the trace chain, and inject W3C Trace Context headers into upstream requests to the selected provider. - Root Context Generation: If the incoming request has no active
traceparent,oxllmgenerates a valid root trace context before forwarding tooteliteto maintain absolute continuous tracking.
- Telemetry uses standard
- Connection & Handshake Timeouts:
- We will enforce a configurable
upstream_timeout_secs(defaulting to 5 seconds) inconfig.toml. If a provider takes longer than this to connect or complete its handshake, it is treated as a5xxconnection error, triggering immediate failover.
- We will enforce a configurable
- Security for Administrative Routes:
- Administrative endpoints (like
/statusand/health) are localhost-restricted (127.0.0.1). External network callers receive an immediate403 Forbiddenresponse.
- Administrative endpoints (like
- Explicit Hot-Reloading via
tokio::sync::watch:- The hot-reloading mechanism is pinned explicitly to
tokio::sync::watch. The Axum server holds awatch::Receiver<AppState>to borrow state with negligible (< 2 ms) overhead, and the UnixSIGHUPlistener holds thewatch::Senderto safely swap the pointer during runtime.
- The hot-reloading mechanism is pinned explicitly to
- Graceful Shutdown & Mid-Stream Failure Penalty:
- We will handle
SIGTERMandSIGINTsignals, integrating with Axum 0.8's graceful shutdown lifecycle to drain in-flight SSE streams before exiting. - If a token stream fails mid-flight, we gracefully close the downstream connection, increment
consecutive_failuresby 1, but do not attempt to dynamically hot-swap providers mid-flight.
- We will handle
- Reqwest Pool Timeout & Non-Standard 429 Failback:
- Reqwest Idle Timeout: Set
.pool_idle_timeout(Duration::from_secs(90))on thereqwest::Clientbuilder to prevent dead sockets from cluttering the system state. - Non-Standard 429 Failback: If a
429arrives without readable headers (like some free-tier proxies that return error JSON blocks), default cleanly to a 30-second backoff.
- Reqwest Idle Timeout: Set
- Axum 0.8 Streaming Gotchas & Fixes:
- Stream Error Conversion:
reqwest::Response::bytes_stream()yieldsResult<Bytes, reqwest::Error>. Axum 0.8'sBody::from_streamexpectsResult<Bytes, Box<dyn std::error::Error + Send + Sync>>. We must explicitly map errors usingStreamExt::map_errfromfutures-util. - Header Map Cross-Over: To avoid dependency conflicts between Axum's and reqwest's re-exported
http::HeaderMaptypes, we will explicitly iterate over upstream headers, converting names and values cleanly via bytes before injecting them into downstream Axum responses.
- Stream Error Conversion:
- Aggressive Compiler Options (Musl Edge Footprints):
- Standard stripped release parameters added directly to the workspace
Cargo.tomlto enforce a tight binary footprint (<15MB) acrossmuslcross-compilation targets.
- Standard stripped release parameters added directly to the workspace
- Cargo Workspace Structure:
crates/oxllm-core: Core logic, TOML config parser with native Unix${VAR}env expansion,RoutingStrategytrait,AdaptivePriorityStrategy, and telemetry worker.crates/oxllm: CLI binary, Axum web routing, andSIGHUPPOSIX signal handling.
graph TD
Workspace[Workspace Root] --> CoreCrate[crates/oxllm-core]
Workspace --> CliCrate[crates/oxllm]
CoreCrate --> Config[config.rs: parse & env expansion]
CoreCrate --> State[state.rs: Arc-RwLock Provider Pool]
CoreCrate --> Router[router.rs: RoutingStrategy Trait & Adaptive Decay]
CoreCrate --> Telemetry[telemetry.rs: bounded try_send OTLP HTTP/JSON]
CliCrate --> Axum[axum server & routes]
CliCrate --> Signals[unix signals: SIGHUP reloader]
CliCrate --> CLI[main.rs: clap interface]
Declares the workspace members, dependency mapping, and optimized release flags.
[workspace]
resolver = "2"
members = [
"crates/oxllm",
"crates/oxllm-core",
]
[workspace.package]
version = "0.1.0"
edition = "2021"
rust-version = "1.85.1"
authors = ["Nigel Jones"]
license = "Apache-2.0"
repository = "https://github.com/planetf1/oxllm"
homepage = "https://github.com/planetf1/oxllm"
[workspace.dependencies]
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
toml = "0.8"
reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "rustls-tls"] }
bytes = "1"
thiserror = "2"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
clap = { version = "4", features = ["derive", "env"] }
axum = { version = "0.8", features = ["http1", "json", "matched-path"] }
time = { version = "0.3", features = ["formatting", "parsing"] }
tokio-stream = "0.1"
futures-util = "0.3"
hex = "0.4"
opentelemetry = { version = "0.28", features = ["trace", "metrics"] }
opentelemetry_sdk = { version = "0.28", features = ["trace", "metrics", "rt-tokio"] }
opentelemetry-otlp = { version = "0.28", default-features = false, features = ["http-json", "reqwest-rustls"] }
opentelemetry-semantic-conventions = "0.28"
[profile.release]
opt-level = "z" # Optimize specifically for binary size
lto = "fat" # Enable Fat Link-Time Optimization
codegen-units = 1 # Maximize compiler optimizations
panic = "abort" # Strip stack unwinding code
strip = true # Automatically strip symbols and debug info
[profile.dist]
inherits = "release"
lto = "thin"Enforces formatting standards identical to your other projects:
edition = "2021"
max_width = 100
tab_spaces = 4
hard_tabs = false
reorder_imports = true
reorder_modules = true
use_field_init_shorthand = true
use_try_shorthand = true
merge_derives = true
remove_nested_parens = true
match_block_trailing_comma = true
newline_style = "Unix"Declares Homebrew distribution setups:
[workspace]
members = ["cargo:."]
[dist]
cargo-dist-version = "0.32.0"
ci = "github"
installers = ["shell", "homebrew"]
targets = ["aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]
tap = "planetf1/homebrew-tap"
publish-jobs = ["homebrew"]
pr-run-mode = "plan"
install-updater = false
allow-dirty = ["ci"]Declares dependencies for core library components.
[package]
name = "oxllm-core"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
description = "Core adaptive routing engine and telemetry worker for oxllm"
[dependencies]
tokio = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
toml = { workspace = true }
reqwest = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
time = { workspace = true }
hex = { workspace = true }
opentelemetry = { workspace = true }
opentelemetry_sdk = { workspace = true }
opentelemetry-otlp = { workspace = true }
opentelemetry-semantic-conventions = { workspace = true }Exposes modules for the workspace.
Defines a robust, public OxllmError enum mapping all core domain, parsing, and routing errors.
Declares the configuration types and performs shell-style ${VAR} expansion natively.
Defines the RoutingStrategy trait, AdaptivePriorityStrategy (including HalfOpen probe-locking logic), and logic for penalty decay and backoffs.
Implements the shared concurrent in-memory AppState wrapper protecting the active provider states behind async locks.
Implements the non-blocking standard OTel batch span processor and telemetry pipeline, backed by bounded channel drops under OOM pressure.
Exposes HTTP dependencies (Axum) and lists oxllm-core as an internal dependency.
[package]
name = "oxllm"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
description = "Minimalist adaptive routing LLM proxy in Rust"
[dependencies]
oxllm-core = { path = "../oxllm-core", version = "0.1.0" }
tokio = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
clap = { workspace = true }
axum = { workspace = true }
bytes = { workspace = true }
tokio-stream = { workspace = true }
futures-util = { workspace = true }
[dev-dependencies]
pretty_assertions = "1"Initializes CLI flag parsers, reads the initial config, spawns the telemetry background thread, registers the SIGHUP unix reload listener (utilizing tokio::sync::watch), and binds the Axum listener.
Defines Axum endpoints: /v1/models, /v1/embeddings, and /v1/chat/completions (supporting SSE chunk-streaming via bytes_stream() wrapped in Axum's Sse and tokio_stream mappings), utilizing {param} syntax.
- Phase 1: Project & Workspace Layout
Create root workspace
Cargo.toml,rustfmt.toml,dist-workspace.toml, and the basic sub-directories. Set up stripped release flags for binary size optimizations (<15MB). - Phase 2: Configuration, Errors & Env Expansion
Implement the standard
OxllmErrortypes. Implement parsing forconfig.tomlsupporting shell${VAR}expansions. - Phase 3: State, Virtual Models & Adaptive Router Trait
Implement the
RoutingStrategytrait andAdaptivePriorityStrategy. IncorporateHalfOpenstates,probe_in_flightAtomicBoollocks to defend against thundering herds, exponential backoffs, and idle-based decay aging. Add virtual model target list expansion. - Phase 4: Non-Blocking Telemetry Ingest
Build the standard OTel metrics and tracing exporter using
opentelemetry-otlpwithhttp-jsonandreqwest-rustls, backed by a boundedmpscqueue and non-blockingtry_senddrops for backpressure safety. - Phase 5: Axum Server & Streaming Engine Implement HTTP endpoints, reactive error retries for embeddings, and byte-stream forwarding for SSE chat completions.
- Phase 6: Unix Signals & Graceful Shutdown
Wire in SIGHUP configuration hot-swaps using
tokio::sync::watch. Set up SIGINT/SIGTERM handlers to gracefully drain open SSE streams.
- Unit tests in
oxllm-corefor:- Unix
${VAR}replacements. - Adaptive decay state-transitions.
- Virtual models mapping.
- Lock-free
AtomicBoolpermits duringHalfOpenstates.
- Unix
- Performance tests inside
crates/oxllm-core/benches/orcrates/oxllm-core/tests/asserting the< 2 msrouting loop overhead under mock candidate environments. - Integration tests inside a dedicated directory
crates/oxllm/tests/utilizing mock upstreams to assert:- Successful retry loops on rate limits.
- SSE event stream forwarding behavior.
-
cargo clippy --workspace --all-targetsreturns 0 warnings. - The project compiles successfully against the
x86_64-unknown-linux-musltarget. - Binary size for
target/release/oxllmis confirmed under 15 MB after runningstrip. - Telemetry
try_senddrops events gracefully without allocating heap memory when the mock endpoint is forced offline. -
cargo fmt --checkpasses with zero formatting issues.