Move the fraud line without eating losses
The decline threshold is 0.7. Tighter blocks good customers, looser costs money, and nobody wants to be the person who changed it — so it never moves.
The problem
The decline threshold is 0.
Risk thresholds are the clearest example of a number that badly needs experimentation and almost never gets it. The downside of a wrong move is measured in real money and real fraud, so the rational choice for any individual is to leave it alone.
That caution is expensive in the other direction. A threshold tuned for last year's fraud patterns declines customers who would have paid, and nobody attributes lost revenue to a setting nobody touched.
The only way this becomes safe is if the blast radius is small by construction and the exit is automatic — a 1% canary, a chargeback guardrail that reverts rather than warns, and a decision record showing exactly which thresholds were in force.
# the number nobody will touch DECLINE_THRESHOLD = 0.70 REVIEW_THRESHOLD = 0.45 if score > DECLINE_THRESHOLD: return decline() # parameterized, it can be moved # on 1% of traffic and reverted
What you put under control
Declared once, then governed centrally. This is the only code step.
| Parameter | Type | Default | Range |
|---|---|---|---|
| risk.decline_threshold | number | 0.70 | 0–1 |
| risk.review_threshold | number | 0.45 | 0–1 |
| risk.step_up_auth_enabled | boolean | false | — |
| Surface | Kind | Role |
|---|---|---|
| Risk service | backend | decision |
| Checkout | frontend | render |
| Manual review queue | other | side_effect |
Those bindings are what compute the risk class — critical: backend surface · decision binding · manual override raised.
| Variant | decline_threshold | step_up_auth |
|---|---|---|
| control | 0.70 | false |
| looser | 0.76 | true |
Risk class: critical
backend surface · decision binding · manual override raised. A human approves the measurement plan before any traffic, and again before the value becomes the product default.
How it runs
The mechanism is configuration. The application code is already done.
Deliberately not an experiment. There is no appetite for a 50/50 split on fraud decisions, so this runs as a one-treatment ramp: 1% canary, then 5, 20, 50, 100 — each step gated on chargeback health.
Adaptive optimization is explicitly the wrong tool here. You never want traffic drifting toward a threshold on its own when the loss function includes fraud.
What you get back
A verdict you can defend, and the reasoning kept for next time.
A threshold that can finally move — because the worst case is 1% of traffic for twenty minutes and an automatic revert.
When it completes, the winning values become the parameter defaults and the whole thing — question, variants, evidence, verdict — is retained. The next person to propose moving this number starts from the answer instead of the argument.
The question asked, the values tried, the interval at the moment of the call, which thresholds were in force, and who approved the promotion.
Keep reading
The mechanics behind this page.
Start with this one number
Parameterize it this week. The first measured change usually pays for the integration.