# Ads Serving Service Architecture

## Tổng Quan / Overview

```mermaid
graph LR
    subgraph "Request Flow < 100ms"
        REQ[Ad Request] --> GW[Traefik Gateway]
        GW --> CACHE[Redis Cache]
        CACHE --> AUC[Auction Engine]
        AUC --> RESP[Response]
        RESP --> EVT[Fire Events Async]
    end
    
    subgraph "Async Events"
        EVT --> MQ[RabbitMQ]
        MQ --> BILL[ads-billing]
        MQ --> TRACK[ads-tracking]
        MQ --> ANAL[ads-analytics]
    end
```

## Domain Aggregates

### AdRequest Aggregate
- **AdRequest**: Placement, UserContext, Device

### Auction Aggregate
- **Auction** (Root): Single ad auction instance
- **Bid**: Candidate ad with calculated score
- **AuctionResult**: Winner, final price

### Pacing Aggregate
- **BudgetPacer**: Smooth/Accelerated spending
- **SpendTracker**: Real-time budget consumption

### Frequency Aggregate
- **FrequencyCap**: Max impressions per user/day
- **UserAdHistory**: Redis-backed view tracking

## eCPM Calculation

```
eCPM = (Bid × Predicted_CTR × 1000) + Quality_Score

Where:
- Bid: Advertiser's bid amount
- Predicted_CTR: ML-predicted click probability
- Quality_Score: Ad relevance + landing page quality
```

## Redis Data Structures

| Key | Type | TTL | Purpose |
|-----|------|-----|---------|
| `ads:active:{placement}` | Sorted Set | 5 min | Active ads by eCPM |
| `freq:{userId}:{date}` | Hash | 24h | Ad views per user |
| `budget:{campaignId}:{date}` | String | 24h | Daily spend counter |
| `target:{criteria}` | Set | 1h | Eligible ad sets |

## Latency Budget

| Phase | Target |
|-------|--------|
| Redis lookup | < 5ms |
| Auction logic | < 20ms |
| Response serialization | < 5ms |
| **Total** | **< 100ms** |
