TL;DR: Register the candidate (immutable version with lineage), validate via gate suite recorded as tags, expose as
@challengerfor shadow or canary, then flip@championto the new version (an atomic, recorded alias reassignment), keeping the old version warm for one-reassignment rollback. Aliases replaced the deprecated fixed Staging/Production stages; using them, and saying why, is the screening point.
How to approach it
A walkthrough question where the structure is the answer: register → validate → expose safely → flip the pointer → keep the escape hatch. There's also a currency check embedded in it, MLflow deprecated fixed stages in favor of aliases, and interviewers on the Databricks stack listen for which vocabulary you use. Use aliases, and say why they won.
A strong answer
Start from a training run that produced a candidate. Promotion then looks like this:
Steps 6 and 7 are the same operation pointed in opposite directions, which is the property worth saying out loud: if promotion is an alias move, then rollback is too.
The flip and the rollback are the same cheap operation in opposite directions, which is the entire argument for aliases.
Register. mlflow.register_model on the run's artifact creates version N under the registered name. The version carries lineage automatically, run, parameters, metrics, code commit, and you attach tags for anything gating needs (eval-suite scores, data snapshot ID). The artifact is now immutable; everything after this is metadata and routing.
Validate. Registration fires a webhook (or a CD job polls) that runs the gate suite: challenger-versus-champion evaluation on the fixed holdout and a recent time slice, segment-level checks, serving-container golden tests, latency budget. Results land as tags on the version, so the evidence is attached to the thing being promoted. For regulated models, a human approval is recorded here too.
Expose as challenger. Set the @challenger alias to version N. Serving infrastructure resolves models:/fraud@challenger for shadow traffic or a small canary slice, real payloads, no or limited real decisions, one to two weeks of soak depending on traffic volume.
Flip. Reassign @champion to version N: client.set_registered_model_alias("fraud", "champion", N). Anything loading models:/fraud@champion, a KServe InferenceService, a Databricks Model Serving endpoint, a batch scorer, picks up the new version on next resolution or via the deployment job the alias-change event triggers. The flip is atomic and recorded: who, when, which version.
Keep the escape hatch. The old version stays deployed and warm. Rollback is the same alias reassignment pointing backwards, which is the entire argument for this pattern: promotion and rollback are the same cheap operation.
"Results land as tags" is abstract until you look at what a gated version's metadata actually holds, so here is the shape after a full gate run:
name: fraud version: 14 status: READY
tags:
eval_auc_holdout: 0.861 (champion: 0.864, within 0.5pt gate)
eval_auc_recent_slice: 0.858
segment_enterprise_auc: 0.881 (delta vs champion: -0.2pt, floor -0.5)
container_p99_ms: 41 (budget 80)
parity_max_diff: 3.1e-9 (train-vs-serve, tolerance 1e-6)
data_snapshot: delta_v1142
gates_passed_at: 2026-08-12T09:41Z by ci/model-cd
approved_by: j.alvarez (model risk)
aliases: @challenger
Every number a promotion decision depended on is welded to the version it justified, timestamped, and attributed. When someone asks in November why version 14 was allowed out, nobody excavates a CI log that rotated away in September; the version answers for itself. That is what "evidence attached to the thing being promoted" buys, and it is also the practical answer to where approvals went when stages disappeared.
Why aliases beat the old Staging/Production stages, worth thirty seconds because it's the screening point: stages were a fixed, global vocabulary that conflated registry state with deployment environments, allowed only one model per stage semantics awkwardly, and made every org bend its workflow to four hardcoded names. Aliases are arbitrary named pointers, @champion, @challenger, @shadow, one per serving context if you like, mutable, atomic, and decoupled from environments. Tags carry the workflow state (validation passed, approved-by) that stages used to smuggle.
One detail that reliably impresses: alias reassignment on a production model is a privileged operation, so it belongs to the CD pipeline's service principal, not to humans, registry ACLs are part of the promotion design, not an afterthought.
What interviewers probe next
- "What if validation passes but shadow looks wrong?", the gates are necessary, not sufficient; shadow disagreement analysis can veto promotion, and the version just never gets the champion alias. Tags record why.
- "How do batch consumers get the new model?", they resolve
@championat job start, which means a long-running batch job is pinned to one version for its whole run, consistent scoring within a job, by construction. - "Multiple environments, dev, staging, prod registries?", on Databricks Unity Catalog, one model per environment catalog with promotion copying versions across; aliases operate within each. Cross-workspace promotion is a CI job, not a manual export.
- "Where do approvals live now that stages are gone?", tags plus webhook-gated transitions, or the platform's built-in approval flow; the audit trail is the version's activity log.
Common mistakes
Narrating the deprecated stage-transition flow as current practice, the single most common dating error on this question. Promoting via UI clicks with no CI involvement, which means no recorded evidence. Tearing down the old version at flip time. And skipping the challenger/shadow step entirely, which turns "promotion" into "deploying an offline-validated model straight to 100% of traffic", the thing this whole machinery exists to prevent.
