Field guideOperating model

2026 · Operating modelAbout 13 min readNovus Stream Solutions

Why we killed our sports-odds project: the real-time data bill we couldn't make cheap

We built and then killed a sports-odds analysis project. This is an engineering and unit-economics retrospective: the product required up-to-the-minute data, which meant a constant, heavy database and feed cost that broke our "runs almost for free" operating constraint.

A product whose constant real-time data refresh created an always-on cost incompatible with a near-free operating model

Overview

The third retirement is the clearest, because the reason is a number rather than a judgment. We built a sports-odds analysis project — software that looked at odds across sources to surface things like expected-value and arbitrage opportunities for sports predictions. As a piece of engineering it was interesting, and the analysis it did was real. We killed it anyway, and the cause was not the analysis or the interface or the demand. It was infrastructure cost: the product structurally required up-to-the-minute data, and keeping data up to the minute meant a constant, heavy load of database reads and writes plus external feeds that was fundamentally incompatible with the way we run everything else. This is an engineering and unit-economics post-mortem, framed strictly around the data and the cost rather than the subject matter.

What makes this retrospective worth writing is that it is a case of a product being incompatible with an operating model rather than being a bad product. The thing worked. The reason to stop was that making it work continuously cost too much, in a specific and unavoidable way, and "too much" was not a temporary inefficiency we could optimize away — it was baked into what the product fundamentally needed to be useful. Some products are structurally at odds with how you have chosen to operate, and recognizing that early is a real form of product judgment.

The hard requirement: up-to-the-minute data

The entire value of an odds-analysis product is in the freshness of the data. Odds move, and the opportunities the analysis is meant to surface — value relative to the current market, discrepancies between sources — exist only relative to the current state of those odds. Analysis built on data that is even a little stale is not just less useful; it is actively misleading, because it points at opportunities that have already closed. So the product had a non-negotiable requirement that distinguishes it from almost everything else we build: the data underneath it had to be current to the minute, all the time, continuously, or the product was worse than nothing. There was no version of this that worked on a slow refresh.

That requirement is the whole story, because "current to the minute, continuously" is an expensive sentence in infrastructure terms. It means a pipeline that is constantly pulling fresh odds from sources, constantly writing those updates into a database, and constantly serving them out to whatever is doing the analysis — and "constantly" here is not a burst you can scale down between, it is a steady, always-on load for as long as the product is meant to be useful, which is whenever events are live. The cost of the product was not a function of how many people used it; it was a function of keeping the world-state fresh, which had to happen whether one person was watching or none.

The data bill that broke the model

Here is where it collided with how we operate. The rest of the Novus portfolio is built so that the marginal cost of running it is close to zero — the consumer tools do their work on the user's own device, the hub has no database to speak of, and a new app adds almost nothing to recurring cost. That near-free cost structure is not a nice-to-have; it is the thing that makes a free, ad-supported, one-person portfolio sustainable. The sports-odds project violated it at the root. It required a database under constant heavy read and write load and a continuous intake of external data, which is an always-on bill that exists independent of usage and grows with how fresh and how broad you want the data to be. It was, in the most literal sense, the opposite of an app that runs almost for free.

And the cost was not the kind you engineer away with a clever optimization. You can trim the edges of a constant-refresh data pipeline, but you cannot make "keep a large, fast-moving dataset current to the minute, continuously" cheap, because the expense is intrinsic to the requirement. The only ways to reduce it meaningfully were to make the data less fresh — which destroys the product, since stale odds are worse than no odds — or to lean harder on heavy external paid feeds, which trades a database bill for an even larger and more dependency-laden one. Every path to lowering the cost either broke the product or deepened exactly the kind of heavy third-party reliance we specifically build to avoid. There was no version of the product that was both useful and cheap to run, and "useful and cheap to run" is the bar.

A constant always-on data-refresh cost that exists regardless of usage, incompatible with near-zero marginal cost
The cost tracked data freshness, not usage — an always-on bill the near-free model has no room for.

Cost that tracks freshness, not usage

The defining and unusual property of this product's economics is that its cost tracked data freshness rather than user count, which inverts the normal relationship between usage and expense. For most software, cost scales with use: more users means more load means a bigger bill, and an idle product costs little. This product was the opposite — its dominant cost was keeping the underlying data current to the minute, which had to happen continuously whenever events were live, regardless of whether anyone was watching the analysis. A single user and a thousand users imposed nearly the same data-freshness cost, because the expense was in maintaining the world-state, not in serving it.

This usage-independent cost structure is what made the product fundamentally incompatible with the operating model, in a way that is worth distinguishing from ordinary expensiveness. A cost that scales with usage can at least be reasoned about in terms of revenue per user; a cost that exists independent of usage is pure overhead that must be paid before a single user provides any value, and continues whether or not anyone shows up. For a free, ad-supported model, a usage-independent cost is especially deadly, because ad revenue scales with usage while this cost did not, so there was no usage level at which the revenue would reliably cover the always-on expense. The cost tracking freshness rather than usage meant the product had a standing bill that its revenue model had no structural way to meet, which is a deeper problem than merely being expensive.

Why no optimization could rescue it

A reasonable response to a high cost is to optimize it down, and it matters that this option genuinely did not exist for the sports-odds project, because the expense was intrinsic to the requirement rather than incidental to the implementation. You can trim inefficiencies at the edges of a data pipeline, but the core cost — keeping a large, fast-moving dataset current to the minute, continuously — cannot be optimized away, because it is the irreducible cost of doing the thing the product exists to do. The only levers that would meaningfully reduce the cost were to make the data less fresh or to lean harder on heavy external paid feeds, and both of those broke something essential.

Making the data less fresh destroys the product, because the entire value is in freshness — stale analysis points at opportunities that have already closed, which is worse than no analysis. Leaning on heavy paid external feeds trades one large bill for an even larger one and deepens exactly the kind of third-party dependency the operation specifically builds to avoid. So every path to lowering the cost either gutted the product's usefulness or violated another core principle, leaving no version that was both useful and affordable to run. This is the signature of a structural cost problem as opposed to an optimization opportunity: when the cost is intrinsic to the requirement, the usual engineering response of optimizing it down simply does not apply, and recognizing that the cost was structural rather than fixable is what made the kill decision clear rather than a temptation to keep trying to optimize.

The third-party dependency trap

The sports-odds project also illustrates a second principle the operation holds, beyond near-zero cost: avoiding heavy reliance on third-party services and paid external feeds. The product could not function without continuous intake of external odds data, which meant a structural dependency on outside feeds that the operation does not control — a dependency that carries cost, fragility, and a loss of autonomy all at once. A product whose core data must come continuously from paid third parties is a product whose viability is hostage to those third parties' pricing, availability, and terms, which is a kind of exposure the operation deliberately avoids by building things that run on its own minimal infrastructure and the user's device.

This dependency aversion is not arbitrary; it is what keeps the operation's products robust and cheap. A tool that runs on the user's device and a lean stack has few external dependencies that could break it, raise its costs, or change its terms — its fate is largely in the operation's own hands. A product built on heavy external feeds is the opposite: its costs and its very ability to function depend on services it does not control, which is fragile and expensive in exactly the ways the operation's whole approach is designed to avoid. The sports-odds project violated this principle as fundamentally as it violated the cost principle, and the two violations were really one — the heavy external dependency was both the source of the cost and the source of the fragility. A product that can only exist by leaning hard on paid third parties is structurally misaligned with an operation built to minimize exactly that reliance, which is a second, independent reason it did not belong.

The operating model as a pre-build filter

The most useful generalization from this retrospective is that an operating model functions as a product filter that should be applied before the question of whether a product is good, not after. The usual order of product evaluation — is this a good idea, do people want it, can we build it well — skips a prior question that for a constrained operation is decisive: can this product exist within the way we have chosen to operate. The sports-odds project would have passed the usual evaluation; it was a good idea, the analysis was real, it was buildable. It failed the prior question, which is whether it was compatible with a near-zero-cost, low-dependency operating model, and that failure was knowable before most of the building.

Applying the operating model as a pre-build filter saves the larger waste of building something well that you then cannot afford to run. The discipline is to ask, at the concept stage, not just whether a product is good but whether its fundamental requirements are compatible with how the operation actually works — and when a product's core requirement, like continuous expensive data freshness, structurally violates a core operating constraint, like near-zero marginal cost, that is a disqualification that should stop the project before significant investment. This is the same structural-no logic the operation applies generally: a product that cannot exist cheaply within how you operate is a complete reason to stop, and the earlier the operating model is applied as a filter, the less is wasted. The sports-odds project taught the value of running that filter first, because it is the case where doing so would have saved the most.

When the decision is a number, not a judgment

What distinguishes the sports-odds retirement from the other two is that the decision rested on a number rather than a judgment call, which made it unusually clear-cut. The Stream Studio decision involved judgment about disguised complexity and bandwidth; the Stream Tools decision involved judgment about redundancy and value — both required interpretation. The sports-odds decision required no interpretation: the product had an intrinsic, always-on infrastructure cost that the near-zero-cost operating model had no structural way to cover, and that incompatibility was a fact about the economics, not an opinion about the product. When the reason to stop is an arithmetic incompatibility rather than a debatable assessment, the decision is as close to objective as product decisions get.

There is a certain clarity in a number-driven kill that judgment-driven ones lack, and it is worth appreciating because it makes the decision both easier and more defensible. A judgment call can be second-guessed — maybe the disguised portfolio could have been rescoped, maybe the generic tool had a niche — but a structural cost incompatibility leaves little room for second-guessing: the product could not exist within the cost model, full stop. This is why the sports-odds retrospective is the clearest of the three. It is the case where the operating model functioned as an unambiguous filter, returning a definite no based on the economics rather than a weighed judgment based on the product's merits. Not every kill decision is this clean, but when one is — when the reason is a number that simply does not work — the clarity is a gift, because it removes the agonizing that judgment-based decisions carry and makes the right call obvious.

Why recording the kills matters

These three retrospectives exist because recording what was killed, and why, is part of operating honestly — a backlog that documents the things tried and stopped, not just the things kept and celebrated. Most operations publicize their launches and bury their retirements, which presents a misleadingly tidy picture of constant success and hides the decisions that actually shaped the portfolio. Writing the kill decisions down plainly, with the real reasoning, is a commitment to the honest version of the story: that a portfolio is shaped as much by what was cut as by what was kept, and that the cuts were deliberate decisions with sound reasons rather than failures to be hidden.

The value of recording the kills is both internal and external. Internally, documenting why each product was retired turns the decisions into reusable lessons — the disguised-portfolio test, the reason-to-exist question, the operating-model filter — that inform future build decisions rather than being forgotten. Externally, the honesty of publishing the retirements alongside the launches builds the kind of credibility that a tidy success-only narrative cannot, because it demonstrates that the keep-or-kill loop is real and that the products which survived did so by passing a genuine evaluation that others failed. A lab that only ever announces what it keeps is asking to be taken on faith; a lab that documents what it killed, and why, is showing its work. The three retrospectives together are that honest record — the disguised portfolio, the redundant utilities, and the structurally-incompatible product — and recording them is itself an expression of the operating model's commitment to honesty about what works and what does not.

Structural mismatch is a valid reason to kill a product

The decision, then, was not close. A product whose core requirement is incompatible with your core operating constraint is not a product you optimize — it is a product you do not build, or stop building once the incompatibility is clear. The sports-odds project was structurally at odds with two of our firmest principles at once: that our apps should run at near-zero marginal cost, and that we avoid heavy reliance on third-party services and paid APIs. It could not satisfy either without sacrificing the thing that made it useful. That is not a failure of execution; it is a mismatch between the product and the operation, and the right response to a genuine mismatch is to stop, not to push.

The transferable lesson is that your operating model is a real product filter, and an early one. Before the question of whether a product is good comes the question of whether it is compatible with how you can actually afford to run things — and for a small operation committed to near-free, low-dependency apps, a product that demands continuous expensive infrastructure is disqualified almost regardless of how good it is. Knowing that constraint and applying it early saves the larger waste of building something well that you then cannot afford to operate. We learned to ask, up front, not just "is this a good product" but "can this product exist within the way we run things" — and when the answer is a structural no, that is a complete reason. The companion retrospectives cover a product that was secretly several apps and one that worked fine but was too generic to earn its place; together the three are the honest record of what the keep-or-kill loop actually decided.