GTM Engineering
Build vs Buy: The $30K Tool That Cost Us $190K
A license price is the smallest of five numbers you will carry. Run the 3-year TCO and the maintained cost jumps an order of magnitude nobody prices at signing. Here is the model, the decision tree, and the weighted scorecard that decide it.
· 14 min read
I once inherited a routing tool that cost $30K a year and did one thing: match a lead to an account and hand it to an owner. The match logic was a join on email domain. The data already lived in our warehouse. We were paying $30K a year, plus a fifth of an ops person to babysit it, for a query I could write in an afternoon. Nobody had run the 3-year number before the demo. They ran the demo, liked the dashboard, and signed. Three years later that $30K sticker had cost us $190K, and not one line item was a surprise to anyone who had done the arithmetic first.
For a long time build-vs-buy was a gut call. Someone sees a polished product, the pain is real, the sticker looks reasonable against one year, and the contract closes before anyone models what it costs across three. The old way asks “does this feel worth it?” The number that settles it is total cost of ownership over the life you will run the thing, and it cuts both ways: bought tools hide four costs behind the license, and a maintained build hides three years of upkeep behind one good week. The sticker you compared is the one number in the deck. It is the smallest of the five you will carry, and the true figure sits an order of magnitude away from it. Zoom out on the $30K before you read another word.
The sticker price stays constant. The field around it grows each level.
Each level is the same tool. The dot in the middle never moves; the sticker is fixed at $30K the whole way out. What grows is the field around it, the cost the sticker never showed you, and it grows by roughly an order of magnitude from the demo-deck number to the number you pay at scale. The five costs at level three are the framework for the rest of this piece: name them, model them, then score the close calls with the person who inherits the maintenance line.
The sticker is one of five numbers
A license price is the number a vendor wants you comparing against a single year. Buy total cost of ownership is the license, plus the implementation you pay once, plus the admin headcount you dedicate forever, plus the integration maintenance when the tool and your CRM drift, plus the switching cost you eat if you ever leave. Build total cost of ownership is the initial build, plus maintenance that recurs every year the thing runs, plus the on-call cost when an upstream API changes its contract at 2am, plus the infrastructure it sits on. Two very different cost shapes, one comparison.
Here is the model as code, so you can drop your own numbers in rather than argue about vibes:
def tco_buy(license_yr, impl_once, admin_fte, loaded_salary, years=3):
"""3-year TCO of a bought tool. Loaded salary = comp * ~1.4."""
recurring = license_yr + admin_fte * loaded_salary
return impl_once + years * recurring
def tco_build(build_hours, hourly, maint_pct, infra_yr=0, years=3):
"""3-year TCO of a build. maint_pct is fraction of build cost
that recurs annually as maintenance (rule of thumb ~0.15-0.30)."""
build = build_hours * hourly
maintenance = years * (build * maint_pct + infra_yr)
return build + maintenance
# the routing tool from the intro
buy = tco_buy(license_yr=30_000, impl_once=10_000, admin_fte=0.2, loaded_salary=150_000)
build = tco_build(build_hours=120, hourly=120, maint_pct=0.30, infra_yr=0)
# buy -> 190_000 (matches the $190K stat tile and the 3-year zoom level)
# build -> 27_360
The routing tool is the long-tail case where a build wins clean: the data is warehouse-native, an owner who can write the query already sits on the team, and the job is stable. That is not every job. Change three inputs and the answer flips. The point of the model is that the answer is a number you compute, not a preference you defend.
The four costs the license hides
| Hidden cost | What it is | Typical size (mid-market) |
|---|---|---|
| Implementation | Setup, data mapping, first integration | $5K to $40K, once |
| Admin overhead | The 0.1 to 0.4 FTE who owns config forever | $15K to $60K per year |
| Integration drift | Re-mapping when CRM or tool schema changes | 1 to 3 eng-weeks per year |
| Switching cost | Data export, re-training, re-integration on exit | 0.5 to 1x a full implementation |
Source: my own post-mortems across mid-market revenue stacks; sizes vary with seat count and integration depth. The pattern does not: the admin FTE is the cost nobody prices at signing and everybody pays every year. A $30K license with a 0.3 FTE admin at a $150K loaded salary is a $75K-a-year tool, which is why the year-one level of the zoom already sits at $70K and not at the sticker. Model it that way or the buy case always looks cheaper than it is. For a public anchor, a single ZoomInfo seat runs near $33.5K a year on its own (ZoomInfo published pricing, 2025), and the admin to keep it clean rides on top of that, not inside it.
The build side hides one cost as reliably: maintenance. A build is a pet, not a one-time expense. Gartner’s application TCO work puts annual software maintenance at roughly 15 to 30 percent of the original build cost every year the thing runs, and GTM builds that call third-party APIs sit at the top of that band because vendors change their contracts without asking you. A build with no named owner skips the 20%-a-year line on paper and instead pays it as a production incident during quarter-end plus a scramble to reverse-engineer code the author already left with.
Watch the two lines cross
The reason build-vs-buy feels hard is that the two costs have different shapes. Buy is a flat annual line: you pay roughly the same every year forever. Build is a step up front and a shallow slope after: expensive to stand up, cheap to keep running if it is owned and stable. For a warehouse-native job the build line stays under the buy line for the whole term. For a job that needs constant vendor data, compliance certification, or a UI real humans use, the build line bends up and never crosses back.
Toggle between the two for the routing job from the intro. Same three years, same team:
View as table
| Point | Value |
|---|---|
| Start | 10K |
| Year 1 | 70K |
| Year 2 | 130K |
| Year 3 | 190K |
The gap at year three is $163K. That is real money for a query on data you already have. Run the same chart for a tool that needs a phone-verified mobile database refreshed monthly, though, and the build line never leaves the ground floor because you cannot build a data vendor. You would be rebuilding an enrichment waterfall and still paying every provider underneath it, so the maintained cost stacks on top of the vendor cost instead of replacing it. The lesson is not “build wins.” It is “run the lines for this specific job.”
The one question that classifies the job
Before the TCO math, one question sorts most decisions: is this job your GTM alpha, or is it commodity infrastructure? Alpha is the proprietary layer competitors do not have, the play only your data can run, the logic that encodes how your team sells. Infrastructure is the hard, boring, certified plumbing everyone needs and nobody differentiates on: sending email at scale, phone-verified mobile numbers, SOC2-compliant storage.
Build your alpha. Buy your infrastructure. A team that builds its own email-sending infrastructure to save a subscription is spending its scarcest engineering hours on the one layer where being average is fine. A team that buys a generic scoring model instead of encoding its own qualification logic is renting someone else’s guess about its business. This maps onto the 5-tool stack argument: buy the five hard infrastructure jobs, build the thin proprietary layer that sits on top of them.
Score it with the owner in the room
The classification and the TCO get you most of the way. For the genuinely close calls, score it. Six criteria, weighted, scored one to five where five points toward build and one points toward buy. Do it with the person who will own the thing on year three sitting at the table, because they are the one who inherits the maintenance line.
# build-vs-buy scorecard. score each 1-5 (5 = build, 1 = buy). weights sum to 1.0
criteria:
proprietary_edge: { weight: 0.25 } # GTM alpha, or commodity anyone has?
data_already_owned: { weight: 0.20 } # does the source live in our warehouse?
in_house_owner: { weight: 0.15 } # is there a SQL/eng owner who stays?
maintenance_tolerance: { weight: 0.15 } # can we absorb the API-breaks-at-2am cost?
time_to_value: { weight: 0.15 } # weeks we can wait before it must work
compliance_lift: { weight: 0.10 } # SOC2 / data residency we would have to build
decision:
weighted_score >= 3.5 -> build
weighted_score <= 2.5 -> buy
otherwise -> hybrid: buy the base, build the proprietary layer
Scored honestly, the routing tool from the intro lands near 4.2: proprietary edge is low but every other criterion points to build because the data was ours and the owner existed. A cold-email sending platform scores near 1.6: you could build it, and you should not, because deliverability infrastructure is the certified plumbing you buy. The scorecard does not make the decision for you; it forces the maintenance-tolerance and in-house-owner rows into the conversation, because those are the two that get skipped and those are the two that bite.
Here is the same six criteria run against three real jobs, so the pattern is visible:
| Job | Proprietary | Data owned | Owner exists | Weighted score | Verdict |
|---|---|---|---|---|---|
| Lead-to-account routing | Low | Yes (warehouse) | Yes | 4.2 | Build |
| Cold-email sending infra | Low | No | No | 1.6 | Buy |
| Custom lead scoring on first-party usage | High | Yes | Yes | 4.6 | Build |
Source: scored from the criteria above. The scoring numbers are illustrative; the ranking is not. Notice the scoring job outscores routing on proprietary edge, which is why it is worth building even though a dozen vendors would sell you a generic model tomorrow. A generic model trained on everyone’s data is average by construction. Your qualification logic is the alpha.
Here is how I would decide it
I run every non-trivial tool decision through the same six steps, in order. The steps exist to stop the demo from making the decision for you.
- 1
1. Write the job in one sentence
If you cannot state the single job in a sentence, you are about to buy a suite to solve a task. Name the job before you name a vendor. "Match inbound leads to the right account and owner" is a job. "Revenue intelligence" is a category.
- 2
2. Classify it: alpha or infrastructure
Is this the proprietary layer competitors lack, or the certified plumbing everyone needs? Alpha leans build, infrastructure leans buy. Most jobs are obvious once you ask. The close ones go to the scorecard.
- 3
3. Run the 3-year TCO both ways
Use the two functions above. Price the buy with the admin FTE included and the build with maintenance included. Compare the cumulative lines, not the year-one numbers. The lines have different shapes; find where they cross.
- 4
4. Score the scorecard with the future owner present
Six weighted criteria, scored one to five, with the person who inherits the maintenance line in the room. The maintenance-tolerance and in-house-owner rows are the ones that decide close calls.
- 5
5. If you build, assign a named owner and a kill date
A build with no owner is the orphaned-build trap waiting to happen. Assign one name, add a monitoring alert, and schedule the review. An unowned build is a liability the moment its author leaves.
- 6
6. Re-run the decision at every renewal
A buy that was right at 20 people can be wrong at 200 when volume makes the license balloon, which is the top level of the zoom. A build that was right at launch can rot into a buy. Put the decision on the renewal calendar.
Buy and build fail differently
The failure modes are not symmetric, and knowing which failure you can tolerate is half the decision. A bought tool fails by costing more than it is worth and being annoying to remove. A build fails by breaking silently, at the worst time, with the only person who understood it already gone. Neither is strictly better. They are different bets, and you should make the one whose failure mode you can survive.
| Bought tool | Maintained build | |
|---|---|---|
| Cost shape | Flat annual, forever | Big up front, shallow slope after |
| Hidden cost | Admin FTE + switching cost | Maintenance at ~20%/yr + on-call |
| Time to value | Days to weeks | Weeks to months |
| Fails by | Overpaying, lock-in on exit | Silent break when owner leaves |
| Best fit | Commodity infrastructure | Proprietary edge on owned data |
| Governance need | A renewal owner who can say no | A named owner + monitoring alert |
The discipline is refusing to decide on the demo, not defaulting to “always build” or “always buy.” Write the job in a sentence, classify it, run both TCO lines, and score the close calls with the future owner in the room. Most stacks are not sprawled because someone bought a bad tool. They are sprawled because nobody ran the 3-year number, and every unowned tool renews forever, which is the exact problem behind tool sprawl governance. The model above takes an afternoon. The wrong call takes three years to pay off, and by then the $30K sticker has quietly become $190K.
Keep reading
One email. Every week.
One email a week: a system I built or broke, with the config, the numbers, and what I would change. No roundups, no theory, unsubscribe whenever it stops being useful.
The newsletter opens soon.
Connect a provider in src/config.ts