All systems

LtvAdx

A programmatic exchange for Connected TV and linear television

Television inventory sold programmatically — Connected TV, FAST channels and addressable linear breaks — through one exchange that also carries the ad server and the stitching layer.

The problem

Television advertising was built for agencies buying quarters in advance. Streaming broke the model without replacing it: a FAST channel has breaks to fill every hour and no practical way to fill them beyond a handful of direct relationships. Meanwhile the buyers who could fill them have no self-serve door into anything except the largest platforms.

How it is put together

  1. 01

    An ad server handling VAST and VMAP requests, plus a control plane holding campaigns, inventory and reporting — deployed as separate services so a serving incident cannot take the dashboard down with it.

  2. 02

    Serving events travel through a Redis stream rather than a direct write, so a slow reporting database never becomes a slow ad response.

  3. 03

    Reporting aggregates into daily summaries on a schedule. Raw events are storage; the summaries answer every query.

  4. 04

    A single-source waterfall ranks six deal types — direct sold, programmatic guaranteed, direct IO, addressable, private marketplace, open auction — and filters on flight dates, channel, break type, duration, platform, country, household segment, completion-rate threshold, floor price and pacing before ranking on effective price.

The hard parts

Zero database reads at serve time

A television break does not wait, which rules out the usual answers. A read replica still costs a network round trip. A conventional cache moves the problem to invalidation, and invalidation across dozens of interacting rules is harder than the original query. What works instead is refusing to read at all: the entire decision runs against an in-memory snapshot rebuilt from the control plane every fifteen seconds and swapped atomically. The cost is that every targeting rule, budget and floor must be expressible in a structure that can be rebuilt wholesale — and that you have to be honest about what a decision means when the snapshot is briefly stale.

Frequency capping across a household, not a device

Capping per device is the obvious implementation and it is the wrong product. A household watching on a television, a phone and a tablet sees your three-per-day cap nine times, and the person paying for it experiences that as being pursued rather than reached. Getting it right means collapsing those devices into one identity, then decrementing a counter shared across all of them — inside the same millisecond budget as the rest of the decision.

Spending money that does not exist yet

Overspend is a refund conversation; underspend is a churn conversation. Holding a campaign to its share means checking spend inside a decision that cannot afford a database read, so the counters live in memory — and that creates the real question, which is what to do when the counter is unavailable. Blocking everything turns a cache blip into an outage. Allowing everything turns it into an unbounded overspend. The answer was a third option: fall back to the durable spend figure carried on the fifteen-second snapshot, and always take whichever of the two is higher. A cache flush can then only ever be as generous as the last confirmed number, never as generous as zero.

Does your serving path have a deadline it cannot miss?

Sub-second budgets, in-memory state that has to be rebuilt without a pause, and correctness while the snapshot is briefly stale. If that is the shape of your problem, I have already built it once.

Get in touch