Data drift vs concept drift vs model drift: how to detect each
Data drift, often called covariate shift, is a change in the inputs a model receives; concept drift is a change in the relationship between those inputs and the correct output; model drift is the umbrella term for the fall in performance either one causes. Detect data drift by comparing live input and prediction distributions with a training baseline, and concept drift by measuring accuracy against real outcomes, using proxies such as confidence, unknown rate and fallback rate until labels arrive. The fix depends on the cause: retrain on fresh data, repair the pipeline, or update the rules around the model.
Data drift, concept drift and model drift defined
Drift is any change in the world that makes the training data a worse description of production. Terminology varies between vendors and glossaries, so this guide uses the definitions most machine learning literature uses, with x as the input and y as the correct output.
The distinction matters because the responses differ. Harmful data drift is usually fixed by retraining on newer data. Concept drift means the right answers have changed, which needs new labels, or only an update to the rules around the model if that is where the change lives. Model drift is the symptom you notice first; the others are its causes.
| Term | What changes | Example | Visible without labels? |
|---|---|---|---|
| Data drift (covariate shift) | The input distribution, P(x); the mapping from input to answer stays the same | Users of a waste-sorting app start photographing items outdoors, in poor light, on new phones | Yes |
| Concept drift | The relationship between input and correct output, P(y | x) | Recycling rules change, so the same item now belongs in a different bin; fraudsters change tactics | Rarely; it needs outcomes or labels |
| Label drift (prior shift) | The mix of outcomes, P(y) | The share of fraudulent transactions rises sharply | Partly, through the predicted class mix |
| Model drift (model decay) | The model's performance, whatever the cause | Accuracy slides a little each month as behaviour slowly changes | Only through proxies |
Rule out pipeline bugs before calling it drift
Check the data pipeline first, because many failures that look like drift are bugs. The model is unchanged, but a feature pipeline has changed, a source table now means something different, an event stream is dropping records, a timestamp is handled in the wrong timezone, or an upstream service has quietly changed a field's format.
Training-serving skew is the classic case: a feature is computed one way in training and another in production, such as a ‘last 30 days’ window anchored to the wrong clock or missing values filled differently online. It looks like drift, but retraining will not fix it. The cure is shared feature definitions and point-in-time correct training data.
So monitor the data path as seriously as the model: null rates, category distributions, fields that stop arriving and feature freshness. These checks are cheap, and they catch the problems that are quickest to fix.
What to monitor for drift
Watch signals at the input, the model, the logic around it and the outcome, because each catches a different change. Simple signals are enough to start. None proves the model is wrong; each shows that behaviour has changed.
| Signal | What a change usually means |
|---|---|
| Input feature distributions, null rates, new categories | Data drift, or an upstream pipeline change |
| Average confidence score falling | Inputs moving away from the training data |
| Rate of unknown or low-confidence predictions rising | New kinds of input the label set does not cover |
| Predicted class distribution shifting | Users sending different things, or a change in the outcome mix |
| Fallback rate and external model calls rising | The main model or the rules cover less; cost will follow |
| Cost per request rising with flat traffic | Behaviour has changed somewhere in the decision path |
| Accuracy on recently labelled data falling | Concept drift or decay; the only direct measure |
| User overrides, corrections and follow-up questions rising | Answers are less useful, even if nothing else moved |
How to detect drift when labels arrive late or never
Monitor proxies continuously and measure real accuracy whenever ground truth arrives. Input distributions, confidence, unknown rate and fallback rate need no labels, so they give early warning, but they cannot prove the model is still right.
That is the main blind spot: concept drift can leave the inputs looking exactly as before. If fraudsters change tactics, the transactions can look normal while the right answer for them has changed. Only outcomes reveal it, so build the label path on purpose.
- Join predictions to delayed outcomes, such as confirmed fraud, a resolved ticket or a returned order, and compute accuracy per week or per cohort.
- Label a small random sample of live traffic by hand on a schedule, so you always have a recent estimate.
- Treat user behaviour as a label: overrides, corrections, escalations and repeat questions are cheap signs of wrong answers.
- Log the model version, input type, prediction, confidence and whether fallback ran with every request, so any later label can be matched to the model that made the call. Keep personal data out of those logs where you can.
Statistical tests and alert thresholds
Compare a recent window of production data with a fixed reference, usually the training data or a known-good period of production, one feature at a time. Each common test suits a kind of feature.
Treat every threshold as a starting point to tune, not a standard. Alert only when someone needs to act, and use sustained conditions rather than single readings: for example, alert only if the unknown rate stays above its threshold for ten consecutive minutes. Signals that fluctuate without needing action belong on a dashboard, grouped into system health, model behaviour, external services and user behaviour panels so the faulty layer is obvious at a glance.
- Population stability index (PSI): bins a numeric feature and sums, across bins, the difference in each bin's share weighted by the log of their ratio. A rule of thumb from credit scoring reads below 0.1 as stable, 0.1 to 0.25 as a moderate shift worth investigating and above 0.25 as significant.
- Kolmogorov-Smirnov test: compares two samples of a continuous feature. On large samples it flags differences too small to matter, so alert on the statistic or a distance rather than the p-value alone.
- Chi-squared test: compares category frequencies, such as predicted classes or a categorical input.
- Jensen-Shannon distance: a bounded, symmetric measure of how far apart two distributions are, useful for whole histograms and prediction mixes.
| Alert | Example starting threshold |
|---|---|
| API error rate | Above 5 percent: alert immediately |
| Unknown or low-confidence prediction rate | Above 20 percent, or double its usual level |
| Average confidence | Below a floor set from validation data |
| Predicted class distribution | A sudden shift, such as PSI above 0.25 against the baseline |
| External model calls and token usage | Above the expected daily level |
import numpy as np
def psi(baseline, current, bins=10, eps=1e-6):
"""Population stability index of one numeric feature against a baseline."""
baseline = np.asarray(baseline, dtype=float)
current = np.asarray(current, dtype=float)
# Bin edges from the baseline's quantiles, open at both ends.
edges = np.unique(np.quantile(baseline, np.linspace(0, 1, bins + 1)))
edges[0], edges[-1] = -np.inf, np.inf
expected = np.histogram(baseline, edges)[0] / len(baseline)
actual = np.histogram(current, edges)[0] / len(current)
expected = np.clip(expected, eps, None)
actual = np.clip(actual, eps, None)
return float(np.sum((actual - expected) * np.log(actual / expected)))
rng = np.random.default_rng(42)
train = rng.normal(0.0, 1.0, 10_000)
print(round(psi(train, rng.normal(0.0, 1.0, 5_000)), 3)) # same distribution: close to 0
print(round(psi(train, rng.normal(0.6, 1.2, 5_000)), 3)) # shifted and wider: above 0.25How to respond: retrain, repair or update the rules
Identify the type of drift before acting, because the responses differ and some do not touch the model at all.
An illustrative case: weeks after launch, a waste-sorting assistant's bill rose sharply with healthy servers and no errors. The dashboard showed calls to the external language model up threefold and the unknown rate climbing. Users had started photographing compostable packaging that was not in the training data, so the vision model returned unknown and the system asked the LLM instead. The model was working; the dataset was out of date. Adding images of the new packaging and retraining fixed accuracy and cost together. Cost is a drift signal, so know your expected LLM cost per user and alert when it moves.
| What you find | Likely cause | Response |
|---|---|---|
| Inputs shifted, accuracy holding | Benign data drift | Keep watching; refresh the training set at the next scheduled retrain |
| Inputs shifted, unknowns and fallbacks rising | Data drift into territory the model never saw | Collect and label the new inputs, retrain, and evaluate against the current model |
| Inputs stable, accuracy falling | Concept drift | Relabel recent data under the new definition and retrain, or update the rules if the change lives there |
| A sudden jump after a deploy or upstream release | Pipeline bug or training-serving skew | Fix and backfill the pipeline; do not retrain on broken features |
| A slow decline over months | Model decay | Retrain on a schedule from recent data |
How often to retrain, and what should trigger it
Retrain as often as your world changes, and let monitoring tell you when that is. The loop of collect, train, evaluate, deploy and monitor might run daily, weekly or only when performance drops; some applications stay stable for long periods.
Hybrid systems need retraining less often. Rules can absorb a change in policy, and a fallback model or human review can cover new cases until the next retrain.
- Scheduled: where data changes steadily, retrain on a fixed cadence from a recent window.
- Triggered: retrain when accuracy on recently labelled data, or a sustained drift alert, crosses its threshold.
- Gated: evaluate every candidate against the current model on recent data before promotion, then release it through a shadow or canary deployment.
- Controlled: version models and the data that trained them, record every deployment, keep a fallback, and require human approval for high-risk systems.
Drift in LLM and RAG applications
LLM applications drift too, but the signals differ because outputs are not deterministic and there is often no label to check. Watch how often the model is called, response time, the share of empty or invalid responses, how often fallback prompts run, and response length and token counts; a jump in tokens often means unexpected prompts or unusual input.
Three sources are common. Users start asking about topics your prompts and documents never covered, which is data drift. The knowledge behind a RAG system goes stale, so a question that looks the same now has a different correct answer, which is concept drift. And a hosted model's behaviour can change when the provider updates it, so pin model versions where the provider allows and rerun your evaluation set before switching. The reliability patterns for LLM APIs cover the fallbacks.
Drift does not mean the model is broken. It means the world has moved away from the conditions the model learned from.
Questions
Is model drift the same as concept drift?
No. Model drift, or model decay, describes the symptom: the model performs worse than it did. Concept drift is one cause, where the relationship between inputs and correct outputs has changed; data drift, label shift and pipeline bugs are others. Knowing which cause is behind the decline tells you whether to retrain, relabel or fix the pipeline.
Can you have concept drift without data drift?
Yes, and it is the hardest case to catch. The inputs can keep exactly the same distribution while the correct answer for them changes, for example when a policy, a pricing rule or an adversary's behaviour changes. Input monitors stay green, so only accuracy against fresh labels or outcome data reveals it.
What PSI value indicates data drift?
A common rule of thumb reads a population stability index below 0.1 as no meaningful change, 0.1 to 0.25 as a moderate shift worth investigating, and above 0.25 as significant. The cut-offs come from credit scoring practice rather than theory, so calibrate them by computing PSI between known-good periods of your own data.
What is the difference between data drift and training-serving skew?
Data drift is a real change in the world: production inputs move away from what the model was trained on. Training-serving skew is a bug: the same feature is computed differently in training and in production, so the model sees different inputs although nothing in the world changed. Skew usually appears suddenly after a release and is fixed in the pipeline, not by retraining.
Which open-source tools detect data drift?
Evidently and NannyML are open-source Python libraries that run the common drift tests and produce reports, and NannyML can also estimate performance before labels arrive. Alibi Detect offers similar detectors, but its releases since 2024 are source-available and need a commercial licence for production use. Start with signals you can compute yourself, such as confidence, unknown rate and PSI on key features, and adopt a library when your features outgrow hand-built checks.
Should you retrain automatically when drift is detected?
Not blindly. Retraining on fresh data helps with data drift, but it will not fix a pipeline bug, and concept drift first needs labels under the new definition. Automate the pipeline, but gate promotion on an evaluation against the current model and require approval where mistakes are costly.