Last year saw multiple changes for the Scala 3 world. In May 2023, Scala 3.3.0 was released as the first Long-Term Support (LTS) version in Scala's history. In autumn, we revised how we work on Scala 3 and designed a new Scala Organization that coordinates work between diverse teams. The first quarter of 2024 saw the inception of the new organization and the beginning of work for the Scala 3 Product Manager. Finally, we recently released Scala 3.4.0 - the first Scala Next release.
This is a good time for a short reiteration of our goals and a retrospective of the entire LTS project.
What does all that mean?
Scala 3, since its inception, has had rock-solid compatibility guarantees. Once the library is compiled and released on Maven Central or any other repository, it can be used by other projects forever. All the future releases of the compiler will be able to read library artifacts. You can use it as a dependency in your project, the only requirement being that your compiler is at least as new as the one the library was compiled with. This is an enormous improvement over Scala 2, where every non-patch release of the compiler constituted a new, separate ecosystem that required cross-publishing and often migration of all libraries.
While it was a massive step in the right direction, it had a drawback. There was no clear answer to the question of which version of Scala 3 should be used for libraries. The answer was simple for projects not intended to be used as external dependencies: always use the newest version. Library authors, however, may have been tempted to use the oldest possible version of Scala, so they were not forcing any of their users to upgrade the compiler version. On the other hand, older Scala versions are no longer supported by the compiler team and do not receive any patches and bug fixes.
Long Term Support versions are our solution. To implement that, we have conceived a plan of splitting Scala versions into the LTS and Next lines.
Scala LTS
Scala LTS was planned as the preferred target version for libraries. It doesn’t change anything about our binary compatibility guarantees. You can still use a library if it was published with the same minor version (x in 3.x.y) or lower than the one you use. Why is it the preferred target version, then? There are two main reasons: extended support and source compatibility guarantees.
Any other minor Scala version receives patches with bug fixes and small usability improvements only until the release of the next minor version. For example, Scala 3.1 will forever remain on the 3.1.3 patch, and all later fixes were available only in Scala 3.2.0 and later versions. The LTS line is unique due to the extended support. Each LTS line receives patches with bug fixes and usability improvements ported from the newer versions. Those patches are guaranteed until at least a year after the release of the next LTS line. Moreover, we ensure that there will be no new LTS line for at least two years after the first release of the current LTS line. This means guaranteed patch releases for a period longer than three years after the initial release.
Scala Next
Scala Next was introduced with the recently released Scala 3.4. It is the default line that is actively developed by the compiler team. Do not be confused; there is nothing experimental or unstable about Scala Next. We keep all the compatibility guarantees and maintenance practices that have been well-established since Scala 3.0.0.
Every significant new feature requires a two-phase approval from the Scala Improvement Committee: first after the design phase and second after the experimentation and initial user feedback. We also keep track of all potential source-compatibility breakages using the Open Community Build. The only difference is that with Scala Next, we prioritize speed of delivery over full source compatibility.
This means that while there won’t be any significant intended incompatibilities, small changes in type inference resulting from fixing bugs may occur. If the incompatibility is minor and the result of a newly introduced bug, we will prioritize fixing it before the next release candidate, but we will usually not delay the release. Most users will never experience any source compatibility breakages if they stay on stable Scala Next releases.
How things went
This plan was designed, discussed, and approved in the middle of 2022. In May 2023, we had the first release of Scala LTS. In February 2024, Scala 3.4 – the first Scala Next release – was announced. Now, the plan is in full swing. We can take a retrospective look and say what we would have done differently now.
What went right
The first thing that is definitely a success is that we now have clear recommendations for users, such as what versions of the language they should use. There is no longer a need to get into the details of the compatibility guarantees, which some users may find unintuitive. Library authors should use the newest patch of Scala LTS. Projects not intended to be an external dependency should use the newest Scala. If the library author wants to use features introduced only in Scala Next in some part of their library, they can move this part of the library to a separate module compiled with a newer version of Scala while the remainder stays on LTS.
We can also be proud to maintain source compatibility. Every open-source Scala project with a version published on Maven Central and source code available on GitHub was tested, and every single one that passes compilation on 3.3.1 also compiles on 3.3.3. Furthermore, during that time, only a single regression was detected by closed-source projects. The regression already has a fix, which is planned to be released in 3.3.4.
The popularity of newer versions of Scala also speaks volumes about the success of our plan. If we look at the download statistics for Scala for March 2024, only around 10% of users are still on versions older than 3.3.0. The users trust the compiler team and updated to Scala 3.3 at a faster pace than used to happen on minor releases in the past.
What we would have done differently today
If we were implementing the LTS process again, having learned everything we have learned since we would probably not have developed 3.3.1 during the release candidate phase of 3.3.0. Since Scala 3.0.0, developing the next version when the current version is in its RC testing phase has been standard practice. We are still doing it for Scala Next. However, there were six release candidates for Scala 3.3.0, and the RC testing period was uncharacteristically long. This allowed for a few regressions to slip in.
There were mainly edge cases, but a few projects stopped passing compilations when the only change was updating from Scala 3.3.0 to 3.3.1. In later versions, we fixed some of those regressions, but we cannot guarantee to provide fixes for all of them that will be both 3.3.1 and 3.3.0-compatible. We know that this situation will not occur again in the future because subsequent LTS patches are prepared by only backporting changes that are beforehand carefully checked for any source incompatibilities using Open Community Build.
If we could turn back time, we would have released 3.3.1 as 3.4.0 and later prepared 3.3.1 through backporting selected changes.
What will the future bring?
We will continue our commitment to both Scala LTS and Scala Next lines. There are currently no plans to release a new LTS line, and it is unlikely to happen in 2025 or even 2026. We will keep focusing on backporting selected changes to the 3.3.x line.
Scala Next will continue to deliver significant improvements to the language. Scala 3.5 is now in development, with the first release candidate scheduled for the second week of May. It will integrate Scala CLI as a default Scala runner and bring pipelined compilation. The following versions will implement Proposals recently approved by the Scala Improvement Process, among them better desugaring of for-comprehension, syntactical enhancements for context bounds, and named tuples.
There is a lot to look forward to.