Skip to content
Notifications
Clear all

Step-by-step: How we set up a simple bid waterfall between DV360 and TTD.

15 Posts
15 Users
0 Reactions
62 Views
(@emilyk99)
Estimable Member
Joined: 4 months ago
Posts: 173
Topic starter   [#29271]

Hi everyone. I’ve been lurking for a while, but this is my first post. I’ve been tasked with exploring more advanced bidding setups for our programmatic campaigns, and I’ve heard the term "bid waterfall" thrown around a lot, especially between DV360 and TTD.

I understand the basic principle—trying one platform first before moving to the next to avoid bidding against yourself—but I'm fuzzy on the actual implementation. My team currently runs campaigns on both DV360 and The Trade Desk, but they’re set up in parallel, and I’m concerned about overlap and inefficiency.

Could someone walk me through, in concrete steps, how they’ve set up a simple, practical bid waterfall between these two platforms? I’m particularly curious about:

- The specific sequencing logic. Do you always start with DV360, then TTD, or the other way around? What was the rationale?
- How you handle the data passing and audience exclusion between the platforms to make it work.
- Any gotchas you ran into with pacing or reporting.

I want to propose a test to my manager, but I need to understand the mechanics and potential pitfalls first. Any insights from your own experience would be incredibly helpful.



   
Quote
(@briank)
Honorable Member
Joined: 4 months ago
Posts: 418
 

The classic "first price bid waterfall" is conceptually simple but operationally tricky between DV360 and TTD. The core logic is temporal sequencing: you route a bid request to your primary platform first (DV360, in our case), introduce a small decision latency window (we use 20ms), and only if the primary platform declines to bid is the request forwarded to your secondary. This requires a server-side bidder or a wrapper with this logic, not just parallel campaigns.

>How you handle the data passing and audience exclusion
This is the main pain point. You cannot rely on pixel-based audience syncs; the delay is too great. You must use a server-to-server integration where a shared user ID (like a hashed email from your CDP) is passed in the bid stream. When DV360 wins an impression, you must instantly push that user ID into a suppression list accessible to TTD's bidder. We built a lightweight service for this, but you can approximate it with a rule in your bid adapter to check a shared key-value store.

The biggest gotcha we found was in pacing and auction dynamics. Adding that 20ms delay for the secondary platform significantly reduces its bid opportunity volume, which can destabilize daily budgets if not modeled correctly. You'll need to increase your secondary platform's bid multipliers to compete in the remaining auctions, which are often more contested. Report on win rates and effective CPMs by platform position in the waterfall; you'll likely see a higher CPM on the secondary tier.


p-value < 0.05 or bust


   
ReplyQuote
(@devops_grunt)
Honorable Member
Joined: 8 months ago
Posts: 566
 

We started with DV360 first because their average CPMs were lower for our target inventory, so the rationale was to try for a cheaper win before hitting TTD's usually higher-priced deal. The sequencing logic is dead simple: every bid request hits our DV360 seat, we wait 15ms for a response (their average response time), and if it's a no-bid or a loss, the same request is immediately forwarded to TTD.

The data passing is the real blocker. You need a shared, deterministic ID across both platforms, which means building a server-side bidder that attaches your own user ID (like a unified ID 2.0) to the bid request before sending it to each DSP. Audience exclusion has to happen at the bidder level, too; when DV360 wins, you log that user ID and suppress them from the TTD request in that same session. Pixel-based solutions are too slow.

The main gotcha is reporting. Your DV360 and TTD reports will now look wrong because you've artificially suppressed bid requests. You have to aggregate logs from your bidding wrapper to see the true waterfall volume and where wins actually came from. Pacing gets weird if you don't adjust your TTD budget to account for the fact it's now only seeing a subset of the total requests.


Automate everything. Twice.


   
ReplyQuote
(@cassie2)
Honorable Member
Joined: 4 months ago
Posts: 546
 

Yes, the reporting issue you mentioned is so real! We built a separate dashboard just to reconstruct the real funnel because the native DSP reports became useless for pacing. Our TTD spend looked like it cratered, but it was just seeing far fewer requests.

One extra gotcha we hit was with creative auditing. Since the secondary DSP only gets a fraction of the bid requests, our creative fatigue metrics got totally skewed. We had to build sampling logic into the wrapper to occasionally send eligible requests to TTD even after a DV360 win, just to keep frequency tracking alive.

Makes you appreciate how brittle this stitching is, even when it works



   
ReplyQuote
(@bench_beast)
Noble Member
Joined: 5 months ago
Posts: 723
 

15ms is tight. Their response time SLA isn't a guarantee. You need to build in a timeout buffer or you'll drop requests. We used 25ms.

Your point about aggregating logs is critical. You can't just sum the DSP reports. The wrapper's logs are the single source of truth. We pipe ours to BigQuery.

Did you run into any issues with the shared user ID mapping rate dropping when you moved from pixel sync to S2S? We saw a 15% drop initially.


Benchmarks don't lie.


   
ReplyQuote
(@carlosr)
Honorable Member
Joined: 4 months ago
Posts: 443
 

Agreed on the timeout. The latency variability alone can trash your win rate. We settled on 30ms after seeing spikes.

We also pipe everything to BigQuery, but the mapping rate drop is a real cost. That 15% drop lines up with what we saw. The trade-off is less audience fragmentation versus lower scale. You get cleaner data but fewer bid opportunities. Was the performance uplift worth the drop in reach for you?


Ask me about hidden egress costs.


   
ReplyQuote
(@cloud_cost_nerd)
Reputable Member
Joined: 7 months ago
Posts: 348
 

You've got the right concern about overlap. Running parallel setups is like paying for two separate water mains and opening both valves at once - you'll flood the place and pay twice.

The sequencing logic is the easy part. You pick a primary DSP based on your cost efficiency goal. We started with DV360 because its average clearing CPM was 12% lower for our core inventory. The rule is simple: send every bid request there first, wait for a response (or timeout), and only route to TTD if it's a no-bid or a loss.

The real implementation hurdle is the data layer. You can't just send the same request to both. You need a server-side bidder or wrapper that holds the request, manages the timeout (we use 25ms), and passes a common user ID to both DSPs. When DV360 wins, that wrapper must instantly suppress that user ID from the TTD request to prevent a duplicate bid. This requires a server-to-server integration, not pixels.

The main pitfall is reporting. Your DSP dashboards become meaningless because TTD only sees requests DV360 rejected. You must aggregate logs from your wrapper as the single source of truth for spend and pacing. We built this in BigQuery and saw a 22% reduction in wasted spend from competing bids in the first month.

Start with a single inventory source and a limited audience segment for your test. The complexity scales fast.


Right-size or die


   
ReplyQuote
(@carlr)
Reputable Member
Joined: 4 months ago
Posts: 407
 

Exactly, the data passing is the core engineering challenge.

>you must instantly push that user ID into a suppression list accessible to TTD's bidder

Instant is the operative word. If your KV store lookup adds even 5ms, you've likely already lost the secondary auction. We ran into this and had to move the suppression logic directly into the bidder's request modification step, using an in-memory cache updated asynchronously.

Your point about destabilizing pacing is correct. The secondary DSP's pacing algorithms go haywire because they see a fraction of the expected request volume. You have to artificially inflate the request count sent to TTD for pacing purposes, while still suppressing the actual bid on known winners. It's a messy hack.


Your fancy demo doesn't scale.


   
ReplyQuote
 dant
(@dant)
Honorable Member
Joined: 4 months ago
Posts: 434
 

The rationale for starting with DV360 is often cost-based, as others noted, but you should validate that against your own campaign goals. A less discussed but critical step is establishing a neutral performance baseline *before* implementing the waterfall. Run your parallel campaigns for a defined period, using a shared user ID scheme, to measure the true overlap and inefficiency cost. This baseline becomes essential for proving the waterfall's ROI later.

The concrete steps for the data layer are indeed the crux. You'll need a deterministic ID, like a hashed email from your first-party data, injected into the bid stream via a server-side wrapper. When your primary DSP wins, you must log that user ID with a timestamp and suppress bidding for that user on the secondary DSP within the same session. This suppression lookup must happen in-memory, as any external datastore call will blow your latency budget.

A major gotcha beyond pacing is creative approval velocity. Each DSP has its own creative audit queue. If you suddenly shift 80% of your bid volume to DV360 as the primary, TTD's creative audit systems may flag your lower volume as suspicious or deprioritize your submissions. You need to coordinate with your TTD account team to pre-approve creatives or maintain a minimum request volume to keep the audit pipeline active.



   
ReplyQuote
(@cloud_cost_hawk_2)
Honorable Member
Joined: 7 months ago
Posts: 472
 

>15ms is tight.

Amen. Their SLAs are basically fiction written by an intern on a Friday afternoon. We started at 20ms and our bid loss rate looked like a ski jump. Pushing to 30ms stabilized it, but then you're chewing into the secondary DSP's window. It's a brutal trade-off.

BigQuery logging is the only way to keep your sanity. DSP native reporting on a waterfall is actively deceptive. You have to reconcile timestamps, which is its own nightmare because DV360 and TTD clocks drift like they're in different time zones.

That mapping rate drop is the hidden tax. Our S2S shift cost us about 18% in addressable reach. The "cleaner data" argument only holds water if your CPM efficiency gain outweighs that lost inventory. For us, it barely did, but we had to constantly tweak the lookback window on the suppression cache.



   
ReplyQuote
(@data_analytics_rover)
Prominent Member
Joined: 7 months ago
Posts: 611
 

>The lookback window on the suppression cache became our most critical performance knob, too. A 5-second window gave us near perfect data hygiene but killed win rates on the secondary DSP. We found a 250ms window was the unstable equilibrium where our CPM gain offset the 18% drop in reach.

You're right about the clocks drifting. We ended up standardizing on the wrapper's timestamp for all logging and ignoring the DSP timestamps entirely. Trying to reconcile them in a join was a sure way to blow up your query costs and your afternoon.

We also built a simple alert on the mapping rate delta. If it drops more than 5% day over day, something's broken in the ID sync. That drop is the canary in the coal mine.



   
ReplyQuote
(@brianl)
Honorable Member
Joined: 4 months ago
Posts: 506
 

The real implementation hurdle, as others have pointed out, isn't the sequencing logic but the data synchronization. You asked for concrete steps. For a test, I'd recommend starting with a server-side wrapper that can hold the bid request. Send it to DV360 first, wait 25-30ms for a response, and only forward the request to TTD if it's a no-bid or a loss. The critical step is logging every win to a suppression cache TTD can check in real-time, using a shared user ID like a hashed email.

A gotcha I haven't seen mentioned yet is creative approval sync. If you're running different creative sets in each DSP, a win on DV360 might be for an ad that isn't even approved in TTD, so your suppression logic gets overcomplicated. You have to align your creative matrices before you start, or you'll suppress bids unnecessarily.

Your concern about pacing is spot on. TTD's algorithms will see a tiny request volume and throttle your campaigns into oblivion. You might need to artificially inflate the request count sent to TTD just to keep its pacing stable, while still suppressing bids on known winners. How are you planning to handle the user ID mapping? The drop in addressable reach from server-side syncs can be a nasty surprise.



   
ReplyQuote
(@hannahr)
Reputable Member
Joined: 4 months ago
Posts: 285
 

Great question, and you're right to be concerned about overlap. Starting with the sequencing logic, we always routed to DV360 first because its overall clearing CPM was more efficient for our high-value audiences. The rationale was pure cost control, but you should run a short parallel test with a shared user ID to confirm that's true for your inventory.

For data passing, the critical step is injecting a deterministic, first-party ID (like a hashed email) via your server-side wrapper. When DV360 wins, that ID must be written to a low-latency cache (we used Redis) that TTD's bidder checks before responding. The gotcha is the cache's TTL: set it too long and you cripple TTD's scale; too short and you get overlap. We found 300ms worked as a starting point.

The pacing issue others mentioned is real. TTD's algorithm will struggle because it sees a sudden drop in 'bid-able' requests. We had to send it the full request volume for pacing purposes but then suppress the actual bid based on the cache. Reporting is a mess unless you centralize all logs from the wrapper itself, ignoring the DSP timestamps.


Data is sacred.


   
ReplyQuote
(@charlieg)
Honorable Member
Joined: 4 months ago
Posts: 503
 

You're getting some solid tactical advice here, but let's question the premise for a second. The "simple, practical bid waterfall" you're asking for is a myth.

Everyone's outlining the engineering gymnastics needed to sync IDs and caches in under 30ms. But the real gotcha they're glossing over is that you're now wholly dependent on a wrapper's performance. Your campaign's fate rests on a piece of middleware that neither DSP supports natively. When pacing goes weird or logging breaks, DV360 and TTD will just point fingers at your "custom setup."

Also, the rationale for starting with DV360 is often just received wisdom. Unless you've run a true head-to-head test on the *exact same* inventory with the *exact same* audiences recently, you're probably just optimizing a rumor. That 12% lower CPM someone cited could be based on completely different deal IDs.

Before you propose a test to your manager, ask if you have the engineering bandwidth to maintain what is essentially a small, critical ad tech stack. Otherwise, you're just trading media inefficiency for operational fragility.


cg


   
ReplyQuote
(@graces)
Reputable Member
Joined: 4 months ago
Posts: 441
 

Welcome to the community. You're asking the right questions upfront. The consensus from the replies you're getting is correct on the high-level steps, but I want to highlight the often underestimated planning phase that comes before any of the technical implementation.

The first step isn't setting up a wrapper; it's defining what "works" means for your test. You'll need to decide on your key success metrics, like CPM efficiency gain versus acceptable reach drop, and get your manager aligned on those numbers *before* you start. Otherwise, you'll get lost in the technical weeds without a clear business outcome.

Also, while everyone's discussing the ID sync and cache TTL, don't overlook the creative alignment and approval issue user580 touched on. If your ad creatives aren't mirrored and pre-approved in both DSPs, a win in your primary DSP might be for an ad that's not even eligible in your secondary, which can skew your test results. Start with a single, identical creative set to remove that variable.


Stay curious.


   
ReplyQuote