System Design Fundamentals

System Design Fundamentals

Complete guide to designing scalable systems

What is System Design?

The process of defining architecture, components, modules, interfaces, and data for a system to satisfy specified requirements.

Why It Matters:

  • Scalability → Handle growing user base
  • Reliability → System stays operational
  • Performance → Fast response times
  • Maintainability → Easy to update and debug

System Design Process

1. Requirements Gathering (~5 min)

  • Functional requirements (what the system does)
  • Non-functional requirements (how well it performs)
  • Constraints and assumptions

2. Capacity Planning (a few min, part of requirements)

  • Estimate scale (users, data, traffic)
  • Calculate storage and bandwidth needs
  • Identify bottlenecks

3. High-Level Design (~10 min)

  • Draw major components
  • Show data flow
  • Choose technology stack

4. Detailed Design (~15 min)

  • Database schema
  • API design
  • Algorithms and data structures

5. Scale and Optimize (~10 min)

  • Identify bottlenecks
  • Add caching, load balancing
  • Discuss trade-offs

Core Technologies

Databases

TypeUse CaseExamples
SQLACID transactions, complex queriesPostgreSQL, MySQL
NoSQL DocumentFlexible schema, JSON dataMongoDB, CouchDB
NoSQL Key-ValueCaching, session storageRedis, DynamoDB
NoSQL GraphRelationships, social networksNeo4j, Amazon Neptune
Time-SeriesMetrics, IoT dataInfluxDB, TimescaleDB

Caching Strategies

  • Browser Cache → Static assets (CSS, JS, images)
  • CDN → Geographic distribution
  • Application Cache → Redis, Memcached
  • Database Cache → Query result caching

Load Balancing

  • Round Robin → Equal distribution
  • Weighted → Based on server capacity
  • Least Connections → Route to least busy server
  • Geographic → Route to nearest server

Message Queues

  • Apache Kafka → High-throughput streaming
  • RabbitMQ → Reliable message delivery
  • Amazon SQS → Managed queue service
  • Redis Pub/Sub → Real-time notifications

Scalability Patterns

Horizontal Scaling

  • Add more servers
  • Better fault tolerance
  • Linear cost increase
  • Complexity in coordination

Vertical Scaling

  • Upgrade existing hardware
  • Simpler to implement
  • Single point of failure
  • Limited by hardware constraints

Database Scaling

Read Replicas

[Write] → [Master DB] → [Replica 1]
                    └→ [Replica 2]
[Read]  ← [Load Balancer] ← [Replica 3]

Sharding

Users A-M → [Shard 1]
Users N-Z → [Shard 2]

Federation

User Service → [User DB]
Post Service → [Post DB]
Chat Service → [Chat DB]

Reliability Patterns

Circuit Breaker

import time
 
class CircuitBreaker:
    def __init__(self, failure_threshold=5, timeout=60):
        self.failure_count = 0
        self.failure_threshold = failure_threshold
        self.timeout = timeout
        self.state = "CLOSED"  # CLOSED, OPEN, HALF_OPEN
    
    def call(self, func, *args, **kwargs):
        if self.state == "OPEN":
            if time.time() - self.last_failure > self.timeout:
                self.state = "HALF_OPEN"
            else:
                raise Exception("Circuit breaker is OPEN")
        
        try:
            result = func(*args, **kwargs)
            if self.state == "HALF_OPEN":
                self.state = "CLOSED"
                self.failure_count = 0
            return result
        except Exception as e:
            self.failure_count += 1
            if self.failure_count >= self.failure_threshold:
                self.state = "OPEN"
                self.last_failure = time.time()
            raise e

Retry with Exponential Backoff

import time
import random
 
def retry_with_backoff(func, max_retries=3, base_delay=1):
    for attempt in range(max_retries):
        try:
            return func()
        except Exception as e:
            if attempt == max_retries - 1:
                raise e
            
            delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
            time.sleep(delay)

Bulkhead Pattern

  • Isolate critical resources
  • Separate thread pools for different operations
  • Prevent cascade failures

Monitoring and Observability

The Three Pillars

1. Metrics (What is happening?)

- Response time (p50, p95, p99)
- Throughput (requests/second)
- Error rate (4xx, 5xx responses)
- Resource utilization (CPU, memory, disk)

2. Logs (What happened?)

{
  "timestamp": "2024-01-01T10:00:00Z",
  "level": "ERROR",
  "service": "user-service",
  "traceId": "abc123",
  "message": "Failed to authenticate user",
  "userId": 12345,
  "error": "Invalid token"
}

3. Traces (How did it happen?)

Request → API Gateway → User Service → Database
  100ms     10ms          80ms          70ms

Tools

  • Metrics: Prometheus + Grafana
  • Logs: ELK Stack (Elasticsearch, Logstash, Kibana)
  • Traces: Jaeger, Zipkin
  • APM: New Relic, Datadog, AppDynamics

Common System Design Questions

Social Media (Instagram/Twitter)

  • User timeline generation
  • News feed algorithm
  • Image/video storage and delivery
  • Real-time notifications

Chat Systems (WhatsApp/Slack)

  • Real-time messaging
  • Message delivery guarantees
  • Group chat management
  • Online presence

E-commerce (Amazon/eBay)

  • Product catalog search
  • Shopping cart management
  • Payment processing
  • Inventory management

Video Streaming (YouTube/Netflix)

  • Video encoding and storage
  • Content delivery network
  • Recommendation system
  • Live streaming

Ride Sharing (Uber/Lyft)

  • Real-time location tracking
  • Matching algorithm
  • Dynamic pricing
  • Route optimization

Interview Tips

Time Management

  • 5 min: Requirements clarification
  • 10 min: High-level design
  • 15 min: Detailed design
  • 10 min: Scale and optimize
  • 5 min: Wrap up and questions

Communication

  • Think out loud
  • Ask clarifying questions
  • Explain trade-offs
  • Start simple, then add complexity

Common Mistakes

  • Jumping to implementation details
  • Not asking about scale requirements
  • Ignoring non-functional requirements
  • Over-engineering the solution

What Interviewers Look For

  • Structured thinking → Systematic approach
  • Trade-off analysis → Understanding implications
  • Scalability awareness → Design for growth
  • Real-world knowledge → Practical experience
Link to original

Unpublished note
High-Level Design (HLD)

High-Level Design (HLD)

System architecture overview showing component interactions

Purpose

  • Component identification → Major system building blocks
  • Data flow → How information moves between components
  • Integration points → External systems and APIs
  • Technology stack → Frameworks, databases, tools

Key Components

1. Presentation Layer

  • Web UI: React, Angular, Vue.js
  • Mobile Apps: iOS, Android
  • API Gateway: Single entry point for all requests

2. Application Layer

  • Load Balancer: Nginx, HAProxy, AWS ALB
  • App Servers: Node.js, Java Spring, Python Django
  • Microservices: Independent, loosely coupled services

3. Data Layer

  • Databases: SQL (PostgreSQL) / NoSQL (MongoDB)
  • Cache: Redis, Memcached
  • Message Queues: Kafka, RabbitMQ
  • File Storage: AWS S3, CDN

4. Infrastructure

  • Monitoring: Prometheus, Grafana, ELK
  • Security: WAF, SSL/TLS, Authentication
  • Deployment: Docker, Kubernetes, CI/CD

Diagram Example

[Users] → [Load Balancer] → [API Gateway] → [Microservices]
                                              ↓
[CDN] ← [File Storage] ← [Cache] ← [Database]

Design Patterns

  • Circuit Breaker: Prevent cascade failures
  • Bulkhead: Isolate critical resources
  • Saga: Distributed transaction management
  • CQRS: Command Query Responsibility Segregation

Blueprint Analogy

Like a house blueprint showing:

  • Room layout (components)
  • Electrical wiring (data flow)
  • Plumbing (connections)
  • Foundation (infrastructure)
Link to original

Low-Level Design (LLD)

Low-Level Design (LLD)

Detailed implementation of HLD components

Purpose

  • Class diagrams → Object-oriented design
  • Database schema → Tables, relationships, indexes
  • API specifications → Request/response formats
  • Algorithms → Detailed logic implementation
  • Code structure → Modules, functions, interfaces

Key Elements

1. Class Design

class UserService {
    private UserRepository userRepo;
    private EmailService emailService;
    
    public User createUser(UserRequest request) {
        // Validation logic
        // Business rules
        // Database operations
    }
}

2. Database Schema

CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
    -- UNIQUE on email already creates an index; no separate idx_email needed
);
 
CREATE TABLE posts (
    id BIGINT PRIMARY KEY,
    user_id BIGINT REFERENCES users(id),
    content TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);
-- Inline INDEX inside CREATE TABLE is MySQL-only; portable (PostgreSQL) form:
CREATE INDEX idx_user_created ON posts (user_id, created_at);

3. API Specification

POST /api/v1/users
Request:
{
  "email": "user@example.com",
  "password": "securePassword123"
}
 
Response:
{
  "userId": 12345,
  "email": "user@example.com",
  "createdAt": "2024-01-01T10:00:00Z"
}

4. Algorithms

import bisect, hashlib
 
def stable_hash(s):
    # Python's built-in hash() is randomised per process for str -> use a stable hash
    return int(hashlib.md5(s.encode()).hexdigest(), 16) % (2**32)
 
def consistent_hash(key, ring):
    """
    Distribute keys across nodes using consistent hashing.
    ring: list of (hash_value, node) sorted by hash_value
          (add several virtual nodes per physical node for balance)
    """
    hashes = [h for h, _ in ring]
    i = bisect.bisect_left(hashes, stable_hash(key))  # first node with hash >= key hash
    return ring[i % len(ring)][1]  # wrap around to smallest hash

Design Patterns

Repository Pattern

interface UserRepository {
    User save(User user);
    Optional<User> findById(Long id);
    Optional<User> findByEmail(String email);  // email is UNIQUE
}

Factory Pattern

class NotificationFactory:
    @staticmethod
    def create_notification(type, message):
        if type == "email":
            return EmailNotification(message)
        elif type == "sms":
            return SMSNotification(message)

Observer Pattern

class EventEmitter {
    constructor() {
        this.listeners = {};
    }
    
    on(event, callback) {
        if (!this.listeners[event]) {
            this.listeners[event] = [];
        }
        this.listeners[event].push(callback);
    }
    
    emit(event, data) {
        if (this.listeners[event]) {
            this.listeners[event].forEach(cb => cb(data));
        }
    }
}

Implementation Checklist

  • Error Handling: Try-catch, validation
  • Logging: Structured logs, correlation IDs
  • Testing: Unit tests, integration tests
  • Security: Input sanitization, SQL injection prevention
  • Performance: Connection pooling, caching
  • Monitoring: Metrics, health checks

Construction Analogy

Like detailed construction plans showing:

  • Exact measurements (data types, constraints)
  • Material specifications (technologies, libraries)
  • Step-by-step instructions (algorithms, workflows)
  • Quality standards (testing, validation)
Link to original

Content Delivery Network (CDN)

Content Delivery Network (CDN)

Geographically distributed network of servers that deliver content to users from the nearest location

What is CDN?

A CDN is a network of strategically placed servers (edge servers) around the world that cache and deliver content to users from the closest geographical location.

Purpose:

  • Reduce Latency → Faster content delivery
  • Improve Performance → Better user experience
  • Reduce Server Load → Distribute traffic
  • Increase Availability → Redundancy and fault tolerance

How CDN Works

Basic Flow:

1. User requests content (e.g., image, video, webpage)
2. DNS routes request to nearest CDN edge server
3. If content exists in cache → Return cached content
4. If not in cache → Fetch from origin server
5. Cache content at edge server for future requests
6. Return content to user

Architecture Diagram:

[User in NYC] → [CDN Edge NYC] → [Origin Server California]
[User in London] → [CDN Edge London] → [Origin Server California]
[User in Tokyo] → [CDN Edge Tokyo] → [Origin Server California]

CDN Components

1. Edge Servers (PoP - Point of Presence)

  • Location: Major cities worldwide
  • Function: Cache and serve content
  • Capacity: High-performance SSD storage
  • Examples: 100+ locations globally

2. Origin Server

  • Source: Original content location
  • Backup: Authoritative content source
  • Updates: Push updates to edge servers

3. Cache Management

  • TTL: Time-to-live for cached content
  • Invalidation: Remove outdated content
  • Prefetching: Proactively cache popular content

4. Load Balancers

  • Traffic Distribution: Route to best edge server
  • Health Checks: Monitor server availability
  • Failover: Redirect if server fails

CDN Types

1. Traditional Pull CDN

  • On-demand: Content cached when first requested
  • Lazy Loading: Cache-miss triggers origin fetch
  • Best For: General web content, images
User Request → Edge Server (cache miss) → Origin Server
                     ↓ (cache content)
User Request → Edge Server (cache hit) → Direct response

2. Push CDN

  • Proactive: Content pushed to edge servers
  • Scheduled: Regular content updates
  • Best For: Static content, scheduled releases
Origin Server → Push content → All Edge Servers
User Request → Edge Server → Cached content (always available)

3. Hybrid CDN

  • Combination: Both pull and push strategies
  • Intelligent: Based on content type and usage patterns
  • Optimal: Best of both approaches

CDN Caching Strategies

1. Cache-Control Headers

Cache-Control: public, max-age=31536000  # 1 year
Cache-Control: private, no-store         # Don't cache at all
Cache-Control: no-cache                  # Store, but revalidate with origin before each use
Cache-Control: public, s-maxage=3600     # CDN cache 1 hour

2. Content Types & TTL

Content TypeTTLReason
Static Images1 yearRarely change
CSS/JS Files1 monthVersion controlled
HTML Pages1 hourDynamic content
API Responses5 minutesReal-time data
User ProfilesNo cachePersonal data

3. Cache Invalidation

// Purge specific file
cdn.purge('/images/logo.png');
 
// Purge by pattern
cdn.purge('/css/*');
 
// Purge by tags
cdn.purgeByTags(['product-123', 'category-electronics']);

Geographic Distribution

CDN Locations (Examples)

North America: 
- East Coast: New York, Atlanta, Miami
- West Coast: Los Angeles, San Francisco, Seattle
- Central: Chicago, Dallas, Denver

Europe:
- Western: London, Paris, Amsterdam, Frankfurt
- Eastern: Warsaw, Prague, Moscow

Asia-Pacific:
- East Asia: Tokyo, Seoul, Hong Kong, Singapore
- South Asia: Mumbai, Bangalore
- Oceania: Sydney, Melbourne

Routing Methods

  1. DNS-based: GeoDNS routes to nearest server
  2. Anycast: Same IP, different physical servers
  3. HTTP Redirect: Application-level routing

Performance Benefits

Latency Reduction

Without CDN:
User (NYC) → Server (California) = ~4000km = ~60-80ms RTT (fibre floor ~40ms)

With CDN:
User (NYC) → CDN Edge (NYC) = ~50km = a few ms RTT
Large latency reduction (exact savings depend on route)

Bandwidth Optimization

  • Compression: Gzip, Brotli compression
  • Image Optimization: WebP, AVIF formats
  • Minification: Remove unnecessary characters
  • HTTP/2: Multiplexing, header compression

Concurrent Connections

HTTP/1.1 browser limit: ~6 connections per domain
Legacy HTTP/1.1 workaround (domain sharding): multiple subdomains
- cdn1.example.com
- cdn2.example.com  
- cdn3.example.com
Result: 18 concurrent connections
HTTP/2 & HTTP/3: one connection multiplexes all requests → domain sharding
is an anti-pattern (extra DNS/TLS handshakes, breaks prioritisation)

Security Features

DDoS Protection

  • Traffic Filtering: Block malicious requests
  • Rate Limiting: Prevent abuse
  • Geographic Blocking: Restrict by country
  • Bot Protection: CAPTCHA challenges

SSL/TLS Termination

User → [HTTPS] → CDN Edge → [HTTPS, origin cert validated] → Origin Server
Benefits:
- Offload SSL processing from origin
- Latest TLS versions at edge
- Certificate management

Web Application Firewall (WAF)

  • SQL Injection: Block malicious SQL queries
  • XSS Protection: Filter cross-site scripting
  • OWASP Top 10: Protection against common attacks

Major Players

ProviderStrengthsUse Cases
CloudflareSecurity, DNS, Edge computingGeneral purpose, security-focused
AWS CloudFrontAWS integration, global reachAWS ecosystem, enterprise
AkamaiLargest network, enterprise featuresLarge enterprises, streaming
FastlyReal-time purging, edge computingDeveloper-friendly, real-time apps
Google Cloud CDNGCP integration, YouTube networkGoogle ecosystem, video content
Azure CDNMicrosoft integration, enterpriseMicrosoft ecosystem, enterprise

Specialized CDNs

  • Video: Wowza, JW Player, Brightcove (video platforms that run on top of CDNs, not CDNs themselves)
  • Gaming: Game downloads are served by general CDNs (Akamai, CloudFront, etc.); Amazon GameLift hosts game servers and is not a CDN (Google Stadia shut down Jan 2023)
  • Mobile: Akamai Ion

Implementation Examples

1. Basic CDN Setup

<!-- Before CDN -->
<img src="https://example.com/images/logo.png" alt="Logo">
<link rel="stylesheet" href="https://example.com/css/style.css">
 
<!-- After CDN -->
<img src="https://cdn.example.com/images/logo.png" alt="Logo">
<link rel="stylesheet" href="https://cdn.example.com/css/style.css">

2. Dynamic Content Caching

// Cache API responses with short TTL
app.get('/api/products', (req, res) => {
  res.set({
    'Cache-Control': 'public, max-age=300', // 5 minutes
    'Vary': 'Accept-Encoding'
  });
  
  // Return product data
  res.json(products);
});

3. Edge Side Includes (ESI)

<!-- Cached page template -->
<html>
<head>
  <esi:include src="/api/user-menu" ttl="60" />
</head>
<body>
  <esi:include src="/api/dynamic-content" ttl="300" />
  <esi:include src="/api/footer" ttl="3600" />
</body>
</html>

Monitoring & Analytics

Key Metrics

Performance Metrics:
- Cache Hit Ratio: 95%+ target
- Origin Load: Should be minimal
- Response Time: <100ms target
- Bandwidth Savings: 70%+ typical

Traffic Metrics:
- Requests per second
- Data transfer volume
- Geographic distribution
- Popular content analysis

Monitoring Tools

// CDN Analytics API example
const analytics = await cdn.getAnalytics({
  startDate: '2024-01-01',
  endDate: '2024-01-31',
  metrics: ['requests', 'bandwidth', 'cacheRatio'],
  groupBy: ['country', 'contentType']
});
 
console.log('Cache Hit Ratio:', analytics.cacheRatio);
console.log('Bandwidth Saved:', analytics.bandwidthSaved);

Best Practices

1. Content Strategy

  • ✅ Static Assets: Always use CDN
  • ✅ Dynamic Content: Cache with short TTL
  • ✅ User-Specific: Avoid caching personal data
  • ✅ API Responses: Cache public data only

2. Performance Optimization

  • ✅ HTTP/2: Enable for multiplexing
  • ✅ Compression: Gzip/Brotli for text content
  • ✅ Image Optimization: WebP/AVIF formats
  • ✅ Minification: CSS, JS, HTML

3. Cache Management

  • ✅ Versioning: Use cache-busting for updates
  • ✅ Purging: Automate cache invalidation
  • ✅ Headers: Set appropriate Cache-Control
  • ✅ Monitoring: Track cache hit ratios

4. Security

  • ✅ HTTPS: Always use SSL/TLS
  • ✅ Headers: Set security headers
  • ✅ Access Control: Restrict sensitive content
  • ✅ DDoS: Enable protection features

Common Pitfalls

1. Cache Invalidation Issues

Problem: Stale content served to users
Solution: Implement proper versioning and purging

2. Dynamic Content Caching

Problem: Caching user-specific data
Solution: Use proper cache headers and vary headers

3. Origin Server Overload

Problem: Cache miss storms during traffic spikes
Solution: Implement cache warming and proper TTLs

4. Geographic Routing Issues

Problem: Users routed to distant edge servers
Solution: Verify DNS configuration and CDN settings

Use Cases

1. E-commerce Websites

  • Product images and catalogs
  • Static CSS/JS files
  • Product recommendation APIs
  • Geographic price optimization

2. Media & Entertainment

  • Video streaming (Netflix, YouTube)
  • Image galleries (Instagram, Pinterest)
  • Audio streaming (Spotify, Apple Music)
  • Live event broadcasting

3. Gaming

  • Game asset downloads
  • (Not real-time multiplayer data: that goes to game servers, not the CDN)
  • Leaderboards and statistics
  • Mobile game content

4. SaaS Applications

  • Application assets
  • Documentation sites
  • API responses
  • User interface components

CDNs are essential for modern web applications, providing faster content delivery, improved user experience, and reduced server costs. Choose the right CDN provider based on your specific needs, budget, and geographic requirements.

Link to original

FinTech System Design - Embedding Use Cases

FinTech System Design - Embedding Use Cases

AI-powered solutions for modern payment systems and financial services

Overview

FinTech companies like JusPay leverage embedding technologies and AI to enhance payment processing, fraud detection, customer support, and compliance. These systems handle millions of transactions daily with high accuracy and low latency.

Key Areas:

  • Customer Support: RAG-based intelligent assistance
  • Anomaly Detection: Real-time transaction monitoring
  • Fraud Prevention: ML-powered risk assessment
  • Compliance: AML/KYC automation
  • Personalization: Recommendation systems

Customer Support using RAG Agent

Retrieval-Augmented Generation for intelligent customer service automation

System Architecture

User Query → [Intent Classification] → [RAG Pipeline] → [Response Generation]
     ↓              ↓                      ↓                    ↓
[NLP Processing] → [Vector Search] → [Context Retrieval] → [LLM Response]
                        ↓
                [Knowledge Base] ← [Document Embeddings]

Components

1. Document Processing Pipeline

# Document ingestion and embedding
class DocumentProcessor:
    def __init__(self):
        self.embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
        self.vector_db = PineconeVectorDB()
    
    def process_documents(self, documents):
        chunks = []
        for doc in documents:
            # Chunk documents (~256 tokens with overlap): all-MiniLM-L6-v2 has a max
            # sequence length of 256 word pieces - longer chunks are silently truncated
            text_chunks = self.chunk_text(doc.content, chunk_size=256)
            
            for chunk in text_chunks:
                embedding = self.embedding_model.encode(chunk)
                metadata = {
                    'source': doc.source,
                    'category': doc.category,
                    'last_updated': doc.timestamp
                }
                chunks.append({
                    'text': chunk,
                    'embedding': embedding,
                    'metadata': metadata
                })
        
        # Store in vector database
        self.vector_db.upsert(chunks)

2. Query Processing & Retrieval

class RAGAgent:
    def __init__(self):
        self.embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
        self.llm = OpenAI(model="gpt-4")
        self.vector_db = PineconeVectorDB()
    
    def answer_query(self, user_query):
        # 1. Generate query embedding
        query_embedding = self.embedding_model.encode(user_query)
        
        # 2. Retrieve relevant contexts
        contexts = self.vector_db.similarity_search(
            query_embedding, 
            top_k=5,
            filter={'category': 'payment_support'}
        )
        
        # 3. Generate response with context
        prompt = f"""
        Context: {' '.join([ctx['text'] for ctx in contexts])}
        
        User Question: {user_query}
        
        Provide a helpful, accurate response based on the context.
        If the information isn't available, say so clearly.
        """
        
        response = self.llm.generate(prompt)
        return {
            'answer': response,
            'sources': [ctx['metadata']['source'] for ctx in contexts],
            'confidence': self.calculate_confidence(contexts, user_query)
        }

Knowledge Base Structure

Example Knowledge Base (illustrative, payment-gateway style):
├── Payment Processing
│   ├── Transaction flows
│   ├── Payment methods (UPI, Cards, Wallets)
│   ├── Error codes and troubleshooting
│   └── Integration guides
├── Compliance & Security
│   ├── PCI DSS requirements
│   ├── RBI guidelines
│   ├── KYC procedures
│   └── Data protection policies
├── APIs & SDKs
│   ├── REST API documentation
│   ├── Mobile SDK guides
│   ├── Webhook implementations
│   └── Testing procedures
└── Business Logic
    ├── Merchant onboarding
    ├── Settlement processes
    ├── Refund policies
    └── Dispute resolution

Performance Metrics (illustrative targets, not published company figures)

  • Response Time: < 2 seconds
  • Accuracy: 95%+ for common queries
  • Coverage: 80%+ query resolution without human intervention
  • Customer Satisfaction: 4.5/5 rating

Anomaly Detection

Real-time transaction monitoring using ML embeddings and statistical analysis

System Architecture

[Transaction Stream] → [Feature Engineering] → [Embedding Generation]
         ↓                      ↓                       ↓
[Real-time Processing] → [Anomaly Detection] → [Alert System]
         ↓                      ↓                       ↓
[Kafka Pipeline] → [ML Models] → [Risk Scoring] → [Action Engine]

Feature Engineering

class TransactionFeatureExtractor:
    def __init__(self):
        self.scaler = StandardScaler()
        self.encoder = LabelEncoder()
    
    def extract_features(self, transaction):
        features = {}
        
        # Temporal features
        features['hour_of_day'] = transaction.timestamp.hour
        features['day_of_week'] = transaction.timestamp.weekday()
        features['is_weekend'] = transaction.timestamp.weekday() >= 5
        
        # Amount-based features
        features['amount'] = transaction.amount
        features['amount_log'] = np.log1p(transaction.amount)
        features['amount_zscore'] = self.calculate_amount_zscore(
            transaction.merchant_id, 
            transaction.amount
        )
        
        # User behavior features
        user_history = self.get_user_history(transaction.user_id, days=30)
        features['avg_transaction_amount'] = user_history.amount.mean()
        features['transaction_frequency'] = len(user_history)
        features['days_since_last_transaction'] = self.days_since_last(
            transaction.user_id
        )
        
        # Merchant features
        features['merchant_category'] = transaction.merchant_category
        features['merchant_risk_score'] = self.get_merchant_risk_score(
            transaction.merchant_id
        )
        
        # Geographic features
        features['location_country'] = transaction.country
        features['location_unusual'] = self.is_unusual_location(
            transaction.user_id, 
            transaction.country
        )
        
        return features

Embedding-based Anomaly Detection

class TransactionEmbeddingModel:
    def __init__(self):
        self.autoencoder, self.encoder = self.build_autoencoder()
        # contamination = expected anomaly fraction; real fraud rates are well under 1%
        # (0.1 would flag 10% of transactions)
        self.isolation_forest = IsolationForest(contamination=0.01)
        
    def build_autoencoder(self):
        """Autoencoder for transaction embeddings"""
        input_dim = 50  # Number of features
        encoding_dim = 16
        
        input_layer = Input(shape=(input_dim,))
        encoded = Dense(32, activation='relu')(input_layer)
        encoded = Dense(encoding_dim, activation='relu')(encoded)
        
        decoded = Dense(32, activation='relu')(encoded)
        decoded = Dense(input_dim, activation='sigmoid')(decoded)
        
        autoencoder = Model(input_layer, decoded)
        encoder = Model(input_layer, encoded)
        
        autoencoder.compile(optimizer='adam', loss='mse')
        return autoencoder, encoder
    
    def detect_anomalies(self, transaction_features):
        # 1. Generate embeddings
        embeddings = self.encoder.predict(transaction_features)
        
        # 2. Reconstruction error
        reconstructed = self.autoencoder.predict(transaction_features)
        reconstruction_error = np.mean(np.square(
            transaction_features - reconstructed
        ), axis=1)
        
        # 3. Isolation Forest: decision_function is centred near 0, LOWER = more
        #    anomalous; its scale differs from MSE, so normalise both to [0, 1]
        isolation_score = self.isolation_forest.decision_function(embeddings)
        if_anomaly = self.normalize(-isolation_score)        # higher = more anomalous
        recon_anomaly = self.normalize(reconstruction_error)
        
        # 4. Combined anomaly score
        anomaly_score = (
            0.6 * recon_anomaly + 
            0.4 * if_anomaly
        )
        
        return {
            'anomaly_score': anomaly_score,
            'is_anomaly': anomaly_score > self.threshold,
            'embedding': embeddings,
            'reconstruction_error': reconstruction_error
        }

Real-time Processing Pipeline

# Kafka consumer for real-time transaction processing
class AnomalyDetectionProcessor:
    def __init__(self):
        self.kafka_consumer = KafkaConsumer('transactions')
        self.feature_extractor = TransactionFeatureExtractor()
        self.anomaly_detector = TransactionEmbeddingModel()
        self.alert_system = AlertSystem()
    
    def process_stream(self):
        for message in self.kafka_consumer:
            transaction = json.loads(message.value)
            
            # Extract features
            features = self.feature_extractor.extract_features(transaction)
            
            # Detect anomalies
            result = self.anomaly_detector.detect_anomalies([features])
            
            if result['is_anomaly']:
                alert = {
                    'transaction_id': transaction['id'],
                    'anomaly_score': result['anomaly_score'],
                    'timestamp': datetime.now(),
                    'features': features,
                    'action_required': self.determine_action(
                        result['anomaly_score']
                    )
                }
                
                self.alert_system.send_alert(alert)
                
                # Take immediate action if high risk
                if result['anomaly_score'] > 0.9:
                    self.block_transaction(transaction['id'])

Anomaly Types Detected

Anomaly TypeDetection MethodAction
Unusual AmountZ-score analysisReview transaction
Velocity FraudFrequency patternsRate limiting
GeographicLocation embeddingAdditional verification
Merchant RiskRisk scoringEnhanced monitoring
Time-basedTemporal patternsTime-based rules
Account TakeoverBehavior changeAccount security check

Avoiding Frauds

Multi-layered fraud prevention using ML, rule engines, and real-time analysis

System Architecture

[Transaction] → [Pre-processing] → [Rule Engine] → [ML Models] → [Decision Engine]
      ↓              ↓                ↓              ↓              ↓
[Enrichment] → [Feature Eng] → [Hard Rules] → [Risk Scoring] → [Final Decision]
      ↓              ↓                ↓              ↓              ↓
[External APIs] → [Embeddings] → [Block/Allow] → [Probability] → [Approve/Decline/Review]

Rule Engine Implementation

class FraudRuleEngine:
    def __init__(self):
        self.rules = self.load_rules()
        self.blacklists = self.load_blacklists()
    
    def evaluate_rules(self, transaction):
        results = []
        
        # Velocity rules
        if self.check_velocity_rules(transaction):
            results.append({
                'rule': 'VELOCITY_EXCEEDED',
                'severity': 'HIGH',
                'action': 'BLOCK'
            })
        
        # Amount rules
        if transaction.amount > 100000:  # > 1 Lakh
            results.append({
                'rule': 'HIGH_AMOUNT',
                'severity': 'MEDIUM',
                'action': 'REVIEW'
            })
        
        # Geographic rules
        if self.is_high_risk_country(transaction.country):
            results.append({
                'rule': 'HIGH_RISK_COUNTRY',
                'severity': 'HIGH',
                'action': 'BLOCK'
            })
        
        # Blacklist checks
        if self.check_blacklists(transaction):
            results.append({
                'rule': 'BLACKLISTED',
                'severity': 'CRITICAL',
                'action': 'BLOCK'
            })
        
        return results
    
    def check_velocity_rules(self, transaction):
        """Check if user exceeds transaction velocity limits"""
        user_id = transaction.user_id
        
        # Last 1 hour
        recent_count = self.get_transaction_count(user_id, hours=1)
        if recent_count > 10:
            return True
        
        # Last 24 hours
        daily_count = self.get_transaction_count(user_id, hours=24)
        if daily_count > 50:
            return True
        
        # Amount velocity
        daily_amount = self.get_transaction_amount(user_id, hours=24)
        if daily_amount > 500000:  # > 5 Lakh per day
            return True
        
        return False

ML-based Fraud Detection

class FraudDetectionML:
    def __init__(self):
        self.models = {
            'xgboost': self.load_xgboost_model(),
            'neural_net': self.load_neural_network(),
            'isolation_forest': self.load_isolation_forest()
        }
        self.feature_importance = self.load_feature_importance()
    
    def predict_fraud(self, transaction_features):
        predictions = {}
        
        # XGBoost prediction
        xgb_prob = self.models['xgboost'].predict_proba(
            [transaction_features]
        )[0][1]
        
        # Neural network prediction
        nn_prob = self.models['neural_net'].predict(
            [transaction_features]
        )[0][0]
        
        # Isolation forest anomaly score (decision_function: lower = more anomalous,
        # centred near 0) -> normalise to [0, 1] with higher = more anomalous
        anomaly_score = self.models['isolation_forest'].decision_function(
            [transaction_features]
        )[0]
        if_anomaly = self.normalize(-anomaly_score)
        
        # Ensemble prediction
        ensemble_prob = (
            0.5 * xgb_prob + 
            0.3 * nn_prob + 
            0.2 * if_anomaly
        )
        
        return {
            'fraud_probability': ensemble_prob,
            'model_predictions': {
                'xgboost': xgb_prob,
                'neural_network': nn_prob,
                'isolation_forest': anomaly_score
            },
            'risk_level': self.calculate_risk_level(ensemble_prob),
            'feature_contributions': self.explain_prediction(
                transaction_features
            )
        }
    
    def calculate_risk_level(self, probability):
        if probability < 0.1:
            return 'LOW'
        elif probability < 0.5:
            return 'MEDIUM'
        elif probability < 0.8:
            return 'HIGH'
        else:
            return 'CRITICAL'

Decision Engine

class FraudDecisionEngine:
    def __init__(self):
        self.rule_engine = FraudRuleEngine()
        self.ml_engine = FraudDetectionML()
        self.risk_policies = self.load_risk_policies()
    
    def make_decision(self, transaction):
        # 1. Rule-based evaluation
        rule_results = self.rule_engine.evaluate_rules(transaction)
        
        # Check for hard blocks
        for rule in rule_results:
            if rule['action'] == 'BLOCK' and rule['severity'] == 'CRITICAL':
                return {
                    'decision': 'DECLINE',
                    'reason': f"Blocked by rule: {rule['rule']}",
                    'confidence': 1.0
                }
        
        # 2. Extract features for ML
        features = self.extract_ml_features(transaction)
        
        # 3. ML prediction
        ml_result = self.ml_engine.predict_fraud(features)
        
        # 4. Combine rule and ML results
        final_decision = self.combine_results(rule_results, ml_result)
        
        return final_decision
    
    def combine_results(self, rule_results, ml_result):
        fraud_prob = ml_result['fraud_probability']
        
        # Adjust probability based on rules
        for rule in rule_results:
            if rule['severity'] == 'HIGH':
                fraud_prob += 0.2
            elif rule['severity'] == 'MEDIUM':
                fraud_prob += 0.1
        
        fraud_prob = min(fraud_prob, 1.0)
        
        # Make final decision
        if fraud_prob > 0.8:
            decision = 'DECLINE'
        elif fraud_prob > 0.5:
            decision = 'REVIEW'
        else:
            decision = 'APPROVE'
        
        return {
            'decision': decision,
            'fraud_probability': fraud_prob,
            'rule_violations': len(rule_results),
            'ml_confidence': ml_result['risk_level'],
            'explanation': self.generate_explanation(rule_results, ml_result)
        }

Feature Engineering for Fraud Detection

class FraudFeatureEngineer:
    def extract_features(self, transaction):
        features = {}
        
        # Transaction features
        features['amount'] = transaction.amount
        features['amount_log'] = np.log1p(transaction.amount)
        features['currency'] = transaction.currency
        features['payment_method'] = transaction.payment_method
        
        # Temporal features
        features['hour'] = transaction.timestamp.hour
        features['day_of_week'] = transaction.timestamp.weekday()
        features['is_weekend'] = transaction.timestamp.weekday() >= 5
        features['is_night'] = transaction.timestamp.hour < 6
        
        # User behavior features
        user_stats = self.get_user_statistics(transaction.user_id)
        features['user_avg_amount'] = user_stats['avg_amount']
        features['user_transaction_count'] = user_stats['transaction_count']
        features['days_since_registration'] = user_stats['days_since_registration']
        features['amount_deviation'] = abs(
            transaction.amount - user_stats['avg_amount']
        ) / user_stats['std_amount']
        
        # Merchant features
        merchant_stats = self.get_merchant_statistics(transaction.merchant_id)
        features['merchant_risk_score'] = merchant_stats['risk_score']
        features['merchant_category'] = merchant_stats['category']
        features['merchant_avg_amount'] = merchant_stats['avg_amount']
        
        # Geographic features
        features['country'] = transaction.country
        features['country_risk_score'] = self.get_country_risk_score(
            transaction.country
        )
        features['is_cross_border'] = (
            transaction.user_country != transaction.merchant_country
        )
        
        # Device features (if available)
        if transaction.device_info:
            features['device_type'] = transaction.device_info.type
            features['browser'] = transaction.device_info.browser
            features['is_mobile'] = transaction.device_info.is_mobile
        
        # Network features
        features['ip_risk_score'] = self.get_ip_risk_score(transaction.ip_address)
        features['is_vpn'] = self.is_vpn_ip(transaction.ip_address)
        features['is_tor'] = self.is_tor_ip(transaction.ip_address)
        
        return features

JusPay-Specific System Design

Architecture below is an illustrative payment-orchestrator design, not JusPay’s documented internals.

Payment Processing Architecture

[Merchant] → [JusPay Gateway] → [Payment Processor] → [Bank/Wallet]
     ↓              ↓                    ↓                ↓
[Checkout] → [Risk Assessment] → [Routing Engine] → [Settlement]
     ↓              ↓                    ↓                ↓
[User] → [Fraud Detection] → [Optimal Route] → [Reconciliation]

Key Components

1. Payment Orchestration

  • Smart Routing: Route to best payment processor
  • Fallback Handling: Retry with alternative routes
  • Cost Optimization: Choose lowest-cost successful route

2. Risk Management

  • Real-time Scoring: ML-based fraud detection
  • Adaptive Rules: Dynamic rule updates
  • Merchant Risk Profiles: Customized risk policies

3. Data Processing

  • Stream Processing: Kafka for real-time events
  • Batch Processing: Apache Spark for analytics
  • Data Lake: Store transaction and user behavior data

Scalability Requirements (illustrative assumptions, not JusPay-published figures)

  • TPS: 10,000+ transactions per second
  • Latency: < 200ms for payment processing
  • Availability: 99.99% uptime
  • Data: Process 1TB+ daily transaction data

Interview Questions for SDE Intern

System Design Questions

  1. Design a real-time fraud detection system for JusPay
  2. Build a payment retry mechanism with smart routing
  3. Create a customer support chatbot using RAG
  4. Design a transaction reconciliation system
  5. Build an anomaly detection pipeline for transactions

Technical Questions

  1. How would you handle high-frequency trading scenarios?
  2. Explain PCI DSS compliance in payment systems
  3. How to ensure idempotency in payment APIs?
  4. Design rate limiting for payment APIs
  5. How to handle eventual consistency in distributed payments?

ML/AI Questions

  1. How to detect concept drift in fraud models?
  2. Explain feature importance in fraud detection
  3. How to handle imbalanced datasets in fraud detection?
  4. Design A/B testing for ML models in production
  5. How to ensure model explainability for regulatory compliance?

This comprehensive guide covers the essential aspects of FinTech system design with a focus on AI/ML applications, specifically tailored for companies like JusPay and suitable for SDE Intern interviews.

Link to original

Notes in this canvas