The team had done everything right, or thought they had. Real transaction data was off limits for training, so they generated a synthetic set, injected a clean 5% of anomalies, trained a detector, and watched it hit 0.98 on the held-out split. They shipped it. Two weeks later the alerts made no sense: it waved through a ring of clearly fraudulent accounts and lit up on a retiree's weekly grocery run.
The post-mortem was short. The synthetic anomalies had been scattered uniformly, a random 5% of rows nudged out of range, independently, everywhere. So the model had learned exactly that: anomaly means a value that looks unusual on its own. Real fraud does not work like that.
Real anomalies concentrate
Fraud lives in a small number of bad actors, and each bad actor does several suspicious things in a cluster, surrounded by ordinary behavior. The signal is not "this transaction is large." It is "this account has a pattern." A detector that never saw entity-level structure in training had no way to learn it.
This is the part CrossRow gets right, and it does it with two numbers that map directly onto how fraud actually distributes:
- entity share: the fraction of accounts, devices, or patients that are bad actors. Around 2% by default.
- row share: within a bad actor's history, the fraction of rows that actually misbehave. Around 10%, because even a fraudulent account looks normal most of the time.
account amount anomaly AC-3301 61.80 - AC-3301 44.10 - AC-9928 9,400.00 yes AC-9928 112.00 - AC-9928 8,750.00 yes the risk lives at the account level
What changed when they regenerated
They rebuilt the training set with anomalies concentrated in a 2% slice of accounts. Same volume of positives, completely different shape. The new detector learned that a suspicious event raises the odds of another from the same account, that most activity from even a bad actor is benign, that risk is a property of the entity and not just the transaction. Those are the patterns that survive contact with production.
The labels came for free. Because CrossRow generates the anomalies, it knows exactly which rows and which entities are positive, at both levels. The team was not guessing which synthetic rows to trust as ground truth; the supervision was exact, which is often the hardest thing to get out of de-identified real data, where the labels are the most sensitive column of all.
Shaped by the domain, not bolted on
The anomalies also fit the schema's own logic instead of being generic outliers. In a banking dataset a bad actor runs an overdraft pattern; in an operations dataset a sensor drifts before a failure. The violation obeys the domain, which makes it a hard example worth training on rather than an obvious one the model clears trivially.
The test of a synthetic anomaly set is whether a model trained on it recognizes the real thing. Scattered noise fails that test in production, quietly, after it has already passed in validation. Concentrated, entity-level, domain-shaped anomalies with exact labels are what pass it. Both shares are tunable, and the quality report tells you the rate that actually landed.