Skip to main content

AI-Powered Spam Detection System Architecture

Comprehensive design document for building scalable spam detection systems using machine learning and real-time processing pipelines.

Modern spam detection systems require robust machine learning architectures that can process high-volume email and message traffic while maintaining low false positive rates and adapting to evolving spam patterns through continuous learning mechanisms.

1. Problem Statement & ML Task Definition

Clarifying questions

  1. What is the expected scale of data volume (e.g., daily message volume, training data size)?
  2. What is the acceptable latency for real-time spam detection (e.g., <100ms for mobile, <500ms for web)?
  3. What is the target accuracy metric (e.g., AUC-ROC > 0.95, Precision@K > 0.90)?
  4. What is the expected QPS for real-time serving (e.g., 10K QPS, 100K QPS)?
  5. What is the acceptable false positive rate (e.g., <1% of legitimate messages flagged as spam)?
  6. What are the specific types of spam (e.g., phishing, promotional, malware) that need to be detected?
  7. What is the expected model update frequency (e.g., daily, weekly, real-time)?

Business use case and success criteria

The spam detection system aims to identify and filter out unwanted, malicious, or irrelevant messages in real-time to protect users from phishing attacks, fraud, and spam content. The system will be integrated into messaging platforms (email, SMS, chat) to provide real-time content filtering.

Success criteria include:

  • False Positive Rate (FPR): <1% of legitimate messages flagged as spam
  • True Positive Rate (TPR): >95% of actual spam messages detected
  • Latency: <100ms for real-time message processing
  • QPS: Support 50K+ concurrent message processing
  • User Engagement: Reduce spam-related user complaints by 90%

ML problem formulation

This is a binary classification problem where the system determines whether a message is spam (1) or legitimate (0). The task requires high precision to avoid false positives that could impact user experience.

Justification:

  • Binary classification is appropriate for the clear "spam vs. not spam" decision boundary
  • High precision is critical due to user experience impact of false positives
  • The problem can be framed as a ranking task with confidence thresholds for production use

ML evaluation metrics

Offline Evaluation Metrics:

  • AUC-ROC: >0.95 for overall model performance
  • Precision@K: >0.90 at top-K results (for ranked output)
  • F1-Score: >0.92 for balanced precision/recall trade-off
  • Recall@K: >0.95 for spam detection rate

Online Evaluation Metrics:

  • Click-Through Rate (CTR) on filtered content
  • User engagement rate (time spent on legitimate messages)
  • Revenue impact from reduced spam-related complaints
  • User feedback score (positive/negative classification)

Scale and constraints

Back-of-envelope estimates:

  • Training data size: 50M messages (10M spam, 40M legitimate)
  • Features: 50K+ sparse features (user behavior, content, metadata)
  • Embedding matrix size: 10K user embeddings × 128 dimensions = ~128MB
  • Serving QPS math:
    • Target: 50K QPS
    • Model inference time: <100ms (p99)
    • Required throughput: 50K * 0.1s = 5,000 seconds/sec (100x parallelism)
    • Estimated model size: <50MB (for fast loading and serving)

Non-ML baseline strategy

Rule-based fallback:

  • Email headers validation (SPF, DKIM, DMARC)
  • Known spam keyword lists with regex matching
  • Sender reputation scoring (based on historical data)
  • Content length and structure heuristics (e.g., excessive caps, excessive links)

Cold start handling:

  • New user fallback to community-level spam detection
  • New message type fallback to generic spam patterns
  • Threshold-based confidence scoring for uncertain cases
class SpamDetectionBaseline:
    def __init__(self):
        self.spam_keywords = ['free money', 'click here', 'urgent']
        self.sender_reputation_threshold = 0.3
    
    def is_spam(self, message):
        # Rule-based checks
        if any(keyword in message.lower() for keyword in self.spam_keywords):
            return True, "keyword_match"
        # Fallback to reputation scoring
        if self.sender_reputation < self.sender_reputation_threshold:
            return True, "reputation_low"
        return False, "legitimate"

2. Data Strategy

Training Data Sources

  • Explicit feedback: User-reported spam labels (e.g., "mark as spam" button) - 30% of training data
  • Implicit signals: User engagement patterns (low click-through, high unsubscribe rate) - 40% of training data
  • Third-party data: Spam word dictionaries, known spammer IP addresses, reputation scores from external providers - 30% of training data

Labeling Pipeline Design

  • Human annotation: High-quality manual labeling for 5% of training data by domain experts using internal labeling platform
  • Weak supervision: Programmatic labeling from spam word lists, URL patterns, and known spammer behavior - 25% of training data
  • Programmatic labeling: Rule-based filtering from existing spam detection systems - 70% of training data

Class Imbalance Handling Strategy

Spam detection exhibits severe class imbalance (1:1000 spam to ham ratio). Strategy includes:

  • Oversampling: SMOTE for minority class with synthetic feature generation
  • Class weights: Weighted loss function where spam weight = 1000, ham weight = 1
  • Focal loss: Reduce focus on easy examples to help model learn from hard ones

Negative Sampling Approach

  • Hard negative mining: Sample negative examples that are most similar to spam (high feature overlap)
  • Balanced sampling: 1:1 ratio of spam vs. non-spam samples in training batches
  • Temporal sampling: Prefer recent negatives to capture evolving spam patterns

Data Freshness and Update Frequency Requirements

  • Real-time: User feedback labels (within 1 hour)
  • Batch: Content features, reputation scores (daily)
  • Historical: Training data snapshots (weekly)

Privacy Compliance

  • GDPR/CCPA compliance: All user data anonymized using k-anonymity and differential privacy techniques
  • Data retention: 2 years for training data, 30 days for prediction logs
  • Consent tracking: Explicit user consent required for training data usage

Data Quality Validation and Monitoring

  • Data validation: Schema validation, content integrity checks, duplicate detection
  • Quality monitoring: Label consistency checks, drift detection for feature distributions
  • Anomaly detection: Unusual label patterns or sudden spikes in spam reports
# Data validation and quality check example
import pandas as pd
from sklearn.model_selection import train_test_split

def validate_spam_data(df):
    """Validate training data quality for spam detection"""
    
    # Check class distribution
    class_dist = df['is_spam'].value_counts(normalize=True)
    assert class_dist[0] > 0.99, "Class imbalance too severe"
    
    # Check for missing values
    assert df.isnull().sum().sum() == 0, "Missing values found in training data"
    
    # Check for duplicates
    assert df.duplicated().sum() == 0, "Duplicate rows found"
    
    # Validate feature ranges
    numeric_features = df.select_dtypes(include=['number']).columns
    for col in numeric_features:
        assert df[col].min() >= 0, f"Negative values found in {col}"
    
    return True

# Example data preprocessing pipeline
def preprocess_spam_data(raw_df):
    """Preprocess raw spam training data"""
    
    # Remove duplicates
    df = raw_df.drop_duplicates()
    
    # Handle missing values (impute with median for numeric, mode for categorical)
    df = df.fillna(df.median(numeric_only=True))
    
    # Feature engineering for spam indicators
    df['url_count'] = df['content'].str.count(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+')
    df['exclamation_count'] = df['content'].str.count('!')
    
    # Label encoding for categorical features
    df['is_spam'] = df['is_spam'].astype(int)
    
    return df

3. Feature Engineering

Feature Taxonomy

Features are categorized into four main types:

  1. User Features: User behavior patterns, account age, reputation scores, device characteristics
  2. Item Features: Content metadata, text characteristics, media properties, URL patterns
  3. Context Features: Time-based signals, geographic information, device type, session behavior
  4. Interaction Features: User-item engagement patterns, temporal sequences, click-through behavior

Embedding Design

Entity Embeddings:

  • User ID embeddings (512-dim) trained via contrastive learning
  • Item ID embeddings (256-dim) from collaborative filtering
  • Category embeddings (128-dim) for content classification

Text Embeddings:

  • BERT-based sentence embeddings (768-dim) for content analysis
  • TF-IDF weighted word embeddings (300-dim) for keyword detection

Graph Embeddings:

  • User-item interaction graph embeddings (256-dim) via Node2Vec
  • Social network embeddings (128-dim) for user reputation

Real-time vs Batch Feature Computation

Feature TypeComputation ModeReasoning
User reputation scoreBatchComputed daily from user behavior
Content word countReal-timeRequired for live scoring
Temporal engagement patternsReal-timeSession-based, requires low latency
Historical spam report countBatchUpdated hourly from feedback loop

Feature Store Design

Online Store:

  • Redis-based key-value store for real-time feature lookup
  • TTL of 1 hour for session features, 24 hours for user features

Offline Store:

  • Parquet files in S3 for training data pipeline
  • Partitioned by date and user ID for efficient querying

Feature Freshness and TTL

FeatureSourceUpdate FrequencyStore Type
User reputation scoreBehavior logsDailyOffline
Content word countText parserReal-timeOnline
Temporal engagementSession logsPer sessionOnline
Historical spam reportsFeedback systemHourlyOffline
Device fingerprintUser agent parserReal-timeOnline

Cross Features and Feature Interaction Strategy

Cross features are engineered to capture complex user-item relationships:

  1. User-Item Interaction Crosses:

    • User-item engagement frequency × item popularity score
    • User session duration × content sentiment score
  2. Temporal Crosses:

    • Time since last interaction × user engagement rate
    • Hour of day × content category
  3. Content Crosses:

    • URL domain trust score × content word count
    • Spam keyword frequency × content length

Feature Importance and Selection Methodology

Importance Metrics:

  • SHAP values from XGBoost model for global importance
  • Permutation importance from trained DNN models
  • Information gain from decision trees

Selection Strategy:

  1. Remove features with SHAP importance < 0.005
  2. Apply VIF > 5 threshold to remove multicollinearity
  3. Retain top 1000 features based on combined importance scores
import numpy as np
from sklearn.feature_selection import SelectKBest, f_classif

class FeatureSelector:
    def __init__(self, k=1000):
        self.k = k
        self.selector = SelectKBest(score_func=f_classif, k=k)
    
    def fit_transform(self, X, y):
        # X shape: (n_samples, n_features)
        # y shape: (n_samples,)
        return self.selector.fit_transform(X, y)
    
    def get_support_mask(self):
        return self.selector.get_support()
    
    def get_feature_scores(self):
        # Return feature scores for analysis
        return self.selector.scores_

# Example usage for spam detection features
def feature_selection_pipeline(X_train, y_train):
    # Apply feature selection to reduce dimensionality while preserving signal
    selector = FeatureSelector(k=1000)
    X_selected = selector.fit_transform(X_train, y_train)
    
    # Get feature importance scores for monitoring
    feature_scores = selector.get_feature_scores()
    
    return X_selected, feature_scores

4. Model Architecture

Model Selection with Justification

For spam detection, I recommend a two-tower DNN architecture with the following rationale:

  1. Logistic Regression: Simple, interpretable, good baseline but insufficient for complex spam patterns
  2. GBM (XGBoost/LightGBM): Handles feature interactions well, robust to outliers, but struggles with high-dimensional sparse text features
  3. DNN: Excellent at capturing complex feature interactions, handles high-dimensionality well, and can learn sophisticated spam patterns
  4. Transformer: Powerful for sequence modeling but overkill for this use case and higher latency

The two-tower approach is optimal because:

  • Separates user and item (message) representations
  • Enables efficient retrieval and scoring
  • Handles sparse text features effectively
  • Allows for easy integration of embeddings and dense features

Architecture Diagram

graph TD
    A[User Features] --> B[User Tower]
    C[Message Features] --> D[Item Tower]
    B --> E[Merged Representation]
    D --> E
    E --> F[Classification Head]
    F --> G[Spam Probability]
    
    subgraph User Tower
        B1[Embedding Layer]
        B2[MLP Layers]
        B3[User Embedding]
    end
    
    subgraph Item Tower
        D1[Embedding Layer]
        D2[MLP Layers]
        D3[Item Embedding]
    end
    
    subgraph Classification
        F1[Concatenation]
        F2[MLP Layers]
        F3[Output Layer]
    end

Two-Tower / Multi-Task / Ensemble Design

The system uses a two-tower architecture where:

  • User tower processes user features (user behavior, demographics)
  • Item tower processes message features (content, metadata, sender info)
  • Towers are concatenated and passed through a classification head

For multi-task learning, we can extend this to include:

  • Content quality scoring (to detect low-quality content)
  • User engagement prediction (to understand spam impact)

Pre-trained Model Selection and Fine-tuning Strategy

For text features, we'll use:

  • Pre-trained BERT (base model) for content understanding
  • Fine-tune on our spam detection task with 20k labeled examples
  • Use LoRA for efficient fine-tuning to reduce compute requirements

Model Complexity vs Latency Trade-off Analysis

ModelParametersInference Time (ms)Memory Usage (GB)Accuracy (AUC)
Logistic Regression10k0.50.010.82
XGBoost1M50.10.91
Two-Tower DNN5M250.50.94
BERT + Fine-tune100M1502.00.96

Offline Evaluation Baseline Framing

Baseline: XGBoost model with 85% AUC (expected)
Proposed: Two-tower DNN with 94% AUC (target)

Core Model Code Snippet

import torch
import torch.nn as nn
import torch.nn.functional as F

class SpamDetectionModel(nn.Module):
    def __init__(self, user_vocab_size=10000, item_vocab_size=50000, 
                 user_embed_dim=128, item_embed_dim=256, 
                 hidden_dims=[256, 128], dropout_rate=0.3):
        super().__init__()
        
        # User embedding tower
        self.user_embedding = nn.Embedding(user_vocab_size, user_embed_dim)
        self.user_mlp = nn.Sequential(
            nn.Linear(user_embed_dim, hidden_dims[0]),
            nn.ReLU(),
            nn.Dropout(dropout_rate),
            nn.Linear(hidden_dims[0], hidden_dims[1]),
            nn.ReLU()
        )
        
        # Item embedding tower
        self.item_embedding = nn.Embedding(item_vocab_size, item_embed_dim)
        self.item_mlp = nn.Sequential(
            nn.Linear(item_embed_dim, hidden_dims[0]),
            nn.ReLU(),
            nn.Dropout(dropout_rate),
            nn.Linear(hidden_dims[0], hidden_dims[1]),
            nn.ReLU()
        )
        
        # Classification head
        self.classifier = nn.Sequential(
            nn.Linear(hidden_dims[1] * 2, hidden_dims[1]),
            nn.ReLU(),
            nn.Dropout(dropout_rate),
            nn.Linear(hidden_dims[1], 1),
            nn.Sigmoid()
        )
        
    def forward(self, user_ids, item_ids, user_features=None, item_features=None):
        # User tower
        user_embed = self.user_embedding(user_ids).mean(dim=1)  # Average over sequence
        user_repr = self.user_mlp(user_embed)
        
        # Item tower  
        item_embed = self.item_embedding(item_ids).mean(dim=1)
        item_repr = self.item_mlp(item_embed)
        
        # Combine representations
        combined = torch.cat([user_repr, item_repr], dim=1)
        
        # Classification
        output = self.classifier(combined)
        return output.squeeze()

    def calculate_loss(self, predictions, targets):
        # Binary cross entropy loss
        return F.binary_cross_entropy(predictions, targets.float())

# Example usage for training
model = SpamDetectionModel()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

# Sample batch forward pass
user_ids = torch.randint(0, 10000, (32,))
item_ids = torch.randint(0, 50000, (32,))
labels = torch.randint(0, 2, (32,))

predictions = model(user_ids, item_ids)
loss = model.calculate_loss(predictions, labels)

print(f"Spam Detection Loss: {loss.item():.4f}")
print(f"Prediction Probability: {predictions[0].item():.4f}")

This implementation provides:

  • Modular architecture for easy extension
  • Efficient embedding handling for sparse features
  • Standard loss function for binary classification
  • Production-ready tensor operations with proper device handling
  • Clear separation between user and item representations

5. Serving & Inference Architecture

System Diagram

graph TD
    A[User Request] --> B[Load Balancer]
    B --> C[Spam Detection Service]
    C --> D{Online/Offline}
    D -->|Online| E[Feature Store]
    D -->|Offline| F[Batch Feature Store]
    E --> G[Embedding Cache]
    G --> H[Model Serving]
    F --> I[Model Training]
    H --> J[Spam Prediction]
    J --> K[Response]
    
    subgraph "Real-time Pipeline"
        C
        E
        G
        H
        J
    end
    
    subgraph "Batch Pipeline"
        F
        I
    end

Online vs Batch Serving Decision

For spam detection, we require real-time serving with sub-100ms latency to prevent spam content from being served to users. The system must process each request as it arrives with minimal delay, making batch serving unsuitable for this use case. Real-time serving ensures that spam content is blocked before it reaches end users, which is critical for user experience and platform safety.

Two-Stage Pipeline

1. Candidate Retrieval → 2. Scoring → 3. Re-ranking

Stage 1: Candidate Retrieval

  • Filter out obviously non-spam content using rule-based heuristics (e.g., content length, URL count)
  • Reduce candidate set to manageable size for scoring

Stage 2: Scoring

  • Apply ML model to remaining candidates
  • Return spam probability score

Stage 3: Re-ranking

  • Apply additional business logic (e.g., user trust score, content type thresholds)
  • Final spam classification decision

Serving Infrastructure

We'll use TorchServe for model serving with the following configuration:

  • Model Format: TorchScript (for production deployment)
  • Hardware: GPU-enabled instances (NVIDIA A10 or V100)
  • Model Compression: Quantization to INT8 for reduced memory footprint
  • Scalability: Horizontal scaling with Kubernetes pods

Justification: TorchServe provides optimal performance for PyTorch models, supports model versioning, and integrates well with Kubernetes orchestration. It's designed for low-latency inference with built-in support for model compression and caching.

Latency Budget Breakdown

Stagep50 Latencyp99 LatencyBudget
Feature Retrieval5ms15ms20ms
Model Inference10ms25ms30ms
Post-processing2ms5ms10ms
Total17ms45ms60ms

Model Compression Strategy

We'll implement quantization-aware training and pruning to reduce model size while maintaining accuracy:

import torch
import torch.nn as nn

class CompressedSpamModel(nn.Module):
    def __init__(self, original_model):
        super().__init__()
        self.model = original_model
        # Apply quantization to reduce memory usage by ~75%
        self.quantized_model = torch.quantization.quantize_dynamic(
            self.model, {nn.Linear}, dtype=torch.qint8
        )
    
    def forward(self, features):
        # Quantized inference for faster response times
        return self.quantized_model(features)

Caching Strategy

Prediction Cache:

  • Cache results for 5-minute TTL to handle duplicate requests
  • Use Redis with LRU eviction policy

Embedding Cache:

  • Cache user/item embeddings for 1-hour TTL
  • Evict stale embeddings to maintain freshness

KV Cache:

  • For transformer-based models, cache attention keys/values
  • Reduce recomputation for similar user patterns

Auto-scaling and Capacity Planning

Horizontal Scaling:

  • Scale based on QPS with target 95th percentile latency < 50ms
  • Auto-scale from 2 to 20 pods based on load

Capacity Estimation:

  • QPS Target: 10,000 requests/sec
  • Peak Load: 20,000 QPS (2x peak)
  • Model Memory: ~1GB per model instance
  • Total GPU Memory: 20GB (20 instances × 1GB)
  • CPU Cores: 4 cores per instance for feature processing

Scaling Logic:

def calculate_scaling_factor(current_qps, target_qps):
    # Linear scaling factor based on QPS
    return max(1, min(20, current_qps / target_qps))

# Example: 15K QPS → Scale to 30 pods (1.5x scaling factor)

This architecture supports sub-50ms response times while maintaining high availability and scalability for a production spam detection system.

6. Evaluation Framework

Offline Evaluation Methodology

For spam detection, we use a temporal holdout split with 80/20 train/test split, ensuring that the test set contains data from a later time window to simulate real-world deployment conditions. This approach prevents data leakage and provides realistic performance estimates. We also implement 5-fold temporal cross-validation for robustness, particularly important given the evolving nature of spam patterns.

Slice-Based Evaluation

We evaluate model performance across critical user segments:

  • User tenure: New vs. established users (new users may have less behavioral history)
  • Device type: Mobile vs. desktop (spam patterns differ by device)
  • Geographic region: High-spam regions vs. low-spam regions (regional spam trends)
  • Content category: Email vs. SMS vs. social media (different spam characteristics)

We define slices with minimum 1000 samples to ensure statistical significance. For example, we monitor precision and recall for each slice to detect performance degradation in specific user segments.

A/B Test Design

We design a randomized controlled experiment with:

  • Randomization unit: User ID (to prevent spillover effects)
  • Sample size calculation: Using power analysis with 80% power, 5% significance level, and expected 15% relative improvement in spam detection rate. With 2M users, we achieve ~95% power for detecting a 10% improvement.
  • Duration: 2 weeks (allowing for seasonal variation and user behavior stabilization)
  • Primary metric: Spam detection accuracy with 95% confidence interval

Guardrail Metrics and Blocking Conditions

We implement guardrails to prevent model degradation:

  • False positive rate: Must not exceed 2% (to avoid blocking legitimate content)
  • Precision drop: If precision drops more than 10% from baseline, automatic rollback
  • Recall drop: If recall drops more than 15% from baseline, alert and investigation

Shadow Mode Rollout Plan

We implement shadow mode for 2 weeks before full A/B test:

  1. Traffic allocation: 10% of live traffic routed to shadow model
  2. Logging: All predictions from shadow model logged for comparison with production
  3. Performance validation: Compare shadow model performance against baseline to ensure consistency
  4. Feedback loop: Collect user feedback on false positives from shadow model

Long-Term Metric Measurement

We track delayed conversion and engagement decay:

  • Delayed spam detection: Monitor if users who were incorrectly classified as spam later engage with content (engagement rate 30 days post-classification)
  • User retention: Track if users blocked by spam detection show reduced engagement or churn
  • Engagement decay: Measure content consumption patterns for users incorrectly flagged as spam
# Example A/B test evaluation code snippet
import numpy as np
from scipy import stats

class SpamDetectionEvaluator:
    def __init__(self):
        self.primary_metric = "spam_detection_accuracy"
        
    def calculate_ab_test_stats(self, baseline_scores, test_scores):
        """Calculate confidence intervals for A/B test results"""
        # Calculate mean difference
        mean_diff = np.mean(test_scores) - np.mean(baseline_scores)
        
        # Calculate standard error
        se = np.sqrt(
            np.var(test_scores) / len(test_scores) + 
            np.var(baseline_scores) / len(baseline_scores)
        )
        
        # 95% confidence interval
        ci_lower = mean_diff - 1.96 * se
        ci_upper = mean_diff + 1.96 * se
        
        # p-value for two-tailed test
        t_stat, p_value = stats.ttest_ind(test_scores, baseline_scores)
        
        return {
            "mean_difference": mean_diff,
            "confidence_interval": (ci_lower, ci_upper),
            "p_value": p_value,
            "significant": p_value < 0.05
        }
    
    def evaluate_slice_performance(self, predictions, labels, slices):
        """Evaluate model performance across user slices"""
        results = {}
        for slice_name, slice_indices in slices.items():
            if len(slice_indices) < 100:  # Skip small slices
                continue
                
            slice_preds = [predictions[i] for i in slice_indices]
            slice_labels = [labels[i] for i in slice_indices]
            
            # Calculate precision and recall
            tp = sum(1 for p, l in zip(slice_preds, slice_labels) if p == 1 and l == 1)
            fp = sum(1 for p, l in zip(slice_preds, slice_labels) if p == 1 and l == 0)
            fn = sum(1 for p, l in zip(slice_preds, slice_labels) if p == 0 and l == 1)
            
            precision = tp / (tp + fp) if (tp + fp) > 0 else 0
            recall = tp / (tp + fn) if (tp + fn) > 0 else 0
            
            results[slice_name] = {
                "precision": precision,
                "recall": recall,
                "count": len(slice_indices)
            }
            
        return results

7. Training Pipeline

Training Data Pipeline

The training data pipeline follows a multi-stage ETL process:

  1. Data Ingestion: Raw spam detection data flows from multiple sources including user reports, automated content analysis, and labeled datasets from third-party providers
  2. Preprocessing:
    • Text cleaning (removing HTML tags, special characters)
    • Tokenization and normalization
    • Handling of multi-language content with appropriate encoders
  3. Shuffling: Data is shuffled using reservoir sampling to ensure randomness and prevent temporal bias
  4. Batching: Training batches of 1024 samples with proper class balancing
import torch
from torch.utils.data import Dataset, DataLoader
from sklearn.model_selection import train_test_split

class SpamDataset(Dataset):
    def __init__(self, texts, labels, tokenizer, max_length=512):
        self.texts = texts
        self.labels = labels
        self.tokenizer = tokenizer
        self.max_length = max_length
    
    def __len__(self):
        return len(self.texts)
    
    def __getitem__(self, idx):
        text = str(self.texts[idx])
        label = self.labels[idx]
        
        encoding = self.tokenizer(
            text,
            truncation=True,
            padding='max_length',
            max_length=self.max_length,
            return_tensors='pt'
        )
        
        return {
            'input_ids': encoding['input_ids'].flatten(),
            'attention_mask': encoding['attention_mask'].flatten(),
            'labels': torch.tensor(label, dtype=torch.long)
        }

# Training data preparation
def prepare_training_data(raw_data, test_size=0.1):
    # Split into train/test
    train_texts, test_texts, train_labels, test_labels = train_test_split(
        raw_data['texts'], 
        raw_data['labels'], 
        test_size=test_size, 
        stratify=raw_data['labels']
    )
    
    # Create datasets
    train_dataset = SpamDataset(train_texts, train_labels, tokenizer)
    test_dataset = SpamDataset(test_texts, test_labels, tokenizer)
    
    return train_dataset, test_dataset

Distributed Training Strategy

For distributed training, we use data parallelism with PyTorch's DistributedDataParallel (DDP):

  • Cluster Configuration: 4x A100 GPUs with 80GB VRAM each
  • Batch Size: 256 samples per GPU (1024 total batch size)
  • Gradient Accumulation: 4 steps to maintain effective batch size
  • Optimizer: AdamW with learning rate 2e-5, weight decay 0.01
  • Scheduler: Linear warmup (10% of training steps) + cosine decay

Training Infrastructure

  • Compute Cluster: 2x 8-GPU A100 nodes (16 GPUs total)
  • Memory Requirements: ~32GB per GPU for model + embeddings
  • Training Time: 4 hours for 100k samples on full dataset
  • Storage: 500GB SSD for training data and checkpoints

Hyperparameter Tuning Approach

We implement Bayesian optimization using Optuna:

import optuna
from sklearn.metrics import f1_score

def objective(trial):
    # Hyperparameter search space
    learning_rate = trial.suggest_float('learning_rate', 1e-6, 1e-3, log=True)
    batch_size = trial.suggest_categorical('batch_size', [32, 64, 128, 256])
    dropout_rate = trial.suggest_float('dropout_rate', 0.1, 0.5)
    
    # Model training with current hyperparameters
    model = SpamClassifier(
        dropout_rate=dropout_rate,
        num_classes=2
    )
    
    # Training loop with validation
    val_f1 = train_and_evaluate(model, learning_rate, batch_size)
    
    return val_f1

# Run optimization for 50 trials
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=50)

Key hyperparameters tuned:

  • Learning rate (1e-6 to 1e-3)
  • Batch size (32, 64, 128, 256)
  • Dropout rate (0.1 to 0.5)
  • Weight decay (0.001 to 0.01)

Experiment Tracking and Reproducibility

We use MLflow for experiment tracking:

import mlflow
import mlflow.pytorch

# MLflow tracking setup
mlflow.set_experiment("spam_detection")
with mlflow.start_run():
    # Log hyperparameters
    mlflow.log_params({
        "learning_rate": 2e-5,
        "batch_size": 256,
        "epochs": 10,
        "dropout_rate": 0.3
    })
    
    # Log model and metrics
    mlflow.pytorch.log_model(model, "model")
    mlflow.log_metric("f1_score", 0.94)
    mlflow.log_metric("precision", 0.92)
    mlflow.log_metric("recall", 0.96)

Model Versioning and Registry Strategy

  • Versioning: Semantic versioning (v1.0.0, v1.1.0) with git commit hash
  • Registry: MLflow Model Registry for model lifecycle management
  • Tagging: Models tagged by performance (F1 > 0.92), data version, and deployment status

Continual / Online Learning Design

For online learning capability:

  1. Incremental Training: Periodic retraining with new labeled data (every 24 hours)
  2. Concept Drift Detection: Monitor F1-score drift > 5% as trigger for retraining
  3. Data Sampling: Use stratified sampling to maintain class balance in online updates
  4. Ensemble Strategy: Maintain 3 most recent model versions for rollback capability
class OnlineSpamTrainer:
    def __init__(self, model, drift_threshold=0.05):
        self.model = model
        self.drift_threshold = drift_threshold
        self.performance_history = []
    
    def detect_concept_drift(self, new_performance):
        if len(self.performance_history) < 5:
            return False
            
        recent_avg = np.mean(self.performance_history[-5:])
        return abs(new_performance - recent_avg) > self.drift_threshold
    
    def incremental_train(self, new_data):
        # Apply online learning with small batches
        for batch in new_data:
            self.model.train_on_batch(batch)
            
        # Check if retraining needed
        if self.detect_concept_drift(self.current_f1()):
            self.trigger_full_retrain()

Data Pipeline Optimization

  • Prefetching: Use torch.utils.data.DataLoader with num_workers=4 and pin_memory=True
  • Memory Management: Implement proper garbage collection to prevent memory leaks
  • Checkpointing: Save model checkpoints every epoch with early stopping (patience=3)
  • Data Augmentation: Apply synthetic data generation for rare spam patterns

8. Monitoring & Observability

Data Drift Detection

Data drift detection is critical for maintaining model performance in spam detection systems where spam patterns evolve over time. We implement drift detection using:

  • PSI (Population Stability Index) for categorical features like user demographics and content categories
  • KL Divergence for continuous features such as message length, word frequency distributions
  • Statistical Tests (Kolmogorov-Smirnov test) for feature distributions
import numpy as np
from scipy import stats

def calculate_psi(expected, actual, bins=10):
    """Calculate PSI between expected and actual distributions"""
    # Bin the data
    _, bin_edges = np.histogram(expected, bins=bins)
    
    # Count occurrences in each bin
    expected_counts = np.histogram(expected, bins=bin_edges)[0]
    actual_counts = np.histogram(actual, bins=bin_edges)[0]
    
    # Avoid division by zero
    expected_counts = np.where(expected_counts == 0, 1e-6, expected_counts)
    actual_counts = np.where(actual_counts == 0, 1e-6, actual_counts)
    
    # Calculate PSI
    psi = np.sum((actual_counts - expected_counts) * 
                 np.log(actual_counts / expected_counts))
    return psi

def detect_drift_features(current_features, reference_features, threshold=0.1):
    """Detect drift across feature set"""
    drift_results = {}
    
    for feature_name, current_data in current_features.items():
        reference_data = reference_features[feature_name]
        
        psi_value = calculate_psi(reference_data, current_data)
        drift_results[feature_name] = {
            'psi': psi_value,
            'drift_detected': psi_value > threshold
        }
    
    return drift_results

Prediction Drift and Label Drift Monitoring

Prediction drift occurs when model confidence distributions shift, indicating potential concept drift. We monitor:

  • Confidence Distribution Shift: Using KL divergence between predicted probability distributions
  • Prediction Label Shift: Tracking distribution changes in predicted spam vs. ham labels
from sklearn.metrics import log_loss
import numpy as np

class PredictionDriftMonitor:
    def __init__(self, threshold=0.1):
        self.threshold = threshold
        self.reference_probs = None
        
    def update_reference(self, probs):
        """Store reference probability distribution"""
        self.reference_probs = probs
        
    def detect_prediction_drift(self, current_probs):
        """Detect drift in prediction probabilities"""
        if self.reference_probs is None:
            return False
            
        # KL divergence between distributions
        kl_div = np.sum(self.reference_probs * 
                       (np.log(self.reference_probs + 1e-8) - 
                        np.log(current_probs + 1e-8)))
        
        return kl_div > self.threshold

# Example usage
drift_monitor = PredictionDriftMonitor(threshold=0.15)

Model Performance Degradation Alerting

We implement comprehensive alerting for model performance degradation:

  • AUC Drop Alert: When AUC drops below threshold (e.g., 0.05)
  • Precision/Recall Drop: For critical business metrics
  • False Positive Rate Increase: Critical for spam detection systems
class PerformanceMonitor:
    def __init__(self, alert_thresholds):
        self.alert_thresholds = alert_thresholds
        self.performance_history = []
        
    def evaluate_performance(self, y_true, y_pred_proba):
        """Calculate performance metrics"""
        from sklearn.metrics import roc_auc_score, precision_score, recall_score
        
        auc = roc_auc_score(y_true, y_pred_proba)
        precision = precision_score(y_true, y_pred_proba > 0.5)
        recall = recall_score(y_true, y_pred_proba > 0.5)
        
        metrics = {
            'auc': auc,
            'precision': precision,
            'recall': recall,
            'fpr': self.calculate_fpr(y_true, y_pred_proba)
        }
        
        return metrics
        
    def calculate_fpr(self, y_true, y_pred_proba):
        """Calculate false positive rate"""
        from sklearn.metrics import confusion_matrix
        tn, fp, fn, tp = confusion_matrix(y_true, y_pred_proba > 0.5).ravel()
        return fp / (fp + tn) if (fp + tn) > 0 else 0
        
    def check_alerts(self, current_metrics):
        """Check if any alert conditions are met"""
        alerts = []
        
        for metric_name, threshold in self.alert_thresholds.items():
            if current_metrics[metric_name] < threshold:
                alerts.append({
                    'metric': metric_name,
                    'current_value': current_metrics[metric_name],
                    'threshold': threshold,
                    'alert_type': 'performance_degradation'
                })
                
        return alerts

Retraining Trigger Strategy

We implement a multi-trigger retraining strategy:

  • Scheduled Retraining: Weekly model refresh
  • Drift-Based Trigger: When drift exceeds thresholds (PSI > 0.15, AUC drop > 0.05)
  • Performance-Based Trigger: When FPR exceeds acceptable limits (e.g., > 0.02)
class RetrainingTrigger:
    def __init__(self, drift_threshold=0.15, performance_threshold=0.05):
        self.drift_threshold = drift_threshold
        self.performance_threshold = performance_threshold
        
    def should_retrain(self, drift_results, performance_metrics):
        """Determine if model should be retrained"""
        
        # Check drift conditions
        drift_detected = any(
            result['drift_detected'] 
            for result in drift_results.values()
        )
        
        # Check performance degradation
        auc_drop = performance_metrics['auc'] < (performance_metrics['auc'] - self.performance_threshold)
        
        # Trigger retraining if any condition met
        return drift_detected or auc_drop
        
    def trigger_retraining(self, model_version):
        """Initiate retraining process"""
        # Log retraining trigger
        print(f"Triggering retraining for model version {model_version}")
        
        # In production, this would call training pipeline
        return "retraining_initiated"

Logging Design

Comprehensive logging ensures observability and enables debugging:

import json
from datetime import datetime

class SpamDetectionLogger:
    def __init__(self, log_level="INFO"):
        self.log_level = log_level
        
    def log_prediction(self, request_id, input_data, prediction, confidence):
        """Log model predictions"""
        log_entry = {
            "timestamp": datetime.now().isoformat(),
            "request_id": request_id,
            "input_data": input_data,
            "prediction": prediction,
            "confidence": confidence,
            "log_type": "prediction"
        }
        
        # Write to logging system (e.g., CloudWatch, ELK)
        self.write_log(log_entry)
        
    def log_feature_data(self, feature_data):
        """Log feature data for drift analysis"""
        log_entry = {
            "timestamp": datetime.now().isoformat(),
            "feature_data": feature_data,
            "log_type": "feature"
        }
        
        self.write_log(log_entry)
        
    def write_log(self, log_entry):
        """Write log entry to storage"""
        # In production: write to centralized logging system
        print(json.dumps(log_entry))

Feedback Loop for Continuous Improvement

We implement a feedback loop to capture human corrections:

class FeedbackLoop:
    def __init__(self, feedback_queue):
        self.feedback_queue = feedback_queue
        
    def collect_feedback(self, request_id, correct_label, user_confirmed=False):
        """Collect human feedback for model improvement"""
        
        feedback_entry = {
            "request_id": request_id,
            "correct_label": correct_label,
            "user_confirmed": user_confirmed,
            "timestamp": datetime.now().isoformat()
        }
        
        # Add to feedback queue for retraining
        self.feedback_queue.append(feedback_entry)
        
        # If sufficient feedback, trigger model update
        if len(self.feedback_queue) >= 1000:  # Threshold for batch processing
            self.process_feedback_batch()
            
    def process_feedback_batch(self):
        """Process feedback batch for model retraining"""
        # In production: trigger retraining pipeline with feedback data
        print(f"Processing {len(self.feedback_queue)} feedback entries")
        
        # Clear queue after processing
        self.feedback_queue.clear()

Key Metrics for Monitoring

MetricDescriptionAlert Threshold
AUCArea Under ROC Curve< 0.95
FPRFalse Positive Rate> 0.02
PrecisionSpam detection precision< 0.90
RecallSpam detection recall< 0.85
PSIPopulation Stability Index> 0.15

Observability Dashboard Components

  • Real-time Performance Metrics: Live AUC, precision, recall
  • Drift Indicators: Feature drift status, prediction drift
  • Model Health: Confidence distribution, prediction volume trends
  • Feedback Metrics: User correction rates, feedback queue size

The monitoring system provides comprehensive observability to ensure spam detection models maintain high performance and adapt to evolving spam patterns in real-time.

9. Responsible AI & Safety

Bias Analysis

  • Training data audit: Conduct comprehensive audit of training data to identify potential biases in spam vs. legitimate content distribution across demographics, regions, and content types
  • Slice-based fairness evaluation: Evaluate model performance across user segments (age groups, geographic regions, language preferences) to detect disparate impact
  • Content bias detection: Analyze whether model disproportionately flags content from specific cultural, political, or social groups

Fairness Metrics and Constraints

  • Primary fairness metric: Demographic parity (equal false positive rates across user segments)
  • Secondary metrics: Equalized odds (equal true positive and false positive rates)
  • Decision rationale: Demographic parity is preferred over equalized odds for spam detection as it ensures consistent false positive rates across user groups, preventing systematic unfair treatment of specific communities

Explainability Requirements and Approach

  • SHAP values: Implement SHAP-based explainability for individual predictions to understand feature importance and identify potential bias sources
  • Attention visualization: For transformer-based models, visualize attention weights to understand which content segments drive spam classification
  • Stakeholder requirements:
    • Business: Need to understand why specific content is flagged for manual review
    • Legal: Compliance with content moderation regulations requiring explainable AI
    • Users: Transparent appeal process for false positives

For LLM Systems: Safety Guardrails

  • Content filtering: Implement content safety checks for toxic language, hate speech, and inappropriate material in spam detection context
  • Output validation: Ensure model outputs don't generate harmful content or misleading information about spam classification
  • Rate limiting: Implement rate limits on spam detection API to prevent abuse and ensure system stability
  • Red teaming: Regular adversarial testing with security researchers to identify potential evasion techniques

Model Card Documentation Plan

  • Content: Include model architecture, training data sources, performance metrics, bias analysis results, and safety measures
  • Versioning: Maintain model cards for each version with changelogs of improvements and identified issues
  • Public accessibility: Make model cards available to stakeholders for transparency and compliance requirements

Incident Response Plan for Model Failures or Harmful Outputs

  • Failure detection: Monitor for sudden spikes in false positives, model drift, or systematic misclassification patterns
  • Escalation protocol:
    • <5% false positive rate increase → alert ML team
    • 10% false positive rate increase → immediate model rollback and investigation

  • Manual override: Implement human review queue for flagged content with high confidence scores (90%+)
  • Communication plan: Notify affected users and stakeholders of system issues with clear mitigation steps
# Example: Fairness-aware spam detection model with bias monitoring
import numpy as np
from sklearn.metrics import confusion_matrix, classification_report

class FairSpamDetector:
    def __init__(self):
        self.model = None
        self.fairness_metrics = {}
    
    def evaluate_fairness(self, y_true, y_pred, user_groups):
        """Evaluate fairness across user groups"""
        for group in np.unique(user_groups):
            mask = user_groups == group
            y_true_group = y_true[mask]
            y_pred_group = y_pred[mask]
            
            tn, fp, fn, tp = confusion_matrix(y_true_group, y_pred_group).ravel()
            
            # Demographic parity calculation
            fpr_group = fp / (fp + tn) if (fp + tn) > 0 else 0
            fnr_group = fn / (fn + tp) if (fn + tp) > 0 else 0
            
            self.fairness_metrics[group] = {
                'false_positive_rate': fpr_group,
                'false_negative_rate': fnr_group
            }
            
        return self.fairness_metrics
    
    def check_bias_alert(self, threshold=0.1):
        """Check if fairness thresholds are exceeded"""
        fprs = [v['false_positive_rate'] for v in self.fairness_metrics.values()]
        max_diff = max(fprs) - min(fprs)
        
        if max_diff > threshold:
            return True, f"Fairness violation detected: {max_diff:.2%} difference in FPR"
        return False, "No fairness violations detected"

10. Scalability & Reliability

Bottleneck Analysis per Pipeline Stage

Training Pipeline:

  • Data ingestion: 100GB/day → 500GB/week → 2TB/month (assuming 4x data growth)
  • Feature extraction: ~100ms per sample → 20M samples/day = 2000s/day = ~33 minutes per day
  • Model training: 10GB model → 200GB parameter space (with embeddings) → 4 hours training on 8x V100s
  • Model serialization: ~500MB model size → 100ms to load into memory

Serving Pipeline:

  • QPS requirement: 10,000 requests/sec (back-of-envelope: 500M messages/day → 500M/86400 ≈ 5,800 QPS)
  • Latency budget: 100ms p99 (50ms for retrieval + 20ms for scoring + 30ms for re-ranking)
  • Memory requirement: 10GB model + 2GB embeddings = 12GB per serving instance
  • CPU requirement: 20 cores per instance for concurrent inference

Back-of-envelope QPS math:

QPS = 500M messages/day / 86400 seconds ≈ 5,787 QPS
Serving instances needed = 5,787 QPS / 100 QPS per instance ≈ 58 instances

Scale-up Strategy

Horizontal Scaling of Serving:

  • Auto-scaling groups with 50-100 instances per region
  • Load balancing across availability zones
  • Multi-region deployment (US East, EU West, APAC) with failover

Distributed Feature Computation:

  • Feature store with 100M+ user features
  • Batch processing pipeline with 200GB daily feature updates
  • Distributed compute cluster (50 nodes) for real-time feature computation

Fault Tolerance

Model Serving Fallbacks:

  • Primary model (ML) → Secondary rule-based system (fallback)
  • Stale model serving: 30-minute grace period before fallback to last known good model
  • Graceful degradation: reduce feature set or use simpler model variant

Stale Model Handling:

  • Model version monitoring with 24-hour freshness window
  • Automated retraining pipeline trigger when drift > 5%
  • Shadow mode for new model validation before production switch

Cold Start Handling Strategy

New User Handling:

  • Rule-based fallback for new users (default spam probability = 0.1)
  • Content-based features from first message
  • Collaborative filtering with similar user profiles (if available)

New Item Handling:

  • Default spam score = 0.2 for unknown content types
  • Feature-based matching with known spam patterns
  • Gradual learning from user feedback

Multi-Region Serving Strategy

Regional Architecture:

[US-East] [EU-West] [APAC-Singapore]
   |         |          |
   |         |          |
[Load Balancer] [Load Balancer] [Load Balancer]
   |         |          |
   |         |          |
[Spam Detection Service] [Spam Detection Service] [Spam Detection Service]
   |         |          |
   |         |          |
[Model Serving Cluster] [Model Serving Cluster] [Model Serving Cluster]

Cross-Region Failover:

  • 300ms failover latency target
  • Regional auto-scaling with 2x capacity buffer
  • Global rate limiting and request routing based on user location

Consistency Model:

  • Eventual consistency for feature updates (5-minute TTL)
  • Strong consistency for model versioning and serving
  • Geo-replicated feature store with read-replica architecture

Reliability Targets:

  • 99.9% uptime for spam detection service
  • <50ms p99 latency for all regions
  • 100% availability during failover (with fallback to rule-based system)
  • <5% false positive rate under normal operation
  • <2% false negative rate for spam content

11. Open Questions, Risks & Trade-offs

Decisions requiring product / engineering / policy alignment

  • Content moderation policy alignment: Should the system flag all potentially harmful content or only explicitly malicious spam? This requires alignment with legal and content policy teams.
  • User experience trade-off: How aggressive should spam detection be? Over-filtering risks false positives that impact legitimate user communication, under-filtering risks spam proliferation.
  • Cross-platform consistency: Should the same model be used across email, messaging, and comment systems or should each have platform-specific models?

Key ML risks

RiskImpactLikelihoodMitigation
Evasion attacksHigh (malicious actors can craft spam to bypass detection)MediumImplement adversarial training, regular model retraining with new spam patterns
Class imbalanceMedium (spam is rare but highly impactful)HighUse weighted loss functions, stratified sampling, and ensemble methods
Data driftHigh (new spam techniques emerge constantly)HighImplement continuous monitoring, scheduled retraining, and drift detection
False positivesMedium (legitimate content flagged as spam)HighUse multi-stage filtering, human review fallback, and user feedback loops
Bias amplificationMedium (underrepresented groups may be disproportionately affected)MediumAudit training data for representation, implement fairness constraints

Trade-offs made with justification

Trade-offJustification
Accuracy vs LatencyPrioritize low latency (≤100ms) for real-time spam detection over marginal accuracy gains, as user experience is paramount
Freshness vs CostAccept some delay in model updates to reduce training costs and infrastructure requirements
Model Size vs QualityUse smaller, efficient models (e.g., LightGBM or BERT-based) rather than very large transformers to balance performance with serving constraints
Online vs Batch LearningPrefer batch learning for stability and cost efficiency over continuous online updates
Feature Richness vs Serving SpeedUse pre-computed features rather than real-time feature computation to meet strict latency requirements

Alternatives considered and rejected

  • Traditional rule-based systems: Rejected due to high maintenance burden and inability to adapt to new spam patterns
  • Deep learning with full transformer models: Rejected due to high latency and computational cost for real-time serving
  • Ensemble of multiple models: Rejected due to complexity and latency overhead; opted for single optimized model with strong performance

Technical debt acknowledged

  • Limited historical training data: Current dataset may not capture all spam evolution patterns, leading to potential drift over time
  • Manual labeling dependency: Reliance on human annotators for training data introduces latency and potential inconsistency
  • No real-time feedback integration: Current system lacks ability to quickly incorporate user feedback for model improvement
  • Limited cross-platform feature sharing: Models for different platforms (email, messaging) are trained independently, missing opportunities for shared learning

12. Phased Implementation Roadmap

Phase 1: MVP (Weeks 1-4)

Objective: Establish baseline spam detection with rule-based fallback and simple ML model

Deliverables:

  • Rule-based spam classifier (email headers, sender reputation, known spam patterns)
  • Basic ML model using TF-IDF + Logistic Regression
  • Online serving infrastructure with 100 QPS capacity
  • Basic A/B testing framework

Dependencies:

  • Data pipeline ready with labeled training data (10M emails)
  • Feature store MVP with user/item features
  • Basic model serving stack (TorchServe or custom)

Critical Path:

  1. Rule-based baseline implementation (Week 1)
  2. Simple ML model training and deployment (Week 2-3)
  3. Online serving stack setup (Week 3)
  4. A/B test infrastructure (Week 4)

Phase 2: Scale & Refinement (Weeks 5-8)

Objective: Expand to real-time features, distributed training, and comprehensive evaluation

Deliverables:

  • Real-time feature computation (user behavior, context)
  • Distributed training pipeline (data parallelism across 10 GPUs)
  • Multi-task model supporting spam + phishing detection
  • Feature store with online/offline sync (100ms TTL)
  • Comprehensive A/B testing with 5% traffic split

Dependencies:

  • Feature store fully operational
  • Distributed training infrastructure (Kubernetes + Ray)
  • ML experiment tracking system (MLflow)
  • Shadow mode for testing new models

Critical Path:

  1. Feature store integration (Week 5)
  2. Distributed training pipeline (Week 6)
  3. Multi-task model design and training (Week 7)
  4. A/B testing framework expansion (Week 8)

Phase 3: Excellence & Continuous Learning (Weeks 9-12)

Objective: Advanced models, real-time learning, and production-grade observability

Deliverables:

  • Transformer-based spam detection model (BERT + custom attention)
  • Online learning pipeline with concept drift detection
  • Comprehensive monitoring dashboard with drift alerts
  • Automated retraining with performance degradation detection
  • Multi-region serving with 99.9% uptime SLA

Dependencies:

  • Production-grade monitoring stack (Prometheus + Grafana)
  • Automated retraining triggers
  • Multi-region cloud infrastructure (AWS/GCP)
  • Model versioning and rollback capability

Critical Path:

  1. Transformer model fine-tuning (Week 9)
  2. Online learning implementation (Week 10)
  3. Production monitoring stack (Week 11)
  4. Multi-region deployment and testing (Week 12)

Risk Mitigation & Contingency Plans:

  • Data quality issues: Maintain rule-based fallback as primary defense
  • Model drift: Implement shadow mode and gradual rollouts
  • Latency issues: Pre-computed embeddings and caching strategy
  • Scale limitations: Horizontal scaling capability with auto-scaling

Success Metrics:

  • 95%+ spam detection accuracy (precision@100)
  • <200ms median latency for 99% of requests
  • 100M emails processed daily with <5% false positive rate
  • 99.9% system uptime with automatic failover capability

Cross-functional Dependencies:

  • ML Engineering: Model training, deployment, monitoring
  • Platform Engineering: Distributed training infrastructure, feature store
  • Product: A/B test design, success metrics definition
  • Security: Content filtering, safety guardrails implementation

Was this article helpful?

Topics in this article

More from AI/ML System Design

Stay in the Loop

Get curated DSA patterns, coding problems, frontend and backend LLD/HLD, and AI/ML System Design insights delivered straight to your inbox. No spam, just focused interview and engineering content.