The 42 Principles · Principle XXV
Every Dependency Has a Price
Capability, coupling, concentration risk, external reliance, and understanding what every dependency can cost.
Foundational Truth
No dependency is free.
Every library.
Every framework.
Every API.
Every cloud service.
Every package.
Every vendor.
Every plugin.
Every integration.
Every database.
Every certificate.
Every external system.
Each one promises new capability.
Each one also introduces new responsibility.
That responsibility may not be visible on the day the dependency is added.
It arrives later.
During upgrades.
During outages.
During security reviews.
During deployments.
During incident response.
Every dependency you introduce becomes another component you must understand, monitor, patch, document, test, secure, and eventually replace.
Functionality is only half of the transaction.
Maintenance is the other half.
Every dependency adds value today. It also creates an obligation tomorrow.
Newton's Third Law of Software
Newton observed that every action has an equal and opposite reaction.
Software architecture often behaves the same way.
Every dependency you add creates an opposing force.
You gain capability.
You lose independence.
You gain speed of development.
You increase operational complexity.
You reduce the amount of code you must write.
You increase the amount of code someone else controls.
You gain features.
You inherit release schedules.
You gain convenience.
You inherit another potential point of failure.
The question is never whether a dependency has a cost.
The question is whether its long-term value exceeds that cost.
The Hidden Invoice
When engineers evaluate a dependency, they often focus on the obvious benefits.
How quickly can it solve today's problem?
How many features does it provide?
How much code will it save us from writing?
Those are important questions.
They are not sufficient.
Every dependency also creates an invisible invoice.
Someone must:
Read the documentation.
Understand its behavior.
Monitor security advisories.
Upgrade versions.
Test compatibility.
Review licensing.
Handle breaking changes.
Update deployment pipelines.
Troubleshoot failures.
Document its purpose.
Train future engineers.
Eventually replace it.
None of that work disappears simply because someone else wrote the software.
The responsibility merely changes hands.
Dependencies Multiply
One dependency rarely remains alone.
That library depends on another.
That framework requires a runtime.
That runtime requires a supported operating system.
That operating system depends upon updated drivers.
That cloud service requires authentication.
Authentication requires certificates.
Certificates require renewal.
Renewal requires monitoring.
Monitoring requires alerting.
Alerting requires ownership.
The dependency graph grows.
Soon, a single feature relies upon dozens of interconnected systems.
Most engineers never intended to build that complexity.
It emerged one convenient decision at a time.
That is why architectural discipline matters.
Small decisions compound.
Ask Before You Add
Before introducing any dependency, ask:
- What problem does this solve?
- Is the problem significant enough to justify another dependency?
- Can we accomplish the same goal with what we already have?
- Who will maintain this five years from now?
- How often is it updated?
- What happens if the vendor disappears?
- What happens if the API changes?
- What happens if the license changes?
- Can we remove it later?
- Is the long-term value greater than the long-term cost?
If those questions cannot be answered confidently, the dependency deserves another look.
Sometimes the right architectural decision is not to add another component.
Sometimes the better decision is to simplify.
Deliberate Architecture
Good engineers do not avoid dependencies.
Modern software would be impossible without them.
Good engineers choose dependencies deliberately.
They understand the value being purchased.
They understand the responsibility being accepted.
Every dependency is an investment.
Some generate extraordinary returns.
Others become technical debt before the first release.
The difference is rarely the technology.
It is the discipline of evaluating the full cost before accepting it.
Closing Thought
Every dependency is a promise.
A promise that someone will maintain it.
A promise that someone will understand it.
A promise that someone will respond when it fails.
Choose those promises carefully.
Every dependency has a price. Make sure you're buying more value than you're inheriting in responsibility.
The Architecture You Don't Own
One of the greatest misconceptions in software engineering is believing that using someone else's code means someone else owns the problem.
They don't.
You do.
The moment you add a dependency to your application, it becomes part of your architecture.
Your users will never know—or care—which company wrote the library.
They won't distinguish between your code and someone else's.
If the application fails, they won't blame the package author.
They will blame your system.
That responsibility cannot be outsourced.
Ownership follows integration.
Every Dependency Creates Operational Work
When a dependency is first introduced, the conversation usually revolves around features.
"This library already solves that problem."
"This API saves us months of development."
"This framework has everything we need."
Those statements may all be true.
What is discussed far less often is everything that happens after the dependency is installed.
Someone must monitor security advisories.
Someone must review new releases.
Someone must test compatibility before every upgrade.
Someone must update deployment pipelines.
Someone must document configuration changes.
Someone must respond when the dependency behaves differently after an update.
Someone must explain why yesterday's deployment worked and today's no longer does.
That "someone" is almost always your team.
The dependency reduced development effort.
It increased operational responsibility.
Vendor Risk Is Still Your Risk
Cloud services have transformed engineering.
Managed databases.
Hosted authentication.
Object storage.
AI services.
Monitoring platforms.
Payment gateways.
The list continues to grow.
Each one offers tremendous value.
Each one also introduces another organization into your critical path.
If their authentication platform becomes unavailable...
Your users cannot sign in.
If their DNS service fails...
Your application may become unreachable.
If their payment processor experiences an outage...
Your business may stop accepting orders.
If their API changes...
Your deployment may fail.
The outage belongs to the vendor.
The business impact belongs to you.
That is why vendor evaluation is never just a feature comparison.
It is an exercise in risk management.
The Cost of Convenience
Convenience is one of the easiest ways to accumulate technical debt.
A developer discovers an open-source package that solves today's problem.
Installation takes minutes.
Writing the equivalent functionality would have taken days.
The decision seems obvious.
Sometimes it is.
Sometimes it is not.
The convenience lasts for one afternoon.
The maintenance may last for ten years.
Every dependency should therefore answer a simple question:
Will this continue creating more value than it costs to own?
That answer may change over time.
Dependencies should be reviewed periodically, not assumed permanent.
Build Versus Buy
One of the oldest engineering questions remains one of the most important.
Should we build it?
Or should we buy it?
There is no universal answer.
Building provides control.
Buying provides speed.
Building requires expertise.
Buying requires trust.
Building creates maintenance.
Buying creates dependency.
The decision should never be based solely on initial effort.
It should consider the entire lifecycle.
How often will the capability change?
How critical is it to the business?
Can we survive if the vendor disappears?
How difficult would it be to migrate away?
What happens if pricing changes dramatically?
What happens if licensing terms change?
Architecture is not only about choosing technology.
It is about choosing commitments.
Design for Replacement
Every dependency should have an exit strategy.
Not because it will certainly fail.
Because someday circumstances will change.
The vendor may discontinue the product.
The API may become obsolete.
The company may be acquired.
Security concerns may emerge.
Licensing may become incompatible.
Your own requirements may evolve.
The easiest dependency to replace is the one designed for replacement from the beginning.
Loose coupling.
Clear interfaces.
Well-defined boundaries.
Those decisions create freedom later.
Tightly coupled dependencies create expensive migrations.
A Dependency Budget
Organizations often manage financial budgets carefully.
Dependency budgets deserve similar attention.
Every new library.
Every new SaaS platform.
Every new vendor.
Every new integration.
Every new framework.
Should consume part of a deliberately managed budget.
Not a financial budget.
An operational budget.
How much additional complexity can this system reasonably support?
At what point does another dependency create more operational cost than engineering value?
That question rarely appears in project planning.
It should.
Closing Thought
The best architects are not those who use the most technology.
They are those who understand which technology is truly worth owning.
Every dependency is a long-term relationship.
Choose it with the same care you would choose someone responsible for your own work.
Good architecture is not measured by how much you can add. It is measured by how little you must depend upon to achieve the same result.
Dependencies Exist Beyond Software
Software engineers are not the only people who manage dependencies.
Families depend upon trust.
Businesses depend upon customers.
Hospitals depend upon electricity.
Airlines depend upon weather, fuel, and maintenance.
Communities depend upon volunteers.
Every meaningful system depends upon something outside itself.
The lesson is universal.
Dependencies are not inherently bad.
They simply require stewardship.
Every dependency creates both capability and responsibility.
Independence Is Rare
Complete independence is usually impossible.
No company manufactures every component it uses.
No engineer writes every line of code.
No organization owns every piece of infrastructure.
The goal is therefore not independence.
The goal is intentional dependence.
Choose relationships that strengthen the whole.
Understand the obligations they create.
Avoid collecting dependencies simply because they are available.
Simplicity Is a Strategic Advantage
Every unnecessary dependency competes for attention.
It requires documentation.
Training.
Monitoring.
Upgrades.
Support.
Eventually, retirement.
A simpler system is often easier to understand, easier to secure, easier to recover, and easier to teach.
Simplicity is not the absence of capability.
It is the absence of unnecessary obligation.
The Dependency Test
Before accepting any dependency, ask:
- Does it solve an important problem?
- Is the value durable or temporary?
- What new responsibilities will it create?
- Who will own it after the original engineer leaves?
- Can the system continue if it disappears?
- Would I choose it again five years from now?
If the answers are uncertain, the dependency deserves another review.
In Practice
- Prefer proven solutions over fashionable ones.
- Remove obsolete dependencies regularly.
- Review third-party libraries and vendors as part of architecture reviews.
- Keep clear ownership for every dependency.
- Design interfaces that make replacement possible.
Closing Thought
The strongest systems are not those with the most integrations.
They are those whose dependencies are understood, deliberate, and worth their cost.
Choose dependencies as carefully as you choose commitments. Both become part of your future.
Founder's Commentary
Convenience Is Easy. Ownership Is Hard.
Early in my career, I loved discovering a new library that promised to solve a difficult problem.
It felt like finding a shortcut.
Sometimes it was.
Sometimes it became a decade-long commitment disguised as a five-minute installation.
That lesson took years to appreciate.
Every dependency enters the project with excitement.
Nobody schedules a meeting to celebrate maintaining it five years later.
But someone will.
Someone will patch it.
Someone will explain it.
Someone will troubleshoot it during an outage.
Someone will answer for it when a vulnerability is published on a Friday afternoon.
If the dependency is part of your application, it becomes part of your reputation.
Over time I stopped asking, "Can this solve my problem?"
I started asking, "Do I want to own everything that comes with this solution?"
That simple change has influenced almost every architectural decision I've made since.
Some dependencies have earned their place many times over.
Others delivered a week of convenience followed by years of maintenance.
Experience has taught me that architecture is less about accumulating technology than it is about protecting the future from unnecessary obligations.
The best engineers I have worked with were not impressed by the number of tools they could assemble.
They were impressed by the number of problems they could solve with the fewest moving parts.
There is wisdom in restraint.
Not every feature deserves another framework.
Not every challenge deserves another vendor.
Not every convenience deserves another lifetime commitment.
When I inherit a system today, I no longer count the features first.
I count the dependencies.
That number usually tells me far more about the future than the feature list ever will.
Good architecture is measured not only by what it enables today, but by what it asks future engineers to carry tomorrow.
Related Principles
Continue the idea.
These Principles share themes with Principle XXV.
Principle XXII
Complexity Is a Cost
Technical, operational, cognitive, and human costs created by unnecessary complexity.
Read Principle XXII →Principle XXIII
Design for Failure
Resilience, graceful failure, recovery, preparation, visibility, and accepting failure as a design constraint.
Read Principle XXIII →Principle XIX
Reliability Is Respect
Reliability as respect for people's time, work, trust, livelihoods, and dependence on what we build.
Read Principle XIX →Principle XXXVII
Solve Real Problems
Prioritization, scope, user needs, problem selection, opportunity cost, and refusing to optimize what does not matter.
Read Principle XXXVII →