Skip to content

Repository files navigation

πŸ›‘οΈ Sentinel β€” Real-Time Transaction Anomaly Scoring engine

Java Spring Boot Apache Kafka Redis PostgreSQL Python FastAPI scikit-learn NumPy Pandas Pydantic Uvicorn Joblib Docker Status

Every transaction. Every millisecond. Every threat.

Sentinel is a production-grade, event-driven transaction anomaly scoring engine that scores financial transactions in real time using a dual-engine approach β€” a 9-rule deterministic engine running in parallel with a live ML microservice β€” aggregating both into a single verdict, streamed to a live dashboard over WebSockets.

Architecture β€’ Rules Engine β€’ ML Service β€’ API Docs β€’ Testing β€’ Setup


πŸŽ₯ Demo Video

Watch Sentinel in action!

πŸ”— Click here to view the Google Drive Demo Video (https://drive.google.com/file/d/1HYvNNlW45PMOqGAbC7aJ-7r429RszniW/view?usp=sharing)


πŸ“Έ Screenshots

Here is a glimpse of the Sentinel Dashboard in action:

Real-Time Alerts & Analytics

Dashboard Overview

User Details Lookup

User Lookup

Transaction Search & History

Recent Transactions

Risk Assessment & Flagging

Risk Status

Detailed Transaction View

Transaction Details

⚑ What Makes Sentinel Different

Feature Sentinel
Processing Model Fully async, event-driven via Apache Kafka
Scoring Engines 9 rule-based checks + Isolation Forest ML model β€” run in parallel
Weighting 75% rules Β· 25% ML Β· graceful timeout fallback
Velocity Tracking Redis ZSET sliding windows: 5-min Β· 1-hr Β· 24-hr
AML Patterns Structuring detection Β· Beneficiary/mule analysis Β· 90-day tracking
Real-time Output WebSocket push to live dashboard on every verdict
Idempotency Duplicate requestId silently ignored β€” safe for retries
DB Write Authority Only Spring Boot writes to the database β€” ML service is read-only

πŸ—οΈ Architecture

High-Level Architecture

graph TB
    Client["πŸ–₯️ Client / Postman"] -->|POST /transaction/check| API["Spring Boot API\n:8080"]

    subgraph "Event Bus β€” Apache Kafka"
        T1["πŸ“¨ transactions-incoming"]
        T2["πŸ“¨ engine-input"]
        T3["πŸ“¨ rule-scores"]
        T4["πŸ“¨ ml-scores"]
        T5["πŸ“¨ risk-results"]
    end

    subgraph "Spring Boot Services"
        TS["TransactionService\n(Kafka Producer + Consumer)"]
        RSS["RiskScoringService\n(9 Rules Engine)"]
        AGG["AggregatorService\n(Score Combiner)"]
        BS["BroadcastService\n(WebSocket)"]
    end

    subgraph "ML Microservice β€” FastAPI :8001"
        FE["FeatureEngineer\n(Redis Feature Extraction)"]
        IF["IsolationForest Model\n(17 behavioral features)"]
    end

    subgraph "Storage"
        PG[("🐘 PostgreSQL\nTransactions + Risk")]
        RD[("πŸ”΄ Redis\nVelocity Β· History Β· Beneficiary")]
    end

    API --> T1
    T1 --> TS
    TS -->|Save txn| PG
    TS -->|Write velocity| RD
    TS -->|Write history| RD
    TS -->|Write beneficiary| RD
    TS --> T2

    T2 --> RSS
    T2 --> FE
    FE --> IF
    RSS --> T3
    IF --> T4

    T3 --> AGG
    T4 --> AGG
    AGG -->|Save RiskAssessment| PG
    AGG --> T5
    T5 --> BS
    BS -->|"/dashboard/alerts"| Dashboard["πŸ“Š Live Dashboard\n(WebSocket + STOMP)"]
Loading

Low-Level Architecture β€” Data Flow

sequenceDiagram
    participant C as Client
    participant SB as Spring Boot
    participant K as Kafka
    participant RE as Rules Engine
    participant ML as ML FastAPI
    participant R as Redis
    participant DB as PostgreSQL
    participant WS as WebSocket

    C->>SB: POST /transaction/check {requestId, amount, userId...}
    SB->>SB: Validate user + merchant exist
    SB->>K: Publish β†’ transactions-incoming
    SB-->>C: 202 Accepted

    K->>SB: consume() [risk-analyzer-group]
    SB->>DB: INSERT Transaction (status=UNFLAGGED)
    SB->>R: ZADD users:{id}:velocity  (5-min/1-hr/24-hr windows)
    SB->>R: ZADD history:users:{id}   (30-day cache)
    SB->>R: ZADD beneficiary:user:{id} (90-day merchant tracking)
    SB->>K: Publish β†’ engine-input (TransactionEnrichedDto)

    par Parallel Execution
        K->>RE: consume() [rules-engine-group]
        RE->>DB: Load 30-day tx history
        RE->>R: Read velocity ZSETs
        RE->>R: Read beneficiary ZSETs
        RE->>RE: Run 9 rules β†’ weighted score
        RE->>K: Publish β†’ rule-scores
    and
        K->>ML: consume() [ml-engine-group]
        ML->>R: Read velocity / beneficiary features
        ML->>ML: Extract 17 features β†’ Isolation Forest
        ML->>K: Publish β†’ ml-scores
    end

    K->>SB: consumeRuleScore() + consumeMlScore()
    SB->>SB: Aggregate: 75% rules + 25% ML
    SB->>DB: SAVE RiskAssessment
    SB->>DB: UPDATE Transaction.status (FLAGGED / UNFLAGGED)
    SB->>K: Publish β†’ risk-results
    K->>WS: consumeForRiskResult()
    WS-->>C: Push RiskAssessmentDto via STOMP /dashboard/alerts
Loading

Aggregator Timeout Logic

flowchart TD
    A["rule-scores received"] --> B{ml-scores\nalready here?}
    B -- Yes --> C["Aggregate Immediately\n75% rules + 25% ML"]
    B -- No --> D["Schedule 3-sec timeout"]
    D --> E{ml-scores arrive\nbefore timeout?}
    E -- Yes --> C
    E -- No --> F["Fallback: 100% rules score"]
    C --> G["Save RiskAssessment β†’ DB"]
    G --> H["Publish β†’ risk-results"]
    H --> I["WebSocket push to dashboard"]
Loading

--

πŸ“ Full Project Structure

Sentinel/
β”‚
β”œβ”€β”€ πŸ“„ docker-compose.yml           # Zookeeper + Kafka + Redis
β”œβ”€β”€ πŸ“„ pom.xml                      # Spring Boot 3.5 deps
β”‚
β”œβ”€β”€ 🐍 ml-service/                  # Python FastAPI ML Microservice
β”‚   β”œβ”€β”€ Dockerfile
β”‚   β”œβ”€β”€ requirements.txt
β”‚   β”œβ”€β”€ train_model.py              # Isolation Forest training script
β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”œβ”€β”€ fraud_model.pkl         # Trained model artifact
β”‚   β”‚   β”œβ”€β”€ scaler.pkl              # StandardScaler artifact
β”‚   β”‚   └── feature_schema.json     # 17-feature strict schema
β”‚   └── app/
β”‚       β”œβ”€β”€ main.py                 # FastAPI app + Kafka consumer/producer
β”‚       β”œβ”€β”€ ml_model.py             # IsolationForest wrapper
β”‚       β”œβ”€β”€ feature_engineering.py  # Redis-backed feature extraction
β”‚       └── config.py               # Pydantic settings
β”‚
└── β˜• src/
    └── main/
        β”œβ”€β”€ resources/
        β”‚   β”œβ”€β”€ application.properties
        β”‚   └── static/
        β”‚       └── index.html      # Built-in Sentinel Dashboard UI
        β”‚
        └── java/com/example/Sentinel/
            β”‚
            β”œβ”€β”€ SentinelApplication.java
            β”œβ”€β”€ WebConfig.java              # CORS config
            β”‚
            β”œβ”€β”€ πŸŽ›οΈ config/
            β”‚   β”œβ”€β”€ KafkaConfig.java        # 5 topics + 5 consumer factories
            β”‚   β”œβ”€β”€ RedisConfig.java        # StringRedisSerializer setup
            β”‚   β”œβ”€β”€ WebsocketConfig.java    # STOMP endpoint config
            β”‚   └── MccRegistry.java        # MCC risk level map
            β”‚
            β”œβ”€β”€ 🌐 controller/
            β”‚   β”œβ”€β”€ TransactionController.java
            β”‚   β”œβ”€β”€ UserController.java
            β”‚   └── DashboardController.java
            β”‚
            β”œβ”€β”€ πŸ“¦ dto/
            β”‚   β”œβ”€β”€ MoneyTransferDto.java       # Inbound request
            β”‚   β”œβ”€β”€ TransactionEnrichedDto.java # Internal Kafka msg
            β”‚   β”œβ”€β”€ RuleScoreDto.java           # Rules engine output
            β”‚   β”œβ”€β”€ MlScoreDto.java             # ML service output
            β”‚   β”œβ”€β”€ RiskAssessmentDto.java      # Final verdict
            β”‚   β”œβ”€β”€ TransactionDto.java
            β”‚   └── UsersDetailDto.java
            β”‚
            β”œβ”€β”€ πŸ—„οΈ entity/
            β”‚   β”œβ”€β”€ Transaction.java
            β”‚   β”œβ”€β”€ Users.java
            β”‚   └── RiskAssessment.java
            β”‚
            β”œβ”€β”€ πŸ—ƒοΈ repo/
            β”‚   β”œβ”€β”€ TransactionRepo.java
            β”‚   β”œβ”€β”€ UsersRepo.java
            β”‚   └── RiskAssessmentRepo.java
            β”‚
            β”œβ”€β”€ βš–οΈ rules/                       # 9 Pluggable Rule Classes
            β”‚   β”œβ”€β”€ AmountRule.java             # Z-score deviation
            β”‚   β”œβ”€β”€ VelocityRule.java           # Redis ZSET sliding windows
            β”‚   β”œβ”€β”€ UserLocationRule.java        # Location frequency %
            β”‚   β”œβ”€β”€ TimeOfTransactionRule.java  # Hour-of-day pattern
            β”‚   β”œβ”€β”€ MerchantCategoryCodeRule.java # MCC risk level
            β”‚   β”œβ”€β”€ CrossBorderRule.java        # International flag
            β”‚   β”œβ”€β”€ DeviceFingerPrintRule.java  # Device frequency %
            β”‚   β”œβ”€β”€ StructuringRule.java        # AML structuring detection
            β”‚   └── BeneficiaryRule.java        # Mule account detection
            β”‚
            └── πŸ”§ services/
                β”œβ”€β”€ TransactionService.java     # Core orchestrator
                β”œβ”€β”€ RiskScoringService.java     # Rules aggregation
                β”œβ”€β”€ AggregatorService.java      # ML + Rules combiner
                └── BroadcastService.java       # WebSocket broadcaster

βš–οΈ Rules Engine

Sentinel runs 9 deterministic rules on every transaction. Each rule produces a score; scores are combined using a calibrated weighted formula.

Rule Scoring Table

Rule Max Score Signal Threshold
Amount Rule 40 Z-score vs. 30-day history >3Οƒ = 40pts
Velocity Rule 35 Redis ZSET count in windows >6 txn/5min = 35pts
Structuring Rule 80 AML near-threshold clustering 5+ txns 70k-100k in 48hr
Merchant Category 30 MCC risk level + novelty Gambling = 30pts
Beneficiary Rule 30 Mule detection via 90-day ZSET >7 unique merchants/24hr
Time Rule 25 Hour-of-day pattern 2AM–5AM unseen = 25pts
Location Rule 10 Location frequency % <60% familiar = 10pts
Device Fingerprint 10 Device frequency % <60% familiar = 10pts
Cross-Border 10 International flag Any cross-border = 10pts

Weighted Score Formula

weighted = (amountScore Γ— 0.20)
         + (velocityScore Γ— 0.15)
         + (locationScore Γ— 0.10)
         + (mccScore Γ— 0.10)
         + (timeScore Γ— 0.10)
         + (crossBorderScore Γ— 0.05)
         + (deviceScore Γ— 0.10)
         + (structuringScore Γ— 0.10)
         + (beneficiaryScore Γ— 0.10)

scaledScore = (weighted / 32.25) Γ— 100

if nonZeroRules β‰₯ 5 β†’ scaledScore Γ— 1.35   ← multi-rule amplifier
if nonZeroRules β‰₯ 3 β†’ scaledScore Γ— 1.20

ruleScore = min(scaledScore, 100)

Final Aggregated Score

finalScore = (ruleScore Γ— 0.75) + (mlScore Γ— 0.25)   ← both engines present
           = ruleScore                                 ← ML timed out (graceful)
           = mlScore                                   ← rules timed out

fraudLevel: LOW (0–35) | MEDIUM (36–50) | HIGH (51–100)

πŸ€– ML Microservice

A standalone Python FastAPI service that consumes the engine-input Kafka topic and publishes scores to ml-scores.

Feature Engineering (17 Features)

Amount Features:       amount_zscore, amount_percentile
Velocity Features:     velocity_5min, velocity_1hr, velocity_24hr, velocity_burst_score
Merchant Features:     merchant_seen_before, unique_merchants_24hr, merchant_diversity_score
Device Features:       device_seen_before, device_novelty_score
Location Features:     location_seen_before, location_novelty_score
Time Features:         hour_of_day, is_unusual_hour, hour_deviation_score
Border Feature:        is_cross_border

All features are extracted from live Redis data β€” no simulation, no stale data.

Model

Algorithm:     Isolation Forest (sklearn)
Training Data: 10,000 synthetic samples (90% legit / 10% fraud)
Scaler:        StandardScaler
Output:        fraud_score (0–100%), confidence, prediction_class

Training the Model

cd ml-service
python train_model.py
# Generates: models/fraud_model.pkl, models/scaler.pkl, models/feature_schema.json

πŸ—ƒοΈ Redis Data Model

Three independent ZSET namespaces power real-time risk signals:

Key Pattern Purpose TTL Window
users:{id}:velocity Transaction count for velocity rule 24 hours
history:users:{id} Transaction ID cache for 30-day lookups 30 days
beneficiary:user:{id} Merchant IDs for mule detection 90 days
ZADD users:1:velocity    <epoch_ms>  <txnId>   β†’ 5-min / 1-hr / 24-hr ZCOUNT
ZADD history:users:1     <epoch_ms>  <txnId>   β†’ rangeByScore for DB fallback
ZADD beneficiary:user:1  <epoch_ms>  <merchantId> β†’ unique merchant count

πŸ“‘ API Documentation

User Management

Create User

POST /users/add
Content-Type: application/json

{
  "email": "alice@example.com",
  "phoneNumber": "9876543210",
  "name": "Alice Johnson",
  "homeLocation": "Mumbai"
}
201 Created
"User created..."

409 Conflict
"User already existed"

Get User Details

GET /users/userdetails?user_id=1
200 OK
{
  "userId": 1,
  "email": "alice@example.com",
  "name": "Alice Johnson",
  "phoneNumber": "9876543210",
  "homeLocation": "Mumbai",
  "createdAt": "2026-03-07T10:00:00"
}

Transaction Flow

Submit Transaction for Fraud Check

POST /transaction/check
Content-Type: application/json

{
  "requestId": "txn-001",
  "amount": 85000.00,
  "locationOfUser": "Mumbai",
  "timeOfPayment": "2026-03-07T03:00:00",
  "merchantId": 4,
  "userId": 1,
  "merchantCategoryCode": 7995,
  "crossBorder": true,
  "deviceFingerPrint": "device-unknown-hacker"
}
202 Accepted
"transaction accepted"

The response is immediate. The actual fraud score is computed asynchronously and pushed to the WebSocket dashboard.

Get Transaction Details

GET /transaction/details?transactionId=1
200 OK
{
  "transactionId": 1,
  "userId": 1,
  "amount": 85000.00,
  "merchantId": 4,
  "userLocation": "Mumbai",
  "timeOfTransaction": "2026-03-07T03:00:00",
  "status": "FLAGGED",
  "merchantCategoryCode": 7995,
  "crossBorder": true,
  "deviceFingerPrint": "device-unknown-hacker"
}

Top 10 Recent Transactions for User

GET /transaction/top10ForUser?userId=1

Last 30 Days Transactions for User

GET /transaction/Last30ForUser?userId=1

Dashboard Endpoints

Full History (for dashboard restore)

GET /dashboard/history
200 OK
[
  {
    "id": 1,
    "transactionId": 42,
    "userId": 1,
    "amount": 85000.00,
    "amountScore": 40,
    "velocityScore": 35,
    "locationScore": 10,
    "timeScore": 25,
    "merchantCategoryScore": 30,
    "crossBorderScore": 10,
    "deviceFingerPrintScore": 10,
    "structuringScore": 30,
    "beneficiaryScore": 15,
    "sequenceScore": 0,
    "overallScore": 94.7,
    "mlScore": 78.3,
    "fraudPossibility": "HIGH",
    "triggeredRules": [
      "Amount Rule",
      "Velocity Rule",
      "Structuring Rule",
      "Cross Border Rule",
      "Merchant Category Rule",
      "Device Finger Print Rule",
      "Time Of Transaction Rule",
      "ML Model Alert"
    ]
  }
]

Risk by Transaction

GET /dashboard/riskByTransaction?transactionId=42

ML Service Endpoints

Health Check

GET http://localhost:8001/health
{
  "status": "healthy",
  "service": "ML Fraud Detection Service",
  "model_version": "fraud-detector-v1.0",
  "model_type": "Behavioral Anomaly Detection"
}

Manual Predict

POST http://localhost:8001/predict
Content-Type: application/json

{ ...transaction fields... }
{
  "fraudScore": 78.3,
  "confidence": 0.82,
  "predictionClass": "FRAUD",
  "modelVersion": "fraud-detector-v1.0",
  "extractedFeatures": { ... }
}

πŸ§ͺ Testing

Postman Test Suite

A curated, production-quality Postman collection is included: Sentinel_Postman_Tests_Version2.json

Import it directly into Postman. Execute folders in order β€” each section builds state for the next.

πŸ“ 1. User Management
   β”œβ”€β”€ 1.1  Create User - Alice (Valid)
   β”œβ”€β”€ 1.2  Create User - Duplicate Email        β†’ expects 409
   β”œβ”€β”€ 1.3a Create User - Bob
   β”œβ”€β”€ 1.3b Create User - Merchant 1 (Electronics)
   β”œβ”€β”€ 1.3c Create User - Merchant 2 (Gambling)
   β”œβ”€β”€ 1.3d Create User - Merchant 3 (Grocery)
   β”œβ”€β”€ 1.4  Get User Details - Valid ID 1
   β”œβ”€β”€ 1.5  Get User Details - Invalid ID 999    β†’ expects 400
   β”œβ”€β”€ 1.6  Create User - Invalid Email          β†’ expects 400
   └── 1.7  Create User - Invalid Phone          β†’ expects 400

πŸ“ 2. Basic Transaction Flow
   β”œβ”€β”€ 2.1  Normal Transaction - Low Risk
   β”œβ”€β”€ 2.1b Verify Transaction Details (ID=1)
   β”œβ”€β”€ 2.2  Duplicate RequestId - Idempotency    β†’ silent no-op
   β”œβ”€β”€ 2.3  Transaction - Non-existent User      β†’ expects 500
   └── 2.4  Transaction - Non-existent Merchant  β†’ expects 500

πŸ“ 3. Amount Rule Testing
   β”œβ”€β”€ 3.1a–e Build Baseline (1000, 1200, 900, 1100, 1050)
   β”œβ”€β”€ 3.2    Moderate Amount (1σ–2Οƒ) β†’ score 10
   β”œβ”€β”€ 3.3    High Amount (2σ–3Οƒ)     β†’ score 25
   └── 3.4    Very High Amount (>3Οƒ)  β†’ score 40

πŸ“ 4. Velocity Rule Testing
   β”œβ”€β”€ 4.1    Normal Velocity Baseline
   β”œβ”€β”€ 4.2a–e 5-min Velocity (1–5 txns) β†’ score 0
   β”œβ”€β”€ 4.3    6th txn in 5 min          β†’ score 15
   └── 4.3b   7th txn in 5 min          β†’ score 35

πŸ“ 5. Location Rule Testing
   β”œβ”€β”€ 5.1a–j Build Mumbai baseline (10 consistent txns)
   β”œβ”€β”€ 5.2    Moderate - Delhi           β†’ score 5
   β”œβ”€β”€ 5.2b   Moderate - Delhi (2nd)    β†’ score 5
   └── 5.3    Suspicious - Kolkata      β†’ score 10

πŸ“ 6. Time Rule Testing
   β”œβ”€β”€ 6.1    Normal Business Hours (2PM) β†’ score 0
   β”œβ”€β”€ 6.2    Unusual Hours (3AM)         β†’ score 25
   └── 6.3    Off-hours (8PM)             β†’ score 15

πŸ“ 7. MCC Rule Testing
   β”œβ”€β”€ 7.1    Low-Risk MCC (Grocery 5411)  β†’ score 5
   β”œβ”€β”€ 7.2    Medium-Risk MCC (Travel 4722) β†’ score 15
   β”œβ”€β”€ 7.3    High-Risk MCC (Gambling 7995) β†’ score 30
   └── 7.4    Unknown MCC (9999)            β†’ score 10

πŸ“ 8. Cross-Border Rule Testing
   β”œβ”€β”€ 8.1    Domestic Transaction β†’ score 0
   └── 8.2    Cross-Border         β†’ score 10

πŸ“ 9. Device Fingerprint Rule Testing
   β”œβ”€β”€ 9.1a–j Consistent Device (10 txns with same fingerprint) β†’ score 0
   β”œβ”€β”€ 9.2    Moderate - New Phone  β†’ score 5
   └── 9.3    Suspicious Unknown Device β†’ score 10

πŸ“ 10. Structuring Rule Testing (AML)
   β”œβ”€β”€ 10.1   Normal single txn (50k)      β†’ no flag
   β”œβ”€β”€ 10.2a–e Rapid Near-Threshold 5 txns (75k–85k in 2hr) β†’ score 30
   └── 10.3   Cumulative >10L (650k)       β†’ score 50+

πŸ“ 11. Beneficiary Rule Testing (Mule Detection)
   β”œβ”€β”€ 11.1   Normal - Existing Merchant  β†’ score 0–5
   β”œβ”€β”€ 11.2a–b 24-hr Merchant Velocity    β†’ score 5–10
   β”œβ”€β”€ 11.3a  High Value to New Beneficiary 1 (25k) β†’ score elevated
   └── 11.3b  High Value to New Beneficiary 2 (30k) β†’ score elevated

Import Instructions

# 1. Open Postman
# 2. Click Import β†’ Upload File β†’ select Sentinel_Postman_Tests_Version2.json
# 3. Set environment variable: baseUrl = http://localhost:8080
# 4. Run folders in sequence 1 β†’ 11

✨ Features

🎯 Core Capabilities

Feature What it does
⚑ Dual-Engine Scoring 9 rules + Isolation Forest ML run in parallel. Weighted 75/25, with 3-sec graceful fallback if either engine lags.
πŸ”„ Fully Async Pipeline API returns 202 Accepted instantly. All scoring flows through 5 Kafka topics β€” zero blocking.
πŸ”΄ Redis Velocity Windows ZSET sliding windows at 5-min Β· 1-hr Β· 24-hr per user. Self-pruning on every write β€” sub-millisecond reads.
🏦 AML Structuring Detection Flags 5+ near-threshold txns (β‚Ή70k–₹1L) within 48hrs, or cumulative volume breaching β‚Ή10L.
πŸ•΅οΈ Mule Account Detection 90-day rolling ZSET tracks unique merchant relationships. Rapid fan-out to new merchants = red flag.
πŸ”’ Idempotent Processing requestId deduplicates at the DB constraint level β€” atomic, race-safe, zero extra round trips.
πŸ“‘ Live WebSocket Dashboard Every verdict pushed via STOMP/SockJS. Built-in /index.html β€” no frontend build needed.
πŸ›‘οΈ Single Write Authority Only Spring Boot writes to PostgreSQL. ML service is purely stateless β€” reads Redis, writes Kafka.

πŸ’» Dashboard Capabilities

Capability Detail
🚨 Live Alert Feed Colour-coded πŸ”΄πŸŸ‘πŸŸ’ verdicts streaming in real time with triggered rule badges and ML score
πŸ“Š Risk Distribution Chart Chart.js doughnut β€” auto-updates on every WebSocket push
πŸ” Transaction Search By txn ID Β· top-10 per user Β· 30-day history β€” all enriched with risk scores
πŸ‘€ User Lookup Instant profile fetch β€” name, email, location, registration date
πŸ“ˆ Live Stats Cards Total transactions Β· High-risk count Β· Avg risk score Β· Flagged rate
πŸ”„ History Restore Pulls full DB history on page load β€” dashboard never starts empty

⚑ Performance Optimization

βœ… Current Optimizations

Optimization Impact
Redis-First Reads ZSETs serve velocity + history + beneficiary at O(log N). PostgreSQL only hit on cold cache. Rule eval stays under 5ms warm.
True Parallel Engines Rules engine and ML service are separate consumer groups on engine-input. Neither blocks the other β€” aggregator merges on first-arrival.
Self-Pruning ZSETs ZREMRANGEBYSCORE runs on every write β€” no TTL jobs, no memory bloat, windows stay exact.
Typed Kafka Factories 5 dedicated ConcurrentKafkaListenerContainerFactory instances β€” deserialization errors in one topic can't contaminate others.
Lazy Loading + EntityGraph FetchType.LAZY everywhere. @EntityGraph applied surgically only where joins are genuinely needed β€” eliminates N+1.
DB-Level Idempotency Unique constraint on requestId β€” atomic duplicate rejection with no extra SELECT or Redis lock.
ConcurrentHashMap Aggregation Pending rule/ML scores held in memory β€” zero DB reads during the aggregation window, cleaned up immediately after publish.

πŸš€ Future Performance Targets

  • Kafka partition-by-userId β€” Guarantee per-user ordering without global locks
  • Redis Cluster sharding β€” Distribute ZSETs across nodes for million-user scale
  • ONNX model serving β€” 3–5Γ— faster ML inference, language-agnostic portability
  • PostgreSQL read replicas β€” Offload dashboard history reads from the primary write node

🌐 Deployment Guide

Infrastructure Overview

Service Platform Free Tier
Spring Boot API Back4App Containers βœ… Yes
ML FastAPI Service Back4App Containers βœ… Yes
Dashboard Frontend Netlify βœ… Yes
PostgreSQL Back4App (built-in) βœ… Yes
Redis Redis Labs (Redis Cloud) βœ… 30MB free
Apache Kafka Upstash Kafka βœ… 10k msg/day free

1️⃣ Redis β€” Redis Labs (Redis Cloud)

1. Go to https://redis.com/try-free/
2. Create a free database (30MB, no credit card)
3. Copy: Public Endpoint, Password
4. Update application.properties:
spring.data.redis.host=redis-XXXXX.c1.us-east-1-2.ec2.cloud.redislabs.com
spring.data.redis.port=XXXXX
spring.data.redis.password=YOUR_REDIS_PASSWORD
# ml-service/app/feature_engineering.py
self.redis_client = redis.Redis(
    host="redis-XXXXX.c1.us-east-1-2.ec2.cloud.redislabs.com",
    port=XXXXX,
    password="YOUR_REDIS_PASSWORD",
    decode_responses=True,
    ssl=True
)

2️⃣ Kafka β€” Upstash

1. Go to https://upstash.com/ β†’ Create Kafka Cluster
2. Create 5 topics manually:
   transactions-incoming Β· engine-input Β· rule-scores Β· ml-scores Β· risk-results
3. Copy: Bootstrap Server URL, Username, Password
4. Update application.properties:
spring.kafka.bootstrap-servers=YOUR-CLUSTER.upstash.io:9092
spring.kafka.properties.security.protocol=SASL_SSL
spring.kafka.properties.sasl.mechanism=SCRAM-SHA-256
spring.kafka.properties.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
  username="YOUR_USERNAME" password="YOUR_PASSWORD";
# ml-service/app/config.py β€” update kafka_bootstrap_servers
# Add SASL config to KafkaConsumer and KafkaProducer in main.py:
security_protocol="SASL_SSL",
sasl_mechanism="SCRAM-SHA-256",
sasl_plain_username="YOUR_USERNAME",
sasl_plain_password="YOUR_PASSWORD"

3️⃣ ML Service β€” Back4App Containers

1. Train model locally first: python train_model.py
   (Commit fraud_model.pkl + scaler.pkl + feature_schema.json to the repo)
2. Go to https://www.back4app.com/ β†’ Containers β†’ New Container
3. Connect your GitHub repo, select the ml-service/ folder
4. Set root directory: ml-service
5. Dockerfile is already present β€” Back4App auto-detects it
6. Add Environment Variables:
KAFKA_BOOTSTRAP_SERVERS=YOUR-CLUSTER.upstash.io:9092
REDIS_HOST=redis-XXXXX.c1.us-east-1-2.ec2.cloud.redislabs.com
REDIS_PORT=XXXXX
REDIS_PASSWORD=YOUR_REDIS_PASSWORD
7. Deploy β†’ Copy the public URL (e.g. https://ml-service-xxx.b4a.run)

4️⃣ Spring Boot API β€” Back4App Containers

1. Create a Dockerfile in the project root:
FROM eclipse-temurin:17-jdk-alpine AS build
WORKDIR /app
COPY . .
RUN ./mvnw package -DskipTests

FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
2. Go to Back4App β†’ Containers β†’ New Container
3. Connect GitHub repo (root directory = project root)
4. Add Environment Variables:
SPRING_DATASOURCE_URL=jdbc:postgresql://YOUR_PG_HOST:5432/sentinel
SPRING_DATASOURCE_USERNAME=postgres
SPRING_DATASOURCE_PASSWORD=YOUR_PG_PASSWORD
SPRING_DATA_REDIS_HOST=redis-XXXXX.c1.us-east-1-2.ec2.cloud.redislabs.com
SPRING_DATA_REDIS_PORT=XXXXX
SPRING_DATA_REDIS_PASSWORD=YOUR_REDIS_PASSWORD
SPRING_KAFKA_BOOTSTRAP_SERVERS=YOUR-CLUSTER.upstash.io:9092
CORS_ORIGINS=https://your-frontend.netlify.app
5. Deploy β†’ Copy the public URL (e.g. https://sentinel-xxx.b4a.run)

5️⃣ Frontend Dashboard β€” Netlify

The dashboard is a single index.html in src/main/resources/static/. Deploy it independently:

1. Copy src/main/resources/static/index.html to a new folder: sentinel-dashboard/
2. Update the API_BASE constant in index.html:
// Line ~230 in index.html
const API_BASE = 'https://sentinel-xxx.b4a.run';  // Your Back4App URL
3. Go to https://netlify.com β†’ Sites β†’ Deploy manually
4. Drag-and-drop the sentinel-dashboard/ folder
5. Done β€” your dashboard is live at https://your-site.netlify.app

βœ… Production Checklist

☐ Redis Cloud endpoint + password updated in both Spring Boot and ML service
☐ Upstash Kafka SASL credentials set in both services
☐ All 5 Kafka topics created in Upstash dashboard
☐ ML model artifacts committed (fraud_model.pkl, scaler.pkl, feature_schema.json)
☐ CORS_ORIGINS set to your Netlify domain in Back4App env vars
☐ API_BASE in index.html updated to Back4App Spring Boot URL
☐ spring.jpa.hibernate.ddl-auto=update (not create-drop) for prod
☐ H2 console disabled: spring.h2.console.enabled=false

πŸš€ Quick Start

Prerequisites

Java 17+
Maven 3.9+
Docker + Docker Compose
Python 3.11+

Step 1 β€” Start Infrastructure

docker-compose up -d
# Starts: Zookeeper (:2181) Β· Kafka (:9092) Β· Redis (:6379)

Step 2 β€” Train the ML Model

cd ml-service
pip install -r requirements.txt
python train_model.py
# Generates fraud_model.pkl + scaler.pkl + feature_schema.json

Step 3 β€” Start the ML Microservice

uvicorn app.main:app --host 0.0.0.0 --port 8001

Step 4 β€” Start the Spring Boot Application

./mvnw spring-boot:run
# API available at http://localhost:8080
# Dashboard at   http://localhost:8080/index.html
# H2 console at  http://localhost:8080/h2-console

Step 5 β€” Run Tests

Import Sentinel_Postman_Tests_Version2.json into Postman and execute all folders in order.


πŸ› οΈ Tech Stack

Backend (Spring Boot)

Technology Version Role
Java 17 Language
Spring Boot 3.5 Framework
Spring Kafka Latest Event streaming
Spring Data JPA Latest ORM
Spring Data Redis Latest Redis client
Spring WebSocket Latest Real-time push
H2 Runtime Dev in-memory DB
PostgreSQL Latest Prod DB
Jakarta Validation Latest Input validation

ML Microservice (Python)

Technology Version Role
FastAPI 0.109 REST API + Kafka service host
Uvicorn 0.27 ASGI server
scikit-learn 1.4 Isolation Forest model
kafka-python 2.0.2 Kafka consumer + producer
Redis-py 5.0.1 Live feature extraction
NumPy 1.26 Numerical computation
Pandas 2.1 Synthetic training data
Joblib 1.3 Model + scaler serialization
Pydantic 2.5 Schema validation
pydantic-settings 2.1 Config via env vars
python-dotenv 1.0 .env file loading

Infrastructure

Service Image Port
Apache Kafka confluentinc/cp-kafka:7.2.1 9092
Zookeeper confluentinc/cp-zookeeper:7.2.1 2181
Redis redis:7-alpine 6379

πŸ”Œ Kafka Topics

Topic Partitions Producer Consumer Payload
transactions-incoming 3 TransactionController TransactionService MoneyTransferDto
engine-input 1 TransactionService RulesEngine + ML TransactionEnrichedDto
rule-scores 3 RulesEngine AggregatorService RuleScoreDto
ml-scores 3 ML FastAPI AggregatorService MlScoreDto
risk-results 3 AggregatorService BroadcastService RiskAssessmentDto

πŸ“Š Risk Scoring Reference

Overall Score Fraud Level Transaction Status
0 – 35 🟒 LOW UNFLAGGED
36 – 50 🟑 MEDIUM UNFLAGGED
51 – 100 πŸ”΄ HIGH FLAGGED

MCC Risk Registry

MCC Code Category Risk Level
7995 Gambling HIGH
6010, 6011 Cash Advance / ATM HIGH
6051 Crypto / Non-bank HIGH
4829 Wire Transfer HIGH
5732, 5944 Electronics / Jewelry MEDIUM
4722, 7011 Travel / Hotels MEDIUM
5411, 5912 Grocery / Pharmacy LOW
5814, 4111 Food / Transit LOW

πŸ” Validation Rules

All inbound MoneyTransferDto fields are validated at the controller layer:

amount          β†’ @Positive, @NotNull
locationOfUser  β†’ @NotBlank
timeOfPayment   β†’ @PastOrPresent (no future timestamps)
merchantId      β†’ @NotNull + must exist in DB
userId          β†’ @NotNull + must exist in DB
merchantCategoryCode β†’ @NotNull
crossBorder     β†’ @NotNull
deviceFingerPrint β†’ @NotBlank
requestId       β†’ @NotBlank (idempotency key)

πŸ“ˆ Future Roadmap

  • PostgreSQL for Prod β€” Replace H2 with persistent PostgreSQL; switch ddl-auto to update
  • Auto ML Retraining β€” Nightly pipeline retrains Isolation Forest on newly flagged transactions
  • Sequence Rule β€” Score unnatural transaction ordering patterns (rapid round-trips, fan-out)
  • Rate Limiting β€” Per-user API throttling via Bucket4j to block transaction flooding
  • Alert Workflow β€” Acknowledge / escalate / dismiss alerts directly from the dashboard
  • Grafana Metrics β€” Kafka consumer lag, rule hit rates, ML latency via Prometheus + Grafana
  • SHAP Explainability β€” Surface top contributing features per ML prediction on the dashboard

πŸ“ License

Distributed under the MIT License. See LICENSE for more information.


⭐ Star this repo if you found it cool!

Built with β˜• Java + 🐍 Python Β· Event-driven with Apache Kafka Β· Real-time with WebSockets

About

πŸ›‘οΈ Transaction anomaly scoring engine | 🧠 Hybrid ML + Rules engine | ⚑ Kafka + Redis | πŸ“‘ Live WebSocket alerts | πŸ”₯ Spring Boot + Python | Anomalies detected instantly. Commit fraud, and you're caught.

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages