{"course":{"slug":"cloud-and-shipping","title":"Shipping It","url":"https://addaly.com/learn/cloud-and-shipping","level":"intermediate","track":"build"},"lesson":{"slug":"when-the-inputs-change","title":"The model that quietly stopped fitting","url":"https://addaly.com/learn/cloud-and-shipping/when-the-inputs-change","position":55,"of":74,"minutes":10,"answer":"A model degrades without any deploy, so watch what you can see immediately (input distributions, missingness and the prediction distribution) collect a small stream of real labels every week.","keyIdea":"A model degrades without any deploy, so watch what you can see immediately (input distributions, missingness and the prediction distribution) collect a small stream of real labels every week, and make retraining a triggered decision that passes the same gate as any other model change."},"body":{"format":"markdown","text":"## Nothing broke, and it got worse\n\nA deployed model has a failure mode that no other part of your system has: it degrades with nobody deploying anything. The code is unchanged, the tests pass, latency is flat, error rate is zero, and the predictions are getting worse, because the world moved and the model did not.\n\nA spam classifier trained on last year's spam meets this year's. A demand forecast trained before a festival season meets the season. A model trained on one country's users meets an influx from another. In every case the machinery is healthy and the output is wrong.\n\n## Three different changes, often confused\n\n- **Data drift** (covariate shift): the inputs change distribution. More mobile traffic, longer messages, a new language appearing in the text field.\n- **Concept drift**: the relationship between inputs and the correct answer changes. The same message that meant \"legitimate\" now means \"scam\", because the scammers adapted.\n- **Label delay**: nothing has drifted, but you will not know for weeks, because ground truth arrives late: a fraud chargeback at 60 days, a churn label at 90.\n\nThey need different responses. Data drift may be harmless if the model handles the new region of input space. Concept drift always hurts. Label delay is what makes both hard to detect quickly, and it is the reason input monitoring exists at all.\n\n## Monitor the inputs, because they are free\n\nYou can measure input distributions today, without waiting for labels. For each important feature, compute a summary on a recent window and compare it with the training distribution:\n\n- Numeric features: mean, standard deviation, and the share falling outside the training range.\n- Categorical features: the proportion of unseen categories, and the shift in the top few.\n- Text or embeddings: mean embedding distance from the training centroid, or the share of inputs beyond a distance threshold.\n- Missingness: the share of nulls per field. A field that suddenly becomes 30% null is usually an upstream change and it is one of the highest-yield checks in this list.\n\nThe standard statistics are the Population Stability Index and the Kolmogorov–Smirnov test. PSI has widely used rules of thumb (under 0.1 stable, 0.1 to 0.25 worth investigating, above 0.25 significant), and those thresholds are conventions, not laws; calibrate them against your own history before you page anybody.\n\nOne caution repeated by everybody who has run this in anger: with enough features and daily tests, statistical drift alarms fire constantly on differences that do not matter. Test a handful of features you have reason to care about, use a window long enough to be stable, and treat a drift signal as a prompt to look, never as an automatic retrain trigger.\n\n## Monitor the outputs, which is cheaper still\n\nThe prediction distribution is available immediately and it moves before the labels do.\n\n- The mean predicted score, day over day. A classifier whose average score jumps from 0.12 to 0.34 has met something new.\n- The share of predictions near the decision threshold, which measures how much of your traffic is a coin flip.\n- The rate of fallbacks, refusals, empty results or low-confidence answers.\n- For a language model: output length, refusal rate, and the rate at which structured output fails to parse. That last one is a beautifully sensitive canary for a provider changing something under you.\n\n## Then get labels, slowly and deliberately\n\nInput and output monitoring tell you something changed. Only labels tell you whether quality fell.\n\n> Figure: Mean predicted score, day by day, with no deploy. Line chart of mean predicted score against day: Mean score across the day's traffic (1, 0.12) (2, 0.13) (3, 0.12) (4, 0.11) (5, 0.13) (6, 0.12) (7, 0.29) (8, 0.33) (9, 0.34) (10, 0.34). Nothing in the code changed. On day seven the classifier met something new, and its average score nearly tripled. The prediction distribution is available immediately; the labels that say whether quality fell arrive weeks later.\n\nThree affordable sources: user actions that imply a judgement (a report, a correction, a deletion, an undo), a small stratified sample reviewed by a person each week, and delayed ground truth when it eventually arrives. Fifty labelled examples a week, chosen to over-sample the uncertain region, is a modest, sustainable practice that will detect real degradation within a month.\n\nKeep those labelled examples forever. They become your regression set, and a set built from real production failures is worth more than a much larger synthetic one.\n\n## Retraining is a decision, not a schedule\n\n\"Retrain nightly\" sounds diligent and is often a way to ship an unevaluated model every day. Retraining on a cadence is fine only if every retrained model passes the same evaluation gate, and is shipped through the same shadow-and-canary path, as a hand-made one. If it is not gated, a data pipeline bug on Tuesday becomes a production model on Wednesday.\n\nRetrain when the evidence says to: measured quality has fallen, drift is sustained rather than a spike, or enough new labels exist to be worth learning from. Write the trigger down before you need it, and record which data snapshot each retrain used so the version lineage from the earlier lesson stays intact.\n\n## The free path\n\nEvidently is a free, open-source library that computes drift reports and quality metrics and produces an HTML page you can look at. NannyML does the harder job of estimating performance when labels have not arrived yet. Neither is required: a weekly SQL query producing ten numbers, stored in a table and drawn on your dashboard, is a working drift monitor, and it is the version that actually gets built."},"check":{"question":"A fraud model shows a stable input distribution and unchanged prediction scores, but chargebacks from two months ago show precision has fallen sharply. Which situation does this best describe?","options":[{"text":"Concept drift revealed by delayed labels, where the same inputs now correspond to different outcomes","correct":true},{"text":"Data drift, since the inputs must have changed for performance to fall","correct":false,"tempting":"Inputs were measured and are stable, so the change is in what those inputs mean rather than in the inputs themselves."},{"text":"Training-serving skew introduced by a recent change to the feature pipeline","correct":false,"tempting":"Skew would show as a difference between offline and online feature values, and would typically appear as soon as the change shipped, not with a two-month lag."},{"text":"A monitoring failure, since input and output monitoring should always detect a real quality drop","correct":false,"tempting":"Overstates what those monitors can do: they detect changes in distribution, and adversaries can change behaviour while keeping input statistics similar."}]},"prev":{"slug":"shipping-a-model-safely","title":"Shadow, then canary, then everybody","url":"https://addaly.com/learn/cloud-and-shipping/shipping-a-model-safely"},"next":{"slug":"feedback-loops","title":"The model that trains on its own decisions","url":"https://addaly.com/learn/cloud-and-shipping/feedback-loops"},"authorship":"Founder and series editor: Dr Mustafa Mun. Written by AI models to a written standard. Exam keys checked blind by a second model: 3,665 of 3,666 agreed. Academic review invited.","review":{"status":"Draft, open for academic review"},"cite":"Addaly (2026) 'The model that quietly stopped fitting', in Shipping It. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/cloud-and-shipping/when-the-inputs-change (Accessed: 13 October 2026).","licence":{"name":"CC BY-NC-SA 4.0","url":"https://creativecommons.org/licenses/by-nc-sa/4.0/"},"reader":{"schema":1,"title":"The model that quietly stopped fitting","courseTitle":"Shipping It","module":{"index":6,"slug":"shipping-a-model","title":"Shipping a model, not just a web app"},"answer":null,"keyIdea":"A model degrades without any deploy, so watch what you can see immediately (input distributions, missingness and the prediction distribution) collect a small stream of real labels every week, and make retraining a triggered decision that passes the same gate as any other model change.","hero":{"kind":"figure","figure":{"t":"figure","label":"Figure","figure":{"type":"line","title":"Mean predicted score, day by day, with no deploy","series":[{"label":"Mean score across the day’s traffic","points":[[1,0.12],[2,0.13],[3,0.12],[4,0.11],[5,0.13],[6,0.12],[7,0.29],[8,0.33],[9,0.34],[10,0.34]]}],"xLabel":"day","yLabel":"mean predicted score","caption":"Nothing in the code changed. On day seven the classifier met something new, and its average score nearly tripled. The prediction distribution is available immediately; the labels that say whether quality fell arrive weeks later."},"alt":"Figure: Mean predicted score, day by day, with no deploy. Line chart of mean predicted score against day: Mean score across the day’s traffic (1, 0.12) (2, 0.13) (3, 0.12) (4, 0.11) (5, 0.13) (6, 0.12) (7, 0.29) (8, 0.33) (9, 0.34) (10, 0.34). Nothing in the code changed. On day seven the classifier met something new, and its average score nearly tripled. The prediction distribution is available immediately; the labels that say whether quality fell arrive weeks later."}},"blocks":[{"t":"h2","id":"nothing-broke-and-it-got-worse","runs":[{"text":"Nothing broke, and it got worse"}]},{"t":"p","runs":[{"text":"A deployed model has a failure mode that no other part of your system has: it degrades with nobody deploying anything. The code is unchanged, the tests pass, latency is flat, error rate is zero, and the predictions are getting worse, because the world moved and the model did not."}]},{"t":"p","runs":[{"text":"A spam classifier trained on last year’s spam meets this year’s. A demand forecast trained before a festival season meets the season. A model trained on one country’s users meets an influx from another. In every case the machinery is healthy and the output is wrong."}]},{"t":"h2","id":"three-different-changes-often-confused","runs":[{"text":"Three different changes, often confused"}]},{"t":"ul","items":[[{"text":"Data drift","b":true},{"text":" (covariate shift): the inputs change distribution. More mobile traffic, longer messages, a new language appearing in the text field."}],[{"text":"Concept drift","b":true},{"text":": the relationship between inputs and the correct answer changes. The same message that meant “legitimate” now means “scam”, because the scammers adapted."}],[{"text":"Label delay","b":true},{"text":": nothing has drifted, but you will not know for weeks, because ground truth arrives late: a fraud chargeback at 60 days, a churn label at 90."}]]},{"t":"p","runs":[{"text":"They need different responses. Data drift may be harmless if the model handles the new region of input space. Concept drift always hurts. Label delay is what makes both hard to detect quickly, and it is the reason input monitoring exists at all."}]},{"t":"h2","id":"monitor-the-inputs-because-they-are-free","runs":[{"text":"Monitor the inputs, because they are free"}]},{"t":"p","runs":[{"text":"You can measure input distributions today, without waiting for labels. For each important feature, compute a summary on a recent window and compare it with the training distribution:"}]},{"t":"ul","items":[[{"text":"Numeric features: mean, standard deviation, and the share falling outside the training range."}],[{"text":"Categorical features: the proportion of unseen categories, and the shift in the top few."}],[{"text":"Text or embeddings: mean embedding distance from the training centroid, or the share of inputs beyond a distance threshold."}],[{"text":"Missingness: the share of nulls per field. A field that suddenly becomes 30% null is usually an upstream change and it is one of the highest-yield checks in this list."}]]},{"t":"p","runs":[{"text":"The standard statistics are the Population Stability Index and the Kolmogorov–Smirnov test. PSI has widely used rules of thumb (under 0.1 stable, 0.1 to 0.25 worth investigating, above 0.25 significant), and those thresholds are conventions, not laws; calibrate them against your own history before you page anybody."}]},{"t":"p","runs":[{"text":"One caution repeated by everybody who has run this in anger: with enough features and daily tests, statistical drift alarms fire constantly on differences that do not matter. Test a handful of features you have reason to care about, use a window long enough to be stable, and treat a drift signal as a prompt to look, never as an automatic retrain trigger."}]},{"t":"h2","id":"monitor-the-outputs-which-is-cheaper-still","runs":[{"text":"Monitor the outputs, which is cheaper still"}]},{"t":"p","runs":[{"text":"The prediction distribution is available immediately and it moves before the labels do."}]},{"t":"ul","items":[[{"text":"The mean predicted score, day over day. A classifier whose average score jumps from 0.12 to 0.34 has met something new."}],[{"text":"The share of predictions near the decision threshold, which measures how much of your traffic is a coin flip."}],[{"text":"The rate of fallbacks, refusals, empty results or low-confidence answers."}],[{"text":"For a language model: output length, refusal rate, and the rate at which structured output fails to parse. That last one is a beautifully sensitive canary for a provider changing something under you."}]]},{"t":"h2","id":"then-get-labels-slowly-and-deliberately","runs":[{"text":"Then get labels, slowly and deliberately"}]},{"t":"p","runs":[{"text":"Input and output monitoring tell you something changed. Only labels tell you whether quality fell."}]},{"t":"p","runs":[{"text":"Three affordable sources: user actions that imply a judgement (a report, a correction, a deletion, an undo), a small stratified sample reviewed by a person each week, and delayed ground truth when it eventually arrives. Fifty labelled examples a week, chosen to over-sample the uncertain region, is a modest, sustainable practice that will detect real degradation within a month."}]},{"t":"p","runs":[{"text":"Keep those labelled examples forever. They become your regression set, and a set built from real production failures is worth more than a much larger synthetic one."}]},{"t":"h2","id":"retraining-is-a-decision-not-a-schedule","runs":[{"text":"Retraining is a decision, not a schedule"}]},{"t":"p","runs":[{"text":"“Retrain nightly” sounds diligent and is often a way to ship an unevaluated model every day. Retraining on a cadence is fine only if every retrained model passes the same evaluation gate, and is shipped through the same shadow-and-canary path, as a hand-made one. If it is not gated, a data pipeline bug on Tuesday becomes a production model on Wednesday."}]},{"t":"p","runs":[{"text":"Retrain when the evidence says to: measured quality has fallen, drift is sustained rather than a spike, or enough new labels exist to be worth learning from. Write the trigger down before you need it, and record which data snapshot each retrain used so the version lineage from the earlier lesson stays intact."}]},{"t":"h2","id":"the-free-path","runs":[{"text":"The free path"}],"role":"free"},{"t":"p","runs":[{"text":"Evidently is a free, open-source library that computes drift reports and quality metrics and produces an HTML page you can look at. NannyML does the harder job of estimating performance when labels have not arrived yet. Neither is required: a weekly SQL query producing ten numbers, stored in a table and drawn on your dashboard, is a working drift monitor, and it is the version that actually gets built."}]}],"check":{"question":[{"text":"A fraud model shows a stable input distribution and unchanged prediction scores, but chargebacks from two months ago show precision has fallen sharply. Which situation does this best describe?"}],"options":[{"text":[{"text":"Concept drift revealed by delayed labels, where the same inputs now correspond to different outcomes"}],"correct":true,"tempting":null},{"text":[{"text":"Data drift, since the inputs must have changed for performance to fall"}],"correct":false,"tempting":[{"text":"Inputs were measured and are stable, so the change is in what those inputs mean rather than in the inputs themselves."}]},{"text":[{"text":"Training-serving skew introduced by a recent change to the feature pipeline"}],"correct":false,"tempting":[{"text":"Skew would show as a difference between offline and online feature values, and would typically appear as soon as the change shipped, not with a two-month lag."}]},{"text":[{"text":"A monitoring failure, since input and output monitoring should always detect a real quality drop"}],"correct":false,"tempting":[{"text":"Overstates what those monitors can do: they detect changes in distribution, and adversaries can change behaviour while keeping input statistics similar."}]}],"order":[3,0,2,1],"why":null},"prev":{"slug":"shipping-a-model-safely","title":"Shadow, then canary, then everybody","minutes":9},"next":{"slug":"feedback-loops","title":"The model that trains on its own decisions","minutes":9}}}