The first release is only part of the cost
- 01LaunchCode, migration, training
- 02OperationsSupport and resources
- 03ChangesFeatures and updates
- 04ExitData and replacement
Bauman Moscow State Technical University, where I studied, has a gallery of engineers and inventors. It is a good reminder of the value of original engineering. Building every component from scratch, however, would not be a sign of maturity in a real product. It would be an expensive extreme.
Reuse, compatibility, and adaptation are all valid strategies. The mistake is counting cost only up to the first release and treating a product, a fork, a compatible implementation, and a new design as the same choice.
Four distinct strategies
Adopt an existing product
The team accepts the architecture and roadmap of a vendor or open-source project in exchange for documentation, updates, and an ecosystem. Licensing, support, supply-chain risk, infrastructure fit, and an exit plan become central.
Maintain a fork
The original code remains recognisable, but local changes diverge from upstream — the original project from which the fork was made. A fork can be sensible when the delta is limited, has an owner, and the team can integrate upstream fixes regularly.
Build a compatible implementation
A new product preserves an external protocol, API, or data format. Consumers can migrate with less change, while the implementing team becomes responsible for every observable part of the contract, including edge cases.
Design a new solution
The team chooses a different contract and architecture for its own constraints. The potential benefit is larger, but so are migration cost, ecosystem work, and the chance of rediscovering problems that a mature product already solved.
“Build or buy” is too small a label for these four decisions.
What belongs in TCO
I divide total cost of ownership into five parts:
TCO = launch + operations + change + risk + exit
This is a decision structure, not a promise of accounting precision.
1. Launch
- licensing and procurement;
- development or adaptation;
- data and integration migration;
- infrastructure, testing, and training;
- security and compliance acceptance.
2. Operations
- compute and storage;
- monitoring, backup, and recovery;
- on-call and user support;
- vulnerability and dependency updates;
- reproducible builds and software supply-chain controls.
3. Change
- integrating upstream fixes;
- developing local capabilities;
- supporting new client versions;
- updating connectors, SDKs, and documentation;
- regression and performance testing.
4. Risk
- dependence on a vendor or a few key engineers;
- licensing and derivative-distribution rights;
- delay in security fixes;
- mismatch with the target infrastructure;
- behavioural drift from the original product.
5. Exit
- data export in an open format;
- replacement cost for APIs and integrations;
- time spent running old and new systems in parallel;
- migration capability inside the organisation;
- reversibility of architecture decisions.
Exit is often omitted even though it determines future freedom of choice.
Why fork cost grows quietly
A local patch may be easy to accept. Every later upgrade must answer three questions:
- Does the reason for this patch still exist?
- Did upstream solve the problem another way?
- Does the patch conflict with the product’s new architecture?
Without a local-change register, those answers disappear. A new engineer knows the upstream product but first has to learn the fork. A security patch cannot be merged cleanly. A connector is nominally compatible but fails on local behaviour.
A managed fork therefore needs:
- a named owner and lifecycle;
- a patch register with rationale and tests;
- a regular upstream-sync cadence;
- upstream contributions where a fix is generally useful;
- automated compatibility and regression tests;
- a response target for critical vulnerabilities;
- a plan to keep the local delta small.
Without these practices, the initial saving becomes a hidden maintenance backlog.
Compatibility has a cost as well
A compatible implementation must reproduce more than the happy path. Consumers may depend on field order, error codes, retry behaviour, size limits, or an old undocumented edge case.
“The same API” is therefore a testable requirement. It needs:
- a formal contract;
- reference requests and responses;
- negative-scenario tests;
- versioning rules;
- an explicit list of deliberate differences;
- a migration mode exercised by real consumers.
Compatibility can create substantial business value without being presented as invention.
When a bespoke build is justified
I would consider it when several conditions hold:
- the technology is a core product capability;
- existing options miss a material data, infrastructure, security, or economic constraint;
- the team is prepared to own the solution for years;
- success is defined by a measurable advantage;
- migration and operations are funded, not deferred;
- the first scope is bounded rather than a promise to rebuild an ecosystem.
Starting from a blank page for the feeling of independence is weak reasoning. Sometimes the more independent choice is an open standard, several interchangeable implementations, and in-house capability to operate them safely.
How I present the decision
Instead of “we built our own equivalent,” a more useful statement is:
- we adapted the product and preserved upstream compatibility;
- we maintain a fork with a defined local delta;
- we implemented a compatible contract and exercised consumer migration;
- we designed a new component for a specific constraint;
- we reduced dependency through an open format and an exit plan.
Precision does not diminish the achievement. It shows what the team actually owns and which costs remain after launch.
For me, technological independence is not the percentage of code written internally. It is the ability to operate, secure, evolve, and replace a solution without losing the product.
Originally published on my Telegram channel @it_underside.
Yours, DPUPP
Related Articles
RAG for a company: from document search to a useful assistant
RAG explained from the ground up: indexing, retrieval, small-team and enterprise architectures, published implementations, evaluation, and the path from answers to useful actions.
“Like FAANG,” Without the Cargo Cult: Bring the Context With the Practice
Architecture practices cannot be separated from scale, team structure, and operational maturity. Here is how to spot accidental complexity before adopting them.
EventStorming: Benefits, Limits, and Practice
A practical guide to EventStorming: what the method helps a team discover, where it falls short, and how to prepare a session that produces useful outcomes.