Building Fraud Detection Systems: Lessons from a BNPL Platform
Leading the design of fraud detection for a distributed BNPL platform taught me something I didn't fully appreciate going in: fraud detection isn't primarily a machine learning problem. The model is one piece. The harder engineering problem is building a system that can make a real-time decision, under latency pressure, without either blocking legitimate customers or letting obvious fraud through, while staying maintainable as fraud patterns keep shifting.
The latency constraint changes everything
A fraud check that takes three seconds is often worse than a slightly less accurate one that takes 200 milliseconds, because the customer is standing at a checkout screen waiting. This constraint shaped almost every architectural decision on that platform. We couldn't run every possible check for every transaction. We had to build a tiered system: fast, cheap rules that caught obvious fraud immediately, backed by a more expensive model-based check only when the cheap rules didn't produce a confident answer either way.
csharp
public async Task<FraudDecision> EvaluateAsync(Transaction transaction)
{
var quickResult = _ruleEngine.Evaluate(transaction);
if (quickResult.Confidence > 0.9) return quickResult.Decision;
return await _mlScoringService.ScoreAsync(transaction);
}
This tiered approach kept the common case fast while still giving genuinely ambiguous transactions the deeper evaluation they needed.
Rules and models need to coexist, not compete
Early on there was a temptation to treat the ML model as the eventual replacement for hand-written rules. In practice, the two served different purposes and both stayed valuable. Rules were transparent, fast to update, and easy to explain to a compliance team asking why a specific transaction was flagged. The model caught subtler patterns rules couldn't easily express, but its decisions were harder to explain after the fact. Keeping both, with rules as the first line and the model as the deeper check, gave us both speed and explainability where each mattered most.
Feedback loops matter more than the initial model
Fraud patterns don't stay still. A model trained on last year's fraud data degrades against new tactics without anyone touching the code. Building a reliable feedback loop, where confirmed fraud and confirmed false positives flow back into retraining, mattered more long-term than any single model's initial accuracy. Teams that treat the model as a one-time deliverable are setting themselves up for quietly worsening detection over time.
False positives have a real cost, not just a theoretical one
It's easy to optimize purely for catching fraud and lose sight of the cost of blocking legitimate customers. A customer wrongly declined at checkout doesn't just fail one transaction, they often don't come back. We tracked false positive rate as seriously as we tracked fraud catch rate, and reviewed both together rather than treating fraud detection as a problem with only one failure mode.
Explaining decisions, even to yourself
When a transaction gets flagged, someone eventually asks why. If your system can't answer that clearly, you're flying blind on your own fraud detection, and worse, you can't improve a decision process you can't inspect. We logged the specific rule or model signal that drove each decision, not just the final outcome, because that log became the single most useful input for improving the system over time.
csharp
_logger.LogInformation("Fraud decision {Decision} for transaction {Id}, triggered by {Signal}",
decision, transaction.Id, triggeredSignal);
Resilience matters here too
A fraud service that goes down shouldn't take checkout down with it. We built explicit fallback behavior, a conservative default when the fraud service was unreachable, rather than letting an outage in one service cascade into blocking every transaction platform-wide. This is the same resilience thinking I'd apply to any critical downstream dependency, applied specifically to a service where both failure directions, blocking everyone or blocking no one, carry real cost.
The real lesson
Fraud detection succeeds or fails on the engineering around the model as much as the model itself: latency budgets, explainability, feedback loops, and graceful degradation when the detection service itself has a bad day. The model gets most of the attention. The system around it is what actually makes it trustworthy in production.