Every acquirer ships its own decline code table, and the overlap between them is smaller than people assume. Pulled logs from six processors on one routing stack: "insufficient funds" alone had 11 distinct raw codes, three of which also fired for "card blocked by issuer" depending on the acquirer.
Naive normalization maps codes to a fixed internal enum once and calls it done. Works fine until a processor changes what a code means after a backend migration and nobody sends a changelog. One acquirer silently reused code 05 for both "do not honor" and "expired card" after a switch upgrade. Our retry logic treated both as retryable soft declines. Over three weeks that pushed 400+ transactions into retry loops against issuers who had already said no permanently. The decline rate on the dashboard looked normal the whole time, because everything eventually landed as "declined" either way, just with extra noise nobody was watching.
Fix was boring: version the mapping table per acquirer per contract date, alert when code distribution shifts past a threshold, stop treating code semantics as static.
Anyone else keeping a live diff on acquirer decline tables, or is everyone just quietly eating the drift?
Top comments (0)