Machine Learning Operations (MLOps) · lesson 07/25
Model Registry
A model registry is the inventory of approved model versions: one immutable record per version, each linked to the run and artifact that produced it, plus a movable label saying which version is currently serving. It is the handoff point between experimentation and production.
The idea
A registry entry holds more than a file path:
- Identity — model name and a monotonically increasing version number.
- Provenance — the source run ID, which carries its commit and data hash.
- Artifact URI — where the weights actually live.
- Pointer — an alias such as
championorchallenger. - Contract — the input/output signature and example inputs.
- History — who promoted it, when, and on what metric.
Two operations matter:
- Register creates a new, immutable version from a logged run. It never overwrites; new code or data means a new version.
- Assign moves a label. Classic MLflow stages (
Staging,Production,Archived) are deprecated in favor of aliases, and serving code resolvesmodels:/churn@championrather than a version number.
Why not "the newest file in S3"? Because serving must resolve a specific version, roll back in seconds, and answer "who changed this and when?" A registry provides all three, plus the metric that justified the change.
Worked example
| Version | Run | Val AUC | Alias |
|---|---|---|---|
| 7 | a1f2c | 0.81 | archived |
| 8 | b23d1 | 0.84 | champion |
| 9 | c90e7 | 0.83 | challenger |
Version 9 trained on newer data and scored slightly lower. The serving deployment still asks for models:/churn@champion, so it keeps answering with version 8 with no redeploy.
Promotion is one call: move champion to 9. Rollback is the same call aimed at 8. Neither touches the container image, which is why the registry decouples model release from code release. Version 9 stays available as challenger for a canary comparison.
In code
import mlflow
from mlflow import MlflowClient
client = MlflowClient()
mv = mlflow.register_model("runs:/b23d1/model", "churn") # creates version 8
client.set_registered_model_alias("churn", "champion", mv.version)
client.set_model_version_tag("churn", mv.version, "approved_by", "risk-review")
client.transition_model_version_stage # legacy stage API; aliases are preferred("churn", mv.version, "Production")Tagging the approval is what makes an audit possible later. The metric is in the run; the decision is in the registry.
Check yourself
- Why should serving code resolve an alias instead of a hardcoded version number?
- What belongs in a registry entry beyond the artifact URI?
- How do aliases make rollback cheaper than rebuilding and redeploying?
Key takeaways
- A registry is immutable versions plus a movable pointer to the approved one.
- Register from a tracked run; never mutate an existing version.
- Aliases decouple promotion from deployment and make rollback a single call.