Ads Serving Service
High-performance microservice for real-time bidding (RTB) and ad delivery with < 100ms latency.
Overview
Ads Serving Service is the heart of the advertising system, handling millions of requests per second:
- Real-Time Bidding (RTB) - Real-time ad auction
- Ad Selection - Select the most relevant ad
- Pacing Algorithm - Budget smoothing
- Frequency Capping - Control ad frequency per user
Requirements
| Requirement | Version |
|---|---|
| .NET SDK | 10.0.101+ |
| Docker | 24.0+ |
| Redis | 7.0+ (required) |
| PostgreSQL | 15+ |
Quick Start
cd services/ads-serving-service-net
docker-compose up -d
Project Structure
ads-serving-service-net/
├── src/
│ ├── AdsServingService.API/
│ │ └── Controllers/
│ │ └── AdServeController.cs
│ │
│ ├── AdsServingService.Domain/
│ │ └── AggregatesModel/
│ │ ├── AdRequestAggregate/
│ │ ├── AuctionAggregate/
│ │ ├── PacingAggregate/
│ │ └── FrequencyAggregate/
│ │
│ └── AdsServingService.Infrastructure/
│
└── AdsServingService.slnx
Ad Serving Flow (< 100ms)
Request → Gateway → Check Cache → Run Auction → Return Ad → Fire Events
│ │ │ │
▼ ▼ ▼ ▼
Traefik Redis eCPM Rank RabbitMQ
(< 5ms) (in-memory) (async)
eCPM Formula
eCPM = (Bid × Predicted CTR × 1000) + Quality Score
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/ads/serve |
Get ad for placement |
POST |
/api/v1/ads/events/impression |
Track impression |
POST |
/api/v1/ads/events/click |
Track click |
Redis Caching
| Key Pattern | TTL | Purpose |
|---|---|---|
ads:active:{placement} |
5 min | Active ads list |
freq:{userId}:{date} |
24h | User frequency |
budget:{campaignId}:{date} |
24h | Budget tracker |
Integration
| Service | Integration |
|---|---|
| ads-manager-service | Consume active ads |
| ads-billing-service | Publish charges |
| ads-tracking-service | Publish events |
License
Proprietary - GoodGo Platform
Admin Backoffice APIs
Auction Management
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/admin/auctions |
List auctions (paginated, with filters) |
GET |
/api/v1/admin/auctions/statistics |
Auction statistics (win rate, eCPM, etc.) |
Budget Management
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/admin/budget/pacers |
List budget pacers |
GET |
/api/v1/admin/budget/campaigns/{id} |
Get campaign budget status |
PUT |
/api/v1/admin/budget/campaigns/{id}/reset |
Reset daily spend (manual) |
GET |
/api/v1/admin/budget/statistics |
Overall budget statistics |
Frequency Cap Management
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/admin/frequency/caps |
List frequency caps |
GET |
/api/v1/admin/frequency/caps/{id} |
Get frequency cap details |
POST |
/api/v1/admin/frequency/caps |
Create frequency cap |
DELETE |
/api/v1/admin/frequency/caps/{id} |
Delete frequency cap |
Database Schema
-- Auctions table
CREATE TABLE auctions (
id UUID PRIMARY KEY,
user_id UUID NOT NULL,
placement_type VARCHAR(50) NOT NULL,
auction_time TIMESTAMP NOT NULL,
bids JSONB,
winning_ad_id UUID,
winning_campaign_id UUID,
final_price DECIMAL(18,4),
winning_ecpm DECIMAL(18,4)
);
-- Budget Pacers table
CREATE TABLE budget_pacers (
id UUID PRIMARY KEY,
campaign_id UUID NOT NULL UNIQUE,
daily_budget DECIMAL(18,4) NOT NULL,
spent_today DECIMAL(18,4) NOT NULL,
strategy VARCHAR(20) NOT NULL,
last_updated TIMESTAMP NOT NULL
);
-- Frequency Caps table
CREATE TABLE frequency_caps (
id UUID PRIMARY KEY,
ad_id UUID NOT NULL,
max_impressions_per_user INT NOT NULL,
window VARCHAR(20) NOT NULL
);
Migrations
# Create migration
dotnet ef migrations add MigrationName --project src/AdsServingService.Infrastructure --startup-project src/AdsServingService.API
# Apply migrations
dotnet ef database update --project src/AdsServingService.Infrastructure --startup-project src/AdsServingService.API