Build versus buy for API capabilities

Compare the total cost of building a capability with buying it as an API, plan a hybrid rollout, and record the decision as an architecture decision record.

  • 40 min
  • Expert

Every capability in a multi-API system was, at some point, a choice: call someone's API, or build it. Usually nobody wrote the choice down. An engineer found an API that worked, or an engineer found a library that worked, and two years later the team is either paying for something trivial or maintaining something hard, with no record of why.

Architects are asked this question constantly, and it is rarely about the API's price. It is about what you take on when you own a capability: the data behind it, the upkeep of that data, the pager when it breaks, and the opportunity cost of the people doing all of that instead of your product. This lesson gives you a way to count those costs, the situations where building honestly wins, a hybrid path that avoids betting the company on the answer, and a format for writing the decision so it survives the people who made it.

What you are actually buying

Split any capability into three layers before comparing anything:

  1. Logic: the code that turns input into an answer. Parsing a phone number, matching a domain against a list, computing a hash.
  2. Data: what the logic consults. Numbering plans, disposable-domain lists, IP ranges, technology fingerprints, registry records.
  3. Operations: keeping both running and current. Refresh jobs, monitoring, scaling, incident response, and the person who knows how it works.

Logic is usually the cheapest layer, and it is the one people estimate when they say "we could build that in a week". Data and operations are where the cost lives, and they recur every month for as long as the capability exists.

Phone validation shows the split clearly. Phone Number Validator runs on Google's libphonenumber numbering-plan data, according to its definition, and its location and carrier fields come from that library's offline maps. libphonenumber is open source. If all you need is "is this a valid number for this country, and what is its E.164 form", the logic and the data for that question are available to embed, and building is a realistic option.

Try it livePhone Number Validator10 credits
GEThttps://api.apiverve.com/v1/phonenumbervalidator
curl "https://api.apiverve.com/v1/phonenumbervalidator?number=%2B390669881022" \
  -H "x-api-key: YOUR_API_KEY"
Sign in or create a free account to run this with your own key.

Validity, type and formatting come from public numbering-plan data. isDisposable comes from something you would have to maintain yourself.

The same response also returns isDisposable, which the definition describes as a check against numbers published on temporary SMS-receiving sites. That is a different kind of data: there is no library for it, it changes continuously, and keeping it current is a crawling and curation job that never ends. Within one API response, one field is cheap to build and another is expensive to own. The build-versus-buy question applies per layer, and often per field.

Disposable email detection is the same story with smaller stakes. A static list of disposable domains is a download away. A list that is current this week is an operation.

Try it liveDisposable Email Checker6 credits
GEThttps://api.apiverve.com/v1/emaildisposablechecker
curl "https://api.apiverve.com/v1/emaildisposablechecker?email=test%40mailinator.com" \
  -H "x-api-key: YOUR_API_KEY"
Sign in or create a free account to run this with your own key.

The answer is one boolean. The value of the API is the list behind it staying current, not the lookup.

Count the total cost of ownership

Total cost of ownership (TCO) is the full monthly cost of a capability, including the costs that do not arrive as an invoice. For the build side, count:

CostWhat it includesEasy to miss because
BuildDesign, implementation, tests, rolloutIt is a one-off, so amortise it over the expected life
Data acquisitionLicences, downloads, crawling, registry accessSome sources rate-limit, charge, or forbid commercial use
MaintenanceRefreshing data, upgrading dependencies, fixing edge casesIt looks like small tasks scattered across many sprints
InfrastructureHosting, storage, databases for the data layerLookup data sets are often larger than the code
On-callBeing reachable when it breaks, and the incidents themselvesIt is paid in attention, not money
OpportunityWhat those engineers would otherwise shipNobody budgets for it

For the buy side, count usage (credits per call times calls), the integration work (smaller, but not zero), and the cost of the provider being wrong or unavailable, which you handle with the fallback and optional-step patterns from lesson two.

A small model keeps the comparison honest and reruns when the inputs change:

tco.mjs
export function monthlyBuy({ calls, creditsPerCall, pricePerCredit, integrationHours = 0, hourly = 0, lifeMonths = 24 }) {
  return calls * creditsPerCall * pricePerCredit + (integrationHours * hourly) / lifeMonths;
}

export function monthlyBuild({
  buildHours, maintenanceHoursPerMonth, onCallHoursPerMonth, hourly,
  dataPerMonth = 0, infraPerMonth = 0, lifeMonths = 24,
}) {
  const people = (buildHours / lifeMonths + maintenanceHoursPerMonth + onCallHoursPerMonth) * hourly;
  return people + dataPerMonth + infraPerMonth;
}

export function breakEvenCalls(build, { creditsPerCall, pricePerCredit }) {
  return Math.round(monthlyBuild(build) / (creditsPerCall * pricePerCredit));
}

// Illustrative inputs only: take pricePerCredit from your own plan
// (monthly price divided by monthly credits) and hours from your own team.
const build = { buildHours: 120, maintenanceHoursPerMonth: 8, onCallHoursPerMonth: 4, hourly: 90, infraPerMonth: 60 };
const usage = { creditsPerCall: 10, pricePerCredit: 0.00015 };

console.log(Math.round(monthlyBuild(build)));            // 1590
console.log(breakEvenCalls(build, usage).toLocaleString()); // 1,060,000

With those illustrative inputs, owning the capability costs about 1,590 a month before it answers a single call, mostly in people. Buying is cheaper until volume passes roughly a million calls a month. Change the inputs and the line moves; the point of the model is that it makes every assumption explicit and arguable. When someone says "building would be cheaper", ask which input they disagree with.

Two habits keep the model honest. Use loaded hourly cost, not salary: benefits, tooling and management overhead are real. Do not set maintenance to zero. Every capability that consults external data has a refresh job, and every refresh job eventually fails at an inconvenient time.

Check yourself

A team argues that building disposable-email detection is cheaper because the logic is a set lookup that takes a day to write. What is the strongest objection?

Run every example on your own key. Free plan, no card.

Scaling up?

Volume pricing, custom SLAs, and dedicated support for high-traffic teams.

Contact sales