LeetLLM
My PlanLearnGlossaryTracksPracticeBlog
LeetLLM

Your go-to resource for mastering AI & LLM systems.

Product

  • Learn
  • Glossary
  • Tracks
  • Practice
  • Blog
  • RSS

Legal

  • Terms of Service
  • Privacy Policy

© 2026 LeetLLM. All rights reserved.

All Topics
Your Progress
0%

0 of 196 articles completed

🛠️Computing Foundations0/9
Git, Shell, Linux for AIDocker for Reproducible AIPython for AI EngineeringNumPy and Tensor ShapesCUDA for ML TrainingMPS & Metal for ML on MacData Structures for AISQL and Data ModelingAlgorithms for ML Engineers
📊Math & Statistics0/9
Gradients and BackpropVectors, Matrices & TensorsLinear Algebra for MLAdam, Momentum, SchedulersProbability for Machine LearningBayesian Inference from EvidenceStatistics and UncertaintyDistributions and SamplingHypothesis Tests, Intervals, and pass@k
📚Preparation & Prerequisites0/13
Neural Networks from ScratchCNNs from ScratchTraining & BackpropagationSoftmax, Cross-Entropy & OptimizationRNNs, LSTMs, GRUs, and Sequence ModelingAutoencoders and VAEsThe Transformer Architecture End-to-EndLanguage Modeling & Next TokensFrom GPT to Modern LLMsPrompt Engineering FundamentalsCalling LLM APIs in ProductionFirst AI App End-to-EndThe LLM Lifecycle
🧮ML Algorithms & Evaluation0/15
Linear Regression from ScratchLogistic Regression and MetricsDecision Trees, Forests, and BoostingReinforcement Learning BasicsValidation and LeakageStatistical Learning and GeneralizationConformal Prediction and UncertaintyClustering and PCAProbabilistic Generative ModelsCore Retrieval AlgorithmsDecoding AlgorithmsExperiment Design and A/B TestingCausal Inference and CounterfactualsPyTorch Training LoopsDataset Pipelines and Data Quality
📦Production ML Systems0/6
Feature Engineering for Production MLBatch and Streaming Feature PipelinesGradient Boosted Trees in ProductionRanking and Recommendation SystemsForecasting and Anomaly DetectionMonitoring Predictive Models
🧪Core LLM Foundations0/8
The Bitter Lesson & ComputeBPE, WordPiece, and SentencePieceStatic to Contextual EmbeddingsPerplexity & Model EvaluationFile Ingestion for AIChunking StrategiesLLM Benchmarks & LimitationsInstruction Tuning & Chat Templates
🧰Applied LLM Engineering0/25
Dimensionality Reduction for EmbeddingsCoT, ToT & Self-Consistency PromptingFunction Calling & Tool UseMCP & Tool Protocol StandardsContext EngineeringPrompt Injection DefenseResponsible AI GovernancePrivacy-Preserving Machine LearningData Labeling and Human FeedbackEvaluating AI AgentsProduction RAG PipelinesHybrid Search: Dense + SparseReranking and Cross-Encoders for RAGRAG Evaluation for Reliable AnswersLLM-as-a-Judge EvaluationBias & Fairness in LLMsHallucination Detection & MitigationLLM Observability & MonitoringExperiment Tracking with MLflow and W&BPrompt Optimization with DSPyModel Versioning & DeploymentSemantic Caching & Cost OptimizationLLM Cost Engineering & Token EconomicsModel Gateways, Routing, and FallbacksDesign an Automated Support Agent
🎓Portfolio Capstones0/9
Capstone: Delivery ETA PredictionCapstone: Product RankingCapstone: Demand ForecastingCapstone: Image Damage ClassifierCapstone: Production ML PipelineCapstone: Document QACapstone: Eval DashboardCapstone: Fine-Tuned ClassifierCapstone: Reproducible ML Study
🧠Transformer Deep Dives0/8
Sentence Embeddings & Contrastive LossEmbedding Similarity & QuantizationScaled Dot-Product AttentionVision Transformers and Image EncodersPositional Encoding: RoPE & ALiBiLayer Normalization: Pre-LN vs Post-LNMechanistic InterpretabilityDecoding Strategies: Greedy to Nucleus
🧬Advanced Training & Adaptation0/17
Scaling Laws & Compute-Optimal TrainingPre-training Data at ScaleBuild GPT from Scratch LabJAX for PyTorch ResearchersContinued Pretraining for Domain ShiftSynthetic Data PipelinesSupervised Fine-Tuning PipelineMixed Precision TrainingDistributed Training: FSDP & ZeROLoRA & Parameter-Efficient TuningTraining Run OperationsReward Modeling from Preference DataRLHF & DPO AlignmentConstitutional AI & Red TeamingRLVR & Verifiable RewardsKnowledge Distillation for LLMsModel Merging and Weight Interpolation
🤖Advanced Agents & Retrieval0/16
Vector DB Internals: HNSW & IVFAdvanced RAG: HyDE & Self-RAGGraphRAG & Knowledge GraphsRAG Security & Access ControlStructured Output GenerationReAct & Plan-and-ExecuteGuardrails & Safety FiltersCode Generation & SandboxingComputer-Use / GUI / Browser AgentsHuman-in-the-Loop Agent ArchitectureAI Coding Workflow with AgentsAgent Memory & PersistenceAgent Failure & RecoveryRecursive Language Models (RLM)Multi-Agent OrchestrationCapstone: Production Agent
⚡Inference & Production Scale0/31
Inference: TTFT, TPS & KV CacheMulti-Query & Grouped-Query AttentionKV Cache & PagedAttentionPrefix Caching and Prompt CachingFlashAttention & Memory EfficiencyContinuous Batching & SchedulingScaling LLM InferenceModel Parallelism for LLM InferenceAccelerator Architecture Field GuideCorrect GPU Profiling and BenchmarkingGPU Kernel Performance Engineering LabGPU Parallel Primitives LabGPU Compilers and Kernel LanguagesGEMM From Naive CUDA to Tensor CoresLow-Precision GPU ProgrammingGPU Runtime Execution LabAI-Generated Kernel EngineeringModel Quantization: GPTQ, AWQ & GGUFLocal LLM DeploymentSLM Specialization & Edge DeploymentSpeculative DecodingLong Context Window ManagementMixture of Experts ArchitectureMamba & State Space ModelsReasoning & Test-Time ComputeAdvanced MLOps & DevOps for AIGPU Serving & AutoscalingGPU Failure OperationsDistributed Inference Data PlaneServing Benchmark EngineeringA/B Testing for LLMs
🏗️System Design Capstones0/9
Content Moderation SystemCode Completion SystemMulti-Tenant LLM PlatformLLM-Powered Search EngineVision-Language Models & CLIPMultimodal LLM ArchitectureDiffusion Models: Images & TextReal-Time Voice AI AgentReasoning Agent System Design
🎤AI Lab Interviewing0/4
AI Lab Coding Interview: Python SystemsAI Lab System Design InterviewAI Lab Behavioral InterviewAI Lab Technical Presentation
🔬Project Deep Dives0/17
Deep Dive - vLLMDeep Dive - SkyRLDeep Dive - FlashAttentionDeep Dive - FlashInferDeep Dive - DeepGEMMDeep Dive - NCCLDeep Dive - MegatronDeep Dive - DeepSpeedDeep Dive - RayDeep Dive - MLflowDeep Dive - PyTorchDeep Dive - TransformersDeep Dive - SGLangDeep Dive - slimeDeep Dive - DeepEPDeep Dive - TinkerDeep Dive - Light-PEFT
Back to Topics
LearnProject Deep DivesDeep Dive - MLflow
⚙️HardMLOps & Deployment

Deep Dive - MLflow

Read MLflow as an evidence and lineage system for models and LLM applications: tracking, artifacts, traces, evaluation datasets, prompts, registries, storage, and governance.

26 min read
Learning path
Step 189 of 196 in the full curriculum
Deep Dive - RayDeep Dive - PyTorch

Personalize this lesson

Adapt explanations and teaching visuals to your background and preferred voice.

At 09:12 in this illustrative incident, hybrid-reranker-v3 answers a return-window question with "30 days" and no citation. Git commit 8b2f9e1 is unchanged, yet a prompt alias, retrieval index, provider model, or evaluator rubric may have moved. Checking the commit alone won't tell us which inputs this request actually used.

Ray showed where that work runs: tasks, actors, object refs, and recovery. MLflow records the evidence around it: experiments, parameters, metrics, artifacts, models, prompts, request traces, and evaluation results, all tied to stable identities. GPU scheduling and attention kernels stay elsewhere. Those links give a team something it can compare, reproduce, promote, debug, and audit.

Keep one policy assistant in view. It retrieves 40 candidates, reranks to 8, and answers from prompt support-answer version 17. Git commit 8b2f9e1 and dataset support-eval-2026-08-01 (short label eval-08-01) identify two more inputs. When a request about the return window cites nothing, its trace becomes case RET-104. Names, scores, and timings here are teaching fixtures, not measurements from a deployed assistant.

The local SDK lab below pins MLflow 3.15.2, released August 26, 2026. The source-reading path uses that release too. Documentation under /latest/ can move ahead of an installed server, so verify feature availability and client/server compatibility before adopting its examples.[1]Reference 1MLflow 3.15.2https://github.com/mlflow/mlflow/releases/tag/v3.15.2

Linked identities, not just a Git commit

Two runs can share a source commit while using different data, parameters, environments, random seeds, or checkpoints. Replay only the commit and you can still get a different model. The original MLflow paper described open interfaces for tracking experiments, packaging reproducible projects, and representing models in several deployment flavors without forcing teams into one framework.[2]Reference 2Accelerating the Machine Learning Lifecycle with MLflow.https://www.usenix.org/conference/opml19/presentation/tut5

That open-interface idea still anchors the project. The current tree extends classical experiment tracking into LLM and agent work. Each asset below answers a different reconstruction question:

AssetWhat the record containsQuestion it answers
RunParameters, metrics, tags, sourceWhat happened in one experiment?
Logged modelModel files, signature, lineageWhich model artifact produced this result?
Prompt versionImmutable template; separately mutable model configWhich instructions reached the application?
TraceOrdered spans, inputs, outputs, timingWhich step failed on this request?
Evaluation datasetCases, expectations, provenanceWhat evidence did releases face?
AssessmentScore, rationale, sourceWho or what judged a trace?
Registry aliasMutable name pointing to a versionWhich asset does this name currently resolve to?

These records earn their value through links. A trace can record the resolved prompt and model, a failure can become an evaluation case, and a candidate evaluation can point back to its model and code. Those links aren't automatic for arbitrary application code. Stable IDs also don't make every field immutable: tags, assessments, aliases, and some configuration can change. Require approval in your promotion workflow; the registry API itself won't refuse every unevaluated alias move.

Why isn't a Git commit enough to reproduce an LLM evaluation?

Answer

Code is only one input. Reproduction also needs model and prompt versions, data or trace cases, parameters, dependencies, evaluator definitions, and artifacts. MLflow records those changing inputs under linked identities.

Metadata and artifacts take different paths

Suppose every request adds a few searchable fields but a checkpoint adds gigabytes. Putting both in one store makes query traffic compete with large-byte transfers. MLflow separates searchable metadata from large bytes: the backend store holds experiment, run, model, prompt, trace, metric, parameter, and tag records, while the artifact store holds model weights, checkpoints, plots, tables, files, and archived trace payloads.[3]Reference 3MLflow Architecture Overviewhttps://mlflow.org/docs/latest/self-hosting/architecture/overview/

That split leaves one routing question: who moves artifact bytes? The tracking server provides an HTTP boundary in front of both stores. Clients can send metadata to the server while either proxying artifact uploads through it or writing directly to object storage. Those modes have different credential and throughput consequences.

Diagram showing SDK / autologging, Tracking server REST + configured auth, Backend store SQL metadata, and proxied artifacts.
SDK / autologging, Tracking server REST + configured auth, Backend store SQL metadata, and proxied artifacts.

SQLite is the default local backend. A production tracking server normally uses a managed relational database plus object storage. The file backend is a legacy path in maintenance mode, and Model Registry requires a database-backed store. Shared workspaces, which group experiments, models, prompts, and artifacts for teams, are opt-in and also need SQL.[4]Reference 4Backend Storeshttps://mlflow.org/docs/latest/self-hosting/architecture/backend-store/[3]Reference 3MLflow Architecture Overviewhttps://mlflow.org/docs/latest/self-hosting/architecture/overview/

Artifact proxying keeps storage credentials on the server, but it also widens the server's authority. Scope that role and enforce access checks on artifact requests; proxying isn't tenant isolation by itself. Direct uploads reduce proxy load, but every client now needs storage access. Existing experiments retain their artifact locations, so changing server flags doesn't automatically migrate their bytes or access paths.[3]Reference 3MLflow Architecture Overviewhttps://mlflow.org/docs/latest/self-hosting/architecture/overview/[5]Reference 5ML Experiment Tracking.https://mlflow.org/docs/latest/ml/tracking/

Code, dataset, and prompt identities feed a run. A logged model ID leads to registered model version 3; a separately identified trace becomes evaluation case RET-104. These identifiers are distinct.
Follow the IDs, not the display names. A run can link to a logged model and traces, while registration assigns a separate model version. Selecting a trace as RET-104 creates an evaluation case; neither link certifies the model's quality.

A diagram of stores still doesn't tell you what one experiment recorded. To answer that, follow one run.

Runs are evidence containers

A run groups parameters, metrics, tags, artifacts, and source metadata. In our example, retrieval depth and rerank width are parameters, nDCG@8 is a metric, the commit and dataset revision are tags, and error_slices.json is an artifact. Each field has a different job when you compare or replay a run.

The MLflow API makes those categories explicit. This example uses a temporary SQLite database and local artifacts, so it needs no tracking server. The metric values are fixtures; reading them back verifies persistence, not retrieval quality. Install mlflow==3.15.2 in an isolated environment before running it:

track_experiment.py
1import os 2from pathlib import Path 3from tempfile import TemporaryDirectory 4 5os.environ["MLFLOW_DISABLE_TELEMETRY"] = "true" 6import mlflow 7 8with TemporaryDirectory() as directory: 9 root = Path(directory) 10 mlflow.set_tracking_uri(f"sqlite:///{root / 'tracking.db'}") 11 experiment_id = mlflow.create_experiment( 12 "retrieval-ranking", artifact_location=(root / "artifacts").as_uri() 13 ) 14 with mlflow.start_run(experiment_id=experiment_id, run_name="hybrid-reranker-v3") as run: 15 mlflow.log_params({"retrieval_k": 40, "rerank_k": 8}) 16 mlflow.log_metrics({"recall_at_40": 0.94, "ndcg_at_8": 0.81}) 17 mlflow.set_tags({"dataset_revision": "eval-08-01", "git_commit": "8b2f9e1"}) 18 mlflow.log_dict({"case": "RET-104", "failure": "missing citation"}, "error_slices.json") 19 stored = mlflow.get_run(run.info.run_id) 20 assert stored.data.params["retrieval_k"] == "40" 21 assert stored.data.metrics["ndcg_at_8"] == 0.81 22 print("read back: retrieval_k=40; ndcg_at_8=0.81")
Output
1read back: retrieval_k=40; ndcg_at_8=0.81

Those calls prove that the API accepted records, not that the records describe a valid experiment. Without a dataset revision, a metric can be impossible to compare. Missing model signatures can let the wrong schema reach an artifact, while mutable environment dependencies can defeat reproduction. MLflow stores evidence; the team still has to decide which evidence a release requires.[5]Reference 5ML Experiment Tracking.https://mlflow.org/docs/latest/ml/tracking/

MLflow's model abstraction packages files with a flavor-specific loader, environment metadata, and an optional input/output signature. A logged model has a model ID and can point back to a source run; that's distinct from a registered model's integer version. A registry version points to an artifact, while tags and aliases remain mutable. Approve the resolved artifact and its digest, then move an alias separately. A version number isn't protection against someone overwriting bytes in the artifact store.[6]Reference 6Model Registry Workflows | MLflow AI Platformhttps://mlflow.org/docs/latest/ml/model-registry/workflow/

The run can say nDCG@8 is 0.81. That aggregate still can't show which span of a live request went wrong, so we need request-level lineage.

LLM traces add request-level lineage

A trace represents one request as a tree of spans. Each span records a named operation, timing, status, attributes, and optional inputs or outputs.

MLflow Tracing is compatible with OpenTelemetry (OTel), an open telemetry standard. It adds LLM-oriented structures while preserving export and ingestion through OTel-compatible systems.[7]Reference 7LLM Tracing and Agent Observabilityhttps://mlflow.org/docs/latest/genai/tracing/[8]Reference 8OpenTelemetry GenAI Semantic Conventionshttps://github.com/open-telemetry/semantic-conventions-genai

The policy assistant's illustrative trace has this shape. Retrieval reports DOC-12, but generation answers "30 days" with no citation. Before reading the timings, predict where you'd investigate first. The root's wall-clock duration is 1,420 ms:

trace-tree.txt
1answer_question 1,420 ms 2├── retrieve_policy_docs 145 ms 3│ ├── embed_query 24 ms 4│ └── vector_search 91 ms 5├── rerank 110 ms 6└── generate_answer 1,130 ms 7 ├── model_call 980 ms 8 └── validate_citations 105 ms

The direct children sum to 145+110+1,130=1,385145+110+1{,}130=1{,}385145+110+1,130=1,385 ms, leaving 35 ms of root work outside those children if they ran sequentially. Never add all nested durations: that double-counts parent time. Overlapping spans also need a timeline rather than a sum to explain the critical path.

Root metadata helps search the trace, while child spans explain it. Model spans can carry token counts and provider metadata. Retrieval spans can record document IDs and scores; tool spans can record arguments, results, and exceptions. Assessments attach feedback or scores. A recorded document ID is evidence of what the instrumentation observed, not proof that the chunk reached the final model context. Check context packing as well as retrieval.

Instrumentation can be manual with @mlflow.trace or span contexts, automatic through integration hooks, or ingested from OpenTelemetry. Automatic tracing is fast to adopt, but manual spans are still useful around business decisions that a library integration can't name.

A trace shows a correct retrieved document but an unsupported answer. Which boundary failed?

Answer

Inspect the retrieved content, final context packing, instructions, model output, and citation validation. A correct document in retrieval output doesn't prove it survived truncation or reached generation. The trace narrows the investigation; it doesn't establish the root cause by itself.

One failure trace doesn't define a release test by itself. Freeze its inputs and write an expected outcome before changing the candidate, so later comparisons can tell whether the fix helped.

Traces become evaluation data

Call that frozen request RET-104. The operations loop starts by capturing development or production traces, then selecting failures and representative successes. Add expectations, labels, or human feedback, such as "the answer must cite a retrieved doc," and store those cases in a versioned evaluation dataset (eval-08-01).

Now run each candidate application version against the same cases. Apply deterministic scorers and calibrated LLM judges, then inspect per-case failures alongside aggregate slices. Our release policy requires every critical case to pass, so a better average can't hide a broken RET-104. Keep separate representative holdout cases: repeatedly tuning against incident cases can overfit the regression suite.

Fixed case RET-104 and candidate prompt v18 enter evaluation. A citation code check and a groundedness judge produce evidence for the release controller. It keeps production on v17 after a failure and moves it to v18 only when all required checks pass.
RET-104 stays a fixed input. Our release workflow requires a citation code check and groundedness assessment before moving the prompt alias to v18. A failed check keeps it on v17; MLflow records the evidence but doesn't enforce this application policy automatically.

Offline evaluation runs when a team calls mlflow.genai.evaluate with cases, a prediction function, and scorers. Use deterministic scorers for exact contracts such as JSON validity, citation existence, tool policy, or numerical tolerance. LLM judges help with relevance or tone when exact code can't express the rubric.

Automatic evaluation applies configured LLM judges asynchronously to sampled or filter-matched traces or conversations. It keeps judge calls off the request's synchronous path, but logging overhead and shared server load still exist. The documented server workflow supports LLM judges rather than code scorers, uses AI Gateway endpoints, considers recent traces within a one-hour window, and doesn't automatically retry failed evaluations. Confirm these version-sensitive limits for your deployment. Monitor the fraction of eligible cases actually scored, not just the average among successful assessments.[9]Reference 9Automatic Evaluationhttps://mlflow.org/docs/latest/genai/eval-monitor/automatic-evaluations/

Judge output isn't ground truth. It changes with judge model, prompt, temperature, context, and rubric. Align judges against human labels, pin configurations, sample disagreements, and keep exact safety rules in code where possible.

Run the evidence loop locally

The downloadable SQLite SDK lab exercises native MLflow APIs with deterministic functions instead of provider calls. It reads back a run, artifact, and two-span trace; registers two prompt versions; moves an alias; then evaluates three response fixtures with mlflow.genai.evaluate and a custom code scorer.[10]Reference 10mlflow.genai Python APIhttps://mlflow.org/docs/latest/api_reference/python_api/mlflow.genai.html

Run the file with uv run mlflow_local_lab.py. Its dependency metadata pins Python 3.12 and MLflow 3.15.2. It disables MLflow usage telemetry and uses a temporary local database and artifact directory, which it removes after checking them. Package installation may need internet access; the lab itself needs neither credentials nor a server.

The three cases have no citation, an unknown citation DOC-99, and an allowed citation DOC-12. The scorer accepts only a nonempty list of allowed document IDs. Thus one of three cases passes, and our all-required-cases release policy blocks promotion. This checks citation membership, not whether “30 days” is supported by the document's text.

Expected lab summaries, excluding MLflow's generated run IDs and progress messages:

Local SDK lab summaries
1tracking: run, metric, artifact, and two-span trace read back 2prompts: old object=v1; fresh alias=v2 3mutability: parameter fixed; tag and prompt model config changed 4evaluation: missing=False; wrong=False; valid=True; mean=1/3 5release: blocked under the all-required-cases policy 6PASS: local SDK contracts; no server, provider, or judge calls

The fresh registry numbers these prompts 1 and 2; they play the roles of v17 and v18 in the incident. Setting cache_ttl_seconds=0 forces fresh alias resolution, so the lab tests alias movement and already-loaded objects, not elapsed-time cache expiry. We'll isolate expiry with a deterministic clock below.

Why should schema validity use a code scorer instead of an LLM judge?

Answer

Schema validity is deterministic and exactly computable. A code scorer is cheaper, repeatable, and easier to debug. Save judges for criteria that genuinely require semantic interpretation.

Instructions are one of the assets that evaluation will promote. They need the same versioning rules as models, which brings us to prompt management.

Prompt Registry makes instructions deployable assets

Prompt text behaves like code and configuration at once. A wording change can alter tool selection, output shape, latency, and safety. MLflow Prompt Registry stores templates with variables, optional model configuration, tags, and commit messages. A created template version is immutable, but its model configuration can be updated. Record the exact resolved configuration or its digest alongside the version; the prompt version alone can't reproduce a historical temperature setting.[11]Reference 11Prompt Registryhttps://mlflow.org/docs/latest/genai/prompt-registry/index.html

Aliases provide mutable names such as candidate or production. Clients can load prompts:/support-answer@production while the alias points to a numbered version. Moving the alias changes subsequent resolution; it doesn't rewrite an already loaded object or hot-reload a worker.

That convenience includes a cache, so an alias move isn't instantly visible to every worker. Version-based loads (prompts:/support-answer/17) have an infinite default time-to-live (TTL); alias-based loads (prompts:/support-answer@production) default to 60 seconds. A process can keep serving v17 until it loads again after expiry. Because attached model configuration is mutable, an indefinitely cached version object can also retain old configuration. Choose an explicit refresh policy and record the resolved configuration used on each request.[11]Reference 11Prompt Registryhttps://mlflow.org/docs/latest/genai/prompt-registry/index.html

The next example isolates cache behavior without calling MLflow. Its integer clock makes expiry reproducible. Versions reject replacement, aliases are scoped by prompt name, and cache entries are keyed by both name and alias. It models immutable templates only, not MLflow's mutable model configuration or concurrent registry writes.

prompt_alias_cache.py
1from dataclasses import dataclass 2 3@dataclass(frozen=True) 4class PromptVersion: 5 name: str 6 version: int 7 template: str 8 9class PromptRegistry: 10 def __init__(self) -> None: 11 self.versions: dict[tuple[str, int], PromptVersion] = {} 12 self.aliases: dict[tuple[str, str], tuple[str, int]] = {} 13 14 def register(self, prompt: PromptVersion) -> None: 15 key = (prompt.name, prompt.version) 16 if key in self.versions: 17 raise ValueError("version already exists") 18 self.versions[key] = prompt 19 20 def set_alias(self, alias: str, prompt: PromptVersion) -> None: 21 key = (prompt.name, prompt.version) 22 if key not in self.versions: 23 raise KeyError(key) 24 self.aliases[(prompt.name, alias)] = key 25 26 def resolve(self, name: str, alias: str) -> PromptVersion: 27 return self.versions[self.aliases[(name, alias)]] 28 29class CachedClient: 30 """Alias loads refresh after ttl_ticks. MLflow's default alias TTL is 60s.""" 31 32 def __init__(self, registry: PromptRegistry, ttl_ticks: int = 1) -> None: 33 if type(ttl_ticks) is not int or ttl_ticks < 0: 34 raise ValueError("TTL must be a nonnegative integer") 35 self.registry = registry 36 self.ttl_ticks = ttl_ticks 37 self._cached: dict[tuple[str, str], tuple[PromptVersion, int]] = {} 38 self._last_tick = -1 39 40 def load(self, name: str, alias: str, tick: int) -> PromptVersion: 41 if type(tick) is not int or tick < 0 or tick < self._last_tick: 42 raise ValueError("clock must be nonnegative and monotonic") 43 self._last_tick = tick 44 key = (name, alias) 45 cached = self._cached.get(key) 46 if cached is None or tick >= cached[1]: 47 cached = (self.registry.resolve(name, alias), tick + self.ttl_ticks) 48 self._cached[key] = cached 49 return cached[0] 50 51def record_trace(alias: str, resolved: PromptVersion) -> dict[str, object]: 52 return { 53 "prompt_alias": alias, 54 "prompt_name": resolved.name, 55 "prompt_version": resolved.version, 56 "template": resolved.template, 57 } 58 59v17 = PromptVersion("support-answer", 17, "Cite retrieved docs.") 60v18 = PromptVersion("support-answer", 18, "Cite retrieved docs. Refuse if none.") 61registry = PromptRegistry() 62registry.register(v17) 63registry.register(v18) 64registry.set_alias("production", v17) 65 66client = CachedClient(registry, ttl_ticks=1) 67served = client.load("support-answer", "production", tick=0) 68assert record_trace("production", served)["prompt_version"] == 17 69 70registry.set_alias("production", v18) 71stale = client.load("support-answer", "production", tick=0) 72assert stale.version == 17 73 74fresh = client.load("support-answer", "production", tick=1) 75assert fresh.version == 18 76print(f"cached={stale.version} then resolved={fresh.version}") 77 78other = PromptVersion("summarize", 1, "Summarize without adding facts.") 79registry.register(other) 80registry.set_alias("production", other) 81assert client.load("summarize", "production", tick=1) == other 82try: 83 registry.register(PromptVersion("support-answer", 17, "Silently changed.")) 84except ValueError: 85 print("version overwrite rejected; another prompt's cache stays separate") 86else: 87 raise AssertionError("immutable template was replaced")
Output
1cached=17 then resolved=18 2version overwrite rejected; another prompt's cache stays separate

Trace RET-104 must store version 17 if that's what the process used, even while the alias already names 18. The alias describes intended routing; the resolved version describes observed behavior. The toy records template text for inspection; a real trace should apply redaction or record a digest when the template contains sensitive material.

Model Registry uses a similar alias model. Fixed stages such as Staging and Production have been deprecated since MLflow 2.9.0 in favor of tags, aliases, and environment-specific registered models. Aliases separate a deployable name from an immutable model version, while CI/CD owns approval and environment promotion.[6]Reference 6Model Registry Workflows | MLflow AI Platformhttps://mlflow.org/docs/latest/ml/model-registry/workflow/

Provider calls are another mutable input. The gateway sees them, but it still isn't the source of application truth.

AI Gateway owns provider access, not application truth

MLflow also includes an OpenAI-compatible gateway surface for provider endpoints. Unified chat-completions live under /gateway/mlflow/v1, while passthrough routes expose a provider's native API. The gateway can centralize credentials, routing, fallbacks, rate limits, budgets, guardrails, and usage records.[12]Reference 12MLflow AI Gatewayhttps://mlflow.org/docs/latest/genai/governance/ai-gateway/

The gateway can answer which provider served a request, how many tokens it used, and whether a routing rule applied. It can't decide whether DOC-12 was the right policy or whether a business action was authorized. Keep those decisions in application and evaluation contracts.

Use this distinction when assigning release ownership:

LayerOwnsDoesn't prove
GatewayProvider access, routing, spend limitsAnswer correctness
TracingRequest path and observed dataEvaluation validity
EvaluationScored evidence on selected casesPopulation coverage
RegistryVersion identity and aliasesRelease approval by itself
CI/CDAutomated promotion rulesLive behavior after release

Linking these layers doesn't transfer responsibility. A trace exists because a request ran. An assessment exists because something scored it. A registry alias moved because a workflow changed it. Each event needs its own authorization and evidence.

Those links only hold up when the tracking server, object store, and exporters are operated like production systems.

Production architecture needs operations work

Database capacity and migrations

Every run metric, trace, span, prompt, alias, and assessment adds write and query load. Use a production database, monitor connection pools and slow queries, and rehearse schema upgrades. Back up before migrations. Large trace payloads may need archival into object storage while lightweight trace metadata remains searchable.[4]Reference 4Backend Storeshttps://mlflow.org/docs/latest/self-hosting/architecture/backend-store/

Artifact storage and credentials

Model checkpoints and evaluation tables can dwarf metadata. Use lifecycle rules, encryption, checksums, and explicit retention. Decide whether clients upload directly or the server proxies them. Don't give a public tracking server a broad object-store role.

Trace privacy

LLM spans can contain prompts, outputs, retrieved documents, tool arguments, secrets, personal data, and source code. Redact before export, sample intentionally, apply access controls, and set retention by data class. Disabling input capture for one integration doesn't automatically sanitize custom span attributes.[13]Reference 13Production Tracinghttps://mlflow.org/docs/latest/genai/tracing/prod-tracing/[14]Reference 14Handling sensitive datahttps://opentelemetry.io/docs/security/handling-sensitive-data/

Async loss and backpressure

Asynchronous tracing protects request latency, and OSS MLflow enables it by default outside Databricks notebooks. A process crash can still drop buffered spans. Current docs warn that a full export queue discards new traces and that failed exports are discarded after the retry window. Flush on graceful shutdown and monitor exporter failures. Then decide whether telemetry loss should fail open or fail closed: most applications should serve traffic while alerting on observability loss, while regulated workflows may choose differently.[13]Reference 13Production Tracinghttps://mlflow.org/docs/latest/genai/tracing/prod-tracing/

For instrumentation-only images, MLflow offers the slimmer mlflow-tracing distribution. Package composition is version-sensitive: the published mlflow==3.15.2 package itself depends on matching mlflow-skinny==3.15.2 and mlflow-tracing==3.15.2. Let the resolver install that supported set; don't independently mix mismatched releases based on older packaging advice.[15]Reference 15MLflow 3.15.2 Distribution Metadatahttps://pypi.org/pypi/mlflow/3.15.2/json

Identity and tenancy

A shared tracking server contains proprietary artifacts and request data. Put authentication, TLS, workspace or experiment permissions, and object-store policies into the threat model. Registry write access is deployment power because moving an alias can change what future clients load.

Strengths and weaknesses

Read each row as a tradeoff, not a feature tally:

StrengthWhy teams value itWeakness or cost
Framework-neutral interfacesOne evidence model across training and LLM appsIntegrations expose uneven detail
Metadata plus artifact splitSearch stays separate from large filesTwo storage systems need backup and policy
OTel-compatible tracingExisting telemetry systems can ingest or export spansLLM payloads create privacy risk
Linked runs, models, prompts, traces, evalsEnd-to-end lineage supports debugging and promotionCorrect links still depend on disciplined logging
Self-hosted Apache-2.0 coreTeams control infrastructure and dataTeam owns upgrades, scaling, auth, and retention
Model and prompt aliasesDeployments can reference stable namesMutable aliases need authorization and cache awareness

MLflow isn't a general distributed scheduler like Ray or Kubernetes. It offers deployment integrations and agent-serving features, but those don't replace the underlying resource scheduler, recovery protocol, or autoscaling system. Identify which component actually owns a GPU allocation or retry before treating a logged event as execution control.

It also doesn't replace a full observability platform. Infrastructure metrics, logs, profiles, and distributed application traces may live elsewhere. OpenTelemetry compatibility helps correlate them, but teams still need consistent trace and deployment identifiers across systems. If a GPU is saturated, MLflow can link the request to its model and release; a GPU profiler still has to explain the kernel.

Project identity

MLflow was created at Databricks and announced in 2018. The original paper's authors included Matei Zaharia, Andrew Chen, Aaron Davidson, Ali Ghodsi, Andy Konwinski, and other Databricks engineers.[2]Reference 2Accelerating the Machine Learning Lifecycle with MLflow.https://www.usenix.org/conference/opml19/presentation/tut5 It focused on experimentation, reproducibility, and deployment through open interfaces rather than a locked framework.

Databricks contributed MLflow to the Linux Foundation on June 25, 2020, giving the project a vendor-neutral governance home.[16]Reference 16The MLflow Project Joins Linux Foundationhttps://www.linuxfoundation.org/press/press-release/the-mlflow-project-joins-linux-foundation Databricks remains a major contributor and offers managed MLflow integrations, while the public project can be self-hosted and accepts community contributions.[17]Reference 17MLflow: Open Source AI Engineering Platformhttps://github.com/mlflow/mlflow[18]Reference 18MLflow on Databrickshttps://docs.databricks.com/gcp/en/mlflow/

FieldCurrent project fact
OriginDatabricks created MLflow; the foundational paper names Matei Zaharia, Andrew Chen, Aaron Davidson, Ali Ghodsi, and collaborators.[2]Reference 2Accelerating the Machine Learning Lifecycle with MLflow.https://www.usenix.org/conference/opml19/presentation/tut5
StewardshipMLflow is a Linux Foundation project with a technical steering committee and core maintainers listed in its contribution guide.[16]Reference 16The MLflow Project Joins Linux Foundationhttps://www.linuxfoundation.org/press/press-release/the-mlflow-project-joins-linux-foundation[19]Reference 19Contributing to MLflowhttps://github.com/mlflow/mlflow/blob/0489fb31d8a144ec3c80d15eb44dbe24b790465e/CONTRIBUTING.md
Contributor modelIssues and pull requests flow through project committers and maintainers, with Developer Certificate of Origin sign-off for incoming code.[19]Reference 19Contributing to MLflowhttps://github.com/mlflow/mlflow/blob/0489fb31d8a144ec3c80d15eb44dbe24b790465e/CONTRIBUTING.md[20]Reference 20MLflow Technical Charterhttps://github.com/mlflow/mlflow/blob/0489fb31d8a144ec3c80d15eb44dbe24b790465e/mlflow-charter.pdf
Project licensesSource code uses Apache-2.0. The technical charter makes project documentation available under CC BY 4.0.[21]Reference 21MLflow Apache License 2.0https://github.com/mlflow/mlflow/blob/0489fb31d8a144ec3c80d15eb44dbe24b790465e/LICENSE.txt[20]Reference 20MLflow Technical Charterhttps://github.com/mlflow/mlflow/blob/0489fb31d8a144ec3c80d15eb44dbe24b790465e/mlflow-charter.pdf
Commercial boundaryDatabricks provides managed MLflow products, while the Linux Foundation repository remains separately governed and self-hostable.[18]Reference 18MLflow on Databrickshttps://docs.databricks.com/gcp/en/mlflow/[16]Reference 16The MLflow Project Joins Linux Foundationhttps://www.linuxfoundation.org/press/press-release/the-mlflow-project-joins-linux-foundation
Asset boundaryLogging a model, dataset, prompt, trace, or artifact doesn't relicense it under MLflow's code license. Your organization still owns its access and retention policy.

The foundational paper explains the original design, not every modern API. Tracing also builds on OpenTelemetry specifications. For evaluation, prompt registry, gateway, and model-lineage behavior, use the documentation and source matching your release.

A code-reading path through MLflow

The public repository makes architectural boundaries visible. Trace one request from client call to store and span, then pin the commit because GenAI code moves quickly:

  1. Start at mlflow/tracking/client.py to see the stable MlflowClient facade.
  2. Follow a log call into mlflow/store/tracking/ and compare REST, file, and SQLAlchemy stores.
  3. Follow an artifact call into mlflow/store/artifact/ to see why large bytes use separate repositories.
  4. Open mlflow/server/handlers.py and trace one REST route to a store operation.
  5. Read mlflow/entities/logged_model.py for model identity and lineage.
  6. Follow mlflow/tracing/provider.py and mlflow/tracing/client.py from span creation to persistence.
  7. Inspect mlflow/genai/ for evaluation datasets, scorers, and prompts; follow gateway-specific handling into mlflow/gateway/.

Use tag v3.15.2 for this reading exercise instead of moving master. Start with MlflowClient.log_param, follow the tracking client to SqlAlchemyStore.log_param, and find the database constraint that rejects changing an existing parameter value. Then compare it with mutable run tags and prompt aliases. Public concepts are more stable than the implementation paths around them.[1]Reference 1MLflow 3.15.2https://github.com/mlflow/mlflow/releases/tag/v3.15.2

Test that distinction before reading deeper. The local lab tries to overwrite retrieval_k=40 with 50, then changes a run tag and a prompt version's temperature. The parameter update must fail; the tag and configuration updates must succeed. A useful source-reading explanation identifies where each rule is enforced and which historical values remain recoverable. Naming three API methods without explaining their different mutability rules misses the important boundary.

A prompt version's template stayed unchanged, but its temperature changed from 0.2 to 0.8. Can an old evaluation receipt containing only the version number reproduce the earlier request?

Answer

No. The template version doesn't identify the historical mutable configuration. Retain the exact configuration used, or its digest plus retrievable content. Resolve configuration deliberately when loading prompts; an already-loaded object may still contain the earlier value.

Designing an evidence contract

Start an MLflow deployment with required fields and release receipts, not with a dashboard. For the policy assistant, require:

  • Application release, source commit (8b2f9e1), environment, and dependency lock.
  • Resolved model provider and exact model identifier.
  • Resolved prompt version alongside its alias (support-answer@production and v17 or v18), plus the model configuration actually used.
  • Retrieval index and corpus revision (eval-08-01 isn't a substitute for the live index hash).
  • Root trace ID plus tool, retrieval, and model spans.
  • Token, latency, failure, and cost attributes with known units.
  • Evaluation dataset revision and scorer versions.
  • Per-case assessments plus aggregate slices, including RET-104.
  • Approval identity, candidate version, and digests of the evaluated artifact and configuration.
  • Alias movement event and rollback target.

That receipt lets a team answer four different questions: what ran, what it observed, how it scored, and why it was promoted. Without those distinctions, one green dashboard can hide missing cases, stale aliases, or dropped traces.

Complete the lesson

Mastery Check

Answer every question, then check your score. Score 75% or higher to mark this lesson complete.

1.A run records parameters and metrics in one database but uploads a 2 GB checkpoint elsewhere. Which MLflow boundary explains that layout?

Correct answer: Put searchable run metadata in the backend store and checkpoint bytes in the artifact store.

MLflow separates queryable run metadata from artifact bytes. A backend store can serve metrics and identities while an artifact store handles large checkpoints.

2.A trace contains a retrieval span, a tool span, and a model span under one request. What structure should evaluation code preserve?

Correct answer: A parent-child span tree with request-level timing, attributes, and component boundaries.

LLM traces add request-level lineage. Parent-child spans let an evaluator attribute latency, inputs, tool calls, and outputs to the same request rather than flattening evidence.

3.A regression gate must fail whenever a JSON field is missing, independent of model wording. Which evaluator is the strongest first choice?

Correct answer: A deterministic schema or code-based scorer that rejects missing fields explicitly.

A deterministic scorer can inspect required keys and values directly. LLM judges are useful for semantic qualities but add variance and should not replace an exact contract.

4.A prompt alias points to version 12, and the alias moves to version 13 while a worker's cache is still warm. What receipt preserves reproducibility?

Correct answer: Record the resolved template version and model configuration, alongside the alias name.

The worker may still use version 12 after the alias moves. Record what it resolved, not what the alias names now. Model configuration can change even within a template version, so capture that configuration or a digest backed by retained content too.

5.Three required regression cases return citation checks False, False, and True. The mean is 1/3. A release policy requires every case to pass. What should the controller do?

Correct answer: Keep the existing alias and retain both failing cases as evidence against promotion.

One pass out of three does not satisfy an all-required-cases policy. The controller must also verify that all expected cases were scored. MLflow stores the results; application release code owns the decision and alias move.

6.A trace includes customer text and retrieved documents. Which production design addresses the highest-risk evidence boundary first?

Correct answer: Redact sensitive fields, then enforce access controls and retention limits for remaining evidence.

Tracing creates a durable copy of inputs and outputs. Privacy requires deliberate redaction, access control, and retention, not only a higher sampling rate or a provider gateway.

7.An MLflow AI Gateway returns a successful provider response, but application answers violate a required schema. What conclusion is justified?

Correct answer: Gateway success proves provider access, not application correctness.

The gateway owns provider access and routing. Schema validation, prompt behavior, and task correctness remain application-level evidence that must be evaluated separately.

8.An asynchronous trace exporter queue is full during an outage. Which behavior should the service make explicit?

Correct answer: Bound the queue and define explicit sampling, drop, retry, and alerting behavior for overload.

Async export protects request latency but introduces loss and backpressure choices. A bounded queue plus an observable policy makes missing evidence measurable instead of silently misleading.

8 questions remaining.

Next Step
Continue to Deep Dive - PyTorch

MLflow showed how to preserve evidence around model work, including the prompt versions and traces a training job should log. <span data-glossary="pytorch">PyTorch</span> opens the execution substrate underneath that work: <span data-glossary="tensor">tensors</span>, automatic differentiation, compiler graphs, accelerator dispatch, and distributed collectives.

PreviousDeep Dive - Ray
Share this article
XFacebookLinkedInBlueskyRedditHacker NewsEmail
References

MLflow 3.15.2

MLflow Project · 2026

https://github.com/mlflow/mlflow/releases/tag/v3.15.2

Accelerating the Machine Learning Lifecycle with MLflow.

Zaharia, M., et al. · 2018 · IEEE Data Engineering Bulletin

https://www.usenix.org/conference/opml19/presentation/tut5

MLflow Architecture Overview

MLflow Project · 2026

https://mlflow.org/docs/latest/self-hosting/architecture/overview/

Backend Stores

MLflow Project · 2026

https://mlflow.org/docs/latest/self-hosting/architecture/backend-store/

ML Experiment Tracking.

MLflow Project. · 2026 · Official documentation

https://mlflow.org/docs/latest/ml/tracking/

Model Registry Workflows | MLflow AI Platform

MLflow · 2026

https://mlflow.org/docs/latest/ml/model-registry/workflow/

LLM Tracing and Agent Observability

MLflow · 2026

https://mlflow.org/docs/latest/genai/tracing/

OpenTelemetry GenAI Semantic Conventions

OpenTelemetry Authors · 2026

https://github.com/open-telemetry/semantic-conventions-genai

Automatic Evaluation

MLflow Project · 2026

https://mlflow.org/docs/latest/genai/eval-monitor/automatic-evaluations/

mlflow.genai Python API

MLflow Project · 2026

https://mlflow.org/docs/latest/api_reference/python_api/mlflow.genai.html

Prompt Registry

MLflow Project · 2026

https://mlflow.org/docs/latest/genai/prompt-registry/index.html

MLflow AI Gateway

MLflow Project · 2026

https://mlflow.org/docs/latest/genai/governance/ai-gateway/

Production Tracing

MLflow Project · 2026

https://mlflow.org/docs/latest/genai/tracing/prod-tracing/

Handling sensitive data

OpenTelemetry Authors · 2026

https://opentelemetry.io/docs/security/handling-sensitive-data/

MLflow 3.15.2 Distribution Metadata

MLflow Project · 2026

https://pypi.org/pypi/mlflow/3.15.2/json

The MLflow Project Joins Linux Foundation

Linux Foundation · 2020

https://www.linuxfoundation.org/press/press-release/the-mlflow-project-joins-linux-foundation

MLflow: Open Source AI Engineering Platform

MLflow Project · 2026

https://github.com/mlflow/mlflow

MLflow on Databricks

Databricks · 2026

https://docs.databricks.com/gcp/en/mlflow/

Contributing to MLflow

MLflow Contributors · 2026

https://github.com/mlflow/mlflow/blob/0489fb31d8a144ec3c80d15eb44dbe24b790465e/CONTRIBUTING.md

MLflow Technical Charter

MLflow Project · 2020

https://github.com/mlflow/mlflow/blob/0489fb31d8a144ec3c80d15eb44dbe24b790465e/mlflow-charter.pdf

MLflow Apache License 2.0

MLflow Contributors · 2026

https://github.com/mlflow/mlflow/blob/0489fb31d8a144ec3c80d15eb44dbe24b790465e/LICENSE.txt

Discussion

Questions and insights from fellow learners.

Discussion loads when you reach this section.