Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ServeIndex & DData

The ServeIndex is Promovolve’s distributed in-memory cache storing auction results for instant serve-time lookups, built on Pekko Distributed Data (DData).

Why DData?

Every API node must serve ads without network round-trips:

AlternativeProblem
Database (PostgreSQL)1-10ms per query
Remote cache (Redis)~0.5ms network hop
Sharded in-memoryRequires request routing
DDataLocal replica on every node, gossip replication

Data Model

ServeIndex
  └── Bucket[0..31]  (32 buckets, power-of-2)
        └── LWWMap[String, ServeView]
              Key:   "siteId|slotId"
              Value: ServeView

ServeView

case class ServeView(
  candidates: Vector[CandidateView],
  version: Long,       // e.g., auction timestamp
  expiresAtMs: Long    // epoch millis; for TTL sweep
) extends CborSerializable

CandidateView

case class CandidateView(
  creativeId: CreativeId,
  campaignId: CampaignId,
  advertiserId: AdvertiserId,
  assetUrl: CDNPath,          // URI to CDN-hosted asset
  mime: MimeType,             // imageJpeg, imagePng, imageGif, imageWebp, videoMp4
  width: Int,
  height: Int,
  category: CategoryId,
  cpm: CPM,
  classifiedAtMs: Long,       // when page content was classified
  categoryScore: Double = 0.5, // classifierConfidence × rankerWeight
  frequencyCap: Option[Int] = None,
  adProductCategory: Option[AdProductCategoryId] = None,
  landingDomain: String = ""
) extends CborSerializable

DData Configuration (from application.conf)

SettingValue
Gossip interval2s
Notify subscribers500ms
Max delta elements500
Durable keysshard-*, exhausted-campaigns
Durable storeLMDB (100 MiB, 200ms write-behind)
Pruning interval120s

Note: ServeIndex entries are not in the durable keys list — they are ephemeral and rebuilt from auctions on restart. Only shard metadata and exhausted-campaign flags are LMDB-durable.