Engineering notes / Decisions & systems
When Should You Buy Instead of Build?
There is a tempting response to an expensive software quote: “We can build this ourselves.” An engineer looks at the product, recognises the components and starts working out an implementation. The price now feels harder to justify.

There is a tempting response to an expensive software quote: “We can build this ourselves.” An engineer looks at the product, recognises the components and starts working out an implementation. The price now feels harder to justify.
I understand the appeal. Building gives us control, a problem to solve and something we can take pride in. But before we turn that instinct into a project, I think we owe the business a harder question: would this still be a good decision if we weren’t excited to build it?
01 / The first version makes a convincing argument
Consider a reporting tool. A few charts, a database connection, filters and an export button. A capable team can see how to put it together. Depending on the requirement, a small custom tool may be all we need.
Then the tool starts being used. One department should not see another department’s data. A report needs to arrive every Monday. An export fails halfway through. Two people get different numbers and want to know which is correct.
The work has changed. We now need permissions, scheduling, failure handling and consistent definitions. Each request makes sense. Together, they can turn a small feature into a product that someone has to keep running.
Authentication offers a similar temptation. A login screen is visible. Account recovery, session revocation, abuse handling and changes to access requirements are less visible in the initial estimate. We can build these too. The question is how much of our capacity we want to commit to them.
I wouldn’t use these examples to argue that every internal tool must grow into a large platform. Many stay small and useful. But “we only need a few features” has to remain a constraint we can enforce, rather than a promise made before anyone starts using the system.
That is why I am wary of comparing a vendor’s price with the effort required for our first version. We need to compare the product we would actually buy with the system we would actually have to support. Sometimes that comparison favours building. We should make it before treating the saving as real.
02 / Control comes with someone’s name attached
One reason to build is control. We can change the code, choose the architecture and avoid waiting for a vendor’s roadmap. That can be valuable. But how much of that control can the organisation actually use?
If only one engineer understands the system, a change still has to wait for that person. If the team is occupied with customer work, an internal feature still sits in a queue. Owning the source code gives us options; it doesn’t automatically give us the capacity to act on them.
An internal dependency can be just as awkward as an external one. The difference is that we often recognise vendor dependency during procurement, while dependence on a particular engineer becomes obvious only when they are unavailable.
Running PostgreSQL ourselves makes this concrete. This is a choice about operating a database, rather than building one, but the responsibility question is similar. A lower infrastructure bill is useful. It also means someone has to own monitoring, patching, backups and recovery.
A backup job succeeding does not tell us how quickly we can restore service. If recovery matters, someone needs to test it and keep the process usable as the system changes. The ability to run a database and the ability to recover it under pressure are different requirements.
A managed service may take over some of that work. It still needs configuration, oversight and a clear understanding of what remains our responsibility. Paying a vendor does not excuse us from understanding the system.
So the useful comparison is specific: what work would each option leave with our team, and can we reliably do it? For a small workload with acceptable downtime, self-hosting may be sensible. For stricter recovery requirements, the service premium may be easier to justify.
This raises an uncomfortable budget question. Engineers already being on the payroll does not make their time free. Building may add little immediate cash expense, but it still uses capacity. We should be able to name the work that will be delayed, rather than assume maintenance will fit around everything else.
03 / Wanting to build is a reason to examine the decision
Learning is a valid reason to build. So is developing expertise the organisation needs. I don’t think every experiment needs an immediate commercial return. But we should be honest about what we are funding.
If a project is mainly an opportunity to learn, give it an experiment budget, a time limit and an owner. Calling it a cost-saving initiative makes it harder to judge fairly, especially when the learning takes longer than expected.
The harder case is a project we genuinely believe the business needs, but which also happens to be much more interesting than the work already waiting in the backlog.
Imagine a team building a flexible workflow engine while customers are waiting for better onboarding and more reliable reports. The engine might eventually help both. But that future benefit needs to justify the delay now. “We can reuse this later” is a possibility to test, not enough on its own.
Would we approve the same project if another team proposed it and we had to pay for the work? Would we still support it if we were responsible for maintenance but someone else got to design it? Those questions can help separate the value of the system from our interest in creating it.
That doesn’t make enthusiasm a problem. Good engineering needs people who care about the work. It means enthusiasm should be accompanied by evidence, particularly when the decision commits other people’s time.
There are strong reasons to build. A customer experience may depend on behaviour existing products cannot support. A vendor’s restrictions may prevent us from delivering something valuable. At sufficient usage, recurring fees may justify the cost of an internal alternative.
In those cases, I would make the argument concrete: which limitation matters, who is affected, and what would improving it be worth? I would also check whether we need to own the whole system or only the part that makes a difference.
A distinctive reporting experience, for example, doesn’t necessarily require a custom warehouse, scheduler and identity system. We can concentrate our engineering effort on how customers understand and act on the data.
The reverse also deserves scrutiny. An integrated data platform may promise to reduce the effort of assembling separate tools. If we still need extensive integration and technical support for every business user, that work belongs alongside the licence fee in our comparison.
A vendor can also change pricing, withdraw a feature or make an exit expensive. We should know what data we can export, which behaviours depend on the product and what we would have to rebuild.
I don’t think buying is automatically the mature answer any more than building is. Both choices need to explain their ongoing cost. Neither should win because one feels more impressive or the other sounds safer in a meeting.
04 / We may be deciding too early
Sometimes the biggest uncertainty is whether people will use the capability at all. We can spend weeks debating which implementation is better before establishing whether the outcome is worth investing in.
Suppose we want to introduce a new reporting feature. An existing product could help us learn which reports customers use, what they find missing and whether the feature changes their willingness to pay. That evidence could justify an internal build, reshape it or save us from one.
This is where I would rent uncertainty: pay for a limited way to learn before taking on a long-term engineering commitment.
There is a cost to doing this. Integration work may be thrown away. Customers may get used to a vendor-specific feature. Moving later may be harder than we expect. The initial choice should account for those risks, with a practical way to retrieve data and a commitment proportionate to the experiment.
I would define what we need to learn and when we will review the result. Otherwise, renting can become permanent through inertia, just as an experimental internal tool can become critical without anyone budgeting for its support.
Before committing to a build, I would also ask whether the case still works if maintaining it takes two good engineers. That is a thought experiment, not a universal staffing estimate. It exposes a plan that depends on ongoing work being negligible.
For a purchased service, I would test the equivalent assumption: does it still make sense when usage grows and our integration costs are included? A low entry price deserves the same scrutiny as an optimistic development estimate.
The answer can change. We might buy while learning, build when a specific limitation becomes valuable to remove, or return to a service when operating our own system stops making sense. Each transition has a cost, so the option to change should be assessed rather than assumed.
I would put the conditions for reconsidering in the original decision: a usage level, a recovery requirement, an unacceptable product limitation or a measurable amount of support effort. That gives us something better than arguing from our attachment to the choice we already made.
For me, this is the discipline behind build versus buy. We should be willing to explain what we gain, what we take responsibility for and what we give up. Then revisit the answer when those facts change.
I would still build where the case is strong. But I would want it to survive an honest comparison with buying, including the parts of ownership that are less enjoyable than writing the first version.
Before asking whether we can build it, we should be able to explain why it deserves our team’s time.