Badger v2.0.0 and Go modules

After a little bit over a year since the last release of Badger, we decided it was time to cut a new release and announce v2.0.0.

This new release includes a bunch of changes, some of them changed the API in backward-incompatible ways, although the data model has remained compatible. Dgraph 1.0.x and other open source projects depend on these changes, so tagging them is necessary for their stability.

At the same time, and following our community’s needs, we are also adding support to use Badger with Go modules. This document explains the subtle interactions and possible inconsistencies of these two changes.

Badger v2.0.0 from a publisher’s point of view

Once v2.0.0 is released, all projects that depend on badger have two options:

use badger without Go Modules: importing it as github.com/dgraph-io/badger as before and managing the dependencies as they did previously (most probably some flavor of vendoring)

use badger as a Go Module: will require to import the package as github.com/dgraph-io/badger/v2 everywhere in their code as otherwise the Go Modules requirements documented [here](Modules · golang/go Wiki · GitHub) will not be met.

From the Go Wiki on Go Modules:

As a result of Semantic Import Versioning, code opting in to Go modulesmust comply with these rules: Follow semver . (An example VCS tag is v1.2.3 ).

). If the module is version v2 or higher, the major version of the modulemustbe included as a /vN at the end of the module paths used in go.mod files (e.g., module github.com/my/mod/v2 , require github.com/my/mod/v2 v2.0.0 ) and in the package import path (e.g.,import " github.com/my/mod/v2/mypkg" ).

at the end of the module paths used in files (e.g., , require ) and in the package import path (e.g.,import " ). If the module is version v0 or v1, do not include the major version in either the module path or the import path.

It is important to note that the constraint on having to import the package with an appended v2 only applies to the code using Go Modules, and it is not a requirement imposed by Badger but rather the Go community and their agreed specification for how Go modules work.

For those not using Go Modules, whether Badger supports Go modules or not has no impact on their build system or code.

This drives me to argue that supporting Go modules on Badger is the right choice. For those using Go Modules, it might cause a change in import path - but that change is due to their decision of using Go Modules rather than our decision to support them.

That sounds good, but actually …

All of the above is correct for modules which do not contain multiple packages which are imported from the module itself. For those, unfortunately, Go Modules require changing the import path used.

So for instance, since github.com/dgraph-io/badger depends on github.com/dgraph-io/badger/table files like db.go will need to update their import path of the table package to indicate they’re using v2 , so the import path would now read "github.com/dgraph-io/badger/v2/table .

Once we introduce this constraint, supporting Go Modules while releasing a v2 version all of a sudden impacts all of our users (including ourselves) in a way that seems unacceptable.

Adopting Go Modules on Badger does force a change in all of our clients. The semantic versioning requirements on the import paths make Go Modules an infectious change which forces all our clients to migrate to them just so they can benefit from our latest release.

Before writing the sentence above, I did spend one hour trying to figure out whether the replace directive could be used to avoid the import path rewrite on the Badger repo. Unfortunately, while it makes Badger compile with Go modules without having to rewrite any import paths, the effect of the replace directive is limited to the module containing it, so when a client using Go modules imports v2 all the import paths will somehow be broken.

If you have any ideas on how to fix this situation, please let me know.

But I want to use Badger’s v2 with Go Modules!

That’s still possible, simply add this line to your go.mod .

require github.com/campoy/gomodtest v2.0.0+incompatible

Badger v2.0.0 from a user’s point of view

Badger is an important project to Dgraph Labs, but it is still just a supporting piece of our main project Dgraph the graph database. As such, we need to be careful with how the different changes the community requests from Badger impact Dgraph too. Go modules is not an exception.

Dgraph is currently keeping all dependencies vendored inside of its own repository and managed by govendor. This can be kept this way, which would allow us to start benefiting from v2.0.0 without having to modify a single line of our code as no import paths need changing.

Since Dgraph is a project mostly distributed as a binary rather than a library, adoption Go modules is not a priority. But if we ever decide to go through that migration, the import path to Badger will have to be updated - but this will also be the case to every single post-v2 dependency supporting Go modules.

Conclusion

Adopting Go Modules forces a rather annoying import path change for dependencies with version 2 or higher. This is unfortunate and something that would be forced onto projects that depend on Badger regardless on their interest on adopting Go modules.

Supporting Go Modules on Badger seems therefore like a change with possibly heavy consequences on our clients and without clear benefits. I’d argue it is better not to support Go modules at this point on Badger.