← Back to blog

Build vs. buy vs. self-host: a decision framework

decision-frameworkinfrastructureleanself-hostingtco
Build vs. buy vs. self-host: a decision framework

There are three ways to get a capability into your stack: build it yourself, buy it from a vendor, or self-host someone else’s software. Most teams pick one of the three on instinct — the platform people self-host everything, the startup people buy everything, the engineer who likes building builds everything — and then defend the instinct with a cost spreadsheet that conveniently leaves out their own time. The framework below is the one I actually run the decision through. It costs ops time honestly, it names the switching cost most spreadsheets ignore, it asks whether the thing is core or context before it asks anything about price, and it states the specific way each of the three options fails so you can pick your poison on purpose instead of by accident.

The short version: decide core-vs-context first, cost it across three years including the hours, then pick the failure mode you can live with. Price is the last question, not the first.

The decision is not “cheapest” — it’s “core or context”

Before any number, one question: is this capability something that makes you you, or is it plumbing that every company in your position also needs?

This is Geoffrey Moore’s core-vs-context distinction, from Dealing with Darwin (2005). Core is the work that creates durable competitive advantage — the thing customers pay you for, the thing a competitor can’t easily copy. Context is everything else: necessary, often unavoidable, but not differentiating. Payroll is context. Auth is context for almost everyone. Your matching engine, your pricing model, your particular way of routing work — that might be core.

Moore’s rule is simple and it survives contact with reality: invest your scarce build capacity in core, and offload context. The common advice that falls out of this — “buy for commodity, build for differentiation” — is repeated across most modern build-vs-buy guides because it’s right. You have a finite number of engineer-hours that can produce something a competitor can’t. Spending those hours rebuilding an auth system, a queue, or a metrics pipeline that a vendor already sells is how teams stay busy while standing still.

So the first cut is not three options, it’s a gate:

  • Core capability → bias toward build. This is where your hours buy advantage. Buying or self-hosting context here is often fine; self-hosting or buying your core hands your differentiation to someone else’s roadmap.
  • Context capability → bias toward buy or self-host. Your hours are wasted building this. The only remaining question is buy versus self-host, which is a cost-and-control question, not a strategy one.

Get this gate wrong and no amount of TCO math saves you. I’ve watched teams lovingly hand-build the context — the internal admin panel, the bespoke deploy tool, the homegrown feature-flag system — while buying the thing that was actually their edge. The spreadsheet said build was cheaper. The spreadsheet was answering the wrong question.

One caveat that earns its keep: core-vs-context is a line that moves. What’s core today can commodify into context in three years. Auth was core in 2008; it’s a checkout-page integration now. So the gate isn’t permanent — revisit it when a market shifts, and be willing to migrate from build to buy when the thing you built stops being a differentiator and starts being a maintenance tax.

TCO is a three-year number, and your time is the line item everyone forgets

Once you’re past the gate, you cost the options. The mistake almost everyone makes is comparing the sticker — the vendor’s monthly invoice against the build’s “we have engineers already” of zero. That comparison is fiction.

Total cost of ownership is every expense over the life of the capability, not the price on the way in. The number that should reframe the whole exercise: a widely-cited figure across build-vs-buy analyses holds that roughly 65% of total software cost lands after the initial deployment — integration, maintenance, upgrades, support, the slow drift of keeping a thing alive. Whatever the exact percentage, the direction is not in dispute: the invoice is the small part.

Here is what actually goes in each column. Cost it over three years, because that’s long enough for the ops tail to show up and short enough that you can still forecast it.

Build:

  • Engineering time to build the first usable version (and be honest — multiply your estimate, you always do)
  • Ongoing engineering time to maintain, patch, and extend it — this never goes to zero
  • The opportunity cost of those hours: what core work didn’t happen because you built context
  • On-call burden when it breaks at 2am and only you understand it
  • The bus-factor risk: the person who built it leaves, and now it’s a haunted house

Buy (SaaS / managed):

  • The subscription, which usually scales with usage or seats — model it at your year-three size, not today’s
  • Integration cost — getting it into your stack, your auth, your data. The hidden integration and onboarding work is the part the sales call never mentions
  • Per-seat or per-event pricing that turns into a tax as you grow
  • The cost of the vendor’s failure becoming your incident, with no code to read and no fix you can ship

Self-host (open-source software on your infra):

  • No license, but you own the ops: deploy, upgrade, back up, secure, monitor it yourself
  • Infra cost — the boxes or instances it runs on
  • The ops time, which is the real price of self-hosting and the number people zero out because “it’s free.” It is not free. It is unpriced.
  • The expertise cost: you now need someone who understands this software well enough to fix it under pressure

The build-cost curve declines over time (you build once, then maintain), while the buy-cost curve climbs with scale — which is why these analyses cite a break-even somewhere around the two-to-three-year mark for mid-sized teams. The shape matters more than the exact crossover: if you’ll outlive the break-even and the usage will keep growing, the recurring buy cost compounds against you. If you won’t, or if the thing is genuinely context you’ll replace, the build never pays back its tail.

Put real hours in the build and self-host columns at a real loaded rate. The moment you price your own time, most “we’ll just build it” decisions for context capabilities collapse on contact.

Switching cost: the line item that decides the next decision, not this one

There’s a cost almost no first-pass analysis includes: how expensive is it to leave the choice you’re about to make? Switching cost is what you pay later to undo today’s decision, and it’s the difference between a reversible bet and a one-way door.

  • Buy usually has the highest switching cost and hides it best. Your data is in their schema, your team’s muscle memory is in their UI, your integrations are wired to their API. The exit is a migration project nobody budgets for until the renewal price doubles. This is lock-in, and it’s the real cost of “buy” — not the monthly fee, the captivity.
  • Self-host has moderate switching cost. It’s open software, so you usually have an export path and the data’s in a format you control. Moving from one self-hosted tool to another is real work but rarely a hostage situation.
  • Build has the switching cost you’d expect of anything bespoke: high to rebuild, but you own every line, so there’s no third party who can hold the exit ransom. The lock-in is to your own past decisions, which is at least a captor you can negotiate with.

The practical move: weight switching cost by how likely you are to switch. For a capability you’ll keep for a decade, lock-in matters less — you’re marrying it anyway. For a fast-moving area where you expect to re-evaluate in eighteen months, a high switching cost can outweigh a lower sticker price, because you’re not buying the tool, you’re buying the option to leave it, and “buy” often sells you that option at a terrible rate.

The honest failure mode of each — pick your poison

Every one of the three options fails. Not “might fail” — fails, in a characteristic way. A real decision is choosing which failure mode you’d rather own. Anyone selling you one of the three without naming its failure is selling, not advising.

Build fails by becoming a tax. The thing you built works, ships, does its job — and then it never stops asking for your time. Every dependency upgrade, every security patch, every new requirement is your problem forever. The person who understood it leaves. The “we’ll just build it in a sprint” turns into a permanent line in every future sprint. Build doesn’t fail by not working; it fails by working and never letting go. The failure is the maintenance tail you didn’t price.

Buy fails by lock-in and the slow loss of control. It works beautifully right up until the vendor raises the price, deprecates the feature you depend on, gets acquired and gutted, or simply decides your use case isn’t on their roadmap. You can’t read the code, can’t ship the fix, can’t move without a migration. Buy doesn’t fail by being expensive on day one; it fails by making you a price-taker and a roadmap-taker on something you now depend on. The failure is the captivity you signed up for without reading it as captivity.

Self-host fails by ops burden landing on a team that can’t carry it. The software is great and free. Then it needs upgrading and nobody’s sure it won’t break. Then it goes down at 2am and the one person who understood it is on holiday. Self-host doesn’t fail at install; it fails six months in, when the operational weight of running it exceeds the team’s actual capacity, and the “free” tool has quietly become the most expensive thing you run because it eats your best engineer’s attention. The failure is the ops competence you assumed you had.

Notice the pattern: build trades money for a time-tax, buy trades control for convenience, self-host trades license fees for ops competence. There is no option that trades nothing. The framework’s whole job is to make you choose the trade deliberately.

Putting it together — the order of operations

The framework, in the order you actually run it:

  1. Core or context? If core, bias build — spend your scarce hours where they buy advantage. If context, the decision is buy-vs-self-host and strategy is off the table.
  2. Three-year TCO, with your hours priced. Real loaded rate on build and self-host. Year-three scale on buy. The invoice is the small part; the ops tail and integration are most of it.
  3. Switching cost, weighted by likelihood of switching. A reversible bet on a fast-moving capability is worth a premium. A one-way door on something you’ll keep forever is fine.
  4. Pick the failure mode you can carry. Build = maintenance tax. Buy = lock-in and lost control. Self-host = ops burden. Choose the one your team is actually staffed to survive.

Most of my own infrastructure decisions land on self-host for context where I have the ops competence, buy for context where I don’t, build only where it’s genuinely core. I self-host a lot — my observability stack, my own boxes — because I’m willing to carry the ops burden and the math works at my scale and time horizon. That’s a choice that fits me; it is explicitly not a recommendation to self-host everything. If you don’t have the ops muscle, self-hosting your critical path is choosing a failure mode you can’t survive, and the framework should tell you that loudly. The point of the framework isn’t to push you toward any one column. It’s to stop you picking by instinct and then back-filling a spreadsheet to justify it.

Decide core-vs-context first. Cost the hours honestly. Name the failure you can live with. Then, and only then, look at the price.