Blog
The Exchange Abstraction Layer
Connect a bidder to ten exchanges naively and you get ten versions of your core logic. The alternative is one internal model and a thin converter per exchange. The abstraction layer is what lets you add supply without forking your brain.
- Author
- Ad360 engineering
- Discipline
- Platform engineering
Imagine building a bidder the naive way. You integrate exchange A, writing your decisioning logic against A's exact request format. Then exchange B arrives with different fields, so you branch the logic. Then C uses a proprietary protocol entirely, so you branch again. By the time you've onboarded ten exchanges, your core bidding logic — the most valuable, most carefully-tested code you own — is a thicket of per-exchange special cases. Every new exchange risks breaking the others. Every change to core logic has to be tested ten ways. You haven't built one bidder; you've built ten tangled ones.
The alternative is the exchange abstraction layer: a single internal model of a bid request and response, with a thin converter for each exchange that translates its dialect into yours. The core logic sees exactly one shape, always. The companion piece argues why this is necessary (exchanges are wildly heterogeneous); this one is about the architecture that solves it — and why it's the difference between scaling supply and drowning in it.
The core idea: one internal model
The foundation is a unified interface layer. Ad360's bidder is built on OpenRTB protocol buffers behind a single internal representation — Ad360BidRequest and Ad360BidResponse — and every exchange's traffic is converted into that representation before the core logic ever runs. Exchanges send requests to dedicated endpoints (for example, /google/requests), where the appropriate converter translates the incoming format, including proprietary protocols like Google's Realtime Bidding format, into the internal model.
The discipline is absolute: core logic never sees an exchange's native format. It only ever operates on Ad360BidRequest. This single rule is what keeps the most valuable code in the system free of integration debt.
What the abstraction hides — and what it exposes
A good abstraction is defined as much by what it hides as what it exposes. The exchange abstraction layer hides:
- Wire formats — JSON, protobuf, or a proprietary protocol; the core doesn't care.
- Field naming and structure — each exchange's idiosyncratic layout is mapped to canonical internal fields.
- Extensions and quirks — per-exchange ext fields and custom semantics are handled in the converter, not the core.
- Non-conformance — malformed or partial requests are normalized (or rejected) at the boundary, so the core receives clean, predictable input.
And it exposes a single, stable, canonical contract: one request shape, one response shape, for all supply. Everything exchange-specific lives in the converter; everything valuable and shared lives behind it.
Why this is what lets you scale
The payoff is that adding an exchange becomes a bounded, local task: write a converter that maps the new exchange to the internal model, and you're done — without touching, retesting, or risking the core decisioning logic. Contrast the two worlds:
- Without the abstraction: N exchanges → N forks of core logic → combinatorial testing → every integration endangers the others.
- With the abstraction: N exchanges → 1 core + N independent converters → each converter testable in isolation → core logic untouched by integration.
This is precisely why, in Ad360's experience, onboarding a new exchange is largely an administrative effort (vetting, commercials) rather than a deep engineering project: the technical work was front-loaded into the abstraction, so each new converter slots into a stable framework. The hard part is built once.
The same pattern, everywhere good systems scale
The exchange abstraction is one instance of a general principle: isolate variation behind a stable interface so the shared core stays simple. It's the same instinct that makes real multi-tenancy work (absorb partner/region divergence as configuration over one core, never fork) and that orders the decisioning funnel (a clean internal request flowing through shared stages). A platform that internalizes this pattern can grow its surface — more exchanges, more tenants, more formats — without growing its complexity proportionally. A platform that doesn't forks itself to death.
Common misconceptions
- "Just handle each exchange where you use it." That scatters exchange-specific code through core logic and forks it; isolate it in converters instead.
- "The abstraction is overhead." The overhead is one-time; it removes the recurring cost of every future integration.
- "A converter is a big project per exchange." Once the internal model is stable, a converter is bounded and local — and testable in isolation.
- "Abstraction means losing exchange-specific features." Extensions are handled in the converter and mapped into the model; nothing is lost, it's normalized.
- "Adding supply is inherently engineering-heavy." Behind a good abstraction, it's mostly administrative onboarding.
What good operation looks like
- Define one canonical internal request/response and never let core logic see anything else.
- Put all exchange-specific handling in converters at the boundary.
- Normalize non-conformance at the edge so the core gets clean input.
- Keep converters independently testable so a new one can't break existing supply.
- Treat the abstraction as strategic infrastructure — it's what turns supply growth from risk into routine.
Open questions
- How should the internal model evolve as OpenRTB adds extensions (CTV, DOOH, audio) without churning every converter?
- What's the right conformance/contract test every converter must pass before going live?
- Where's the line between normalizing a quirk and surfacing it because it carries real signal?
The temptation, integrating exchange by exchange, is to handle each one where you meet it. That path ends in a bidder that's really ten bidders, each fragile, none maintainable. The exchange abstraction layer makes a different bet: pay once to define a single internal model, push every exchange's chaos into a converter, and keep the valuable core pristine. The reward is the ability to add supply almost indefinitely without your core logic ever knowing the difference. That's not just cleaner code — it's the architecture that lets the business scale its supply at all.