Maintain, risk compounds silently
https://sangtd.net/maintain-risk-compounds-silently/Risk compounds silently. Every day maintenance is deferred, the risk increases. A security vulnerability discovered today might have been patched last month if dependencies had been updated. A bug that causes a production outage might have been fixed in a newer version of the library. The cost of inaction is not static; it grows over time.
A security audit reveals the application is running a version of lodash with a known prototype pollution vulnerability. The Docker base image has not been updated in eight months and contains seventeen CVEs. The security team asks: “When was the last time dependencies were reviewed?” The answer is: unknown. Features have been shipping on top of a foundation that has been silently decaying.
Maintenance is often seen as cleanup work done when there is time. The important work is finished, then the code is cleaned up, dependencies are updated, warnings are fixed. But maintenance is not less important than feature work; it is a different category of work. Feature work adds capability. Maintenance reduces risk. Both are necessary, and neither can be deferred indefinitely without consequences.
Risk accumulates in three dimensions: security vulnerabilities, dependency debt, and technical debt. Each dimension compounds over time, and the cost of addressing them increases exponentially the longer the wait.
Security vulnerabilities are the most urgent. Every dependency used is a potential attack surface. When a vulnerability is discovered in a library, the maintainers release a patch. If automated security scanning is running, notification is immediate. If not, the vulnerability might not be known until an attacker exploits it. The window between disclosure and exploitation is shrinking. Automated security scanning — SAST for code, dependency scanning for libraries, image scanning for containers — is not a luxury; it is a necessity. It converts unknown risk into known risk, and known risk can be managed.
Dependency debt is less urgent but equally dangerous. Every outdated dependency is a missed security patch, a missed bug fix, a missed performance improvement. When dependency updates are deferred, debt accumulates. The longer the wait, the larger the gap between the current version and the latest version. The larger the gap, the more breaking changes must be absorbed when the update finally happens. The update that would have taken an hour six months ago now takes a week because three major versions must be migrated through. This is why tools like Renovate exist. Renovate automatically creates pull requests to update dependencies as soon as new versions are released. The PR is reviewed, the CI runs, the merge happens. The debt never accumulates because it is being paid down continuously.
Technical debt is the slowest to accumulate but the hardest to reverse. Every TODO comment, every workaround, every quick fix is a small piece of debt. Individually, they are harmless. Collectively, they make the codebase harder to understand, harder to modify, harder to test. The cost of adding a new feature increases as technical debt accumulates because navigation around the debt is required. The fix is not a big refactoring project; the fix is continuous small improvements. The TODO is fixed when the file is touched. The workaround is replaced when the problem is better understood. The debt never accumulates because it is being paid down continuously.
The common thread is continuous reduction. Maintenance is not done when there is time; it is done because risk accumulates when it is not. The security vulnerability does not wait for time to be available. The dependency update does not wait for time to be available. The technical debt does not wait for time to be available. They accumulate regardless, and the cost of addressing them increases regardless.
The practical implication is that maintenance should be automated as much as possible. Renovate automates dependency updates. Security scanning automates vulnerability detection. Linters automate code quality checks. The automation does not eliminate the work, but it converts the work from “remember to check” to “review the pull request.” The cognitive load is reduced from “am I up to date?” to “should this PR be merged?”
The trade-off is that automation requires setup and maintenance. Renovate must be configured, security scanning must be set up, linter rules must be configured. This is itself a form of maintenance. But the trade-off is worth it because the alternative is manual maintenance, which is slower, less consistent, and more likely to be skipped when busy.
Maintenance is not optional; it is part of the job. The job is not finished when the feature works; the job is finished when the risk is managed. The risk compounds silently, and the cost of inaction grows every day maintenance is deferred.