Skip to main content
See also: Frequency Caps REST API reference for request/response shapes, status codes, and error semantics.

Frequency Caps

Frequency caps are system-wide delivery caps that automatically block offers when their budget is exhausted. They operate independently of contact policies — contact policies protect individual customers, while frequency caps protect the business from over-delivery.

Cap Scopes

A global-scoped cap needs no scopeId. When its budget is exhausted it excludes every candidate at decision time, and each response increments it once — symmetric with offer, category, and channel caps.

How It Works

  1. Frequency caps are checked during the Contact Policy stage of the decision pipeline
  2. The system queries frequency_caps for the tenant where enabled=true and resetAt > now()
  3. Any cap where currentCount >= maxVolume adds its scope to the exclusion set
  4. Candidates matching excluded scopes (offer, category, or channel) are filtered out

Counter Increment

The currentCount is incremented by the Respond API when an impression outcome is recorded:
  • Only impression-type outcomes increment the counter (clicks/conversions don’t)
  • The increment is atomic (prevents race conditions in concurrent delivery)
  • Counters reset when resetAt passes (configured per cap)

Configuration

Frequency caps are stored in the frequency_caps table:

Best Practices

  • Set channel-level caps for batch channels (Direct Mail, SMS) to control vendor costs
  • Set offer-level caps for limited-inventory promotions
  • Monitor currentCount vs maxVolume in the Operations dashboard
  • To keep a channel’s placements consistent when a cap empties one of them, use the channel’s coupling mode (Channel.couplingMode, or a per-flow DecisionFlow.couplingOverride). The old Group-node allowPartial flag is deprecated and now a no-op.