Short answer
An RTB bidder receives bid requests at a rate the exchanges choose, decides whether and what to bid, and must answer inside a deadline that includes the network. A bidder built for that keeps connections alive, drops requests it will never buy before doing real work, finds eligible campaigns through an index rather than a scan, keeps budget and frequency checks local, answers a fast no-bid when it cannot finish, and measures p99 per exchange connection. Rust or C++ removes collector pauses from the bid path; the network, the design and the measurement still decide the tail.
| Step | What happens | Where time is lost |
|---|---|---|
| 1. Connection | The request arrives on a persistent connection | A lapsed keep-alive forces a new TLS handshake inside the auction window |
| 2. Admission | Read tmax, compare it with the current queue delay | Work started on a request that cannot finish in time still costs CPU |
| 3. Decode | Read only the fields the bidder uses | Building a full object graph for every request |
| 4. Pre-filter | Drop requests blocked by category, advertiser or floor | Evaluating campaigns for requests that could never win |
| 5. Candidate selection | Look up eligible campaigns in an index keyed by targeting attributes | Scanning every campaign on every request |
| 6. Budget and frequency | Check local counters synchronised in the background | A remote call per request on the hot path |
| 7. Pricing | Rules or a model produce the bid price | Model inference without its own deadline and fallback price |
| 8. Response | Serialise the bid with markup or notice URLs | Allocation and copying at the boundary |
| 9. Notices | Win, billing and loss notices processed off the bid path | Mixing notice handling into the request threads |
Several of these steps are defined by the protocol. OpenRTB's best practice reads: "One of the simplest and most effective ways of improving connection performance is to enable HTTP Persistent Connections, also known as Keep-Alive"[1]. The request carries the filters for step 4: bcat, "Blocked advertiser categories using the specified category taxonomy"; badv, a "Block list of advertisers by their domains"; and bidfloor, the "Minimum bid for this impression expressed in CPM"[1]. A no-bid can be "an empty response with HTTP 204"[1]. The win notice URL is called "if the bid wins (not necessarily indicative of a delivered, viewed, or billable ad)", which is why spend is counted on the separate billing notice[1].
OpenRTB defines tmax as the "Maximum time in milliseconds the exchange allows for bids to be received including Internet latency to avoid timeout"[1]. The bidder's own budget is what is left after the round trip.
On Google's Authorized Buyers, "The deadline typically ranges from 80 to 1000 ms"[2].
Google states: "We require that 85 percent of responses be received within the deadline from the perspective of the trading location and will throttle bidders that cannot consistently achieve this"[2].
Google recommends "targeting a total time well below the deadline" to leave a buffer for changes in network latency between the bidder and the trading location, and lists its trading locations as Northern Virginia, the San Francisco Bay Area, Amsterdam and Singapore[2].
In practice this means one internal deadline per exchange connection, derived from that connection's measured round trip, and admission control that answers a no-bid when the queue already makes the deadline impossible. A fast no-bid counts as an answer; a late bid counts as a timeout.
tmax and the heaviest requests first.| Option | What it removes | What it keeps or adds |
|---|---|---|
| Rust | Garbage-collection pauses; data races in shared state are caught at compile time | Allocator behaviour, scheduling, network and design still set the tail |
| C++ | Garbage-collection pauses | Memory-safety bugs are found by review and tooling, not the compiler |
| Go, tuned | Nothing structural; allocation rate, live heap and runtime settings reduce collector cost | A collector that belongs to the whole process |
| JVM, tuned | Collector choice lowers pauses at a memory cost | Tuning per collector and per heap size |
A rewrite pays when the measured milliseconds are in the handler and the collector; it returns nothing when they are on the wire or in the scheduler. Moving the smallest piece that owns the allocations, candidate selection, targeting or pricing, is often enough.
RTB4FREE describes its bidder as "The OpenRTB 2.0 compliant bidder for RTB4FREE, the open source bidder / DSP"; it is written in Java under Apache-2.0, and its repository was last pushed on 16 November 2022[3].
Beeswax, described by AdExchanger in December 2020 as "the 'bidder-as-a-service'" when FreeWheel bought it, was a product where "users can install their own algorithms"[4].
An open-source bidder is a reading reference and a test harness more than a starting point when it is no longer maintained. A bidder-as-a-service keeps infrastructure rented and puts your logic inside it. A bidder of your own makes sense when the logic, the data and the infrastructure cost are all yours to change; the rest of the platform around it is on DSP development company, and the rented DSPs are compared on white-label DSP vs own DSP.
tmax distributions and a timing split of the current bidder, if there is one.tmax?About amBrain
Related on this site: DSP case study and real-time bidding infrastructure.
The service in a DSP that receives bid requests from exchanges, decides whether and how much to bid for each impression, and answers before the exchange's deadline. Campaign tools, reporting and billing sit around it.
Because the exchange judges each response, not the average. A tail on one connection, from a collector, a queue, a lapsed keep-alive or distance, shows up as timeouts long before it moves the mean.
Rust removes collector pauses from the bid path, which matters when the measured tail is in the handler. If the time is lost on the wire or in scheduling, a rewrite in any language returns little; measure the split first.
Yes: run the new bidder on mirrored traffic in shadow mode, compare decisions, then move one exchange connection at a time with an automatic rollback threshold.
Product and company names are trademarks of their respective owners and are used only to identify their products. No vendor named here reviewed or endorsed this page.
Related