At a glance
Triggers when the trailing 1-hour decline rate exceeds the 24-hour rolling baseline by more than 2 standard deviations. The fastest detection of a payment integration regression, an issuer-side outage, or a fraud-attack burst. Pause if it’s an integration-side issue; tune Radar if it’s a fraud-attack spike; do nothing if it’s an issuer-side blip that resolves on its own.
| What it counts | (declined_charges_last_1h ÷ total_attempted_last_1h) compared to a 24-hour rolling baseline mean and standard deviation. Fires when the 1h rate exceeds mean + 2σ. |
| Currency | n/a, this alert is rate-based, not value-based. |
| Fees / processing cost | n/a, declined charges don’t generate fees. |
| Refunds | n/a. |
| Disputes / chargebacks | Declines and disputes are different events; this alert is decline-only. |
| Failed / declined payments | This is the alert source. Specifically status = failed charges are the numerator. |
| Payout timing | n/a. |
| Decline categorisation | Both soft declines (insufficient_funds, do_not_honor, generic_decline, expired_card) and hard declines (lost_card, stolen_card, pickup_card) feed the rate. A spike driven by hard declines suggests a fraud-attack pattern; a spike driven by soft declines suggests issuer-side or integration-side issues. |
| Baseline computation | 24-hour rolling baseline excludes the most recent 1 hour (so the alert isn’t comparing the spike against itself). The baseline naturally adapts to time-of-day patterns (e.g. higher decline rates overnight when batch retries fire). |
| 3DS-required charges | requires_action and canceled (3DS abandonment) are NOT counted as declines for this alert; they’re tracked separately on the 3DS Friction Loss card. |
| Page cap | 1,000 charges per refresh. The alert hour-bucket can be truncated for very high-volume merchants; in practice spikes are visible long before the cap matters. |
| Time window | RT for the 1-hour spike; 24H for the baseline. |
| Alert trigger | >2σ vs 1h baseline, ~95th percentile of normal variation. Tune to >3σ for noise reduction; tune to >1.5σ for early detection. |
| Roles | owner, finance, operations |
Calculation
Calculated automatically from your Stripe data. See the At a glance summary above for what the metric tracks and the worked example below for a typical reading.Worked example
A US DTC subscription brand on Shopify + Stripe, monthly volume ~$840,000 across ~6,800 charges. Average decline rate is 4.8%; baseline 24-hour standard deviation is 1.2%. Hour-by-hour decline rate during a Sunday-evening incident on 11 Apr 26:| Hour (UTC) | Charges attempted | Declined | Decline rate | Baseline | σ from baseline |
|---|---|---|---|---|---|
| 18:00 | 240 | 12 | 5.0% | 4.8% | +0.2σ |
| 19:00 | 280 | 14 | 5.0% | 4.8% | +0.2σ |
| 20:00 | 320 | 28 | 8.7% | 4.8% | +3.3σ ALERT FIRED |
| 21:00 | 290 | 36 | 12.4% | 4.8% | +6.3σ ESCALATED |
| 22:00 | 310 | 19 | 6.1% | 4.8% | +1.1σ |
| 23:00 | 280 | 14 | 5.0% | 4.8% | +0.2σ |
| Reason | Count | Pattern |
|---|---|---|
do_not_honor | 38 | Issuer-side, normal but elevated |
insufficient_funds | 12 | Customer-side, normal |
expired_card | 4 | Normal |
lost_card | 3 | Slightly elevated |
stolen_card | 5 | Elevated |
card_velocity_exceeded | 22 | Anomalous spike, fraud pattern |
- The alert fired at 20:00 on a 3.3σ deviation, escalated at 21:00 to 6.3σ. Two-hour total: 64 declined charges, ~$3,200 of declined revenue.
- The cause was a card-testing fraud attack. The
card_velocity_exceededdeclines are the smoking gun, the same card being tried multiple times in rapid succession is a classic card-testing pattern (a fraudster testing stolen card numbers against a low-value endpoint to verify which are still valid). Stripe’s velocity rules caught most of them; the spike represents what got close to (or through) Radar’s first line. - The right response was Radar tuning, not pausing payments. The merchant on-call: (a) confirmed via Stripe Dashboard that legitimate charges were still succeeding (4.8% baseline meant 95% of charges still worked normally), (b) added a Radar rule blocking small-value charges (<$5) from new customers, (c) added a 5-minute IP-throttle rule for repeat-card attempts. Total response time: 12 minutes. The spike resolved itself by hour 22:00 as the attacker moved on.
- The 1.1σ reading at hour 22:00 didn’t trigger. This is the right behaviour, the alert is meant to surface real anomalies, not chase noise. The spike was over by then.
- A worse outcome would have been pausing payments unnecessarily. If the on-call had assumed it was an integration regression and paused legitimate charges for the 90 minutes until the alert cleared, the merchant would have lost an estimated $14,400 of legitimate revenue while attempting to “fix” something that was already self-resolving. The card pairs with Decline Reasons precisely so the on-call can identify the spike type before acting.
Sibling cards merchants should reference together
| Card | Why pair it with Decline Spike Alert |
|---|---|
| Decline Rate | The trend view. The alert is the spike layer; the rate is the dashboard layer. Use the spike for “act now”; use the rate for trend over weeks. |
| Decline Reasons | The diagnostic decomposition. Knowing which reasons drove the spike determines the response: integration regression, issuer outage, fraud attack, or normal noise. |
| Top Declining Issuers | The issuer-side view. A spike concentrated on one issuer points to issuer-side outage, not merchant-side. |
| Decline Rate by Card Country | The geographic view. Spikes concentrated on one country often indicate fraud-attack patterns (the attacker is using cards from one origin). |
| Recoverable Declines | The dollar context. How much revenue is the spike costing? Useful for triage prioritisation. |
| Auth Rate | The complement view. Decline rate spike = auth rate drop; the two move inversely. |
| Radar Score Distribution | The fraud-prevention lever. If the spike is fraud-attack pattern, Radar tuning is the upstream fix. |
| Payment Health Score | The composite view. Decline-spike alerts contribute to the health score; sustained spikes drag the score lower. |
Reconciling against the vendor’s own dashboard
Where to look in Stripe Dashboard: Payments → Overview for the live decline rate. The default view shows the trailing 24 hours; toggle to “Last hour” for the matching window. Reports → Decline analysis for per-reason decompositions. Useful for diagnosing what drove the spike after it has fired. Radar → Reviews for live fraud-blocking decisions; useful for confirming a spike was Radar-driven (fraud attack) vs issuer-driven. For real-time monitoring, set up Stripe Workbench → Custom dashboards with a 1-hour decline-rate view; this matches the alert’s input. Why our number may legitimately differ from Stripe Dashboard:| Reason | Direction | Why |
|---|---|---|
| Real-time vs reported. Vortex IQ reads charges as they come; the Dashboard refresh has its own batching. | Vortex IQ leads | This is the point, the alert beats the reporting view. |
| Hour bucketing. Vortex IQ uses rolling 1-hour windows; Dashboard often uses calendar hours (12:00 to 13:00). | Boundary effects | Spike alerts robust to bucketing. |
3DS exclusion. This alert excludes requires_action and canceled (3DS abandons); the Dashboard may include them in some views. | Vortex IQ lower | The 3DS Friction Loss card is the right tool for those. |
| Time-zone. Stripe Dashboard uses your account-level time zone; Vortex IQ uses UTC for the spike-detection logic. | Boundary days off | Doesn’t affect the 1-hour spike detection. |
Threshold tuning. The default >2σ produces ~5% false-positive rate. | Sensitive | Tune to >3σ for noise reduction; >1.5σ for early detection. |
| Card | Expected relationship | What causes legitimate divergence |
|---|---|---|
shopify.checkout_abandon_rate | Decline spike often coincides with checkout abandon spike | Customers whose card is declined at Stripe abandon the checkout; the two move together during issuer outages. |
paypal.pp_decline_rate | Stripe and PayPal decline rates are independent for different reasons | Issuer-side outages affect both card processors; merchant-side regressions affect one. Both moving together = issuer-side; one moving = merchant-side. |
shopify.refund_rate | Weak relationship | Decline spikes don’t drive refunds directly because the charge never succeeded; recoverable declines that customers retry and complete can produce a small refund-rate echo days later. |
card_velocity_exceeded count (fraud-side) answer it in 2 to 3 minutes.
Known limitations / merchant FAQs
The alert fired. What’s the playbook? Three steps in order, total time 5 to 10 minutes. (1) Identify the spike type by checking Decline Reasons. 100%generic_decline or 100% one reason from one issuer = integration regression or issuer outage; mixed reasons with card_velocity_exceeded = fraud attack; mixed reasons with no clear pattern = noise / false positive. (2) Match the response to the type. Integration regression: pause and rollback. Issuer outage: do nothing, wait. Fraud attack: tune Radar with a velocity rule. Noise: do nothing. (3) Verify legitimate charges are still succeeding by checking Auth Rate; if the auth rate is still close to baseline, you’re not in a global outage.
False positives, what causes them?
Three common patterns. (a) Low-volume hour bucket, an hour with only 30 charges and 4 declines is statistically a 13% rate, which trips the alert against a 5% baseline despite being only 4 absolute declines. (b) Batch retry timing, subscription renewal batches that fire at the same time each day produce predictable decline-rate spikes; the baseline should adapt within 24 to 48 hours but the first time a new batch runs it can fire. (c) Promotional spike, a viral campaign brings new shoppers with higher decline rates (new customers fail more often than repeat); the spike is real but isn’t an issue.
Should I auto-pause Stripe when this fires?
Almost never. Pausing Stripe means refusing legitimate charges, which is far more expensive than absorbing the few minutes of additional declines until the spike type is identified. The right pattern is: alert → human triage → action. Auto-pause logic should consider absolute decline count AND multiple confirming signals (decline rate spike + auth rate drop + checkout abandon spike); pause only when all three fire simultaneously.
The alert keeps firing on the same overnight hour. Is it broken?
Probably not, but it’s noise. Subscription-heavy merchants often have predictable overnight retry batches that produce decline-rate spikes; the baseline should adapt but if the pattern is sharp and recurring it can fire repeatedly. Two fixes: (a) tune the alert window to exclude the known-noisy hour from baseline calculation, or (b) raise the threshold to >3σ to reduce sensitivity. The pattern is real; the alert just isn’t actionable.
My alert fired but Stripe Dashboard shows the spike already resolved by the time I logged in. Did I miss anything?
No. The alert is meant to surface anomalies fast; many anomalies self-resolve within 30 to 60 minutes (issuer-side blips, ephemeral fraud attacks, batch processing waves). The right response is acknowledgement and review, not always action. The card alongside the alert lets you confirm what happened post-mortem.
Why is this rate-based and not absolute-count-based?
Different merchants have different volumes; an absolute-count alert (e.g. “10 declines in an hour”) fails for high-volume merchants (10 declines is a rounding error) and over-fires for low-volume merchants (10 declines is a real signal). A rate threshold normalises across volumes; a sigma-based threshold further normalises across each merchant’s baseline noise. The alert is meant to find genuine anomalies, not arbitrary thresholds.
Stripe Radar already blocks high-risk transactions. Why am I getting decline spikes from fraud attacks?
Radar’s blocking decisions are pre-charge (the charge never reaches the issuer); these don’t show up as declines in this card. The card surfaces post-charge declines, the issuer rejected the charge for fraud / velocity reasons. A fraud-attack-driven decline spike means the attacker’s cards are reaching Stripe but failing at the issuer side. The fix is tuning Radar to block earlier (raise the block threshold from “high” to “elevated” risk), at the cost of slightly higher false-positive rate on legitimate transactions.
My subscription billing batch fires at midnight UTC. The alert always fires at 00:30. What do I do?
This is the canonical “predictable noise” case. Two fixes. (a) Configure the alert to exclude the 00:00 to 01:00 window from the baseline (so the baseline reflects normal hours only); the spike will still be visible in the dashboard but won’t trip the alert. (b) Run the subscription batch with built-in retry-spread (e.g. randomly distribute over 4 hours) which smooths the decline-rate spike. Stripe Smart Retries does this automatically if enabled.
Why does the alert use a 24-hour baseline and not a longer one?
Decline rate has strong time-of-day patterns (lower during business hours, higher at night when batch retries fire). A 24-hour rolling baseline naturally adapts to these patterns; longer baselines (7 days, 30 days) average out the time-of-day signal and produce more false-positives at predictable peak hours. The 24-hour window is a balance between adaptiveness and stability.