ModernCS
Session 1.190 minFree preview

What MLOps Actually Owns

The boundary: the engineering around a model, not the model, and who gets paged when it rots.

By the end of this session you will be able to:

  • Draw the line between model work and platform work for a real deployed model, and name the artifacts on your side of it
  • Sort any "the model is broken" report into one of four failure classes, each with a different owner and a different fix
  • Write a one page ownership sheet for a live model and count the lines nobody owns

The model is the small box

A trained model is a file and a function signature. It takes a vector, it returns a number. That is the whole thing. In the 2015 paper Hidden Technical Debt in Machine Learning Systems, Sculley and colleagues drew a production ML system where the box labelled "ML code" is a small rectangle surrounded by much larger ones: data collection, feature extraction, configuration, serving infrastructure, monitoring. Eleven years later the tools have changed and the proportions have not.

MLOps owns the large boxes. Not the loss function, not the architecture, not the feature engineering ideas. You own whether a rerun of that loss on that data produces the same number six months from now, which version is answering requests, how you would know it stopped working, and how you would put the old one back.

Most job descriptions blur that line, so state it in one sentence: the modeling team decides what the model should learn, and you decide what is true about the model in production. When nobody holds the second half, the symptom is always the same. The model works. The notebook that made it is on someone's laptop, the person left in March, the container serving it was built from a branch that has since moved, and when the fraud rate jumps in July there is no honest answer to "what changed".

Four things people call "the model is broken"

When a page fires, or a product manager says the model got worse, you are looking at one of four things. They are not equally likely and they do not share an owner.

  1. Data. An upstream producer changed a column. A currency field switched from cents to dollars, a nullable field started arriving null, a join that returned one row now returns three. The model is fine. It is being fed something it never saw. Owner: the team producing that data, and the contract check that should have caught it.
  2. Feature or transform. The code computing inputs at training time is not the code computing them at serving time. One rounds, the other truncates. One sees a value the real request does not have yet. Owner: you. There is nothing a data scientist can do about this from a notebook.
  3. Infrastructure. Latency doubled, the pod is out of memory, the GPU driver moved under you, a deploy shipped a different image than the one that passed the gate. Owner: you, with whoever runs the cluster.
  4. Model logic. The world moved and the decision boundary is genuinely wrong now. Owner: the modeling team, and the fix is retraining or a different objective.

Only the fourth is a modeling problem, and in most systems it is the least common page. If every alert routes to the person who trained the model, you are waking a researcher at 2am to look at a container digest. Make the first triage step "which of these four is it", because the answer changes who you call and what you touch.

If you cannot tell classes 1, 2 and 3 apart from your logs in the first ten minutes, you do not have a monitoring problem yet. You have an ownership problem.

The lines you own

Each line below is an artifact or a fact that has to have a value, and each has a specific bad day attached when it does not.

  • The run record. Which code, which data, which config produced this file. Missing: every regression investigation starts from zero.
  • The data version. Not a copy of the data, a pointer to the state it was in. Missing: your rerun trains on a table that has since been backfilled, and scores half a point higher for no reason.
  • The environment. Lockfile and image digest. Missing: the rerun quietly uses a different numeric library and the outputs shift by an amount too small to notice and too large to ignore.
  • The identity of what is live. A digest or an immutable version, never a branch name or latest. Missing: you cannot say which model produced a given prediction.
  • The transform, defined once. Missing: class 2 above, permanently.
  • The prediction log. Input, model version, output, and a key the true label can be joined to later. Missing: you can never measure the model, only guess at it.
  • The rollback. A tested path back to the previous version that does not involve retraining. Missing: your worst incident lasts as long as a training run.

Each of those becomes a full session later in this course. Right now the point is that they are yours, and that a model with six of the seven unowned is not a deployed model, it is a demo receiving traffic.

A worked example: the ownership sheet

Write it down. One file, one model, no prose. Here is a fraud scorer, filled in honestly, so some lines say UNOWNED:

model: fraud-scorer
business_owner: risk-ops@example.com
oncall_rotation: ml-platform
 
what_is_live:
  registry_version: "models:/fraud-scorer/41"
  artifact_digest: "sha256:9f1c0a2b7e4d5a63c8f0b1d2e3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8"
  serving_since: "2026-07-19T14:02:00Z"
 
how_it_was_built:
  code_commit: "e3b0c44298fc1c149afbf4c8996fb924d9a7f210"
  data_snapshot: UNOWNED
  training_config: UNOWNED
  environment_digest: UNOWNED
 
how_it_is_watched:
  prediction_log: "s3://fraud-logs/predictions/"
  label_delay_days: 31
  performance_alert: UNOWNED
 
how_it_is_undone:
  rollback: "point the champion alias at version 40"
  rollback_last_tested: "2026-06-02"

Read that file as a forecast. Three UNOWNED lines under how_it_was_built mean that when someone asks why version 41 behaves differently from version 39, the answer takes a week of archaeology instead of a diff. performance_alert: UNOWNED next to a 31 day label delay means the model can be wrong for a month before anyone notices, and the one who notices will be a customer.

The value of the sheet is not the filled lines. It is that UNOWNED now sits where a hand wave used to be.

Try it

Pick one model running somewhere you can inspect: your team's, an internal service, or a serving endpoint in a repository you can read. Write its ownership.yaml using the sections above.

One rule: a line gets a value only if you can verify it yourself in under five minutes without asking another person. Everything else is UNOWNED. "I think it comes from the nightly job" is UNOWNED.

You are done when you can state two numbers: how many lines are unowned, and which single unowned line would have made your last ML incident shorter. Most first sheets land at four to seven unowned. If you got zero, you guessed on at least one, usually artifact_digest or rollback_last_tested.

Install what the next session needs while you are here:

pip install "mlflow==3.15.1"
mlflow --version

Common mistakes

  • Treating the notebook as the source of truth. It runs, so it feels finished. But a notebook records neither the data state nor the environment, and its cells ran in an order you no longer remember. Keep it for thinking, and point at the run record instead.
  • Routing every model alert to the person who trained the model. It looks like ownership. In practice it pages a researcher for infrastructure faults, and the real class 1 and class 3 owners never build the reflexes to catch their own failures.
  • Buying a platform before drawing the boundary. A tool cannot tell you who gets paged. Teams install a large ML platform, get all seven lines above as dashboard widgets, and still cannot say which version is live.
  • Confusing "the model is live" with "the model is owned". Traffic reaching an endpoint proves the network works. It says nothing about whether you can rebuild, measure, or reverse what is on the other end.

Where this goes next

The first unowned line on almost every sheet is the run record, so that is where the course starts building. In Tracking Runs in MLflow you turn "which code and config produced this file" into a queryable record: runs, params, metrics, artifacts, and the LoggedModel entity that ties a training run to the thing you deployed.

That was one session of 5 in this phase.

ML Platform and MLOps runs to 5 phases. Buy the whole course, or just the phase you need.