Originally published at mlopslab.org — updated weekly. 0 sponsors, 0 affiliate links.
⚡ The problem in one sentence: Your model shipped and worked great on day one. Now, weeks later, it's making worse decisions — silently, without throwing a single error. Drift detection is how you catch this before the damage is done.
Table of Contents
- What is model drift detection?
- Three types of drift you must monitor
- Why it matters in production
- Statistical methods for drift detection
- Tools comparison
- Step-by-step tutorial with Evidently AI
- When drift is detected — what to do
- FAQ
1. What is model drift detection?
Model drift detection is the practice of monitoring ML models in production to identify when they start degrading due to changes in real-world data.
Without it, a model that worked perfectly at deployment starts making worse predictions — often silently, without any errors or alerts. This is the #1 reason ML projects fail in production. By the time you notice the problem, you've already lost revenue, damaged user trust, or made critical bad decisions based on stale model outputs.
📉 The silent killer: Most teams only discover drift when a stakeholder complains. By then, the model has been wrong for weeks — sometimes months. A drift detection system would have flagged this on day one.
2. Three types of drift you must monitor
There are three distinct failure modes, and they require different detection strategies.
Data drift
Input feature distributions change over time. Your model encounters data it was never trained on. This is the most common type and the easiest to detect — you're comparing distributions, not outcomes.
Example: A fraud detection model trained on 2024 transaction patterns encounters completely different spending behavior in 2026. Feature distributions shift, and accuracy silently collapses.
Concept drift
The relationship between inputs and outputs changes. What the model learned is no longer valid in the current world — even if the input data looks similar, the correct answer has changed.
Example: A house price model trained pre-COVID fails badly after remote work permanently shifts housing demand dynamics. The features are the same; the world has changed.
Prediction drift
The distribution of model outputs shifts over time — even before you can measure accuracy. This is a leading indicator that something upstream has changed and is often the earliest signal you'll get.
Example: A recommendation model starts surfacing entirely different categories as user behavior shifts after a product redesign.
⚠️ The hard truth: These three types compound each other. Data drift often causes concept drift, which then shows up as prediction drift. Monitor all three.
3. Why it matters in production
The business impact of undetected drift breaks down into three categories:
Revenue loss — Bad recommendations, wrong pricing, and failed fraud detection translate directly to lost money. A single undetected fraud spike or pricing error can cost more than an entire year of monitoring infrastructure.
User trust — Users notice when your model is wrong before you do. Once trust is damaged it's extremely hard to recover.
Compliance — In regulated industries like finance and healthcare, model monitoring isn't optional. It's legally required. Unmonitored model degradation is an audit finding.
✅ Business case: One properly implemented drift detection system can save months of debugging time and prevent millions in revenue loss. The ROI justifies itself on the first incident it catches.
4. Statistical methods for drift detection
Three methods cover the vast majority of production use cases:
PSI — Population Stability Index
The most widely used metric in production drift detection. PSI measures how much a distribution has shifted between a reference (training) sample and a current (production) sample.
| PSI value | Interpretation | Action |
|---|---|---|
| < 0.1 | Stable | None required |
| 0.1 – 0.25 | Moderate shift | Investigate |
| > 0.25 | Major shift | Retrain |
PSI is fast to compute and easy to explain to non-technical stakeholders, which is why it's the default choice for most teams.
KS Test — Kolmogorov-Smirnov
A non-parametric statistical test that compares two distributions and returns a p-value. Low p-value (< 0.05) signals that the distributions are statistically different. More rigorous than PSI, better for smaller sample sizes.
Distribution plots
Visual comparison of feature distributions over time. Look for shifts in mean, variance, shape changes, or the appearance of new modes. Essential for communicating drift results to stakeholders and debugging which features are causing the problem.
Rule of thumb: If any feature's distribution changes by more than 15–20%, investigate immediately. Don't wait for accuracy to drop.
5. Tools comparison
| Tool | Type | Best for |
|---|---|---|
| Evidently AI | Open source | Self-hosted drift reports, full customization |
| WhyLabs | SaaS (free tier) | Teams without dedicated ML infra |
| Prometheus + Grafana | Infrastructure | Drift as time-series metrics, custom alerting |
| MLflow | Open source | Teams already using MLflow for experiment tracking |
This tutorial uses Evidently AI — it's free, self-hosted, runs as a pip install, and produces detailed HTML reports with PSI and KS tests across all features automatically.
6. Step-by-step tutorial with Evidently AI
⏱ ~30 minutes end-to-end
The setup assumes you have a FastAPI model serving endpoint already running. If not, the logging and detection steps still apply — just swap the FastAPI parts for however you're serving predictions.
Step 1 — Install Evidently
pip install evidently
Step 2 — Log predictions from your FastAPI endpoint
Add prediction logging to your /predict endpoint. Every prediction gets stored to a JSONL file for later drift analysis.
# Add this to your FastAPI /predict endpoint
import json
from datetime import datetime
def log_prediction(features: dict, prediction: int, probability: float):
log_entry = {
"timestamp": datetime.utcnow().isoformat(),
"features": features,
"prediction": prediction,
"probability": probability
}
with open("predictions.jsonl", "a") as f:
f.write(json.dumps(log_entry) + "\n")
Call log_prediction() inside your endpoint every time you serve a result. The JSONL format appends one JSON object per line — it's cheap, crash-safe, and trivial to read back.
Step 3 — Load your reference (training) distribution
import pandas as pd
from evidently import ColumnMapping
# Load the same data the model was trained on
reference_data = pd.read_csv("data/training_features.csv")
reference_data["prediction"] = training_predictions
reference_data["probability"] = training_probabilities
This is your ground truth — the distribution your model expects to see. Evidently will compare everything in production against this.
Step 4 — Run the drift detection report
Evidently's DataDriftPreset automatically runs PSI and KS tests across all features and produces a visual HTML report.
from evidently.report import Report
from evidently.metric_preset import DataDriftPreset
# Load recent production predictions
current_data = pd.read_json("predictions.jsonl", lines=True)
# Run the report
data_drift_report = Report(metrics=[DataDriftPreset()])
data_drift_report.run(
reference_data=reference_data,
current_data=current_data
)
# Save as HTML
data_drift_report.save_html("drift_report.html")
Open drift_report.html in your browser. Evidently shows a per-feature breakdown with drift scores, p-values, and distribution overlay plots for every feature in your dataset.
Step 5 — Configure alerts (Slack / PagerDuty)
Don't just generate reports — trigger alerts automatically. The report is useful for debugging, but you need push notifications so your team is alerted the moment drift appears.
from evidently.metrics import DatasetDriftMetric
drift_metric = DatasetDriftMetric()
drift_metric.reference = reference_data
drift_metric.current = current_data
if drift_metric.get_result().drift_detected:
print("⚠ DRIFT DETECTED — investigate immediately")
import requests
requests.post(
"https://hooks.slack.com/services/YOUR_WEBHOOK",
json={"text": "🚨 Model drift detected in production! Check drift_report.html"}
)
Replace the Slack webhook with PagerDuty, email, or any HTTP webhook your team uses.
Step 6 — Automate with cron or Airflow
Drift detection should run on a schedule, not manually. For simplicity, add it to cron:
# Run drift detection every day at 9:00 AM
# Add with: crontab -e
0 9 * * * python3 /opt/ml/drift_detection.py
For teams that need retry logic, backfill, or alerting on the pipeline itself, wrap the detection script in an Airflow DAG instead.
💡 Pro tip on frequency: Run detection daily for revenue-critical models, weekly for lower-stakes ones. The cost of a single missed drift event vastly outweighs the cost of running scheduled checks.
7. When drift is detected — what to do
Detection is only half the job. Here's the response workflow:
1. Identify the drifting features. Open the Evidently report and look at which specific features are flagged. Sort by drift score descending. One or two features causing the problem is common — it narrows your investigation significantly.
2. Diagnose the root cause. Is it seasonal? A data pipeline bug? A real-world behavioral shift? Drift detection tells you what changed, not why. You still need to investigate upstream — check your data pipeline, talk to the product team, look at recent product changes.
3. Trigger retraining if drift is confirmed. If the drift is real and significant, retrain on newer labeled data. Don't retrain blindly — confirm you have sufficient new labeled data first. Retraining on insufficient data can make performance worse.
4. Recalibrate your thresholds. Update your alert thresholds based on what you learned. Some drift is acceptable for your use case (seasonal variation, for example). Tune PSI/KS thresholds to minimize false alarms without missing real incidents.
5. Document the incident. Add it to your model's changelog. Include what drifted, what the root cause was, and how you resolved it. This becomes your team's institutional knowledge for the next incident.
🔁 Retraining strategy: Don't retrain reflexively every time an alert fires. Only retrain when drift is confirmed AND you have sufficient new labeled data. Premature retraining on noisy data is a common mistake that creates more instability.
8. FAQ
How is drift detection different from just monitoring accuracy?
Accuracy monitoring requires labeled ground-truth data, which is often delayed or unavailable in real time. Drift detection works on inputs alone — you can catch problems the moment production data starts diverging from training data, before any labels are needed. Think of drift detection as an early warning system and accuracy monitoring as confirmation.
How much production data do I need before running drift detection?
For PSI to be statistically meaningful, you generally want at least 500–1,000 recent predictions as your "current" window. With smaller samples, KS test tends to be more reliable. Start collecting logs from day one, even if you don't run reports immediately.
What if my model has hundreds of features?
Evidently handles this automatically — it runs tests per feature and aggregates them into a dataset-level drift score. In practice, flag features with PSI > 0.25 or KS p-value < 0.05, then focus your investigation on the top 5–10 by drift score. Feature importance can also help prioritize which drifting features actually affect model output.
Can I use this approach for LLMs or generative models?
The statistical methods in this tutorial (PSI, KS test) work on structured tabular data. For LLMs, drift detection looks different — you'd monitor prompt distribution shifts, output length changes, semantic similarity between batches, or task-specific evaluation metrics. See LLM Observability: The ML Engineer's Practical Guide for that use case.
Does retraining always fix drift?
Not always. If the drift is caused by a data pipeline bug, retraining on corrupted data makes things worse. If it's concept drift (the world changed), you need new labeled data that reflects the new reality — retraining on old data does nothing. Always diagnose before retraining.
Conclusion
Model drift is not an edge case — it's the default outcome for any model in production long enough. The question isn't whether your model will drift, it's whether you'll find out before your users do.
The minimum viable setup:
- Log every prediction → run Evidently daily → alert on
drift_detected=True
That combination, running on a cron schedule, gives you complete coverage with maybe a day of implementation work.
🔗 Next step: Add
log_prediction()to your serving code today. Even if you don't set up Evidently yet, having the logs means you can run drift analysis retroactively. The habit of logging is the foundation.
Related articles on MLOpsLab
- MLflow Tutorial: Track ML Experiments Like a Pro (2026)
- Kubeflow vs Airflow: Which Pipeline Tool Should You Use for ML?
- ML Pipeline Tutorial: Build Your First Production ML Pipeline (2026)
- MLOps Roadmap 2026: How to Become an ML Engineer Step by Step
- LLM Observability: The ML Engineer's Practical Guide (2026)
References
- Evidently AI Documentation. https://docs.evidentlyai.com
- Gama, J., et al. (2014). A Survey on Concept Drift Adaptation. ACM Computing Surveys, 46(4). https://doi.org/10.1145/2523813
- FastAPI Documentation. https://fastapi.tiangolo.com
Written by Ayub Shah — ML Engineering student, MLOps enthusiast. Testing every tool so you don't have to. No sponsors, no affiliate links.
→ More at mlopslab.org
Top comments (0)