Someone types a search, hits enter, and before the page finishes loading, an auction has already run, ranked the ads, and set the prices. Total time: under 100 milliseconds. I’ve spent years pulling apart systems like this, and I still find it slightly ridiculous how much engineering goes into that tiny window. No hand-waving. Let’s look at the real machinery.

The Pre-Auction Stage: Indexing and Candidate Selection
Google’s ad platform doesn’t wait for a query to start thinking about ads. It keeps a gigantic, constantly refreshed index of active ads. Every ad gets tied to keywords, targeting rules, and a bunch of quality signals that get updated in the background. When a query comes in, the system can’t afford to scan the whole index. That would be absurdly slow. So the first job is candidate generation: narrowing the field to a manageable set.
The workhorse here is an inverted index keyed on keyword tokens. A query like “wireless noise-canceling headphones” gets split into tokens. The inverted index spits back ads whose keywords match those tokens—plus synonyms, close variants, and sometimes misspellings. Then geographic and device filters chop the list down further. You end up with dozens of eligible ads, not thousands. That pruning matters because the actual auction runs per-impression, and the latency budget is a hard constraint.
Negative keywords and account-level blocks also get applied, but token matching does the heavy lifting. This is a classic IR problem. The data structures are probably custom B-tree and skip list variants tuned for in-memory operation across thousands of machines. Nothing exotic. Just solid engineering.
Real-Time Bidding and the Ad Rank Formula
Once the candidate set exists, the auction calculates an Ad Rank for each ad. The formula itself is simple. The complexity lives in how the components are fetched and assembled under latency pressure.
The core equation:
Ad Rank = Max CPC Bid × Quality Score
Quality Score isn’t a single number someone typed in. It’s a composite of predicted click-through rate, ad relevance, and landing page experience—all generated by ML models that run continuously. For every ad in the candidate set, the system has to grab or compute:
- The advertiser’s max cost-per-click bid, possibly tweaked by modifiers for device, location, or time of day.
- Quality Score components, which are usually cached but can refresh near-real-time if fresh engagement signals arrive.
- Ad extensions and formats, because those shift expected CTR and bump Ad Rank indirectly.
Ad Rank decides position. Higher score, higher slot on the page. But the actual cost-per-click isn’t the max bid. That’s handled by a second-price auction variant, which we’ll get into next.

The Generalized Second-Price Auction and Pricing Mechanics
Google uses a generalized second-price auction, not a pure Vickrey. In a GSP, the advertiser in slot i pays the minimum needed to stay above the advertiser just below them. Specifically:
Actual CPC for position i = (Ad Rank of position i+1) / (Quality Score of position i) + $0.01
That formula keeps an advertiser from overpaying relative to the next competitor. The system calculates it incrementally, starting at the top slot and moving down. Rounding and floating-point quirks could cause financial drift, so it’s done with fixed-point arithmetic or integer cents. Boring but necessary.
The hard part is that an auction isn’t a clean, isolated event. Multiple ads can land on the same Ad Rank, so tie-breaking rules kick in—sometimes randomization, sometimes account history metrics. Ad extensions complicate the geometry, too. A top ad with sitelinks eats more vertical space, which can shove lower-ranked ads below the fold. The auction engine has to account for those layout effects in real time, often by adjusting the effective CTR of extensions.
Distributed Systems and Latency Budgets
A single query’s auction touches a surprising number of services: the keyword index, quality score caches, bid repositories, user profile stores, billing recorders. All of this runs on Google’s global infrastructure, with data centers handling queries from nearby regions to shave milliseconds off round-trip time.
The end-to-end latency target—from query arrival to ad placement—is under 100 milliseconds, often closer to 60 ms. The auction logic itself gets maybe 20–30 ms after you subtract network and parsing overhead. To make that work, the system leans on:
- In-memory data stores: Quality scores, bids, and ad metadata live in RAM. Systems like Bigtable or custom key-value stores handle low-latency access.
- Parallelization: Candidate ads get evaluated concurrently across threads or machines. An aggregator stitches the results together.
- Tail-tolerant design: If one server drags, the auction can proceed with partial results—ad relevance might dip slightly, but the ad still shows. Google has published research on wrangling stragglers in large systems.
- Precomputation: Broad match expansions and other signals get precomputed and stored, not derived on the fly.
One piece people overlook is the bidding infrastructure itself. Advertisers push bid changes through the Google Ads API, which writes to a distributed bid store. That store has to propagate updates within seconds; otherwise, stale bids slip into auctions. The consistency model is typically eventual, with conflict resolution favoring the most recent change.
The Role of Quality Score in Technical Detail
Quality Score often gets treated like a proprietary black box, but the technical shape of it isn’t mysterious. It’s a normalized value, usually 1–10, built from three sub-scores:
- Expected CTR: A prediction of how likely a click is for this ad on this query. It leans on historical click data, smoothed with hierarchical models so rare queries don’t produce wild guesses.
- Ad Relevance: A similarity measure between query and ad text, computed via semantic matching models—not just keyword overlap.
- Landing Page Experience: A score from automated crawlers checking page speed, mobile-friendliness, and content relevance.
These sub-scores get combined with a weighted function. Google doesn’t publish the exact weights, but the computation is deterministic per auction. Outputs are cached with a TTL that balances freshness against compute cost. For high-volume queries, the TTL might be minutes. For tail queries, it could stretch to hours.
Offline recalibration pipelines run in the background. If an ad’s predicted CTR is 5%, the actual CTR should hover near 5% over time. If it doesn’t, the prediction model gets retrained. No magic, just continuous adjustment.

Handling Billions of Daily Auctions
Google handles north of 8.5 billion searches a day, and a big fraction trigger ad auctions. That’s roughly 100,000 auctions per second at peak. The engineering problem isn’t just latency—it’s throughput. The system has to swallow that load without queueing delays that would blow the latency budget.
The architecture is microservices-based, with each service independently scalable. The auction service itself is stateless, so instances get added or yanked based on load. Front-end servers distribute requests to auction workers via consistent hashing, which nudges the same query-ad pair toward the same worker, improving cache locality.
Logging and billing run asynchronously. After the auction finishes, the result lands in a durable log, and billing events queue up for later processing. That decouples the latency-sensitive path from billing, which can tolerate minutes of lag.
Failure modes are handled with circuit breakers and fallback logic. If the Quality Score service degrades, the auction might use the last known good cached score—with a slight penalty to avoid overcharging. If the bid store goes dark for a particular account, that account’s ads get excluded from the auction. Better to miss an impression than mis-price a click.
Ad Rank Thresholds and the Auction Reserve
Not every ad that passes candidate selection makes it onto the page. A minimum Ad Rank threshold acts as a reserve price. It blocks ads with very low Quality Scores or bids, preserving some baseline user experience and page value. The threshold varies by query: higher for commercially hot queries, lower for informational ones.
Technically, it’s a simple filter applied after Ad Rank calculation. Ads below the threshold get dropped, and the rest are ranked. If nobody clears the bar, the page shows zero ads. That happens a lot with long-tail queries that have sparse advertiser coverage.
The threshold isn’t nailed in place. It shifts periodically based on auction pressure and engagement metrics. When ad inventory is tight relative to demand, the threshold rises. When inventory is loose, it falls. The adjustment is a control loop targeting a specific ad coverage rate—so the system doesn’t over-deliver or under-deliver.
FAQ
Why does Google use a second-price auction instead of a first-price auction?
A second-price auction encourages advertisers to bid their real value for a click, because they only pay a penny more than the next-highest bidder’s Ad Rank divided by their own Quality Score. In a first-price auction, advertisers would constantly shade bids downward to avoid overpaying, which leads to instability and less efficient allocation. The GSP variant also keeps the pricing logic deterministic—no need to solve complex game-theoretic equilibria in real time.
How does Quality Score stay accurate when a new ad has no click history?
For new ads, expected CTR leans hard on historical performance of similar ads—those with overlapping keywords, ad text patterns, and landing page domains. Hierarchical Bayesian models let the system borrow strength from related signals. Ad relevance and landing page experience get scored immediately through automated analysis, so the Quality Score is partly aggregate data, partly direct evaluation. As clicks roll in, the model shifts weight toward the ad’s own performance.
What happens if my bid change doesn’t propagate before the next auction?
The bid store uses a distributed consensus protocol to push changes. In the rare case a bid update hasn’t reached the auction server yet, the system uses the last known bid. Google’s infrastructure keeps propagation delays to a few seconds normally, and the financial impact of a single stale bid is tiny. Still, advertisers running high-frequency strategies often bake in margin with automated rules to handle that latency.
Can an ad with a lower bid ever outrank a higher bid?
Yes, and it happens all the time. Ad Rank is bid times Quality Score, so an ad with a low bid and a very high Quality Score can sail past an ad with a high bid and a lousy Quality Score. Example: a $1 bid with Quality Score 10 gives Ad Rank 10; a $5 bid with Quality Score 1 gives Ad Rank 5. The first ad ranks higher and pays less per click. The system rewards relevance over brute-force spending.