Not Invented Here
Rejecting an external solution and building your own, not because the homegrown version is better but because it’s yours.
Also known as: Reinventing the Wheel, NIH
The phrase names the dismissal: a solution gets waved off because it was “not invented here.” In code, the trap looks like writing your own date library, job queue, or auth flow when a maintained option exists.
Symptoms
- A standard problem (dates, backoff retries, password hashing, email validation) has a hand-rolled implementation.
- The reason is a feeling (“I didn’t trust the library”), not a named requirement the library failed.
- The homegrown version handles the happy path but misses edge cases a mature library already learned.
- Nobody can state what the external option lacked, only that it “wasn’t quite right.”
- An agent writes a utility the standard library or installed package already covers.
- Reviews spend time on bugs a well-known library fixed long ago.
Why It Happens
The honest version is caution. You do not want a dependency you cannot inspect, patch, or trust with security-sensitive work. The trap begins when caution rejects every outside option without comparison.
Several forces feed it. Building is more fun than reading docs. Authorship feels like control. Teams underestimate their own work, so the rebuild looks cheap. A homegrown component really is simpler on day one, before the edge cases arrive.
Agents make the reflex faster. Ask a model for a function and the cheapest path is to generate one. It does not feel dependency cost, weigh community support, or check whether the project already solved the problem. It writes a bespoke CSV parser, custom retry loop, or hand-rolled slug generator because nobody told it to look first.
Learning is the honest exception. Rebuilding a known tool to understand it can be worthwhile. Shipping that exercise as production infrastructure is a different decision.
The Harm
The cost arrives later as maintenance you own alone.
A maintained library carries fixes for cases you have not hit. Leap seconds, malformed input, the timezone that changed its rules in 2016, and the encoding that breaks on one customer’s data are already in its history. Your rebuilt version starts at zero and relearns those lessons through incidents. You did not avoid a dependency. You became its maintainer without the community, test suite, or bug reports that made the original trustworthy.
The bill compounds. Every rebuilt component must be understood, tested, secured, and carried forward. Security-sensitive rebuilds, such as crypto, auth, or input sanitizers, are the most dangerous. The gap between “passes our tests” and “withstands attack” is the gap a mature library spent years closing.
Agents multiply the harm by volume. One bespoke utility is rarely a disaster. A hundred small reinventions become a codebase that solves the same solved problems a dozen incompatible ways.
The Way Out
Make the choice deliberate. Not Invented Here is a decision you fell into; the cure is to make it out loud, against real alternatives.
Run the build-versus-buy call explicitly. Before building something a library already does, apply Build-vs-Don’t-Build Judgment. Name what the external option lacks, name the lifetime cost of building, and decide on that comparison. If you cannot name a concrete gap, that is your answer.
Name the real tradeoff. A homegrown component is not free; it is a tradeoff you are choosing to own. Weigh the library’s costs (control, inspectability, updates) against the rebuild’s costs (edge cases, maintenance, security surface). The trade is sometimes worth it. Make it visible.
Let “boring” win for solved problems. Date math, retries, hashing, parsing, and serialization are solved. Reach for the maintained option first. Save your building energy for the part no library could anticipate because it is specific to your product.
Keep learning exercises out of the production path. Time-box them, label them, and do not let them become the maintained implementation by accident.
Tell the agent to look before it builds. Agents reinvent by default, so change the default. Ask the agent to check standard libraries and installed dependencies first, and to justify any new common utility. “Prefer existing libraries for common functionality; explain why if you write your own” catches most machine-speed wheel-reinvention before review.
When an agent hands you a custom slugifier, deep-clone, or email validator, ask: “what library already does this?” You have context the agent lacks.
How It Plays Out
A backend team needs retries for a flaky payment API. A library offers exponential backoff with jitter, circuit breaking, and configurable limits. The lead was burned by an abandoned dependency once, so the team writes its own retry loop. It works in testing. Three months later it retries a non-idempotent charge during an outage and double-bills customers. The homegrown loop never learned the distinction encoded in the library’s defaults.
An agent is asked to turn article titles into URL slugs. Instead of using the project’s slug utility, it generates a regex. The new function handles ASCII but mangles accented characters and emoji, producing two slugs for titles the existing utility would have matched. A reviewer sees two slug functions. There is no reason. The agent wrote the shortest code it could see.
A platform team distrusts an open-source feature-flag service and builds its own. Then they need percentage rollouts, per-tenant overrides, and an audit log of flag changes, each a feature the rejected service shipped on day one. The team has rebuilt the product it declined to adopt, except with fewer tests and one maintainer. When that maintainer leaves, the flag system becomes organizational debt nobody chose.
Related Articles
Sources
The phrase Not Invented Here predates software; it described the resistance of research and engineering organizations to adopting ideas developed elsewhere, and was studied in management literature on organizational behavior and innovation, notably Ralph Katz and Thomas J. Allen’s work on R&D team performance in the early 1980s.
William J. Brown, Raphael C. Malveau, Thomas J. Mowbray, and Hays W. “Skip” McCormick III’s AntiPatterns (Wiley, 1998) catalogs Reinventing the Wheel among the recurring development antipatterns, framing it as the cost of teams solving already-solved problems in isolation.