# Model Registry, Versions and Aliases — MLOps

Source: https://www.skillbyai.com/en/mlops/g-registry

> One place that says which model is live.

## Versions and pointers

A **model registry** stores named models with numbered **versions**, each linked to the run that produced it. Production code should not load a file path; it loads a **reference** such as an alias (champion, challenger) or a stage that the registry resolves to a version. Promoting or rolling back then means moving the alias, not redeploying code. Record who promoted which version and why, and require evaluation evidence before promotion.

## Version, test, gate

A registry tracks model versions and their status; CI tests code, data and models before promotion.

![Three ideas: registry, ML tests, evaluation gate.](assets/figures/mlops/section-4-map.svg) — Figure 4.1 — Registry, tests and gate.

## Registering versions and loading by alias, run

I ran this with Python 3, MLflow 3.16.1, scikit-learn 1.9.1, scipy 1.18.1 and numpy 2.5.3, using bundled or seeded synthetic data and a local SQLite tracking store. Two logistic regression runs register versions 1 and 2 of cancer-clf in a local MLflow registry. The champion alias is pointed at version 2 and the model is loaded through models:/cancer-clf@champion to make a prediction.

```python
import os, tempfile, logging, warnings
os.environ["MLFLOW_DISABLE_AGENT_HINT"] = "1"; logging.getLogger("mlflow").setLevel(logging.ERROR); warnings.filterwarnings("ignore")
import mlflow
from mlflow import MlflowClient
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
d = tempfile.mkdtemp()
mlflow.set_tracking_uri("sqlite:///" + os.path.join(d, "mlflow.db"))
mlflow.set_experiment("cancer-classifier")
X, y = load_breast_cancer(return_X_y=True)
for c in [0.01, 1.0]:
    with mlflow.start_run():
        model = make_pipeline(StandardScaler(), LogisticRegression(C=c)).fit(X, y)
        mlflow.sklearn.log_model(model, name="model", registered_model_name="cancer-clf", input_example=X[:2])
client = MlflowClient()
versions = sorted(int(v.version) for v in client.search_model_versions("name='cancer-clf'"))
print("registered versions:", versions)
client.set_registered_model_alias("cancer-clf", "champion", "2")
champion = mlflow.sklearn.load_model("models:/cancer-clf@champion")
print("champion alias ->", client.get_model_version_by_alias("cancer-clf", "champion").version)
print("prediction for first row:", champion.predict(X[:1]).tolist())
```

Output:

```
registered versions: [1, 2]
champion alias -> 2
prediction for first row: [0]
```

## Roll back by moving the alias

Keep the previous champion version available; rollback should be a one-line alias change.

**Quiz:** Why load production models by alias rather than a file path?

- [x] Promotion and rollback become pointer changes without code changes
- [ ] Aliases make models more accurate
- [ ] File paths are illegal
- [ ] Aliases compress the model

*Answer:* Promotion and rollback become pointer changes without code changes. The registry decides which version is live.
