It’s practically a protection racket. Only AWS gets the money.
Also, that’s a bit dismissive for HN.
But let me offer a different perspective: Hyrum’s law is neither a technical contract nor a social contract. It’s an emergent technical property in a sufficiently used system.
How you respond to that emergent property depends on the social context.
If you are a FOSS maintainer, and an optimization speeds up 99.99% of users and requires 0.01% to either fix their code or upgrade to a new API, you ship it.
If you are working at a big tech company, you need both the optimization and breaking 0% of the company. So you will work across teams to find the sweet spot.
If you are an enterprise software company, and you change breaks 0.1% if users, but that user is one of the top 5 contracts, you don’t ship.
This is also a sufficient description of "social contract" for this context.
DOS didn't have any precision clocks either as far as I know (it seems that there's interrupt 1A but it only updates 18 times a second, which is an eternity). Apparently there's 8254 based timer code after a few PC generations.
Windows 95 came up with QueryPerformanceCounter() and that simplified life quite a bit.
Maybe not intentionally.
But there have been several times where I've seen bugs where two tasks are done concurrently, but task A always takes longer than task B, then someone makes A faster, and that exposes some race condition or deadlock that only occurs if A completes before B.
In short, I wouldn't consider emergent behaviours of a machine as part of an intentional interface or any kind of contract and therefore I wouldn't see it as a breaking change, the same as fixing a subtle bug in a function wouldn't be seen as a breaking change even if someone depended on the unintentional behaviour.
I think it's more of a testament to Go's hardcore commitment to backwards compatibility, in this case, than anything else.
Nobody is rewriting `==` to compare strings in constant time, not because it breaks some kind of API contract, but because it would result in a massive waste of CPU time. The point is, though, that they could. But then they are deciding to sacrifice performance for this one problem.
Crypto is obviously a case of it own when it comes to optimisations and as much as I called out the parent for approaching the absurd, we can pull out many similar special cases of our own.
But there are still informal limits. If the performance impact is bad enough, (say, 5x slower, or changing a linear algorithm to quadratic), it’s probably going to be reverted anyway. We just don‘t have any practical way of formalizing rough performance guarantees at an API boundary.
Even worse, it's possible to select a new algorithm that improves the best-case and average-case runtimes while degrading the worst-case runtime, so no matter what you do it will punish some users and reward others.
Well yeah, that's pretty much the textbook example of Hyrum's Law (or some funnier variation like "I was relying on the heat from the CPU to warm my bedroom, can you please revert your change that improved CPU performance").
I agree with your point, but that's poor example because you can't rely on function's speed reliably and easily.
Timing differs between hw, OS, OS updates, whatever.
Meanwhile it is trivial and easy to rely on error messages.
Therefore it's unavoidable that what constitutes a "breaking change" is a social contract, not a technical contract, because the alternative is that literally nothing is ever allowed to change. So as a library author, document what parts of your API are guaranteed not to change, be reasonable, and have empathy for your users. And as a library consumer, understand that making undocumented interfaces into load-bearing constructs is done at your own risk, and have empathy for the library authors.