The cargo cult of versioning
&quot;We&#x27;re all on the internet, and we&#x27;re all constantly running npm install or equivalent.&quot;<p>This is not at all accurate, at least in my work. I use version pinning to be resilient to changes in the greater internet: builds don&#x27;t use the internet, and instead use internally pinned and vendored sources for third party libraries.<p>If you rely upon the internet to build and deploy your code, then someone <i>else&#x27;s</i> outage (like github&#x27;s) can become <i>your</i> outage, or make yours worse. If you work on a product which has high uptime requirements, this is unacceptable.<p>Just as important, suppose any <i>one</i> of those dependencies breaks the social contract described in the posted article: they make a backwards-incompatible change, and your code no longer compiles or builds or (much worse!) subtly breaks. Now you&#x27;re relying very strongly upon the good intentions and competency of all third party maintainers.<p>Worst of all, suppose any of your dependencies gets compromised and now has a security vulnerability. What do you do?<p>This is not a nitpick; I think it&#x27;s central. Because I need network-free, reproducible builds of known-good code, I need to maintain a copy of third-party code somewhere. When I start doing that, I need to keep track of what version (which could be a commit, sure) I&#x27;m storing to know when I&#x27;m out of date. Then, when my cached copy is out of date, I need to know how safe it is to update to match the remote version: should I expect builds to break, or not?<p>Semantic versioning is a way for package maintainers to signal their expectations. It&#x27;s not something you can rely completely on - in these systems I&#x27;m describing, you still need automated tests to give you more confidence that upgrading is safe. But semantic versioning improves your confidence which helps avoid wasting work on an upgrade that will <i>certainly</i> fail, and helps identify problems in advance.<p>It&#x27;s also helpful to have minor and patch versions so applications can concisely describe which features of third-party dependencies are required to build and run your code. This makes it easier to integrate new applications - you can clearly see whether your cached copy of the third-party code is up-to-date enough.