Versioning is a complex and opinionated topic. Over the years, we’ve gotten great feedback from our users about our releases. We realize that while making frequent releases helps our users get access to new features and bug fixes, these can also introduce unpredictable breaking changes. We want to avoid a situation where our developers are faced with a broken application after upgrades because we didn’t communicate the lack of backward compatibility in advance. Our ultimate goal is to achieve a continuous delivery model where users can benefit from a seamless upgrade experience.
However, it is hard to achieve that with typical Semantic Versioning. Even a small API breaking change requires a major version increase, while a very large feature affecting the way data is laid out on disk (but containing no API changes), would be considered a minor release. It goes to say that in over 4 years of Dgraph, there has only been one major release, which doesn’t do justice to all the work that has gone into the system. At the same time, our upcoming v2.0 release has led to a rush of cramming in all possible breaking changes to avoid another major version release within a few months, which delays the release process and makes it hard to do testing.
Instead of slowing down and complicating our releases, we decided to put a versioning system in place that is flexible but has a rigorous and predictable schedule. When looking for a solution, we researched how other databases are tackling this challenging task. We found that traditional databases (Postgres and MySQL) are using Semantic Versioning, while newer ones (MongoDB, CockroachDB) are using an even/odd versioning model and Calendar Versioning. We thought of adding that research in our post to provide a broader context to our users and to the general audience interested in understanding versioning schemes.
A bit of Market Research
Postgres: A major version is indicated by increasing the first part of the version, e.g. 10 to 11. Minor releases are numbered by increasing the last part of the version number, e.g. 10.0 to 10.1. PostgreSQL releases a new major version containing new features about once a year. Minor releases containing bug fixes are at least every 3 months, with exceptions for security fixes. End of Life Policy is 5 years. Major versions usually change the internal format of system tables and data files. Backward compatibility of all stored data is not maintained in major releases. Reference
MySQL: Release names consist of three numbers and an optional suffix; for example, mysql-5.7.1-m1. The first number (5) is the major version number. The second number (7) is the minor version number. Taken together, the major and minor numbers constitute the release series number. The series number describes the stable feature set. The third number (1) is the version number within the release series. This is incremented for each new bugfix release. The absence of a suffix indicates a General Availability (GA) or Production release. The overall goal is to produce a new GA release every 18 to 24 months. Reference
MongoDB: MongoDB versioning has the form X.Y.Z where X.Y refers to either a release series or development series and Z refers to the revision/patch number. If Y is even, X.Y refers to a release series and is stable and suitable for production. If Y is odd, X.Y refers to a development series and is for testing only and not for production. End of Life Policy can be between 2-4 years, but it is not consistent between all releases. Changes in the release series (e.g. 4.0 to 4.2) generally mark the introduction of new features that may break backward compatibility. Changes to the revision number (e.g. 4.0.11 to 4.0.12) generally mark the release of bug fixes and backward-compatible changes. Reference
Ubuntu: Ubuntu isn’t a database, but an operating system that most Dgraph team members use. We really liked how easy it is to correlate the version number of Ubuntu with when it was released and its end of life policy. Ubuntu uses Calendar Versioning.
Releases of Ubuntu get a development codename and are versioned by the year and month of delivery - for example, Ubuntu 19.10 was released in October 2019. LTS or ‘Long Term Support’ releases are published every two years in April. Every six months between LTS versions, Canonical publishes an interim release of Ubuntu. These are production-quality releases and are supported for 9 months, with sufficient time provided for users to update, but these releases do not receive the long-term commitment of LTS releases. Reference
CockroachDB: As of February 2019, CockroachDB has switched from Semantic Versioning to Calendar Versioning. Reference
Introducing Calendar Versioning
After our research and a lot of internal discussions, we concluded that a date-based approach will be the most suitable solution. Starting with the next release, Dgraph releases are going to be based on Calendar Versioning or CalVer. That means Dgraph will be released at a regular, pre-determined cadence (3 times a year). Each release would be considered a major release. This system is flexible because we will not hold our release for new features that are not completely ready yet. It is also predictable because by looking at a release version, a user can judge when it was released and when it would reach its end of life. As mentioned above, this versioning scheme is quite inspired by Ubuntu.
The shift to Calendar Versioning and adopting regulated End Of Life policy will reflect the rapid progress we are making and will also manage our internal problem of maintaining too many released versions. Starting in March, our release scheme will be YY.0M.PatchNumber for major releases and YY.0M.0-beta.MMDD for beta releases of a future release.
Versioning SchemeYY: Short year which indicates which year the release was made GA.
0M: Zero padded month indicating the month that the release was made GA. We will have major releases every four months: (March, July, November) or (03, 07, 11). These releases will have bug fixes and new features with the possibility of breaking changes. We will provide scripts and tools to make upgrades easier between these versions.
PatchNumber: Patch releases are focused on bug fixes and are backward compatible. If a bug fix has a breaking change it will not be released until the next major release but will be available as a beta.
Beta Releases: Beta releases are available before the GA and are cut from the release branch, which will be in sync with the master branch. Their naming scheme contains the release the beta is destined for (YY.0M.0-betaMMDD), and the date that the beta was made available (YY.0M.0-beta.MMDD). Before GA we will have a period of code freeze on the release branch and then we will make the release GA. This is done to make sure we are releasing a high quality and stable product. After the release is GA, every new feature will then go to the next release branch. It is up to the Dgraph team to decide when to do a beta release, we will aim to do a beta release every time we are ready with a new feature.
End of Life PolicyWe will support the release series for one year and security patches for 18 months. For example, release series (20.03.x) will be supported until March 2021 with security patches until September 2021.
Versioning for Dgraph LibrariesIt is our intention to keep things as simple as possible. In March, we are going to sync all of our user-facing libraries with the Dgraph release version. So, along with March Dgraph release, we will also release all clients (dgo, dgraph4j, …) with the same release number as Dgraph. For releases after March, we will release any client that has a breaking change and will sync its release number with Dgraph. So at any given time, the client’s release number will be in sync with the earliest compatible Dgraph version.
Example: We will have our first CalVer release in March. The version for the March GA release: 20.03.0. Later we will release a patch with bug fixes and no breaking changes as 20.03.1. Let’s say it is June 15th and we are ready with a new feature or a bug fix that has breaking changes. Since it is not July yet, we will release a beta from the release branch as 20.07.0-beta.Jun15. On the July release date, we will make the July GA release 20.07.0. In March, all client versions would be set to 20.03.0. If the July release only breaks a particular client, we will only release that client. If the Dgraph version 20.07.0 has client API changes, then the client library version will be 20.07.0. Any client libraries not affected will remain as 20.03.0, indicating they are compatible with both March and July releases.
For client-versioning, there’s a special exception for the Go client. dgo versions would include an extra digit in the YY number to allow for breaking changes within the year. In a hypothetical scenario, they could be called v200.03.0, v201.07.0, v202.11.0 if there are multiple breaking API changes within the year. This versioning scheme still correlates to Dgraph versions, yet supports Go Modules which mandates using Semantic Versioning.
Conclusion
We hope this versioning scheme is clear and makes sense to all our users. This scheme makes it much easier for us to ensure that we keep releasing Dgraph regularly, while also communicating to our users about client/server compatibility, our maintenance policy and when it is time to upgrade.
Let us know if you have any questions or comments!
Top image: Microgravity - U.S. Marned Spacecraft Launch Vehicle Size Comparison
This is a companion discussion topic for the original entry at https://blog.dgraph.io/post/dgraph-calendar-versioning/