Sovren · Live ads · Shipped 2025

I cut half the build, then shipped ads into live in 45 days.

Ninety days of engineering was on the table. The research said we were building the wrong half.

RoleProduct lead · co-owned with a senior engineering lead
When2025 · 45 days to partner channels live with ads
OwnedScope, targeting model, floors, sales terms, partner deal
ResultFill settled into a 60 to 80% band with floors binding, after I raised them on purpose
01 · The bet

I agreed with the goal and killed half the plan.

Leadership wanted live as a flagship bet, and they were right to want it. The plan ran ninety days. Ingest, encode, a player, chat, and a full creator capture tool, built against platforms with a decade of head start.

So I went and looked at who would use it. We did not have an audience that wanted to originate a livestream on our platform. Nobody was waiting for us to build them a broadcasting tool.

What we did have were two groups nobody had counted. Creators already going live elsewhere, happy to also broadcast with us. And network partners willing to share channel feeds they were already producing.

The plan assumed we had to originate. All we had to do was receive.

That killed half the build. Ingest over RTMP and HLS, a player that could take those streams, and everything we saved went into server-side insertion against the ad server we already owned.

Forty-five days means partner channels were live with ads in them. It doesn't mean the system was finished, and it doesn't mean I built it.

02 · The system

Two supplies that constrain in opposite directions.

A viewer taps a creator's stream and a pre-roll plays before it attaches. One serve call per viewer, with the creator's profile carried as the targeting. Network feeds arrive the other way, an HLS pull from a broadcaster's origin, and we sell breaks inside a schedule somebody else sets.

I drew both paths before we priced either one. Here's how each one clears.

AT THE DOOR AD AD AD one call per viewer IN THE BREAK ONE POD one decision, every viewer

Both paths clear through our own ad server against our own supply, and every bidder in them was an advertiser we had sold to ourselves. Hand-set prices clear at face value. Machine-managed bids clear second price. That is an internal auction over inventory we own.

Pre-roll at the door carries a real cost. A viewer who stays three hours sees one ad. I took that trade because cutting into a creator's stream on a platform they were simulcasting to was the fastest way to lose the supply we had just convinced them to give us.

Timing shaped everything downstream. Breaks arrive as SCTE-35 cues, in three dialects across our partners (CUE-OUT, DATERANGE and OATCLS), and the stitcher splices the pod into the HLS manifest. A cue is a courtesy measured in single-digit seconds, and a live splice has to budget for the decision's worst case. So the pod is decided ahead of the break, and the cue only fires a splice we have already priced.

I specified that sequence before anyone wrote the stitcher, so the splice never waits on a decision. Run the whole break, beat by beat.

03 · Ownership

I owned what it had to do and what it was allowed to cost.

I co-owned this with a senior engineering lead. He owned how the pipeline got built.

  • Mine. The scope cut and the research behind it, the targeting model, the floors and when to move them, what sales could sell and at what price, the terms we offered broadcasters, and the definition of the guardrail metric.
  • Not mine. The manifest stitcher, the rendition ladder, the delivery work.
04 · The money decision

I took fill down on purpose, and defended it upstairs.

No floor was set on day one, on purpose. Nothing was proven, the book was thin, and a floor on a thin book is mostly a reason for a break to go empty. We wanted fill, and evidence the model worked at all.

Then we instrumented the funnel. Realised eCPM per slot, pod position, fill source, clearing price, all queryable. It showed that the floors we had since introduced were non-binding. Nothing was clearing near them. A floor nothing touches protects no revenue and costs none either.

So I raised floors by tier and took the trade knowingly. Fill went down. Revenue per avail went up. Indexed to the week before the raise, fill settled at 77 and revenue per avail at 160. Steady state settled into a sixty to eighty percent band with the floors holding.

I held the floors where that band held. Above ninety percent I read the floors as set too low.

60–80% FILL BAND fill, no floors revenue per avail 160 77 BOTH INDEXED TO 100 THE WEEK BEFORE FLOORS RAISED

One definition matters here, because it's the one people skip. That fill number counts house spots, the partner's own promos running at zero against unsold network breaks. Filled and monetised are different numbers, and that fill rate includes house inventory.

Then I had to go explain a fill number that came down on purpose. Walking leadership from fill to revenue per avail is what keeps the authority to make that call again. So it got reported with revenue per avail beside it and the band named as the target.

05 · The counterintuitive one

I made the creator the sellable unit, and wrote down when to stop.

Everyone's instinct in ad tech is finer targeting. We widened instead. In a second-price auction the runner-up sets your revenue, so restricting which campaigns are eligible for a break narrows the field, and on a thin book a narrow field drags the clearing price toward the reserve. Ten bidders in an open break can clear higher than two in a perfectly targeted one.

The arithmetic is in the chart.

UNTARGETED · 10 BIDDERS CLEARS ≈ $13.20 second-highest of ten draws PERFECTLY TARGETED · 2 CLEARS ≈ $11.30 the runner-up prices the winner
Stylised numbers, real order statistics. Valuations are drawn uniform over a ten dollar range, so read the gap between the two clears and ignore the dollar amounts.

We could describe the viewer in the request and let campaigns decide whether to care. We stopped short of making segment membership a condition of eligibility, because at our demand depth the marginal bidder was worth more than the marginal signal. So the sellable thing became the creator. Category, brand-safety tier, audience band, computed per stream.

The counterargument: bidder count and bidder value aren't independent, an open field summons ten cheaper bidders, and some budgets won't transact without audience signal at all. At our demand depth, widening won. At a deeper book it would not, so it shipped with an exit condition: Eligible-demand depth per stream. When the pools reach the hundreds, viewer targeting ships.

06 · The people decisions

Two negotiations, before a line of integration code.

Partner
Filling a broadcaster's breaks replaces their own ad sales, so the deal came before the deploy. Revenue share on filled breaks, their house spots as our fallback fill, and measurement they trusted, meaning our impression beacons against their reconciliation. That conversation started the same week the engineering did.
Sales
I gave our team the reserved first slot as a sponsorship product on select streams, a real thing to sell that didn't require bypassing the auction. What I kept was the price. They could sell the slot, and they had to clear the floor I set.

Our director of business development pushed to fill below the floor. He was measured on the number of advertisers on the platform, and a cheap yes is the fastest way to move that number. I said no and I held it. Every advertiser after him would have priced against whatever we let him pay, and the floor I had just spent a quarter finding would have been worth nothing.

07 · What broke

We shipped the wrong fallback first.

Live broke two ways. Cues misfired, arriving at the wrong moment or for a duration the pod couldn't fill. And decisions sometimes came back with nothing. An open window, and nothing to put in it.

Our first fallback was cutting straight back to programming. It was wrong. The abrupt return read as a malfunction, so viewers experienced a bug where we had built a recovery. Slate replaced it, holding the window with something that looks deliberate.

Which is why slate seconds became a guardrail metric. It is the failure a viewer feels. We instrumented it after shipping the worse version.

08 · Boundaries

What this doesn't prove.

The system has served over 10 million ad impressions to date. That is a lifetime count. Peak concurrency was tens of thousands, and millions concurrent is a different problem. The forty-five days was standing up the live product and integrating an ad server that already existed. Building that ad server was separate work, done long before this.

Every advertiser in these auctions was ours, sold by our own team through our own interface, so nothing here proves I've run demand I didn't own. And it was co-owned with an engineering lead who deserves half the credit for everything above.

And I made that cut without deciding which number would settle it. That part is in How I build now.

09 · Portability

What I'd ask in week one at 30 million concurrent.

I keyed every decision to the stream, because each stream carried one audience. At one stream and tens of millions of audiences, that keying has to move inside it.

OURS many streams, one audience each THEIRS × millions one stream, many audiences

The pipeline has to personalise on the opposite axis. Four questions I'd take into week one.

01
At what demand depth does per-viewer eligibility beat a wider field? That's the exit condition I wrote down and never got to trip.
02
Is the pod decided once for the stream or once per viewer, and what does that cost the splice budget?
03
Where does frequency capping get enforced when one break becomes millions of distinct pods?
04
What's the guardrail metric here, and who has the authority to hold a launch on it?