Skip to main content

dynamo_runtime/config/
environment_names.rs

1// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Environment variable name constants for centralized management across the codebase
5//!
6//! This module provides centralized environment variable name constants to ensure
7//! consistency and avoid duplication across the codebase, similar to how
8//! `prometheus_names.rs` manages metric names.
9//!
10//! ## Organization
11//!
12//! Environment variables are organized by functional area:
13//! - **Logging**: Log level, configuration, and OTLP tracing
14//! - **Runtime**: Tokio runtime configuration and system server settings
15//! - **NATS**: NATS client connection and authentication
16//! - **ETCD**: ETCD client connection and authentication
17//! - **TCP Response Stream**: TCP response stream server (CallHome) port and host
18//! - **Event Plane**: Event transport selection (NATS)
19//! - **KVBM**: Key-Value Block Manager configuration
20//! - **LLM**: Language model inference configuration
21//! - **Model**: Model loading and caching
22//! - **Worker**: Worker lifecycle and shutdown
23//! - **Testing**: Test-specific configuration
24//! - **Mocker**: Mocker (mock scheduler/KV manager) configuration
25
26/// Logging and tracing environment variables
27pub mod logging {
28    /// Log level (e.g., "debug", "info", "warn", "error")
29    pub const DYN_LOG: &str = "DYN_LOG";
30
31    /// Path to logging configuration file
32    pub const DYN_LOGGING_CONFIG_PATH: &str = "DYN_LOGGING_CONFIG_PATH";
33
34    /// Enable JSONL logging format
35    pub const DYN_LOGGING_JSONL: &str = "DYN_LOGGING_JSONL";
36
37    /// Disable ANSI terminal colors in logs
38    pub const DYN_SDK_DISABLE_ANSI_LOGGING: &str = "DYN_SDK_DISABLE_ANSI_LOGGING";
39
40    /// Use local timezone for logging timestamps (default is UTC)
41    pub const DYN_LOG_USE_LOCAL_TZ: &str = "DYN_LOG_USE_LOCAL_TZ";
42
43    /// Enable span event logging (create/close events)
44    pub const DYN_LOGGING_SPAN_EVENTS: &str = "DYN_LOGGING_SPAN_EVENTS";
45
46    /// OTLP (OpenTelemetry Protocol) tracing and logging configuration
47    pub mod otlp {
48        /// Enable OTLP export for traces and logs (set to "1" to enable)
49        pub const OTEL_EXPORT_ENABLED: &str = "OTEL_EXPORT_ENABLED";
50
51        /// OTLP exporter transport protocol. Supported values: "grpc", "http/protobuf".
52        pub const OTEL_EXPORTER_OTLP_PROTOCOL: &str = "OTEL_EXPORTER_OTLP_PROTOCOL";
53
54        /// OTLP exporter transport protocol for traces. Defaults to OTEL_EXPORTER_OTLP_PROTOCOL.
55        pub const OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: &str = "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL";
56
57        /// OTLP exporter transport protocol for logs. Defaults to OTEL_EXPORTER_OTLP_PROTOCOL.
58        pub const OTEL_EXPORTER_OTLP_LOGS_PROTOCOL: &str = "OTEL_EXPORTER_OTLP_LOGS_PROTOCOL";
59
60        /// Generic OTLP exporter endpoint URL used when signal-specific endpoints are unset.
61        pub const OTEL_EXPORTER_OTLP_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_ENDPOINT";
62
63        /// OTLP exporter endpoint URL for traces
64        /// Spec: https://opentelemetry.io/docs/specs/otel/protocol/exporter/
65        pub const OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT";
66
67        /// OTLP exporter endpoint URL for logs. Falls back to OTEL_EXPORTER_OTLP_ENDPOINT or the protocol default when unset.
68        pub const OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT";
69
70        /// Trace sampling ratio used when set. Example: "0.01" samples roughly 1% of traces.
71        pub const OTEL_TRACES_SAMPLE_RATIO: &str = "OTEL_TRACES_SAMPLE_RATIO";
72
73        /// Service name for OTLP traces and logs
74        pub const OTEL_SERVICE_NAME: &str = "OTEL_SERVICE_NAME";
75    }
76}
77
78/// Runtime configuration environment variables
79///
80/// These control the Tokio runtime, system health/metrics server, and worker behavior
81pub mod runtime {
82    /// Number of async worker threads for Tokio runtime
83    pub const DYN_RUNTIME_NUM_WORKER_THREADS: &str = "DYN_RUNTIME_NUM_WORKER_THREADS";
84
85    /// Maximum number of blocking threads for Tokio runtime
86    pub const DYN_RUNTIME_MAX_BLOCKING_THREADS: &str = "DYN_RUNTIME_MAX_BLOCKING_THREADS";
87
88    /// Maximum time to wait for graceful endpoint drain during runtime shutdown.
89    pub const DYN_RUNTIME_GRACEFUL_SHUTDOWN_TIMEOUT_SECS: &str =
90        "DYN_RUNTIME_GRACEFUL_SHUTDOWN_TIMEOUT_SECS";
91
92    /// Maximum duration for local worker inhibition after a request failure. Zero disables it.
93    pub const DYN_RUNTIME_INHIBITED_DURATION_SECS: &str = "DYN_RUNTIME_INHIBITED_DURATION_SECS";
94
95    /// Enable Tokio task poll-time histogram (calls enable_metrics_poll_time_histogram on builder).
96    /// Set to "1", "true", or "yes" to enable. Adds ~2× overhead of Instant::now() per task poll.
97    pub const DYN_ENABLE_POLL_HISTOGRAM: &str = "DYN_ENABLE_POLL_HISTOGRAM";
98
99    /// System status server configuration
100    pub mod system {
101        /// Enable system status server for health and metrics endpoints
102        /// ⚠️ DEPRECATED: will be removed soon
103        pub const DYN_SYSTEM_ENABLED: &str = "DYN_SYSTEM_ENABLED";
104
105        /// System status server host
106        pub const DYN_SYSTEM_HOST: &str = "DYN_SYSTEM_HOST";
107
108        /// System status server port
109        pub const DYN_SYSTEM_PORT: &str = "DYN_SYSTEM_PORT";
110
111        /// Use endpoint health status for system health
112        /// ⚠️ DEPRECATED: No longer used
113        pub const DYN_SYSTEM_USE_ENDPOINT_HEALTH_STATUS: &str =
114            "DYN_SYSTEM_USE_ENDPOINT_HEALTH_STATUS";
115
116        /// Starting health status for the system
117        pub const DYN_SYSTEM_STARTING_HEALTH_STATUS: &str = "DYN_SYSTEM_STARTING_HEALTH_STATUS";
118
119        /// Health check endpoint path
120        pub const DYN_SYSTEM_HEALTH_PATH: &str = "DYN_SYSTEM_HEALTH_PATH";
121
122        /// Liveness check endpoint path
123        pub const DYN_SYSTEM_LIVE_PATH: &str = "DYN_SYSTEM_LIVE_PATH";
124    }
125
126    /// Compute configuration
127    pub mod compute {
128        /// Prefix for compute-related environment variables
129        pub const PREFIX: &str = "DYN_COMPUTE_";
130    }
131
132    /// Canary deployment configuration
133    pub mod canary {
134        /// Wait time in seconds for canary deployments
135        pub const DYN_CANARY_WAIT_TIME: &str = "DYN_CANARY_WAIT_TIME";
136    }
137}
138
139/// Worker lifecycle environment variables
140pub mod worker {
141    /// Graceful shutdown timeout in seconds
142    pub const DYN_WORKER_GRACEFUL_SHUTDOWN_TIMEOUT: &str = "DYN_WORKER_GRACEFUL_SHUTDOWN_TIMEOUT";
143}
144
145/// NATS transport environment variables
146pub mod nats {
147    /// NATS server address (e.g., "nats://localhost:4222")
148    pub const NATS_SERVER: &str = "NATS_SERVER";
149
150    /// NATS request/reply timeout in seconds. Unset = async-nats default (10 s).
151    pub const DYN_NATS_REQUEST_TIMEOUT_SECS: &str = "DYN_NATS_REQUEST_TIMEOUT_SECS";
152
153    /// NATS authentication environment variables (checked in priority order)
154    pub mod auth {
155        /// Username for NATS authentication (use with NATS_AUTH_PASSWORD)
156        pub const NATS_AUTH_USERNAME: &str = "NATS_AUTH_USERNAME";
157
158        /// Password for NATS authentication (use with NATS_AUTH_USERNAME)
159        pub const NATS_AUTH_PASSWORD: &str = "NATS_AUTH_PASSWORD";
160
161        /// Token for NATS authentication
162        pub const NATS_AUTH_TOKEN: &str = "NATS_AUTH_TOKEN";
163
164        /// NKey for NATS authentication
165        pub const NATS_AUTH_NKEY: &str = "NATS_AUTH_NKEY";
166
167        /// Path to NATS credentials file
168        pub const NATS_AUTH_CREDENTIALS_FILE: &str = "NATS_AUTH_CREDENTIALS_FILE";
169    }
170
171    /// NATS stream configuration
172    pub mod stream {
173        /// Maximum age for messages in NATS stream (in seconds)
174        pub const DYN_NATS_STREAM_MAX_AGE: &str = "DYN_NATS_STREAM_MAX_AGE";
175    }
176}
177
178/// ETCD transport environment variables
179pub mod etcd {
180    /// ETCD endpoints (comma-separated list of URLs)
181    pub const ETCD_ENDPOINTS: &str = "ETCD_ENDPOINTS";
182
183    /// ETCD lease TTL in seconds (default: 10)
184    pub const ETCD_LEASE_TTL: &str = "ETCD_LEASE_TTL";
185
186    /// ETCD authentication environment variables
187    pub mod auth {
188        /// Username for ETCD authentication
189        pub const ETCD_AUTH_USERNAME: &str = "ETCD_AUTH_USERNAME";
190
191        /// Password for ETCD authentication
192        pub const ETCD_AUTH_PASSWORD: &str = "ETCD_AUTH_PASSWORD";
193
194        /// Path to CA certificate for ETCD TLS
195        pub const ETCD_AUTH_CA: &str = "ETCD_AUTH_CA";
196
197        /// Path to client certificate for ETCD TLS
198        pub const ETCD_AUTH_CLIENT_CERT: &str = "ETCD_AUTH_CLIENT_CERT";
199
200        /// Path to client key for ETCD TLS
201        pub const ETCD_AUTH_CLIENT_KEY: &str = "ETCD_AUTH_CLIENT_KEY";
202    }
203}
204
205/// Key-Value Block Manager (KVBM) environment variables
206pub mod kvbm {
207    /// Enable KVBM metrics endpoint
208    pub const DYN_KVBM_METRICS: &str = "DYN_KVBM_METRICS";
209
210    /// KVBM metrics endpoint port
211    pub const DYN_KVBM_METRICS_PORT: &str = "DYN_KVBM_METRICS_PORT";
212
213    /// Enable KVBM recording for debugging.
214    pub const DYN_KVBM_ENABLE_RECORD: &str = "DYN_KVBM_ENABLE_RECORD";
215
216    /// Disable disk offload filter
217    pub const DYN_KVBM_DISABLE_DISK_OFFLOAD_FILTER: &str = "DYN_KVBM_DISABLE_DISK_OFFLOAD_FILTER";
218
219    /// CPU cache configuration
220    pub mod cpu_cache {
221        /// CPU cache size in GB
222        pub const DYN_KVBM_CPU_CACHE_GB: &str = "DYN_KVBM_CPU_CACHE_GB";
223
224        /// CPU cache size in number of blocks (override)
225        pub const DYN_KVBM_CPU_CACHE_OVERRIDE_NUM_BLOCKS: &str =
226            "DYN_KVBM_CPU_CACHE_OVERRIDE_NUM_BLOCKS";
227    }
228
229    /// Disk cache configuration
230    pub mod disk_cache {
231        /// Disk cache size in GB
232        pub const DYN_KVBM_DISK_CACHE_GB: &str = "DYN_KVBM_DISK_CACHE_GB";
233
234        /// Disk cache size in number of blocks (override)
235        pub const DYN_KVBM_DISK_CACHE_OVERRIDE_NUM_BLOCKS: &str =
236            "DYN_KVBM_DISK_CACHE_OVERRIDE_NUM_BLOCKS";
237    }
238
239    /// Object storage configuration
240    pub mod object_storage {
241        /// Enable object storage. Set to "1" to enable.
242        pub const DYN_KVBM_OBJECT_ENABLED: &str = "DYN_KVBM_OBJECT_ENABLED";
243
244        /// Bucket name for object storage cache
245        /// Supports `{worker_id}` template for per-worker buckets
246        /// Example: "kv-cache-{worker_id}"
247        pub const DYN_KVBM_OBJECT_BUCKET: &str = "DYN_KVBM_OBJECT_BUCKET";
248
249        /// Endpoint for object storage
250        pub const DYN_KVBM_OBJECT_ENDPOINT: &str = "DYN_KVBM_OBJECT_ENDPOINT";
251
252        /// Region for object storage
253        pub const DYN_KVBM_OBJECT_REGION: &str = "DYN_KVBM_OBJECT_REGION";
254
255        /// Access key for authentication
256        pub const DYN_KVBM_OBJECT_ACCESS_KEY: &str = "DYN_KVBM_OBJECT_ACCESS_KEY";
257
258        /// Secret key for authentication
259        pub const DYN_KVBM_OBJECT_SECRET_KEY: &str = "DYN_KVBM_OBJECT_SECRET_KEY";
260
261        /// Number of blocks to store in object storage
262        pub const DYN_KVBM_OBJECT_NUM_BLOCKS: &str = "DYN_KVBM_OBJECT_NUM_BLOCKS";
263    }
264    /// Transfer configuration
265    pub mod transfer {
266        /// Maximum number of blocks per transfer batch
267        pub const DYN_KVBM_TRANSFER_BATCH_SIZE: &str = "DYN_KVBM_TRANSFER_BATCH_SIZE";
268    }
269
270    /// KVBM leader (distributed mode) configuration
271    pub mod leader {
272        /// Timeout in seconds for KVBM leader and worker initialization
273        pub const DYN_KVBM_LEADER_WORKER_INIT_TIMEOUT_SECS: &str =
274            "DYN_KVBM_LEADER_WORKER_INIT_TIMEOUT_SECS";
275
276        /// ZMQ host for KVBM leader
277        pub const DYN_KVBM_LEADER_ZMQ_HOST: &str = "DYN_KVBM_LEADER_ZMQ_HOST";
278
279        /// ZMQ publish port for KVBM leader
280        pub const DYN_KVBM_LEADER_ZMQ_PUB_PORT: &str = "DYN_KVBM_LEADER_ZMQ_PUB_PORT";
281
282        /// ZMQ acknowledgment port for KVBM leader
283        pub const DYN_KVBM_LEADER_ZMQ_ACK_PORT: &str = "DYN_KVBM_LEADER_ZMQ_ACK_PORT";
284    }
285
286    /// NIXL backend configuration
287    pub mod nixl {
288        /// Prefix for NIXL backend environment variables
289        /// Pattern: DYN_KVBM_NIXL_BACKEND_<backend>=true/false
290        /// Example: DYN_KVBM_NIXL_BACKEND_UCX=true
291        pub const PREFIX: &str = "DYN_KVBM_NIXL_BACKEND_";
292    }
293}
294
295/// LLM (Language Model) inference environment variables
296pub mod llm {
297    /// HTTP body size limit in MB
298    pub const DYN_HTTP_BODY_LIMIT_MB: &str = "DYN_HTTP_BODY_LIMIT_MB";
299
300    pub const DYN_HTTP_GRACEFUL_SHUTDOWN_TIMEOUT_SECS: &str =
301        "DYN_HTTP_GRACEFUL_SHUTDOWN_TIMEOUT_SECS";
302
303    /// HTTP status code returned when the frontend rejects a request because
304    /// all workers are overloaded. Defaults to 529 ("Site is overloaded"); set
305    /// to 503 for Service Unavailable retry semantics. Status codes from 200
306    /// through 999 are accepted; an informational value from 100 through 199,
307    /// an unparseable value, or an out-of-range value falls back to 529. The
308    /// value is read and cached on first use.
309    pub const DYN_HTTP_OVERLOAD_STATUS_CODE: &str = "DYN_HTTP_OVERLOAD_STATUS_CODE";
310
311    /// Enable LoRA adapter support (set to "true" to enable)
312    pub const DYN_LORA_ENABLED: &str = "DYN_LORA_ENABLED";
313
314    /// LoRA cache directory path
315    pub const DYN_LORA_PATH: &str = "DYN_LORA_PATH";
316
317    /// Enable the experimental Anthropic Messages API endpoint (/v1/messages)
318    pub const DYN_ENABLE_ANTHROPIC_API: &str = "DYN_ENABLE_ANTHROPIC_API";
319
320    /// Master switch for the `nvext` extension protocol on the frontend.
321    /// The protocol is **enabled by default**; this variable disables it.
322    /// Truthy values (`1` / `true` / `yes` / `on`, case-insensitive) cause
323    /// the frontend to drop `request.nvext` at handler entry, ignore the
324    /// routing-override headers (`x-dynamo-worker-instance-id`,
325    /// `x-dynamo-prefill-instance-id`, `x-dynamo-dp-rank`,
326    /// `x-dynamo-prefill-dp-rank`), and silently ignore the response-side
327    /// `extra_fields` opt-in.
328    pub const DYN_DISABLE_FRONTEND_NVEXT: &str = "DYN_DISABLE_FRONTEND_NVEXT";
329
330    /// Ignore unknown OpenAI frontend request fields. Unknown fields are dropped,
331    /// not handled; known pass-through fields remain type-validated.
332    pub const DYN_IGNORE_OPENAI_FE_UNSUPPORTED_FIELDS: &str =
333        "DYN_IGNORE_OPENAI_FE_UNSUPPORTED_FIELDS";
334
335    /// Master switch for the frontend's HTTP admin API surface.
336    /// The admin API is **enabled by default**; this variable disables it.
337    /// Truthy values (`1` / `true` / `yes` / `on`, case-insensitive) prevent
338    /// registration of `GET` / `POST /busy_threshold`. Inference, metrics,
339    /// models, health, and liveness routes are unaffected.
340    pub const DYN_DISABLE_FRONTEND_ADMIN_API: &str = "DYN_DISABLE_FRONTEND_ADMIN_API";
341
342    /// Strip the Claude Code billing preamble (`x-anthropic-billing-header: ...`)
343    /// from the system prompt before forwarding to the target model. The preamble
344    /// varies per session and per release, wasting tokens and breaking prompt caching.
345    pub const DYN_STRIP_ANTHROPIC_PREAMBLE: &str = "DYN_STRIP_ANTHROPIC_PREAMBLE";
346
347    /// When truthy, force usage in streaming chat and text-completion responses
348    /// regardless of the request's `stream_options.include_usage` value.
349    /// Unset or false preserves request-controlled defaults.
350    pub const DYN_ENABLE_FORCE_INCLUDE_USAGE: &str = "DYN_ENABLE_FORCE_INCLUDE_USAGE";
351
352    /// Enable streaming tool call dispatch (`event: tool_call_dispatch` SSE events)
353    pub const DYN_ENABLE_STREAMING_TOOL_DISPATCH: &str = "DYN_ENABLE_STREAMING_TOOL_DISPATCH";
354
355    /// Enable streaming reasoning dispatch (`event: reasoning_dispatch` SSE events)
356    pub const DYN_ENABLE_STREAMING_REASONING_DISPATCH: &str =
357        "DYN_ENABLE_STREAMING_REASONING_DISPATCH";
358
359    /// \[EXPERIMENTAL\] Route supported tool-call families (Qwen3-Coder, DeepSeek-V4)
360    /// through the `dynamo-parsers-v2` streaming parser for BOTH the batch and the
361    /// streaming path, bypassing the v1 tool-call jail. Off by default; when set, the
362    /// v2 parser owns incremental tool-call emission and drops values truncated at EOF.
363    pub const DYN_ENABLE_EXPERIMENTAL_PARSERS_V2: &str = "DYN_ENABLE_EXPERIMENTAL_PARSERS_V2";
364
365    /// Backend stream inactivity timeout in seconds.
366    ///
367    /// When set to a positive integer, the frontend will kill the engine context
368    /// and drop the inflight guard if no SSE event is received from the backend
369    /// within this many seconds. Acts as a circuit breaker for zombie workers
370    /// that hold a live TCP connection but never produce output.
371    ///
372    /// Set to `0` or leave unset to disable the timeout (default: disabled).
373    pub const DYN_HTTP_BACKEND_STREAM_TIMEOUT_SECS: &str = "DYN_HTTP_BACKEND_STREAM_TIMEOUT_SECS";
374
375    /// Enable the LoRA allocation controller (set to "true" to enable)
376    pub const DYN_LORA_ALLOCATION_ENABLED: &str = "DYN_LORA_ALLOCATION_ENABLED";
377
378    /// LoRA allocation algorithm ("hrw", "random", or "mcf")
379    pub const DYN_LORA_ALLOCATION_ALGORITHM: &str = "DYN_LORA_ALLOCATION_ALGORITHM";
380
381    /// JSON configuration for the MCF (min-cost flow) placement solver.
382    /// Example: '{"candidate_m":16,"gamma_load":2000,"beta_keep":500}'
383    /// Omitted fields use defaults. Only relevant when algorithm is "mcf".
384    pub const DYN_LORA_MCF_CONFIG: &str = "DYN_LORA_MCF_CONFIG";
385
386    /// LoRA allocation controller recompute interval in seconds
387    pub const DYN_LORA_ALLOCATION_TIMESTEP_SECS: &str = "DYN_LORA_ALLOCATION_TIMESTEP_SECS";
388
389    /// Ticks to wait before scaling down a LoRA's replicas
390    pub const DYN_LORA_ALLOCATION_SCALE_DOWN_COOLDOWN_TICKS: &str =
391        "DYN_LORA_ALLOCATION_SCALE_DOWN_COOLDOWN_TICKS";
392
393    /// Multiplier for the load estimator's rate window relative to the controller timestep.
394    pub const DYN_LORA_ALLOCATION_RATE_WINDOW_MULTIPLIER: &str =
395        "DYN_LORA_ALLOCATION_RATE_WINDOW_MULTIPLIER";
396
397    /// Number of counter buckets per second in the BucketedRateCounter.
398    pub const DYN_LORA_ALLOCATION_BUCKETS_PER_SECOND: &str =
399        "DYN_LORA_ALLOCATION_BUCKETS_PER_SECOND";
400
401    /// Load predictor type: "none" (raw counts) or "ema" (exponential moving average).
402    pub const DYN_LORA_ALLOCATION_PREDICTOR_TYPE: &str = "DYN_LORA_ALLOCATION_PREDICTOR_TYPE";
403
404    /// EMA smoothing factor (alpha) for the EMA predictor. Range [0.0, 1.0].
405    pub const DYN_LORA_ALLOCATION_EMA_ALPHA: &str = "DYN_LORA_ALLOCATION_EMA_ALPHA";
406
407    /// Metrics configuration
408    pub mod metrics {
409        /// Custom metrics prefix (overrides default "dynamo_frontend")
410        pub const DYN_METRICS_PREFIX: &str = "DYN_METRICS_PREFIX";
411
412        /// Histogram bucket configuration (pattern: <PREFIX>_MIN, <PREFIX>_MAX, <PREFIX>_COUNT)
413        /// Example: DYN_HISTOGRAM_TTFT_MIN, DYN_HISTOGRAM_TTFT_MAX, DYN_HISTOGRAM_TTFT_COUNT
414        pub const HISTOGRAM_PREFIX: &str = "DYN_HISTOGRAM_";
415    }
416
417    /// Forward-pass-metrics trace configuration.
418    pub mod fpm_trace {
419        /// Master switch. Truthy values persist locally produced FPM events.
420        pub const DYN_FPM_TRACE: &str = "DYN_FPM_TRACE";
421
422        /// Local gzip JSONL segment prefix. A sanitized producer id is appended
423        /// before the segment index so multiple producers do not share files.
424        pub const DYN_FPM_OUTPUT_PATH: &str = "DYN_FPM_OUTPUT_PATH";
425
426        /// Capture mode: `sampled` (latest event per DP rank each interval) or
427        /// `full` (every event reaching the producer-side trace tap).
428        pub const DYN_FPM_MODE: &str = "DYN_FPM_MODE";
429
430        /// Sampling interval in milliseconds when `DYN_FPM_MODE=sampled`.
431        pub const DYN_FPM_SAMPLE_INTERVAL_MS: &str = "DYN_FPM_SAMPLE_INTERVAL_MS";
432
433        /// Rotating gzip JSONL threshold in uncompressed bytes.
434        pub const DYN_FPM_JSONL_GZ_ROLL_BYTES: &str = "DYN_FPM_JSONL_GZ_ROLL_BYTES";
435
436        /// Maximum number of gzip JSONL segments retained per producer,
437        /// including the active segment.
438        pub const DYN_FPM_MAX_SEGMENTS: &str = "DYN_FPM_MAX_SEGMENTS";
439    }
440
441    /// Deprecated audit payload logging aliases. Prefer `llm::request_trace`.
442    pub mod audit {
443        /// Deprecated alias for `DYN_REQUEST_TRACE_SINKS`. Legacy values
444        /// `jsonl` and `jsonl_gz` map to the request trace `file` sink.
445        pub const DYN_AUDIT_SINKS: &str = "DYN_AUDIT_SINKS";
446
447        /// Deprecated migration shim for `DYN_REQUEST_TRACE_RECORDS=request_payload`.
448        pub const DYN_AUDIT_FORCE_LOGGING: &str = "DYN_AUDIT_FORCE_LOGGING";
449
450        /// Deprecated alias for `DYN_REQUEST_TRACE_CAPACITY`.
451        pub const DYN_AUDIT_CAPACITY: &str = "DYN_AUDIT_CAPACITY";
452
453        /// Deprecated alias for `DYN_REQUEST_TRACE_NATS_SUBJECT`.
454        pub const DYN_AUDIT_NATS_SUBJECT: &str = "DYN_AUDIT_NATS_SUBJECT";
455
456        /// Deprecated alias for `DYN_REQUEST_TRACE_FILE_PATH`.
457        pub const DYN_AUDIT_OUTPUT_PATH: &str = "DYN_AUDIT_OUTPUT_PATH";
458
459        /// Deprecated alias for `DYN_REQUEST_TRACE_FILE_BUFFER_BYTES`.
460        pub const DYN_AUDIT_JSONL_BUFFER_BYTES: &str = "DYN_AUDIT_JSONL_BUFFER_BYTES";
461
462        /// Deprecated alias for `DYN_REQUEST_TRACE_FILE_FLUSH_INTERVAL_MS`.
463        pub const DYN_AUDIT_JSONL_FLUSH_INTERVAL_MS: &str = "DYN_AUDIT_JSONL_FLUSH_INTERVAL_MS";
464
465        /// Deprecated alias for `DYN_REQUEST_TRACE_FILE_ROLL_BYTES`.
466        pub const DYN_AUDIT_JSONL_GZ_ROLL_BYTES: &str = "DYN_AUDIT_JSONL_GZ_ROLL_BYTES";
467
468        /// Deprecated alias for `DYN_REQUEST_TRACE_FILE_ROLL_LINES`.
469        pub const DYN_AUDIT_JSONL_GZ_ROLL_LINES: &str = "DYN_AUDIT_JSONL_GZ_ROLL_LINES";
470
471        /// Deprecated alias for `DYN_REQUEST_TRACE_OTEL_MAX_PAYLOAD_BYTES`.
472        pub const DYN_AUDIT_OTEL_MAX_PAYLOAD_BYTES: &str = "DYN_AUDIT_OTEL_MAX_PAYLOAD_BYTES";
473    }
474
475    /// Request trace and request payload logging configuration.
476    pub mod request_trace {
477        /// Master switch. Truthy enables request trace emission.
478        pub const DYN_REQUEST_TRACE: &str = "DYN_REQUEST_TRACE";
479
480        /// Request trace sink selection. Comma-separated values: `file`, `stderr`, `nats`, `otel`.
481        ///
482        /// Legacy values map as follows: `jsonl` => `file` with `jsonl` format,
483        /// `jsonl_gz` => `file` with `jsonl_gz` format, `stderr` => `stderr`,
484        /// `nats` => `nats`, and `otel` => `otel`.
485        pub const DYN_REQUEST_TRACE_SINKS: &str = "DYN_REQUEST_TRACE_SINKS";
486
487        /// Local output path for request trace file records.
488        ///
489        /// With `DYN_REQUEST_TRACE_FILE_FORMAT=jsonl`, this is the literal JSONL
490        /// path. With `jsonl_gz`, this is the segment prefix used to derive
491        /// `<prefix>.<index>.jsonl.gz` files.
492        pub const DYN_REQUEST_TRACE_FILE_PATH: &str = "DYN_REQUEST_TRACE_FILE_PATH";
493
494        /// Deprecated alias for `DYN_REQUEST_TRACE_FILE_PATH`.
495        pub const DYN_REQUEST_TRACE_OUTPUT_PATH: &str = "DYN_REQUEST_TRACE_OUTPUT_PATH";
496
497        /// Request trace file record format. Supported values: `jsonl`, `jsonl_gz`.
498        pub const DYN_REQUEST_TRACE_FILE_FORMAT: &str = "DYN_REQUEST_TRACE_FILE_FORMAT";
499
500        /// In-process trace bus capacity.
501        pub const DYN_REQUEST_TRACE_CAPACITY: &str = "DYN_REQUEST_TRACE_CAPACITY";
502
503        /// Request trace record selection. Comma-separated values: `request_end`,
504        /// `request_payload`, `tool`.
505        pub const DYN_REQUEST_TRACE_RECORDS: &str = "DYN_REQUEST_TRACE_RECORDS";
506
507        /// NATS subject the request trace sink publishes to.
508        pub const DYN_REQUEST_TRACE_NATS_SUBJECT: &str = "DYN_REQUEST_TRACE_NATS_SUBJECT";
509
510        /// Maximum serialized OTEL payload bytes. Oversized request payload
511        /// records emit an incomplete marker payload instead of the full request/response.
512        pub const DYN_REQUEST_TRACE_OTEL_MAX_PAYLOAD_BYTES: &str =
513            "DYN_REQUEST_TRACE_OTEL_MAX_PAYLOAD_BYTES";
514
515        /// Request trace file sink buffer size in bytes.
516        pub const DYN_REQUEST_TRACE_FILE_BUFFER_BYTES: &str = "DYN_REQUEST_TRACE_FILE_BUFFER_BYTES";
517
518        /// Deprecated alias for `DYN_REQUEST_TRACE_FILE_BUFFER_BYTES`.
519        pub const DYN_REQUEST_TRACE_JSONL_BUFFER_BYTES: &str =
520            "DYN_REQUEST_TRACE_JSONL_BUFFER_BYTES";
521
522        /// Request trace file sink periodic flush interval in milliseconds.
523        pub const DYN_REQUEST_TRACE_FILE_FLUSH_INTERVAL_MS: &str =
524            "DYN_REQUEST_TRACE_FILE_FLUSH_INTERVAL_MS";
525
526        /// Deprecated alias for `DYN_REQUEST_TRACE_FILE_FLUSH_INTERVAL_MS`.
527        pub const DYN_REQUEST_TRACE_JSONL_FLUSH_INTERVAL_MS: &str =
528            "DYN_REQUEST_TRACE_JSONL_FLUSH_INTERVAL_MS";
529
530        /// Gzip file sink roll threshold in uncompressed bytes.
531        pub const DYN_REQUEST_TRACE_FILE_ROLL_BYTES: &str = "DYN_REQUEST_TRACE_FILE_ROLL_BYTES";
532
533        /// Deprecated alias for `DYN_REQUEST_TRACE_FILE_ROLL_BYTES`.
534        pub const DYN_REQUEST_TRACE_JSONL_GZ_ROLL_BYTES: &str =
535            "DYN_REQUEST_TRACE_JSONL_GZ_ROLL_BYTES";
536
537        /// Gzip file sink roll threshold in record lines.
538        pub const DYN_REQUEST_TRACE_FILE_ROLL_LINES: &str = "DYN_REQUEST_TRACE_FILE_ROLL_LINES";
539
540        /// Deprecated alias for `DYN_REQUEST_TRACE_FILE_ROLL_LINES`.
541        pub const DYN_REQUEST_TRACE_JSONL_GZ_ROLL_LINES: &str =
542            "DYN_REQUEST_TRACE_JSONL_GZ_ROLL_LINES";
543
544        /// Local ZMQ PULL endpoint Dynamo binds for harness tool events.
545        pub const DYN_REQUEST_TRACE_TOOL_EVENTS_ZMQ_ENDPOINT: &str =
546            "DYN_REQUEST_TRACE_TOOL_EVENTS_ZMQ_ENDPOINT";
547
548        /// First-frame ZMQ topic filter override for harness tool events.
549        pub const DYN_REQUEST_TRACE_TOOL_EVENTS_ZMQ_TOPIC: &str =
550            "DYN_REQUEST_TRACE_TOOL_EVENTS_ZMQ_TOPIC";
551
552        /// Comma/whitespace-separated allowlist of HTTP request header names to
553        /// record in request payload records. Unset/empty captures none. Values
554        /// are recorded unredacted; avoid credential-bearing headers.
555        pub const DYN_REQUEST_TRACE_HTTP_HEADER_CAPTURE_LIST: &str =
556            "DYN_REQUEST_TRACE_HTTP_HEADER_CAPTURE_LIST";
557    }
558}
559
560/// Model loading and caching environment variables
561pub mod model {
562    /// Model Express configuration
563    pub mod model_express {
564        /// Model Express server endpoint URL
565        pub const MODEL_EXPRESS_URL: &str = "MODEL_EXPRESS_URL";
566
567        /// Model Express cache path
568        pub const MODEL_EXPRESS_CACHE_PATH: &str = "MODEL_EXPRESS_CACHE_PATH";
569
570        /// Disable shared-storage mode for the Model Express client. When set,
571        /// the client streams model files from the server over gRPC instead of
572        /// relying on a shared filesystem path. Required when the Model Express
573        /// server and worker pods do not share a filesystem (e.g. RWO PVCs,
574        /// cross-namespace deployments). Set to "1" or "true" to enable.
575        pub const MODEL_EXPRESS_NO_SHARED_STORAGE: &str = "MODEL_EXPRESS_NO_SHARED_STORAGE";
576    }
577
578    /// Hugging Face configuration
579    pub mod huggingface {
580        /// Hugging Face authentication token
581        pub const HF_TOKEN: &str = "HF_TOKEN";
582
583        /// Deprecated alias for the Hugging Face authentication token
584        pub const HUGGING_FACE_HUB_TOKEN: &str = "HUGGING_FACE_HUB_TOKEN";
585
586        /// Path to the stored Hugging Face authentication token
587        pub const HF_TOKEN_PATH: &str = "HF_TOKEN_PATH";
588
589        /// Hugging Face Hub cache directory
590        pub const HF_HUB_CACHE: &str = "HF_HUB_CACHE";
591
592        /// Hugging Face home directory
593        pub const HF_HOME: &str = "HF_HOME";
594
595        /// Override the Hugging Face Hub API endpoint
596        pub const HF_ENDPOINT: &str = "HF_ENDPOINT";
597
598        /// Offline mode - skip API calls when model is cached
599        /// Set to "1", "true", "on", or "yes" to enable
600        pub const HF_HUB_OFFLINE: &str = "HF_HUB_OFFLINE";
601    }
602}
603
604/// KV Router configuration environment variables
605pub mod router {
606    /// Scale applied to adjusted prompt-side prefill load after overlap/cache-hit credits.
607    pub const DYN_ROUTER_PREFILL_LOAD_SCALE: &str = "DYN_ROUTER_PREFILL_LOAD_SCALE";
608
609    /// Queue threshold fraction for prefill token capacity.
610    /// When set, requests are queued if all workers exceed this fraction of max_num_batched_tokens.
611    pub const DYN_ROUTER_QUEUE_THRESHOLD: &str = "DYN_ROUTER_QUEUE_THRESHOLD";
612
613    /// Scheduling policy for the router queue ("fcfs" or "wspt").
614    pub const DYN_ROUTER_QUEUE_POLICY: &str = "DYN_ROUTER_QUEUE_POLICY";
615    pub const DYN_ROUTER_POLICY_CONFIG: &str = "DYN_ROUTER_POLICY_CONFIG";
616
617    /// Stale active-request cleanup guard in seconds; this is not a request timeout.
618    pub const DYN_ROUTER_ACTIVE_REQUEST_EXPIRY_SECS: &str = "DYN_ROUTER_ACTIVE_REQUEST_EXPIRY_SECS";
619}
620
621/// Request plane transport environment variables
622pub mod request_plane {
623    /// Preferred payload codec advertised by every request-plane endpoint in this process.
624    /// The process-wide value is cached on first use and defaults to "msgpack". Outbound requests
625    /// use the destination endpoint's advertised codec, or "json" for a legacy destination.
626    pub const DYN_REQUEST_PLANE_CODEC: &str = "DYN_REQUEST_PLANE_CODEC";
627}
628
629/// TCP response stream server (CallHome listener) environment variables
630pub mod tcp_response_stream {
631    /// Port for the TCP response stream server.
632    /// If unset or 0, the OS assigns a free ephemeral port.
633    pub const DYN_TCP_RESPONSE_STREAM_PORT: &str = "DYN_TCP_RESPONSE_STREAM_PORT";
634
635    /// Host/interface for the TCP response stream server.
636    /// If unset, the server auto-detects a routable local IP.
637    pub const DYN_TCP_RESPONSE_STREAM_HOST: &str = "DYN_TCP_RESPONSE_STREAM_HOST";
638}
639
640/// Event Plane transport environment variables
641pub mod event_plane {
642    /// Event transport selection: "zmq" or "nats".
643    ///
644    /// When unset the default depends on the discovery backend:
645    /// - `file` / `mem` backends: defaults to `zmq` (no external services required).
646    /// - `etcd` / `kubernetes` backends: defaults to `nats`.
647    ///
648    /// Set this explicitly to override the context-aware default.
649    pub const DYN_EVENT_PLANE: &str = "DYN_EVENT_PLANE";
650
651    /// Event plane codec selection: "json" or "msgpack".
652    pub const DYN_EVENT_PLANE_CODEC: &str = "DYN_EVENT_PLANE_CODEC";
653
654    /// Bounded capacity of the direct ZMQ event-subscriber's merged event channel.
655    ///
656    /// Many peer publishers (e.g. every other frontend under replica-sync) feed
657    /// this single-consumer channel; an unbounded channel grows RSS without limit
658    /// when the consumer can't keep up. When the channel is full, new events are
659    /// dropped — the event plane is already best-effort/lossy (ZMQ RCVHWM), so a
660    /// dropped event costs routing-estimate freshness, not correctness.
661    /// Default: 100_000 (matches ZMQ_RCVHWM). Applies only to the direct ZMQ
662    /// subscriber path.
663    pub const DYN_ZMQ_EVENT_SUBSCRIBER_CHANNEL_CAPACITY: &str =
664        "DYN_ZMQ_EVENT_SUBSCRIBER_CHANNEL_CAPACITY";
665}
666
667/// ZMQ Broker environment variables
668pub mod zmq_broker {
669    /// Explicit ZMQ broker URL (takes precedence over discovery)
670    /// Format: "xsub=<url1>[;<url2>...] , xpub=<url1>[;<url2>...]"
671    /// Example: "xsub=tcp://broker:5555 , xpub=tcp://broker:5556"
672    pub const DYN_ZMQ_BROKER_URL: &str = "DYN_ZMQ_BROKER_URL";
673
674    /// Enable ZMQ broker discovery mode
675    pub const DYN_ZMQ_BROKER_ENABLED: &str = "DYN_ZMQ_BROKER_ENABLED";
676
677    /// XSUB bind address (broker binary only)
678    pub const ZMQ_BROKER_XSUB_BIND: &str = "ZMQ_BROKER_XSUB_BIND";
679
680    /// XPUB bind address (broker binary only)
681    pub const ZMQ_BROKER_XPUB_BIND: &str = "ZMQ_BROKER_XPUB_BIND";
682
683    /// Namespace for broker discovery registration
684    pub const ZMQ_BROKER_NAMESPACE: &str = "ZMQ_BROKER_NAMESPACE";
685}
686
687/// Discovery environment variables
688pub mod discovery {
689    /// Discovery backend: "kubernetes" or "etcd" (default)
690    pub const DYN_DISCOVERY_BACKEND: &str = "DYN_DISCOVERY_BACKEND";
691
692    /// Kube discovery mode: "pod" (default) or "container" (each container registers independently)
693    pub const DYN_KUBE_DISCOVERY_MODE: &str = "DYN_KUBE_DISCOVERY_MODE";
694}
695
696/// CUDA and GPU environment variables
697pub mod cuda {
698    /// Path to custom CUDA fatbin file.
699    ///
700    /// Note: build.rs files cannot import this constant at build time,
701    /// so they must define local constants with the same value.
702    pub const DYN_FATBIN_PATH: &str = "DYN_FATBIN_PATH";
703}
704
705/// Build-time environment variables
706pub mod build {
707    /// Cargo output directory for build artifacts
708    ///
709    /// Note: This constant cannot be used with the `env!()` macro,
710    /// which requires a string literal at compile time.
711    /// Build scripts (build.rs) also cannot import this constant.
712    pub const OUT_DIR: &str = "OUT_DIR";
713}
714
715/// Mocker (mock scheduler/KV manager) environment variables
716pub mod mocker {
717    /// Enable structured KV cache allocation/eviction trace logs (set to "1" or "true" to enable)
718    pub const DYN_MOCKER_KV_CACHE_TRACE: &str = "DYN_MOCKER_KV_CACHE_TRACE";
719
720    /// Use the original direct() code path in the mocker request dispatch.
721    ///
722    /// This path is race-prone during startup; prefer leaving it unset unless you are
723    /// explicitly trying to reproduce the original behavior.
724    pub const DYN_MOCKER_SYNC_DIRECT: &str = "DYN_MOCKER_SYNC_DIRECT";
725}
726
727/// Testing environment variables
728pub mod testing {
729    /// Enable queued-up request processing in tests
730    pub const DYN_QUEUED_UP_PROCESSING: &str = "DYN_QUEUED_UP_PROCESSING";
731
732    /// Soak test run duration (e.g., "3s", "5m")
733    pub const DYN_SOAK_RUN_DURATION: &str = "DYN_SOAK_RUN_DURATION";
734
735    /// Soak test batch load size
736    pub const DYN_SOAK_BATCH_LOAD: &str = "DYN_SOAK_BATCH_LOAD";
737}
738
739#[cfg(test)]
740mod tests {
741    use super::*;
742
743    #[test]
744    fn test_no_duplicate_env_var_names() {
745        use std::collections::HashSet;
746
747        let mut seen = HashSet::new();
748        let vars = [
749            // Logging
750            logging::DYN_LOG,
751            logging::DYN_LOGGING_CONFIG_PATH,
752            logging::DYN_LOGGING_JSONL,
753            logging::DYN_SDK_DISABLE_ANSI_LOGGING,
754            logging::DYN_LOG_USE_LOCAL_TZ,
755            logging::DYN_LOGGING_SPAN_EVENTS,
756            logging::otlp::OTEL_EXPORT_ENABLED,
757            logging::otlp::OTEL_EXPORTER_OTLP_PROTOCOL,
758            logging::otlp::OTEL_EXPORTER_OTLP_TRACES_PROTOCOL,
759            logging::otlp::OTEL_EXPORTER_OTLP_LOGS_PROTOCOL,
760            logging::otlp::OTEL_EXPORTER_OTLP_ENDPOINT,
761            logging::otlp::OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,
762            logging::otlp::OTEL_SERVICE_NAME,
763            logging::otlp::OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
764            logging::otlp::OTEL_TRACES_SAMPLE_RATIO,
765            // Runtime
766            runtime::DYN_RUNTIME_NUM_WORKER_THREADS,
767            runtime::DYN_RUNTIME_MAX_BLOCKING_THREADS,
768            runtime::DYN_RUNTIME_GRACEFUL_SHUTDOWN_TIMEOUT_SECS,
769            runtime::DYN_RUNTIME_INHIBITED_DURATION_SECS,
770            runtime::system::DYN_SYSTEM_ENABLED,
771            runtime::system::DYN_SYSTEM_HOST,
772            runtime::system::DYN_SYSTEM_PORT,
773            runtime::system::DYN_SYSTEM_USE_ENDPOINT_HEALTH_STATUS,
774            runtime::system::DYN_SYSTEM_STARTING_HEALTH_STATUS,
775            runtime::system::DYN_SYSTEM_HEALTH_PATH,
776            runtime::system::DYN_SYSTEM_LIVE_PATH,
777            runtime::canary::DYN_CANARY_WAIT_TIME,
778            // Worker
779            worker::DYN_WORKER_GRACEFUL_SHUTDOWN_TIMEOUT,
780            // NATS
781            nats::NATS_SERVER,
782            nats::DYN_NATS_REQUEST_TIMEOUT_SECS,
783            nats::auth::NATS_AUTH_USERNAME,
784            nats::auth::NATS_AUTH_PASSWORD,
785            nats::auth::NATS_AUTH_TOKEN,
786            nats::auth::NATS_AUTH_NKEY,
787            nats::auth::NATS_AUTH_CREDENTIALS_FILE,
788            nats::stream::DYN_NATS_STREAM_MAX_AGE,
789            // ETCD
790            etcd::ETCD_ENDPOINTS,
791            etcd::ETCD_LEASE_TTL,
792            etcd::auth::ETCD_AUTH_USERNAME,
793            etcd::auth::ETCD_AUTH_PASSWORD,
794            etcd::auth::ETCD_AUTH_CA,
795            etcd::auth::ETCD_AUTH_CLIENT_CERT,
796            etcd::auth::ETCD_AUTH_CLIENT_KEY,
797            // KVBM
798            kvbm::DYN_KVBM_METRICS,
799            kvbm::DYN_KVBM_METRICS_PORT,
800            kvbm::DYN_KVBM_ENABLE_RECORD,
801            kvbm::DYN_KVBM_DISABLE_DISK_OFFLOAD_FILTER,
802            kvbm::cpu_cache::DYN_KVBM_CPU_CACHE_GB,
803            kvbm::cpu_cache::DYN_KVBM_CPU_CACHE_OVERRIDE_NUM_BLOCKS,
804            kvbm::disk_cache::DYN_KVBM_DISK_CACHE_GB,
805            kvbm::disk_cache::DYN_KVBM_DISK_CACHE_OVERRIDE_NUM_BLOCKS,
806            kvbm::leader::DYN_KVBM_LEADER_WORKER_INIT_TIMEOUT_SECS,
807            kvbm::leader::DYN_KVBM_LEADER_ZMQ_HOST,
808            kvbm::leader::DYN_KVBM_LEADER_ZMQ_PUB_PORT,
809            kvbm::leader::DYN_KVBM_LEADER_ZMQ_ACK_PORT,
810            // LLM
811            llm::DYN_HTTP_BODY_LIMIT_MB,
812            llm::DYN_HTTP_GRACEFUL_SHUTDOWN_TIMEOUT_SECS,
813            llm::DYN_HTTP_OVERLOAD_STATUS_CODE,
814            llm::DYN_HTTP_BACKEND_STREAM_TIMEOUT_SECS,
815            llm::DYN_LORA_ENABLED,
816            llm::DYN_LORA_PATH,
817            llm::DYN_ENABLE_ANTHROPIC_API,
818            llm::DYN_DISABLE_FRONTEND_NVEXT,
819            llm::DYN_IGNORE_OPENAI_FE_UNSUPPORTED_FIELDS,
820            llm::DYN_DISABLE_FRONTEND_ADMIN_API,
821            llm::DYN_STRIP_ANTHROPIC_PREAMBLE,
822            llm::DYN_ENABLE_FORCE_INCLUDE_USAGE,
823            llm::DYN_ENABLE_STREAMING_TOOL_DISPATCH,
824            llm::DYN_ENABLE_STREAMING_REASONING_DISPATCH,
825            llm::DYN_ENABLE_EXPERIMENTAL_PARSERS_V2,
826            llm::DYN_LORA_ALLOCATION_ENABLED,
827            llm::DYN_LORA_ALLOCATION_ALGORITHM,
828            llm::DYN_LORA_ALLOCATION_TIMESTEP_SECS,
829            llm::DYN_LORA_ALLOCATION_SCALE_DOWN_COOLDOWN_TICKS,
830            llm::DYN_LORA_ALLOCATION_RATE_WINDOW_MULTIPLIER,
831            llm::DYN_LORA_ALLOCATION_BUCKETS_PER_SECOND,
832            llm::DYN_LORA_ALLOCATION_PREDICTOR_TYPE,
833            llm::DYN_LORA_ALLOCATION_EMA_ALPHA,
834            llm::DYN_LORA_MCF_CONFIG,
835            llm::metrics::DYN_METRICS_PREFIX,
836            llm::audit::DYN_AUDIT_SINKS,
837            llm::audit::DYN_AUDIT_FORCE_LOGGING,
838            llm::audit::DYN_AUDIT_CAPACITY,
839            llm::audit::DYN_AUDIT_NATS_SUBJECT,
840            llm::audit::DYN_AUDIT_OUTPUT_PATH,
841            llm::audit::DYN_AUDIT_JSONL_BUFFER_BYTES,
842            llm::audit::DYN_AUDIT_JSONL_FLUSH_INTERVAL_MS,
843            llm::audit::DYN_AUDIT_JSONL_GZ_ROLL_BYTES,
844            llm::audit::DYN_AUDIT_JSONL_GZ_ROLL_LINES,
845            llm::request_trace::DYN_REQUEST_TRACE,
846            llm::request_trace::DYN_REQUEST_TRACE_SINKS,
847            llm::request_trace::DYN_REQUEST_TRACE_FILE_PATH,
848            llm::request_trace::DYN_REQUEST_TRACE_OUTPUT_PATH,
849            llm::request_trace::DYN_REQUEST_TRACE_FILE_FORMAT,
850            llm::request_trace::DYN_REQUEST_TRACE_CAPACITY,
851            llm::request_trace::DYN_REQUEST_TRACE_RECORDS,
852            llm::request_trace::DYN_REQUEST_TRACE_NATS_SUBJECT,
853            llm::request_trace::DYN_REQUEST_TRACE_OTEL_MAX_PAYLOAD_BYTES,
854            llm::request_trace::DYN_REQUEST_TRACE_FILE_BUFFER_BYTES,
855            llm::request_trace::DYN_REQUEST_TRACE_JSONL_BUFFER_BYTES,
856            llm::request_trace::DYN_REQUEST_TRACE_FILE_FLUSH_INTERVAL_MS,
857            llm::request_trace::DYN_REQUEST_TRACE_JSONL_FLUSH_INTERVAL_MS,
858            llm::request_trace::DYN_REQUEST_TRACE_FILE_ROLL_BYTES,
859            llm::request_trace::DYN_REQUEST_TRACE_JSONL_GZ_ROLL_BYTES,
860            llm::request_trace::DYN_REQUEST_TRACE_FILE_ROLL_LINES,
861            llm::request_trace::DYN_REQUEST_TRACE_JSONL_GZ_ROLL_LINES,
862            llm::request_trace::DYN_REQUEST_TRACE_TOOL_EVENTS_ZMQ_ENDPOINT,
863            llm::request_trace::DYN_REQUEST_TRACE_TOOL_EVENTS_ZMQ_TOPIC,
864            llm::request_trace::DYN_REQUEST_TRACE_HTTP_HEADER_CAPTURE_LIST,
865            llm::audit::DYN_AUDIT_OTEL_MAX_PAYLOAD_BYTES,
866            // Model
867            model::model_express::MODEL_EXPRESS_URL,
868            model::model_express::MODEL_EXPRESS_CACHE_PATH,
869            model::model_express::MODEL_EXPRESS_NO_SHARED_STORAGE,
870            model::huggingface::HF_TOKEN,
871            model::huggingface::HUGGING_FACE_HUB_TOKEN,
872            model::huggingface::HF_TOKEN_PATH,
873            model::huggingface::HF_HUB_CACHE,
874            model::huggingface::HF_HOME,
875            model::huggingface::HF_ENDPOINT,
876            model::huggingface::HF_HUB_OFFLINE,
877            // Router
878            router::DYN_ROUTER_PREFILL_LOAD_SCALE,
879            router::DYN_ROUTER_QUEUE_THRESHOLD,
880            router::DYN_ROUTER_QUEUE_POLICY,
881            router::DYN_ROUTER_POLICY_CONFIG,
882            router::DYN_ROUTER_ACTIVE_REQUEST_EXPIRY_SECS,
883            request_plane::DYN_REQUEST_PLANE_CODEC,
884            // TCP Response Stream
885            tcp_response_stream::DYN_TCP_RESPONSE_STREAM_PORT,
886            tcp_response_stream::DYN_TCP_RESPONSE_STREAM_HOST,
887            // Event Plane
888            event_plane::DYN_EVENT_PLANE,
889            event_plane::DYN_EVENT_PLANE_CODEC,
890            event_plane::DYN_ZMQ_EVENT_SUBSCRIBER_CHANNEL_CAPACITY,
891            // ZMQ Broker
892            zmq_broker::DYN_ZMQ_BROKER_URL,
893            zmq_broker::DYN_ZMQ_BROKER_ENABLED,
894            zmq_broker::ZMQ_BROKER_XSUB_BIND,
895            zmq_broker::ZMQ_BROKER_XPUB_BIND,
896            zmq_broker::ZMQ_BROKER_NAMESPACE,
897            // Discovery
898            discovery::DYN_DISCOVERY_BACKEND,
899            discovery::DYN_KUBE_DISCOVERY_MODE,
900            // CUDA
901            cuda::DYN_FATBIN_PATH,
902            // Build
903            build::OUT_DIR,
904            // Mocker
905            mocker::DYN_MOCKER_KV_CACHE_TRACE,
906            mocker::DYN_MOCKER_SYNC_DIRECT,
907            // Testing
908            testing::DYN_QUEUED_UP_PROCESSING,
909            testing::DYN_SOAK_RUN_DURATION,
910            testing::DYN_SOAK_BATCH_LOAD,
911        ];
912
913        for var in &vars {
914            if !seen.insert(var) {
915                panic!("Duplicate environment variable name: {}", var);
916            }
917        }
918    }
919
920    #[test]
921    fn test_naming_conventions() {
922        // Dynamo-specific vars should start with DYN_
923        assert!(runtime::DYN_RUNTIME_NUM_WORKER_THREADS.starts_with("DYN_"));
924        assert!(runtime::DYN_RUNTIME_GRACEFUL_SHUTDOWN_TIMEOUT_SECS.starts_with("DYN_"));
925        assert!(runtime::system::DYN_SYSTEM_ENABLED.starts_with("DYN_"));
926        assert!(kvbm::DYN_KVBM_METRICS.starts_with("DYN_"));
927        assert!(worker::DYN_WORKER_GRACEFUL_SHUTDOWN_TIMEOUT.starts_with("DYN_"));
928
929        // NATS vars should start with NATS_
930        assert!(nats::NATS_SERVER.starts_with("NATS_"));
931        assert!(nats::auth::NATS_AUTH_USERNAME.starts_with("NATS_AUTH_"));
932
933        // ETCD vars should start with ETCD_
934        assert!(etcd::ETCD_ENDPOINTS.starts_with("ETCD_"));
935        assert!(etcd::ETCD_LEASE_TTL.starts_with("ETCD_"));
936        assert!(etcd::auth::ETCD_AUTH_USERNAME.starts_with("ETCD_AUTH_"));
937
938        // OpenTelemetry vars should start with OTEL_
939        assert!(logging::otlp::OTEL_EXPORT_ENABLED.starts_with("OTEL_"));
940        assert!(logging::otlp::OTEL_EXPORTER_OTLP_ENDPOINT.starts_with("OTEL_"));
941        assert!(logging::otlp::OTEL_SERVICE_NAME.starts_with("OTEL_"));
942    }
943}