High-Performance Ad Serving Engine built with NestJS & Fastify
The next-generation, ultra-fast serving layer for OpenAdServer
Features • Architecture • Quick Start • Tech Stack
OpenAdServer Node is a rewrite of the serving layer of OpenAdServer, migrated from Python (FastAPI) to Node.js (NestJS + Fastify).
While the original Python version excels at Data Science and Model Training integrations, this Node.js version is engineered for pure serving performance, concurrency, and scalability. It maintains the exact same 5-step Recommendation Pipeline logic but optimizes it for the V8 engine's asynchronous I/O capabilities.
Note: This project is strictly for the Serving Engine. Model training (DeepFM/LR) is still handled by the Python ecosystem, communicating via ONNX or shared storage/DB.
- NestJS + Fastify: Built on one of the fastest Node.js web frameworks, offering lower overhead than Express.
- Asynchronous Pipeline: Fully non-blocking I/O for database and Redis lookups.
- In-Memory Caching: Active campaigns and creatives are pre-loaded into hot memory (
Map) for O(1) retrieval, eliminating DB hits during the critical path.
- Retrieval: Selects candidates based on Targeting Rules (Geo, OS, Device).
- Filter: Enforces Budget (Redis) and Frequency Capping (Redis) in real-time.
- Prediction: Integration point for CTR/CVR prediction (Statistical or ONNX).
- Ranking: Calculates eCPM (Bid * pCTR * 1000) to maximize revenue.
- Rerank: Improves result quality with Diversity rules (e.g., max 2 ads per advertiser).
- TypeScript: Full type safety from Database to API DTOs.
- Drizzle ORM: Lightweight, SQL-like, type-safe database access.
- Modular Architecture: Clean separation of concerns (Engine, Tracking, Shared resources).
graph LR
User[Client / Device] -->|POST /ad/get| API[Fastify Controller]
User -->|GET /track| Track[Tracking Controller]
subgraph "Ad Engine (NestJS)"
API --> Engine[AdEngine Service]
Engine --> Step1[1. Retrieval]
Engine --> Step2[2. Filter]
Engine --> Step3[3. Prediction]
Engine --> Step4[4. Ranking]
Engine --> Step5[5. Rerank]
Step1 --> Cache[In-Memory Cache]
Step2 --> Redis[Redis Checks]
end
subgraph "Data Store"
Redis -->|Freq / Budget| RedisStore[(Redis)]
Cache -->|Refresh 1m| DB[(PostgreSQL)]
Track -->|Insert| DB
Track -->|Incr| RedisStore
end
| Component | Technology | Rationale |
|---|---|---|
| Framework | NestJS | Structured, scalable, enterprise-grade DI/Module system. |
| Web Adapter | Fastify | High throughput, low overhead HTTP processing. |
| Language | TypeScript | Type safety, reliability, and better developer experience. |
| Database ORM | Drizzle | Best-in-class TypeScript ORM, no runtime overhead like TypeORM/Prisma. |
| Cache/KV | Redis (ioredis) | Real-time counters for frequency capping and budgeting. |
| Database | PostgreSQL | Relational data for campaigns, users, and reporting. |
- Node.js 20+
- PostgreSQL
- Redis
git clone <repo-url>
cd openadserver-node
npm installCreate .env file:
cp .env.example .envEdit .env and set your DATABASE_URL and REDIS_HOST.
This command will:
- Push the schema to your database (using
drizzle-kit push --force). - Seed the database with test data (Advertisers, Campaigns, Creatives).
npm run init:dbNote: Ensure your
.envpoints to a valid database (e.g.,postgres://user:password@localhost:5432/oas).
# Development mode
npm run start:dev
# Production build
npm run build
npm run start:prodGet an Ad:
curl -X POST http://localhost:3000/ad/get \
-H "Content-Type: application/json" \
-d '{
"slot_id": "home_banner",
"user_id": "test_user_1",
"os": "ios",
"country": "US"
}'Debug Database State:
npx ts-node scripts/debug-db.tsA Vue.js 3 based admin panel is included in web-admin/ to manage advertisers, campaigns, and creatives.
- Navigate to the directory:
cd web-admin - Install dependencies:
npm install
- Start the development server:
npm run dev
- Open the browser at
http://localhost:5173. - Ensure the NestJS backend is running on
http://localhost:3000(CORS is enabled).
src/
├── database/ # Drizzle schema & connection
├── modules/
│ ├── engine/ # Core Ad Serving Logic
│ │ ├── pipeline/ # The 5 Steps (Retrieval...Rerank)
│ │ ├── services/ # CacheService, TargetingMatcher
│ │ └── dto/ # Request/Response DTOs
│ └── tracking/ # Pixel & Event Tracking
└── shared/
├── redis/ # Redis Client wrapper
└── types.ts # Shared Enums & Interfaces
This node version aims to keep parity with the main Python repo logic-wise unless specific performance optimizations dictate otherwise. Please match the Python implementation's intent when porting features.
Apache License 2.0 (Same as original OpenAdServer)