You trained a model. It’s good. Now what? You need a place to store it, track which version is running in production, and swap versions without redeploying your entire stack. MLflow Model Registry handles all of this – versioning, aliasing, metadata tagging, and serving – through a Python API and CLI that work with any ML framework.
This guide covers the full workflow: logging a model, registering it, assigning aliases like champion and challenger, loading specific versions for inference, and spinning up a REST endpoint with one command.
Set Up MLflow Tracking
Before you register anything, you need an MLflow tracking server. For local development, a SQLite-backed server works fine.
| |
Point your client at it:
| |
If you skip this, MLflow writes to a local mlruns/ directory. That works for experimentation but breaks down fast when multiple people need access to the same models.
Train and Register a Model
The fastest path is to register the model in the same call that logs it. Pass registered_model_name to log_model() and MLflow creates the registered model (if it doesn’t exist) and adds a new version automatically.
| |
Every subsequent call with the same registered_model_name increments the version number. Version 1, version 2, version 3 – each tied to a specific run with its own parameters, metrics, and artifacts.
If you already logged a model and want to register it after the fact, use mlflow.register_model() with the run URI:
| |
Assign Aliases Instead of Stages
MLflow used to have a stage system – Staging, Production, Archive. That’s deprecated since MLflow 2.9. Use aliases instead. They’re more flexible: you can assign multiple aliases to a single version, name them whatever you want, and reassign them without any state machine constraints.
| |
The @alias syntax works in model URIs, so your deployment code never needs to change version numbers:
| |
This is the key advantage over hardcoded version numbers. Your serving infrastructure points at @champion. When you promote a new version, you update the alias and the next request picks up the new model. No redeploy needed.
Tag Versions with Metadata
Tags let you attach arbitrary key-value metadata to registered models and individual versions. Use them to track validation status, training datasets, or approval workflows.
| |
Serve a Model as a REST API
MLflow can serve any registered model as a REST endpoint with a single CLI command. It builds a virtual environment with pinned dependencies and exposes a /invocations endpoint.
| |
The --no-conda flag skips creating a conda environment and uses your current Python environment. Drop it if you want full environment isolation.
Test it with curl:
| |
The response comes back as a JSON array of predictions. Use dataframe_split format – it preserves column ordering, unlike dataframe_records.
Search and Compare Versions
When you have dozens of versions, you need to search and filter them programmatically.
| |
The copy_model_version call is useful when you run separate MLflow instances for staging and production. It copies the model artifact and metadata to a different registered model name, which can live on a different tracking server.
Common Errors and Fixes
RESOURCE_DOES_NOT_EXIST when loading a model:
| |
This means the model name doesn’t exist in the registry. Check for typos. Model names are case-sensitive. You can verify with client.search_registered_models().
Model registry functionality is unavailable:
| |
You’re running MLflow without a proper backend store. The file-based default (mlruns/) supports the registry, but you need to specify it explicitly. Start the server with --backend-store-uri sqlite:///mlflow.db or point to a PostgreSQL/MySQL instance.
RESOURCE_ALREADY_EXISTS on experiment creation:
| |
This happens when you call mlflow.create_experiment() for an experiment that already exists. Use mlflow.set_experiment() instead – it creates the experiment if missing and sets it as active if it exists.
Version not found after registering:
If register_model() returns successfully but get_model_version() fails immediately after, it’s a race condition with the backend store. Add a short retry loop or check the version status:
| |
Putting It All Together
A realistic workflow looks like this: train a model in an experiment, register it, tag the version with metadata, run validation, assign the champion alias, and serve it. When a better model comes along, register a new version, alias it as challenger, run an A/B test, and swap the champion alias over. Your serving code never changes – it always loads @champion. The registry keeps a complete history of every version, who promoted it, and what metrics it achieved.
That’s the core MLflow Model Registry loop. It’s not fancy, but it solves the “which model is running in production right now?” problem without building custom infrastructure.
Related Guides
- How to Build a Model Metadata Store with SQLite and FastAPI
- How to Implement Canary Deployments for ML Models
- How to Build a Model Configuration Management Pipeline with Hydra
- How to Build a Model Dependency Scanner and Vulnerability Checker
- How to Build a Model Feature Store Pipeline with Redis and FastAPI
- How to Build a Model Versioning Pipeline with DVC and S3
- How to Build a Model Input Validation Pipeline with Pydantic and FastAPI
- How to Set Up CI/CD for Machine Learning Models with GitHub Actions
- How to Build a Model Rollback Pipeline with Health Checks
- How to Build a Model Serving Pipeline with Ray Serve and FastAPI