Fair-lending monitoring is the machinery that recomputes disparate-impact metrics on live credit decisions and raises an alert when they drift. A launch test only proves the model was fair on the frozen data you had that day. Production asks a harder question: is the model still fair on the population applying today, under the feeds and model version running now?
Catch that drift late and the cost is a quarter of lending already booked under a model that slid. The failure mode is quiet. Nobody edits the scoring code. Nobody ships a change labelled “make this unfair.” Instead a data feed changes what a proxy looks like, marketing opens a new acquisition channel and shifts the applicant mix, a bureau reclassifies a field, and the approval-rate ratio between two groups slides from 0.94 to 0.79 over eleven weeks. If the only fairness evidence you hold is the launch memo, you find out when a regulator or an internal audit asks, and by then the decisions are made.
What you actually measure, and on what
Monitoring is worth nothing if you cannot slice live decisions by protected characteristic. That is the first build decision and it is uncomfortable: you need the attribute available for measurement without it ever touching the model as an input. Sometimes you hold self-reported attributes in a separate store keyed to the application, walled off from the feature pipeline. Where collection is restricted, you fall back to a documented proxy method such as Bayesian Improved Surname Geocoding for race, and you write down that it is a proxy with known error. A monitoring number built on a silent proxy will mislead you at the worst moment.
On that sliced data, two metrics carry most of the weight:
- Outcome disparity. Approval rates, or score-band distributions, or priced rate, compared across groups as ratios. This is the classic adverse-impact ratio. You compute it on the decisions the model actually produced, at the score and threshold in force that day, not on a backfilled rescore. Point-in-time correctness matters as much here as it does in a backtest. Recompute yesterday’s fairness with today’s feature values and you are measuring a model that never ran.
- Proxy strength over time. How well the current feature set predicts the protected attribute. A model can pass outcome disparity for months and then, after a feed change, start reconstructing group membership more cleanly from postcode and merchant patterns. Tracking proxy-prediction strength as a time series catches the mechanism before the outcome metric fully moves.
Both need a denominator large enough to mean something. A slice with forty applicants a month produces a ratio that swings on noise. Part of the design is deciding the smallest window over which each slice is statistically worth reading, then not alerting inside that window.
Wiring it into the decision path
The monitoring cannot live in a notebook someone runs when they remember. It reads from the same audit trail that already records every decision: the model version, the feature vector as scored, the threshold, the outcome, the timestamp. If you have straight-through processing for approvals, that log is your source of truth, and fairness metrics are just another consumer of it. If decisions are logged inconsistently, fix that first, because a fairness time series is only as reliable as the reconciliation behind the decision log.
The pipeline runs on a clock. A monthly batch computes the full metric set per slice and appends it, dated, with the model version and feed vintage it ran against. A lighter weekly job watches the input distribution, meaning the applicant mix and the feature drift, because a population shift leads and the outcome metric lags. Every run is stored and never overwritten. When someone asks whether the model was fair in April, the answer is a row you can point to, with lineage back to the exact model and data version, not a rerun that may quietly use different code.
Alerting is where most fairness monitoring goes wrong, in both directions. Set the bands too tight and every sampling wobble pages the team, they learn to ignore it, and the real drift arrives to a muted channel. Set them too loose and you catch the slide after it is a headline. We set alert bands per slice against a false-positive budget, an agreed rate at which the team is willing to be interrupted for something that turns out to be noise. A breach fires when the ratio crosses the band and stays there across enough decisions to clear the slice’s noise floor. The alert names the model version and the feeds that changed in the same window, so the on-call analyst starts triage with a hypothesis instead of a blank screen.
What happens when it fires
An alert opens an investigation rather than settling one, and the workflow around it decides whether the monitoring is real or theatre. The team needs a runbook: confirm the breach is not a data-quality artefact in the protected-attribute store or the proxy, isolate whether a model release or a feed change lines up with the inflection, and quantify how many decisions were made in the drifted period. That last number drives everything downstream, including whether adverse-action reasons issued during the window still reflect what the model did.
Some of this connects directly to remediation you may owe. If a proxy strengthened and outcome disparity followed, the fix usually lives in the features, and you will want the proxy-analysis output that shows which ones moved. Keep all of it. The stored metric history, the alert record, the investigation notes, and the change that resolved it are the same audit-trail discipline as data lineage, and they are what turns “we monitor for fair lending” from a sentence in a policy into evidence a reviewer can read. A launch test is a claim. A dated series of production metrics, with alerts that fired and were worked, is the proof that the claim held after launch.
FAQ
How often should fair-lending monitoring run?
Fast enough to catch drift before a full quarter of decisions accumulates under it. Batch fairness metrics monthly at minimum, and run a lightweight distribution check on the incoming population weekly if your feeds move quickly.
Can you monitor for disparate impact without collecting protected attributes?
Not directly. You need the attribute held to one side for testing, or a documented proxy method like BISG for the cases where collection is restricted. Monitoring a fairness metric you cannot compute is not monitoring.
What triggers a fair-lending alert versus normal noise?
A disparate-impact ratio crossing a pre-agreed band, sustained across enough decisions to be more than sampling noise, and tied to a specific model version or feed change. Single-day blips inside your confidence interval should not page anyone.