skip to content
all projects
HSBC · Senior ML Engineer · 2025–2026

Real-Time Fraud Detection

A streaming ML platform screening 1M+ transactions a day at sub-100ms latency, cutting false positives against a legacy rules engine without sacrificing fraud recall.

status delivered
domain real-time ML · streaming
compliance FCA · PCI-DSS
stack Python · Kafka · XGBoost · Azure ML · FastAPI · Redis
OVERVIEW

What the system does

Every card transaction is scored for fraud risk in real time before it completes. The platform ingests transaction events off Kafka, computes behavioural and transactional features against a low-latency store, scores them with an XGBoost + Isolation Forest ensemble, and returns an allow / review / block decision — all inside a sub-100ms budget at 1M+ transactions per day.

ENGINEERING GOAL
Reduce false positives that were blocking legitimate customers under the legacy rules engine, without lowering fraud recall — and do it within a hard real-time latency budget.
PROBLEM

Why the rules engine wasn't enough

A static rules engine over-flags: it can't weigh weak signals jointly, so it blocks legitimate transactions and generates alert fatigue for analysts. The requirement was a model that could learn the joint distribution of fraud signals — velocity, device fingerprint, peer-group behaviour — and decision fast enough to sit inline in the authorisation path.

ARCHITECTURE

System architecture

A fault-tolerant streaming pipeline with exactly-once delivery guarantees, a Redis-backed feature store for customer-profile lookups, and an ensemble scoring service exposed over FastAPI.

Card Swipe transaction event Kafka exactly-once ingest Feature Store Redis · low-latency Ensemble XGBoost + IF Risk Score 0–1 calibrated Decision Engine rules + threshold Action / Allow <100ms end-to-end
Figure 1 · HSBC real-time fraud pipeline — Kafka ingestion through inline sub-100ms decisioning.
RELIABILITY

Latency & reliability engineering

The latency budget drove the design. Feature reads are served from Redis rather than recomputed; the ensemble is kept small and quantised; the scoring service is stateless and horizontally scaled.

feature read + score (representative) representative pattern
async def score(txn: Transaction) -> Decision:
    # low-latency feature read (Redis) — no recompute in the hot path
    feats = await feature_store.get(txn.customer_id, txn)   # ~ single-digit ms
    risk = ensemble.predict_proba(feats)                     # XGBoost + IsolationForest
    if risk >= BLOCK_THRESHOLD:
        return Decision.block(reason=top_factor(feats))
    if risk >= REVIEW_THRESHOLD:
        return Decision.review()
    return Decision.allow()                                   # full path < 100ms
EXACTLY-ONCE, NOT AT-LEAST-ONCE
Duplicate scoring on a retried event could double-charge risk or mis-decision. The Kafka pipeline uses exactly-once semantics with reliable ordering so each transaction is scored once, deterministically.
DESIGN DECISIONS

Architecture decision records

ADR-01

Ensemble over a single deep model

accepted

Decision: XGBoost for supervised fraud signal + Isolation Forest for unsupervised anomaly, rather than a single deep net.

Consequence: fast inference within the latency budget, interpretable top-factor reasons for analysts, and coverage of novel fraud the supervised model hasn't seen.

ADR-02

Precompute features, read in the hot path

accepted

Decision: behavioural features are maintained in Redis and read at scoring time, never recomputed inline.

Consequence: the model call, not feature computation, dominates latency — keeping end-to-end under 100ms.

OUTCOMES

Outcomes

VOLUME
1M+/day
LATENCY
<100ms
RECALL
94%
FALSE +
−38%
ON THE FIGURES
Metrics reflect the delivered system; code shown is a representative pattern, not proprietary implementation.