> Real cardholders almost never buy something for exactly $1.00. Coffee is $4.73, gas is $52.81. The roundness is the signal.
Surely this depends on how the vendor sets their prices? If you're going to buy something from a website to test a stolen credit card you don't just get to make up your own prices.
And I think you may be over-indexing on the US "prices don't include tax" thing. Elsewhere, round-number prices are extremely common.
In fact a lot of the rest of the stuff in the post seems like it wouldn't work very well either. (E.g. you're flagging anyone who has done a transaction in the last 90 days outside the range of hours at which they have 2+ transactions? Wouldn't that be like 50% of people?).
It's unclear to me whether this article is an attempt at breaking down complex expertise into over-simplified SQL queries, or whether it is all speculative and made up.
There is a conflict between "Six SQL patterns I use to catch transaction fraud" and "Nothing here comes from anything I’ve actually worked on or seen".
The "transaction outside usual hour range" seems pretty basic.
I don't usually buy gas, coffee or snacks at 2am. But on the very rare occasion that I do, I'm dealing with some kind of personal emergency and don't also want to have to call my bank.
I get that that's also a time opportunistic thieves, etc, might be operating. But the cost of false positives is also a thing.
This is also
a) trivial to bypass by adding dither to the test transactions and
b) trivial to improve upon with proper statistical analysis and
c) shouldn't this kind of heuristic pattern recognition with no expectation of near-100% accuracy be what AI is good at?
Worse than that.
Coffee usually _is_ a round number in my experience, and I know of people who aim for round numbers when filling their car, and of fuel stations which require a pre-set value, often 10, 20, 50€ etc
Yes, as your parent comment points out, the article centers itself on US transactions, where listed prices seldom include tax and are frequently a cent below a round number. For example, the menu says a dish is $15.00 but the restaurant charges $18.83 after tax and tip. Globally, there's no doubt the US is the exception rather than the norm.
All of that is easy to account for, all of the metadata you need is available. This also applies to the sibling comment about rounding up to charity at the grocery store, the data is all there, even if it's e.g. the fraud analyst at the bank or credit card company instead of the fraud analyst at the grocery store.
I don't need to account for it - I'm just stating that this doesn't match my experience:
> Real cardholders almost never buy something for exactly $1.00. Coffee is $4.73, gas is $52.81. The roundness is the signal.
I'm seeing a few stores here and there which have a "round up to donate" option. I guess I'm a bit of a sucker and I always use that option. My groceries are always a round number as a result.
> Border crossings inside 10 minutes. International rings.
Or normal people living in Europe in border-adjacent areas.
Also, I guess you don't include card-not-present transactions in this, but you incorrectly assume that every merchant has their location set correctly. And that every sale happens in a brick-and-mortar establishment, not from travelling salespeople or whatever. And that all transactions happen online.
> Fraud detection in transaction data is mostly SQL. Not machine learning, not graph databases, not whatever Gartner is hyping this year. SQL, run against the right tables, with the right joins, looking for the right shapes.
It's also not all program-integrity, which is the only work that could justify such blanket statements. Worse is better as long as it addresses the problem domain.
Fintech clients are generally interested in knowing whether a transaction happening _right now_ is fraud. They want to know that in a few milliseconds, for high-dimensional data. It's work done at a scale where relational databases cannot meet these real-time constraints, and instead find other uses like historical data loading. That's how you end up with in-memory databases, stream-processing engines, and yes, even machine learning.
Having said that, some of the author's points are valid, and I'm looking forward for their next writings, in particular dealing with noisy alerts is a general problem beyond performance engineering.
Wait, you can clone a credit card? Why don't they use a public-private key pair?
You can only clone magnetic stripe. In a lot of places, you can’t make large transactions with it
> Drawback: this doesn’t work until you have history. New accounts have no baseline.
This is an underrated CX factor: If my card gets denied when i’m a new customer or exhibiting a new pattern, i’m impressed with their software.
However if they deny a transaction where there is any previous history of me authenticating, then I’m frustrated by their naive paranoid algorithm.
The incentives of the bank is to cut fraud.
Fraudulent transactions will eventually cost the bank (when they would have to reverse/reimburse it and eat the loss). A denied transaction only results in an angry customer who will quickly forget after they complained - so the customer bears the brunt of the externalized cost.
Therefore, the bank's incentive is to err on the side of more caution, and deny transactions when finding false positives.
When someone disputes a charge and wins banks charge processor and the original merchant. The bank won’t loose a penny, merchant will.
Isn't the point of ML that you learn these rules from the data? The right approach to me would be to use ML models to detect patterns that correspond with fraud and then evaluate them to see if any make sense. This way you might discover new hyptotheses.
Anything that can't be explained and iterated deterministically is too risky for the business of declining financial transactions.
Human analysts need to be able to explain to compliance in a single 5 minute email why a specific transaction was declined, and most importantly, what could have been done differently to avoid the adverse decision.
Fixing one problem with ML often creates two new problems that aren't quite obvious yet. SQL tends to have fewer surprises with regard to regressions and unexpected side effects as things change over time.
In my experience, Visa support can’t tell me why my legitimate transaction was tagged as fraudulent, other than to say it triggered an AI thing. They also can’t tweak the settings like they used to do, but they can manually allow specific transactions one by one on an ad hoc basis.
I assume that this option is unlocked once you enter litigation against the company.
Umm no, they submit thousands of random pages of business communication and system spec in discovery. This does not include the source code of their algorithm, which in any case if not stored in any form which can be recreated and shared. If you pay a lawyer a million bucks to read them all it would say that they don't know how the algo works. At the same time they offer you low four digits to make the case go away, if you have a case. If you don't have a valid case at all, they rapidly spend $250,000 on filings and motions which you would have to spend $100,000 to stay in the game.
If a card swipes in Chicago and seven minutes later swipes in Los Angeles, one of those swipes is fake.
How does this work with online shopping? When I am sitting on the couch and buy from Amazon, where does the address get registered?
Can also imagine an edge case: couple shares an online account, one is traveling and purchases with the saved card details.
Swiping a card (or inserting, or tapping) is a "card present" transaction. Online shopping, where you type in the card number, is a "card not present" transaction. Retailers and banks can tell the difference.
Also, a Apple/Google/Samsung tap has a different DPAN to the physical card, so it's "card present" but a different card.
They can tell based on transaction metadata. Source: I worked at a cc company
I believe the system distinguishes between card present and card not present.
2 can be genuine use. I let my partner use my card and I use it on my phone as rfid. Maybe ignore phone usages since they are secured pretty well.
All of them can be genuine use, these are fraud signals not fraud proofs, and the article does cover this:
> What works is running them all and scoring each transaction across the signals. A transaction that fails on three or four of them is almost always fraud. A transaction that fails on one might be your grandma being weird with her debit card on vacation.
> If a card swipes in Chicago and seven minutes later swipes in Los Angeles, one of those swipes is fake. The card is cloned. This is the most uncontroversial fraud signal you’ll find — there’s almost no legitimate reason a single card is in two distant places in seven minutes.
The question is whether they would treat that as a single card (physical vs digital).
If they don't then this is a good detection system for a very specific scenario (but nonetheless a good trick)
The Apple/Google Pay cards have a DPAN (device account number) that is different to the CPAN of the physical card. It keeps the same issuer (first 6 digits) and the same "last 4" digits, but the others are different.
The DPAN is translated into the CPAN by software at the issuing bank, so it's not identifiable by the merchants.
Merchants get the "last 4" digits, but that's not enough to identify specific CPANs.
They can distinguish a physical card vs Apple Pay
Exactly, hopefully this is not an autoblock in the future.
> A transaction that fails on three or four of them is almost always fraud. A transaction that fails on one might be your grandma being weird with her debit card on vacation.
The article states that the particular item is a clear sign of fraud. If that was true, then it should be treated in a special manner. A more paranoid bank could enforce it without adhering to this guidance of multi-factor detection.
It isn't though, so balancing it with other rules is fine.
This takes me back, fighting telephone fraud back when folks use to accept cc over the phone. We used similar patterns but only had phone numbers and the white pages. Cross state boundaries inside similar time frames and categorizing similar merchant types. It’s fun to see these same patterns still in use 20 years later for the same purpose.
The main problem with these SQL calculations is that they are deterministic shortcuts for a probabilistic problem. Fraud is not usually a “true because rule X matched.” It is more like "what is the probability this is fraudulent"? SQL patterns are useful, but they are blunt instruments. I really don't think banks use deterministic heuristics but more data science stuff.
This is quite interesting, but the blatantly AI generated explanations are like an anti-signal for quality
What if I go on a roadtrip and suddenly get gas at 2am?
I had this happen once - I flew to a city about 8 hours of driving time away to buy a motorcycle and landed late in the evening. My card was declined when I got gas a little after midnight and I had no cash or other card with me so I called the 24 hour support line. I had a quick conversation with a support agent explaining that I was traveling and the card needed to be reactivated right away. Within five minutes the card was working and I was back to working my way down a long chain of mistakes.
As the tail end of the article explains these are independent pieces of evidence not independent proofs: most of them can be legitimate operations (even the speed one, airliners cruise at that speed but if you get to ride a long-range business plane they can cruise faster).
This is the sort of thing I used to love doing and I often gaze at raw data analysis and sometimes wish my career had pivoted towards working with data like this.
But I must admit there was a point where I suddenly lost my love for SQL and it was pretty much when the OVER PARTITION BY syntax appeared.
It never clicks. I always have to look up how it works, I always find it unintuitive. I've never understood why I hate it so much.
> If a card swipes in Chicago and seven minutes later swipes in Los Angeles, one of those swipes is fake. The card is cloned.
Or, the cardholder is trying to do the cannonball run:
This seems interesting, but has so many signs of AI writing that I worry it's not just edited but generated from whole cloth. Probably still a lot of truth in there but it does give me pause!
> The roundness is the signal.
> Slight pain, same result.
to point at a few.
> The “two or more in that hour” filter on the inner query is doing important work.
This is Claude talking isn’t it.
> Three filters. That’s it.
And my favourite most hated pattern, the no no no:
> Not machine learning, not graph databases, not whatever Gartner is hyping this year.
Oh shyte, I use (and have used) these for a long time. Guess everything is classes as AI nowadays just yield and use it (everyone thinks you do anyway)
Not everything of course, not because of a few phrases, not your comment.
But the recent omnipresence of these is just hard to ignore.
This comment certainly does not scan as AI! Look, this isn't perfect, but it's the best we've got, and so long as AI writing is meaningfully worse than human writing, people are going to try to tell the difference.
the real question is whether you would point hour agentic system at this blog post and create
chargeback-mcp
or would you turn it all into a markdown file and call it a skill?
> Real cardholders almost never buy something for exactly $1.00. Coffee is $4.73, gas is $52.81. The roundness is the signal.
Surely this depends on how the vendor sets their prices? If you're going to buy something from a website to test a stolen credit card you don't just get to make up your own prices.
And I think you may be over-indexing on the US "prices don't include tax" thing. Elsewhere, round-number prices are extremely common.
In fact a lot of the rest of the stuff in the post seems like it wouldn't work very well either. (E.g. you're flagging anyone who has done a transaction in the last 90 days outside the range of hours at which they have 2+ transactions? Wouldn't that be like 50% of people?).
It's unclear to me whether this article is an attempt at breaking down complex expertise into over-simplified SQL queries, or whether it is all speculative and made up.
There is a conflict between "Six SQL patterns I use to catch transaction fraud" and "Nothing here comes from anything I’ve actually worked on or seen".
The "transaction outside usual hour range" seems pretty basic.
I don't usually buy gas, coffee or snacks at 2am. But on the very rare occasion that I do, I'm dealing with some kind of personal emergency and don't also want to have to call my bank.
I get that that's also a time opportunistic thieves, etc, might be operating. But the cost of false positives is also a thing.
This is also
a) trivial to bypass by adding dither to the test transactions and
b) trivial to improve upon with proper statistical analysis and
c) shouldn't this kind of heuristic pattern recognition with no expectation of near-100% accuracy be what AI is good at?
Worse than that.
Coffee usually _is_ a round number in my experience, and I know of people who aim for round numbers when filling their car, and of fuel stations which require a pre-set value, often 10, 20, 50€ etc
Yes, as your parent comment points out, the article centers itself on US transactions, where listed prices seldom include tax and are frequently a cent below a round number. For example, the menu says a dish is $15.00 but the restaurant charges $18.83 after tax and tip. Globally, there's no doubt the US is the exception rather than the norm.
All of that is easy to account for, all of the metadata you need is available. This also applies to the sibling comment about rounding up to charity at the grocery store, the data is all there, even if it's e.g. the fraud analyst at the bank or credit card company instead of the fraud analyst at the grocery store.
I don't need to account for it - I'm just stating that this doesn't match my experience:
> Real cardholders almost never buy something for exactly $1.00. Coffee is $4.73, gas is $52.81. The roundness is the signal.
I'm seeing a few stores here and there which have a "round up to donate" option. I guess I'm a bit of a sucker and I always use that option. My groceries are always a round number as a result.
> Border crossings inside 10 minutes. International rings.
Or normal people living in Europe in border-adjacent areas.
Also, I guess you don't include card-not-present transactions in this, but you incorrectly assume that every merchant has their location set correctly. And that every sale happens in a brick-and-mortar establishment, not from travelling salespeople or whatever. And that all transactions happen online.
> Fraud detection in transaction data is mostly SQL. Not machine learning, not graph databases, not whatever Gartner is hyping this year. SQL, run against the right tables, with the right joins, looking for the right shapes.
It's also not all program-integrity, which is the only work that could justify such blanket statements. Worse is better as long as it addresses the problem domain.
Fintech clients are generally interested in knowing whether a transaction happening _right now_ is fraud. They want to know that in a few milliseconds, for high-dimensional data. It's work done at a scale where relational databases cannot meet these real-time constraints, and instead find other uses like historical data loading. That's how you end up with in-memory databases, stream-processing engines, and yes, even machine learning.
Having said that, some of the author's points are valid, and I'm looking forward for their next writings, in particular dealing with noisy alerts is a general problem beyond performance engineering.
Wait, you can clone a credit card? Why don't they use a public-private key pair?
You can only clone magnetic stripe. In a lot of places, you can’t make large transactions with it
> Drawback: this doesn’t work until you have history. New accounts have no baseline.
This is an underrated CX factor: If my card gets denied when i’m a new customer or exhibiting a new pattern, i’m impressed with their software.
However if they deny a transaction where there is any previous history of me authenticating, then I’m frustrated by their naive paranoid algorithm.
The incentives of the bank is to cut fraud.
Fraudulent transactions will eventually cost the bank (when they would have to reverse/reimburse it and eat the loss). A denied transaction only results in an angry customer who will quickly forget after they complained - so the customer bears the brunt of the externalized cost.
Therefore, the bank's incentive is to err on the side of more caution, and deny transactions when finding false positives.
When someone disputes a charge and wins banks charge processor and the original merchant. The bank won’t loose a penny, merchant will.
Isn't the point of ML that you learn these rules from the data? The right approach to me would be to use ML models to detect patterns that correspond with fraud and then evaluate them to see if any make sense. This way you might discover new hyptotheses.
Anything that can't be explained and iterated deterministically is too risky for the business of declining financial transactions.
Human analysts need to be able to explain to compliance in a single 5 minute email why a specific transaction was declined, and most importantly, what could have been done differently to avoid the adverse decision.
Fixing one problem with ML often creates two new problems that aren't quite obvious yet. SQL tends to have fewer surprises with regard to regressions and unexpected side effects as things change over time.
In my experience, Visa support can’t tell me why my legitimate transaction was tagged as fraudulent, other than to say it triggered an AI thing. They also can’t tweak the settings like they used to do, but they can manually allow specific transactions one by one on an ad hoc basis.
I assume that this option is unlocked once you enter litigation against the company.
Umm no, they submit thousands of random pages of business communication and system spec in discovery. This does not include the source code of their algorithm, which in any case if not stored in any form which can be recreated and shared. If you pay a lawyer a million bucks to read them all it would say that they don't know how the algo works. At the same time they offer you low four digits to make the case go away, if you have a case. If you don't have a valid case at all, they rapidly spend $250,000 on filings and motions which you would have to spend $100,000 to stay in the game.
Can also imagine an edge case: couple shares an online account, one is traveling and purchases with the saved card details.
Swiping a card (or inserting, or tapping) is a "card present" transaction. Online shopping, where you type in the card number, is a "card not present" transaction. Retailers and banks can tell the difference.
Also, a Apple/Google/Samsung tap has a different DPAN to the physical card, so it's "card present" but a different card.
They can tell based on transaction metadata. Source: I worked at a cc company
I believe the system distinguishes between card present and card not present.
2 can be genuine use. I let my partner use my card and I use it on my phone as rfid. Maybe ignore phone usages since they are secured pretty well.
All of them can be genuine use, these are fraud signals not fraud proofs, and the article does cover this:
> What works is running them all and scoring each transaction across the signals. A transaction that fails on three or four of them is almost always fraud. A transaction that fails on one might be your grandma being weird with her debit card on vacation.
> If a card swipes in Chicago and seven minutes later swipes in Los Angeles, one of those swipes is fake. The card is cloned. This is the most uncontroversial fraud signal you’ll find — there’s almost no legitimate reason a single card is in two distant places in seven minutes.
The question is whether they would treat that as a single card (physical vs digital).
If they don't then this is a good detection system for a very specific scenario (but nonetheless a good trick)
The Apple/Google Pay cards have a DPAN (device account number) that is different to the CPAN of the physical card. It keeps the same issuer (first 6 digits) and the same "last 4" digits, but the others are different.
The DPAN is translated into the CPAN by software at the issuing bank, so it's not identifiable by the merchants.
Merchants get the "last 4" digits, but that's not enough to identify specific CPANs.
They can distinguish a physical card vs Apple Pay
Exactly, hopefully this is not an autoblock in the future.
> A transaction that fails on three or four of them is almost always fraud. A transaction that fails on one might be your grandma being weird with her debit card on vacation.
The article states that the particular item is a clear sign of fraud. If that was true, then it should be treated in a special manner. A more paranoid bank could enforce it without adhering to this guidance of multi-factor detection.
It isn't though, so balancing it with other rules is fine.
This takes me back, fighting telephone fraud back when folks use to accept cc over the phone. We used similar patterns but only had phone numbers and the white pages. Cross state boundaries inside similar time frames and categorizing similar merchant types. It’s fun to see these same patterns still in use 20 years later for the same purpose.
The main problem with these SQL calculations is that they are deterministic shortcuts for a probabilistic problem. Fraud is not usually a “true because rule X matched.” It is more like "what is the probability this is fraudulent"? SQL patterns are useful, but they are blunt instruments. I really don't think banks use deterministic heuristics but more data science stuff.
This is quite interesting, but the blatantly AI generated explanations are like an anti-signal for quality
What if I go on a roadtrip and suddenly get gas at 2am?
I had this happen once - I flew to a city about 8 hours of driving time away to buy a motorcycle and landed late in the evening. My card was declined when I got gas a little after midnight and I had no cash or other card with me so I called the 24 hour support line. I had a quick conversation with a support agent explaining that I was traveling and the card needed to be reactivated right away. Within five minutes the card was working and I was back to working my way down a long chain of mistakes.
As the tail end of the article explains these are independent pieces of evidence not independent proofs: most of them can be legitimate operations (even the speed one, airliners cruise at that speed but if you get to ride a long-range business plane they can cruise faster).
This is the sort of thing I used to love doing and I often gaze at raw data analysis and sometimes wish my career had pivoted towards working with data like this.
But I must admit there was a point where I suddenly lost my love for SQL and it was pretty much when the OVER PARTITION BY syntax appeared.
It never clicks. I always have to look up how it works, I always find it unintuitive. I've never understood why I hate it so much.
> If a card swipes in Chicago and seven minutes later swipes in Los Angeles, one of those swipes is fake. The card is cloned.
Or, the cardholder is trying to do the cannonball run:
https://www.youtube.com/shorts/Dx5WPNIEwiE
This seems interesting, but has so many signs of AI writing that I worry it's not just edited but generated from whole cloth. Probably still a lot of truth in there but it does give me pause!
> The roundness is the signal.
> Slight pain, same result.
to point at a few.
> The “two or more in that hour” filter on the inner query is doing important work.
This is Claude talking isn’t it.
> Three filters. That’s it.
And my favourite most hated pattern, the no no no:
> Not machine learning, not graph databases, not whatever Gartner is hyping this year.
Oh shyte, I use (and have used) these for a long time. Guess everything is classes as AI nowadays just yield and use it (everyone thinks you do anyway)
Not everything of course, not because of a few phrases, not your comment. But the recent omnipresence of these is just hard to ignore.
This comment certainly does not scan as AI! Look, this isn't perfect, but it's the best we've got, and so long as AI writing is meaningfully worse than human writing, people are going to try to tell the difference.
the real question is whether you would point hour agentic system at this blog post and create
chargeback-mcp
or would you turn it all into a markdown file and call it a skill?