Model Deployment
Take a trained model out of the notebook and turn it into a service real users can call — save it, wrap it in an API, validate every input, containerise it, and keep watch once it is live.
Learn Model Deployment in our free AI & Machine Learning course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a…
Part of the free AI & Machine Learning course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Training a model is like building one perfect prototype in your workshop. It works on your bench, with your tools, in your hands. Deployment is everything that happens after — getting that product into the hands of thousands of customers, reliably, every day.
Around 80% of ML projects never reach customers. The model is the prototype; this lesson is the shop, the crate, and the quality control.
A trained model lives in memory. The moment Python exits, it's gone. Serialising means writing the model to a file so a completely separate program — your API server — can load it back later.
Critically, you save more than the weights. You also save the preprocessing recipe (feature order, scaling means and stds, encoders) so serving can repeat it exactly. Run the worked example below, then read the comments about which format to use when.
Other programs can't import your Python model directly. A REST API is a shop counter: a client sends a small JSON order over HTTP, your service runs the model, and hands a JSON prediction back.
FastAPI is the modern Python choice (Flask is the older, simpler alternative). With FastAPI you declare the expected input as a class and it validates every request for you — a missing field or wrong type is rejected automatically before your code runs. Note the two rules below.
Study the real serving shape (this is read-only — you'll write runnable plain Python just below):
Two failures sink more deployments than bad models. First, no input validation — a missing or negative field crashes your service. Second, train/serve skew — the model was trained on scaled features, but serving forgot to scale them the same way, so every prediction is quietly wrong.
The fix for both: validate first, then run the exact same preprocessing you used in training (same feature order, same scaling, same encoders). In the exercise below you'll write a predict() that validates the request and standardises each feature with the saved means and stds before scoring.
"It works on my machine" is the classic deployment failure — a library version differs in the cloud and the service breaks. A Docker container is a sealed shipping crate that freezes the OS, the Python version, and every dependency, so the service runs identically everywhere.
You pin your dependencies in a requirements.txt , copy them and your code into an image, and run it anywhere. Copying dependencies before the code lets Docker cache that slow step.
The same model can be served three ways — only the wrapper around it changes. Pick the one that matches how predictions are consumed.
In the next exercise you'll take the same scoring logic and run it over a whole batch of houses instead of one request.
Shipping once is easy; shipping safely over and over is the job. CI/CD (Continuous Integration / Continuous Delivery) is an automated pipeline — a tool like GitHub Actions runs your tests, builds the Docker image, and deploys it whenever you push a new model. No manual steps means fewer human mistakes.
Once live, monitoring takes over. A model trained on yesterday's data slowly goes stale as the world changes — this is data drift . You can't see it from the code, only from the metrics. Track these and alert when they cross a threshold, then retrain.
Common tools: GitHub Actions / MLflow / DVC for CI/CD, and Prometheus + Grafana / Evidently for monitoring. Start simple — wire these in only once you have real traffic.
These five mistakes break far more deployments than poorly-tuned models. Learn to spot each one.
❌ Train/serve skew — predictions silently wrong
You scaled features during training but serve raw values, so the maths no longer lines up:
✅ Fix: reuse the saved means/stds at serve time:
A request missing a field throws and takes down the worker:
Overwriting model.joblib with no version means a bad model can't be undone and you can't tell which one made a prediction.
❌ Blocking inference — API freezes under load
Loading the model (or training!) inside the handler makes every request slow:
✅ Fix: load once at startup, reuse the object:
❌ Missing dependencies — ModuleNotFoundError in production
It runs locally but the server lacks a library:
✅ Fix: pin every dep and bake it into the container:
Time to fly with the support faded. Build a small prediction function from the brief in the comments — it must validate its input, run the model, and return a versioned result. Check your output against the expected lines.
Lesson 14 complete — your model is in production!
You can serialise a model, serve it through a validated REST API, keep training and serving in lockstep to avoid skew, seal it in a Docker container, choose batch vs real-time vs edge, and hand off to CI/CD and monitoring. That's the full journey from workshop to customer.
🚀 Up next: Unsupervised Learning — find hidden patterns in unlabelled data, no targets required.
Practice quiz
What does it mean to serialise a model?
- Delete its weights
- Train it for more epochs
- Write it to a file so a separate program can load it later
- Convert it to an image
Answer: Write it to a file so a separate program can load it later. A trained model lives in memory; serialising writes it to disk so your API server can load it back.
Which format is recommended for saving scikit-learn models?
- joblib
- JPEG
- CSV
- HTML
Answer: joblib. joblib handles large NumPy arrays efficiently, making it the go-to for scikit-learn models.
What is train/serve skew?
- Training on a GPU but serving on a CPU
- A model that is too large
- Serving from the wrong country
- Data processed differently during training vs serving, making predictions silently wrong
Answer: Data processed differently during training vs serving, making predictions silently wrong. If preprocessing (scaling, encoding, feature order) differs between training and serving, predictions go quietly wrong.
How do you avoid train/serve skew?
- Retrain on every request
- Save the preprocessing parameters with the model and reuse the identical code path at serve time
- Skip preprocessing at serve time
- Use a larger model
Answer: Save the preprocessing parameters with the model and reuse the identical code path at serve time. Store means, stds, encoders, and feature order alongside the model and apply the exact same steps when serving.
Where should you load the model in a REST API service?
- Once at startup, then reuse the object
- Inside every request handler
- Never load it
- Only when an error occurs
Answer: Once at startup, then reuse the object. Loading the model once at startup keeps requests fast; loading it per request makes every call slow.
What is the purpose of input validation in a prediction endpoint?
- To speed up training
- To compress the model
- To reject bad or missing input cleanly instead of crashing
- To increase accuracy
Answer: To reject bad or missing input cleanly instead of crashing. Validating first lets you return a clean 400 error for missing/invalid fields rather than crashing the worker.
What problem does packaging a service in a Docker container solve?
- It makes the model more accurate
- It freezes the OS, Python version, and dependencies so it runs identically everywhere
- It removes the need for a model
- It trains the model faster
Answer: It freezes the OS, Python version, and dependencies so it runs identically everywhere. A container seals the environment, eliminating 'it works on my machine' and missing-dependency failures.
Real-time (online) inference is best described as:
- Scoring thousands of rows on a nightly schedule
- Running on a phone with no network
- Training the model continuously
- Answering a single request as fast as possible behind an API
Answer: Answering a single request as fast as possible behind an API. Real-time inference serves one request with low latency, e.g. a price shown the instant a user clicks.
What is data drift?
- The model file getting corrupted
- Real-world input distributions changing over time so a model goes stale
- The learning rate decaying
- The server losing network
Answer: Real-world input distributions changing over time so a model goes stale. A model trained on yesterday's data degrades as the world changes; monitoring catches drift so you can retrain.
Why store a version string with each saved model?
- It improves accuracy
- It is required to load the file
- So you can tell which model made a prediction and roll back a bad one
- It compresses the weights
Answer: So you can tell which model made a prediction and roll back a bad one. Versioning lets you identify and roll back models; returning the version with each prediction aids debugging.