CASE STUDY

Ad Budget Pacing System

4 min read·686 words·Advanced

Asked at

1 candidate report in Apr 2026

How to use this case study

SDE-2 / Mid

Explain what pacing is (spreading a budget evenly over the flight), and a simple approach using a spend target per time slot.

SDE-3 / Senior

Go deeper on a feedback controller (throttle probability), near-real-time spend tracking, and avoiding overspend across many ad servers.

Staff / Principal

Discuss traffic forecasting (daily and weekly curves), delivery goals (impressions vs spend vs reach), end-of-flight behavior and monitoring delivery health.


0) Problem Restatement

Advertisers create campaigns with a budget (e.g., $70,000), a flight (start and end dates, e.g., 7 days), targeting, and a delivery goal (impressions or spend). Without pacing, a campaign that wins many auctions could spend everything in the first few hours (a waste: bad timing and less reach). Pacing spreads delivery smoothly over the flight, following when viewers actually watch, and adapts to traffic changes. Netflix asked this for its video ads platform.


1) Requirements

  • Deliver close to 100% of the budget by the end of the flight, without going over (or within a tiny tolerance).
  • Spread delivery following the audience's traffic curve (more in the evening, less at 4 AM).
  • Adapt quickly to changes: traffic spikes, targeting changes, budget edits.
  • Work across hundreds of ad servers deciding in parallel, each in milliseconds.


2) The Core Idea

  1. Plan: compute an ideal cumulative spend curve for the flight, using a traffic forecast. For example, if 8–10 PM usually has 20% of the day's matching traffic, plan 20% of the daily budget there.
  2. Measure: track actual spend in near real time.
  3. Control: every minute, compare actual vs planned. If spending is ahead, slow down. If behind, speed up.

How do we slow down or speed up? Two common "knobs":

  • Throttling probability (pacing rate): the campaign only enters a fraction p of eligible auctions. p is adjusted every minute.
  • Bid shading: lower or raise the bid, which wins fewer or more auctions (used in auction-based platforms).


3) Architecture

Architecture Diagram

flowchart LR
    AS["Ad servers - use pacing rate p"] -->|"impressions, spend"| K[("Kafka - delivery events")]
    K --> SPD["Spend aggregator - per campaign per minute"]
    SPD --> ST[("Spend store")]
    FC["Traffic forecaster"] --> PLAN["Plan: target curve per campaign"]
    PLAN --> CTRL["Pacing controller - every minute"]
    ST --> CTRL
    CTRL -->|"new p per campaign"| CFG[("Pacing config")]
    CFG -->|"push"| AS

4) The Controller (simple and explainable)

Every minute, for each campaign:

target_so_far = planned cumulative spend at this time
actual_so_far = measured spend
error = (target_so_far - actual_so_far) / remaining_budget
p_new = clamp(p_old × (1 + k × error), p_min, 1.0)
  • This is a proportional controller (a PID controller without the I and D parts). Adding some smoothing avoids oscillation.
  • Also recompute the plan for the remaining time and budget (e.g., if we underspent yesterday, spread the leftover over the remaining days rather than dumping it in one hour).


5) Avoiding Overspend Across Many Servers

  • Spend data arrives with a delay (seconds to a minute), and hundreds of ad servers serve at once. Near the end of the budget, they could all keep serving and overspend.
  • Budget slices: the controller gives each ad server (or region) a small allowance for the next minute. Servers stop the campaign locally when their slice is used up, and refill each minute.
  • Safety margin: as the remaining budget gets small, reduce the slices and p more aggressively, and stop at ~99.x% if needed.
  • Hard stop: a separate fast check blocks a campaign when total spend reaches the budget, and it's pushed to all servers immediately.


6) Forecasting and Goals

  • Traffic forecast: from historical impressions for the campaign's targeting (by hour of day and day of week), updated with recent trends.
  • Goals: pacing by spend (most common), by impressions, or with frequency and reach goals (combined with frequency capping).
  • End of flight: allow slightly faster delivery near the end if behind (within limits), so the campaign doesn't under-deliver.


7) Trade-offs & Alternatives

DecisionChoiceWhyAlternative
KnobThrottle probabilitySimple, works for fixed-price adsBid shading: better for auctions, more complex
Control loopPer-minute proportional controller + re-planAdapts, explainableFixed hourly caps: can't adapt
Overspend protectionBudget slices + hard stopTight control with delayed dataRely on delayed spend only: overspend
PlanTraffic-weighted curveMatches when viewers watchEven split per hour: wasteful at night

8) Wrap-Up

Plan a target cumulative spend curve from a traffic forecast, measure spend in near real time from delivery events, and run a per-minute controller that adjusts each campaign's throttle probability (or bid) based on how far ahead or behind plan it is, re-planning the remaining budget. Prevent overspend with per-server budget slices, tighter control near the end, and a fast hard stop pushed to all ad servers.

More Case Studies

Practice with a Mock Interview

Apply what you learned in a live system design mock interview with our AI interviewer.

Start System Design Interview →