Go made a promise to developers. Code that was written today would always compile with newer versions of Go. And so far, they’ve kept that promise.

But for developers of software that is maintained, they’ve also broken that promise. The language can now change, and Go changes its behavior based on the version defined in the go.mod file of a project. So if you don’t want to update your program to follow the new behavior of the language, you can keep your go.mod version aligned with that of your code.

Except developers do not control their go.mod version, not solely. Every dependency they include also controls the version in their go.mod. Every dependency update is a risk that the project is forced to adopt a new release. And that upgrade is recursive through all the dependencies.

So when a low level dependency like golang.org/x forces an upgrade, all projects that use those libraries are now forced to upgrade their go.mod to that release. And that means the behavior of their code is now forced to follow the new language behavior.

So far, those behavior changes have been very popular. But the forced upgrade isn’t always welcome, some projects would prefer to support more versions of Go, and only upgrade when the project adopts a new language feature.

If the go.mod version specified the compiler behavior for a specific project, and wasn’t upgraded for dependencies, this would allow developers to control how their code is interpreted. We already have the inverse scenario, if a dependency declares they should be interpreted with an older syntax, Go will adjust how it parses that project.

But what about security, shouldn’t we be encouraging developers to run the latest patched compiler? The go.mod version is different from the Go compiler version. Which means you can, and often do, use the latest compiler with an older go.mod Go version.

The concern here is for those that do want to patch their application with upgraded dependencies, but do not want to change how their code is parsed. That’s the use case where Go has broken the compatibility promise, and those are the developers we should want to support the most. We do not want to discourage developers from maintaining their dependencies.