Skip to content
All posts

August 5, 2026 · 9 min

Shipping ML Products, Not Just Models

BurnoutCompass AI started as a Kaggle dataset and ended as a deployed product: a React frontend, a FastAPI backend, and an ensemble of Random Forest, Gradient Boosting, and a stacking meta-learner hitting 98.5% accuracy. The accuracy number is the least interesting thing about it. What I learned was everything that happens around the model.

The gap between notebook and product

The model was the easy 20%. The other 80% was everything around it: input validation with Pydantic, a clean /predict contract returning {burnout_level, label}, CORS, deployment, and a UI that explains the prediction instead of just showing a number.

None of that work shows up in a Kaggle notebook. A notebook has one caller: you, with clean data you already trust. A product has strangers sending malformed JSON, missing fields, and values in ranges you never saw in training. Every one of those is an error message you have to write.

Design the contract before training

The single best decision I made was writing the API contract first. POST /predict takes specific fields with specific ranges; it returns burnout_level and a human-readable label. Once that existed, the training pipeline had a target: the preprocessing had to survive serialization, the features had to be computable from the request payload, and the outputs had to map onto the contract.

Most ML failure I've seen comes from doing it the other way — a model gets trained on features that turn out to be impossible to compute at request time, and the whole serving layer becomes a pile of hacks.

The preprocessing travels with the model

A model artifact without its preprocessing is a broken promise. Scalers, encoders and imputers are part of the model. I ship them as one pipeline object, versioned together, so the thing that serves predictions is byte-identical to the thing that produced the validation metrics. If they diverge — even silently, even slightly — your metrics are fiction.

Explain, don't just predict

A burnout score with no context is a number a user can't act on. The UI shows the contributing factors behind each prediction, because the product's job is to start a conversation, not to grade people. This changed the frontend work too: instead of a form plus a result, it became a guided flow that makes the input space feel finite and fair.

What I'd tell my earlier self

Ship early. A simple deployed model teaches you more than a perfect local one, because deployment is where the real requirements surface — latency, input weirdness, error handling, the wording of failure states. The notebook gets you the model. The product gets you the judgment.

thanks for reading — more soon ✦

keep reading

M

drawing ideas into systems...