[HN Gopher] Hyrum's Law
       ___________________________________________________________________
        
       Hyrum's Law
        
       Author : andsoitis
       Score  : 85 points
       Date   : 2025-08-01 14:58 UTC (8 hours ago)
        
 (HTM) web link (www.hyrumslaw.com)
 (TXT) w3m dump (www.hyrumslaw.com)
        
       | azhenley wrote:
       | Discussion last year:
       | https://news.ycombinator.com/item?id=39401973
        
         | dang wrote:
         | Thanks! Macroexpanded:
         | 
         |  _Hyrum's Law in Golang_ -
         | https://news.ycombinator.com/item?id=42201892 - Nov 2024 (183
         | comments)
         | 
         |  _Hash Ordering and Hyrum 's Law_ -
         | https://news.ycombinator.com/item?id=41673295 - Sept 2024 (41
         | comments)
         | 
         |  _Hyrum 's Law_ - https://news.ycombinator.com/item?id=39401973
         | - Feb 2024 (66 comments)
         | 
         |  _Git archive generation meets Hyrum 's law_ -
         | https://news.ycombinator.com/item?id=34631275 - Feb 2023 (76
         | comments)
         | 
         |  _Hyrum 's Law_ - https://news.ycombinator.com/item?id=33283849
         | - Oct 2022 (52 comments)
         | 
         |  _Hyrum 's Law_ - https://news.ycombinator.com/item?id=29848295
         | - Jan 2022 (36 comments)
         | 
         |  _Hyrum 's Law_ - https://news.ycombinator.com/item?id=27386818
         | - June 2021 (5 comments)
         | 
         |  _Hyrum 's Law: An Observation on Software Engineering_ -
         | https://news.ycombinator.com/item?id=21515225 - Nov 2019 (6
         | comments)
         | 
         |  _Hyrum 's Law_ - https://news.ycombinator.com/item?id=19249199
         | - Feb 2019 (1 comment)
        
       | AdamH12113 wrote:
       | From an API designer's standpoint (especially if that API has
       | paying customers), Hyrum's Law is something that has to be taken
       | into account. But from a user's standpoint, it is engineering
       | malpractice, plain and simple. At the very least, relying on
       | quirks of someone else's implementation is a risk that should be
       | understood and accounted for, and no one has any _reasonable_
       | grounds for complaint if those quirks suddenly change in a new
       | version.
        
         | kccqzy wrote:
         | Malpractice? It's usually just plain old bugs unintentionally
         | written that way.
        
         | breppp wrote:
         | Depends on the product. Sometimes you are completely dependent
         | on an API ecosystem (iOS, Android, Windows) where the only way
         | to achieve something is a quirk
        
         | Ygg2 wrote:
         | > But from a user's standpoint
         | 
         | Not true generally. One man's engineering malpractice is
         | another man's clever hack.
         | 
         | Users of Windows 95 complained that Windows 95 broke SimCity.
         | 
         | What did Windows 95 break? It fixed an obscure allocator bug
         | SimCity was relying on.
         | 
         | Users loved Windows 95, for ""fixing"" this. How was it fixed?
         | By introducing an obscure switch to old allocator if it
         | detected SimCity in the app name.
         | 
         | https://arstechnica.com/gadgets/2022/10/windows-95-went-the-...
        
           | bigstrat2003 wrote:
           | Different users. The users that GP was accusing of
           | malpractice would be the Maxis devs in this case, not the end
           | users who were trying to install SimCity on their Windows 95
           | machine.
           | 
           | Microsoft has a commitment to backwards compatibility that I
           | think is going too far, but I understand why. Raymond Chen
           | has explained that if a user buys the new version of Windows
           | and their programs stop working, they will blame MS
           | regardless because they don't have any way to know it's the
           | program's fault. So MS is incentivized to go out of their way
           | to enable these other programs' bad behavior, because it
           | keeps their (Microsoft's) customers happy.
        
         | patrickmay wrote:
         | Exactly. Hyrum's Law should always be paired with Postel's Law:
         | Be conservative in what you do, be liberal in what you accept
         | from others.
        
           | chuckadams wrote:
           | Being liberal in what you accept also leads to users
           | depending on you accepting marginal input that exploits
           | implementation quirks, either because the quirks get the job
           | done or for more nefarious reasons.
        
             | bigstrat2003 wrote:
             | Yeah, I definitely don't agree with the "be liberal in what
             | you accept" paradigm. It's worth it to force users to send
             | correctly-formed data, IMO.
        
         | don-code wrote:
         | I don't think such usage is malicious, so much as ignorant -
         | it's sometimes hard to know that a behavior _isn't_ part of the
         | API, especially if the API is poorly documented to begin with.
         | 
         | I maintain a number of such poorly-documented systems (you
         | could, loosely, call them "APIs") for internal customers. We've
         | had a number of scenarios where we've found a bug, flagged it
         | as a breaking change (which it is), said "there's _no way_
         | anybody's depending on that behavior", only to have one or two
         | teams reach out and say yes, they are in fact depending on that
         | behavior.
         | 
         | For that reason, we end up shipping many of those types of
         | changes ship with a "bug flag". The default is to use the
         | correct behavior; the flag changes the behavior to remain
         | buggy, to keep the internal teams happy. It's then up to us to
         | drive the users to change their ways, which.. doesn't always
         | happen efficiently, let's say.
        
         | twodave wrote:
         | Hard disagree. If my users are exploiting some unintended,
         | unannounced part of my API then me patching that out is
         | something they're just going to have to deal with. In well-
         | described systems these sorts of behaviors lead to nasty bugs
         | down the line, sometimes months in the future (e.g. "Huh, why
         | aren't my tax reports tying out?").
        
           | partdavid wrote:
           | I think you're agreeing with GP, not disagreeing.
        
             | twodave wrote:
             | I was disagreeing with the notion that this law has to be
             | taken into account. I suppose that's true for certain
             | software, but if e.g. Apple can get away with breaking
             | these use cases then I don't see why, as an API designer, I
             | should care either.
        
               | bryanrasmussen wrote:
               | I think this really depends on who your customers are and
               | how they pay for your services.
        
         | RyanCavanaugh wrote:
         | The problem is that people commonly don't even realize they're
         | depending on implementation quirks.
         | 
         | For example, they write code that unintentionally depends on
         | some distantly-invoked async tasks resolving in a certain
         | order, and then the library implementation changes performance
         | characteristics and the other order happens instead, and it
         | creates a new bug in the application.
        
         | throw0101c wrote:
         | > _From an API designer 's standpoint (especially if that API
         | has paying customers), Hyrum's Law is something that has to be
         | taken into account._
         | 
         | How good-of-an-idea / best practice is API versioning?
         | /api/v1/foo         /api/v2/foo
         | 
         | What are the pluses and minuses?
        
           | detaro wrote:
           | you end up with a lot of versions if you version everything
           | that could change some non-guaranteed behavior in some corner
           | case.
        
           | ad_hockey wrote:
           | A couple of considerations are:
           | 
           | - You have to decide whether to bump the entire API version
           | or only the /foo endpoint. The former can be a big deal (and
           | you don't want to do it often), the latter is messy.
           | Especially if you end up with some endpoints on /v1 (you got
           | it right first time) while others are on /v4 or /v5. Some
           | clients like to hard-code the URL prefix of your API,
           | including the version, as a constant.
           | 
           | - You still have to decide what your deprecation and removal
           | policy will be. Does there come a time when you remove
           | /api/v1/foo completely, breaking even the clients who are
           | using it correctly, or will you support it forever?
           | 
           | It's not easy at all, especially if you have to comply with a
           | backwards compatibility policy. I've had many debates about
           | whether it's OK to introduce breaking changes if we consider
           | them to be bug fixes. It depends on factors like whether
           | either behaviour is documented and subjective calls on how
           | "obviously unintended" the behaviour might be.
        
           | cogman10 wrote:
           | Plus, easy to see that you might have to do something
           | different to move over to v2 as client.
           | 
           | Minus, You will support v1 forever. It's almost impossible to
           | make it go away.
        
         | gwd wrote:
         | > At the very least, relying on quirks of someone else's
         | implementation is a risk that should be understood and
         | accounted for, and no one has any reasonable grounds for
         | complaint if those quirks suddenly change in a new version.
         | 
         | It's almost always unintentional. Someone wrote some code, it
         | works, they ship it, not realizing it only works if the list
         | comes back in a specific order, or with a specific timing. Then
         | a year or two later they do some updates, the list comes back
         | in a different order, or something is faster or slower, and
         | suddenly what worked before doesn't work.
         | 
         | This is why in Golang, for instance, when you iterate over map
         | keys, it purposely does it in a random order -- to make sure
         | that your program doesn't accidentally begin to rely on the
         | internal implementation of the hash function.
         | 
         | ETA: But of course, that's not _truly_ random, just
         | _pseudorandom_. It 's not impossible that someone's code only
         | works because of the particular pseudorandom order they're
         | generating, and that if Golang even _changes the pseudorandom
         | number generator they 're using to evade Hyrum's Law_ that
         | someone's code will break.
        
           | RyanCavanaugh wrote:
           | There's probably at least one game out there somewhere that
           | uses Go's map iteration order to shuffle a deck of cards, and
           | would thus be broken by Go removing the thing that's supposed
           | to prevent you from depending on implementation details.
        
           | deathanatos wrote:
           | Intent enters into it when someone complains about something
           | that is obviously out of the specification breaking.
           | 
           | Prior that, yeah, that's just a bug.
           | 
           | > _This is why in Golang, for instance, when you iterate over
           | map keys, it purposely does it in a random order_
           | 
           | It could be that Go's intentions are different here, but IIRC
           | languages will mix randomization into hashtables as it is
           | otherwise a security issue. (You typically know the hash
           | function, usually, so without randomization you can force
           | hash collisions & turn O(1) lookups into O(n).)
        
             | CobrastanJorji wrote:
             | A counterexample would be Python, where dictionaries
             | maintain their insertion order.
        
               | deathanatos wrote:
               | Python does the same hash randomization, but yes, it
               | _also_ maintains the insertion order. This is more
               | expensive, obviously, as additional data has to be
               | tracked.
        
             | porridgeraisin wrote:
             | > mix randomisation into hash tables.
             | 
             | I believe you don't understand.
             | 
             | In go, they literally randomly permute the iteration order
             | of the map each time you iterate over it.
             | 
             | e.g                 for x in map {              }
             | for x in map {        // different order       }
             | 
             | Now, the fact that they randomize means people use it as a
             | cheap "select random item from map" function :D, which is
             | hyrums law all over again.                 var randomUser
             | User       for userId, user in usersMap {
             | randomUser = user         break       }
             | 
             | Funny isn't it.
        
               | deathanatos wrote:
               | Well ... it seems like you're right. (A playground --
               | https://go.dev/play/p/OHQTIuDWicd -- if anyone is
               | curious.)
               | 
               | That's ... pretty surprising, since that would seem to
               | imply that iteration would require a O(n) sized chunk of
               | memory somewhere to reify the order into. (And probably
               | O(n) time to do the shuffle, or at least, a copy of the
               | ordering; we should shuffle as we go, I suppose, but we'd
               | need to track what we've emitted & what we've not, hence
               | O(n) time & space to populate that scratch...) That seems
               | undesirable.
        
       | nvader wrote:
       | It seems to me that there's some advantages to undertaking
       | "Freedom of Navigation Operations" by randomizing implementations
       | from time to time to discourage any dependence on internal
       | behaviors.
       | 
       | For instance, traversal order of maps in Go is always randomized,
       | to prevent subtle bugs caused by depending on the order.
       | 
       | As AI generated code becomes cheaper, it may be worthwhile to
       | change some subset of your internal behaviors from release to
       | release, so that users don't become too complacent.
        
       | avidiax wrote:
       | There's a corollary:                  Even if you explicitly deny
       | a guarantee of a certain behavior in your contract,        if you
       | usually deliver that behavior,        most of your customers will
       | depend on it.
       | 
       | Some examples:
       | 
       | If you make a queueing system, it's impossible to guarantee
       | anything other than delivery "at most once" (some loss occurs),
       | or "at least once" (some duplication occurs), but if you usually
       | provide "exactly once" in practice, most of your customers will
       | depend on this.
       | 
       | If you provide a data bucket service, and guarantee availability,
       | but not performance, and you usually provide 100MB/s throughput,
       | your customers will have major problems if you only provide
       | 10MB/s throughput in some cases.
       | 
       | If you make a self-driving car, and it requires human monitoring,
       | but it's really good, say one intervention per year of driving .
       | . . your customers will die because they aren't paying attention.
        
         | dongkyun wrote:
         | This is explicitly recognized in contract law: course of
         | performance / dealing is a factor courts will consider in
         | evaluating the nature of a deal. (Most contracts will try and
         | carve it out).
        
         | chuckadams wrote:
         | Can't disagree with anything you said, though I think there are
         | steps to address at least some of them: for queueing systems,
         | testing with a chaos monkey isn't a bad idea... you'd want a
         | test environment representative of production workloads, which
         | is hard to do, but anything should be better than nothing.
         | 
         | In the self-driving car scenario, you'd probably go with cold
         | statistics: is it killing fewer people than ones that need more
         | interventions? Just like queueing though, experiments in
         | production could be problematic.
        
           | worik wrote:
           | > In the self-driving car scenario, you'd probably go with
           | cold statistics
           | 
           | No. There is a big difference in an accident caused by human
           | error and an accident caused by machine failure.
           | 
           | We tolerate much more of the former than the latter.
           | 
           | This feels like a cognitive failure, but I do not think it is
        
         | weinzierl wrote:
         | "Die normative Kraft des Faktischen" or "the normative force of
         | the factual" is a thing and usually not seen as necessarily
         | bad.
         | 
         | It recognizes that legitimacy often emerges organically from
         | social acceptance rather than top-down imposition. In
         | technology we often see that evolving reference implementations
         | work better than elaborate specifications.
        
           | leoc wrote:
           | In its form as 'the normalisation of deviance' it's generally
           | recognised as bad.
        
         | Animats wrote:
         | > If you make a queueing system, it's impossible to guarantee
         | anything other than delivery "at most once" (some loss occurs),
         | or "at least once" (some duplication occurs), but if you
         | usually provide "exactly once" in practice, most of your
         | customers will depend on this.
         | 
         | That's only a condition at termination. For ongoing
         | communication, you can guarantee exactly once delivery. When
         | communication ceases, the final state between the ends is
         | indeterminate. If you can keep talking, or resume after breaks,
         | it's a solvable problem.
        
         | doormatt wrote:
         | We ran into this at SNS (AWS) all the time.
        
         | rossant wrote:
         | If I'm not mistaken, CPython's dict preserved insertion order
         | as an implementation detail at first, but because too many
         | users came to rely on it, it was made part of the language
         | specification starting in Python 3.7.
        
       | TehCorwiz wrote:
       | XKCD always has a relevant comic: https://xkcd.com/1172/
        
         | xatax wrote:
         | That's linked in the OP.
        
       | amelius wrote:
       | This is why an API should always have an
       | "assertions": true
       | 
       | option. Why should normal function calls have assertion/invariant
       | checks, and not API calls?
        
         | porridgeraisin wrote:
         | This idea looks good. Have you used it in practice? Can you
         | share how?
        
           | amelius wrote:
           | Yes, you basically use the option whenever you have
           | assertions turned on in your code.
           | 
           | Then the service running the API will do extra checking when
           | the assertions option is true, basically making it less
           | forgiving and following the specification closely.
        
       | prats226 wrote:
       | This is super interesting to think about in LLM world where lot
       | of software is getting replaced with LLM calls.
       | 
       | In terms of output of an LLM, there is no clear promise in the
       | contract, only observable behaviour. Also the observable
       | behaviour is subject to change with every update in LLM. So all
       | the downstream systems have to have evals to counter this.
       | 
       | One good example is claude code where now people have started
       | complaining them switching models effecting their downstream
       | coding workflows.
        
         | worik wrote:
         | Yes.
         | 
         | This is the unfortunate thing about wrapping LLMs in API calls
         | to provide services.
         | 
         | Unless you control the model absolutely (even then?) you can
         | prompt the model with a well manicured prompt on Tuesday and
         | get an answer - a block of text - and on Thursday, using the
         | exact same prompt, get a different answer.
         | 
         | This is very hard to build good APIs around. If done expect
         | rare corner case errors that cannot be fixed.
         | 
         | Or reproduced.
        
       | fsmv wrote:
       | A good example of defence against this is go maps randomize
       | iteration order just so that people don't rely on it being
       | consistent.
        
       | kiitos wrote:
       | > if an interface has enough consumers, they will collectively
       | depend on every aspect of the implementation ...
       | 
       | Yep!
       | 
       | > [and that] constrains changes to the implementation, which must
       | now conform to both the explicitly documented interface, as well
       | as the implicit interface captured by usage
       | 
       | Nope!
       | 
       | Software authors define the rules for the software that they
       | author. I understand it's a spectrum and the rules are different
       | in different circumstances but at the end of the day my API is
       | what I say it is and if you rely on something that I don't
       | guarantee that's on you and not me. Hyrum's Law describes a
       | common pathology, it doesn't define an expected rule or
       | requirement.
        
       | cafard wrote:
       | Actually, I think that in _The Mythical Man-Month_ Brooks
       | mentioned users depending on nominally undefined, practically
       | consistent behavior, e.g. what was left in some part of a
       | register.
        
       ___________________________________________________________________
       (page generated 2025-08-01 23:00 UTC)