Getting Started & Versions

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

This page is written against Scala 3.10.0 (released 2026-10-12) and every program on it was run with Scala CLI 1.17.1 on JDK 26 on macOS, checked on 2026-10-15. It explains what Scala is for, what makes the language what it is, why the Scala 3 line exists, and how the release lines fit together, so that the choice of a version in the rest of the section is not a mystery. The next pages are Installing Scala and Hello World & @main Methods. The landing page, Scala, places this page in the section.

Every example in this section uses one small scenario, trailhead, a toolkit that plans hikes on a network of mountain trails. This page only needs its smallest pieces: a Trail and a Difficulty.

What Scala is used for

Scala is a statically typed language that fuses object-oriented and functional programming. The name comes from "scalable": the same language is meant to serve a ten-line script and a large service. It runs on the JVM, in the browser and on Node.js through Scala.js, and as native code through Scala Native. In practice the language shows up in a few recurring jobs:

Use What it looks like in practice

Backend services

HTTP and messaging services on the JVM, from small microservices to large systems, using the Java ecosystem directly plus Scala libraries; see Web Servers with Cask and the ecosystem page for the frameworks built on Scala

Data engineering

big-data and streaming jobs, most visibly Apache Spark, which is written in Scala and exposes a Scala API; the collections vocabulary (map, filter, groupBy) in Collection Operations transfers almost unchanged

Compilers and tools

parsers, interpreters, static analysers and build tools; algebraic data types and pattern matching (see Enums and Pattern Matching) make syntax trees pleasant to write. The Scala 3 compiler is itself written in Scala

Front ends and cross-platform code

Scala.js compiles Scala to JavaScript, so shared domain code can run in the browser and on the server; see Scala.js & Scala Native

Scripts and small tools

single-file programs run with Scala CLI, with dependencies declared in the file; see Scala CLI and the Scala Toolkit pages starting at Files & Processes with OS-Lib

High-level features

The official Scala 3 Book describes the language from "30,000 feet" with a short list of statements. Each one is a design decision with a consequence for the code you write, so it is worth reading them as a set.

Feature What it means

High-level language

no pointers or manual memory management, and with lambdas and higher-order functions you describe what you want rather than how to loop for it

Concise, readable syntax

type inference removes most annotations on locals; traits, classes and methods have a light syntax, and since Scala 3 indentation can replace braces (see Optional Braces & Indentation)

Statically typed, but feels dynamic

every expression has a type checked at compile time, yet inference, union types and anonymous functions keep the code free of ceremony

Expressive type system

generics with variance and bounds, union and intersection types, opaque types, match types and more; see Generics & Bounds and Union & Intersection Types

Functional programming

functions are values, data is immutable by convention, and case classes with pattern matching model algebraic data

Object-oriented programming

every value is an object, behaviour is organised in classes and traits, and traits give mixin composition instead of multiple inheritance of state

FP and OOP fused

functions for the logic and objects for the modularity; the standard library’s List is a class built from small traits (Iterable, Seq, LinearSeq) and also offers dozens of higher-order methods

Contextual abstractions

one family of features (given, using, extension methods, context functions) expresses the intent that Scala 2 encoded with a single mechanism, implicits; see Contextual Abstractions Overview

Runs on the JVM (and in the browser)

compiled classes run on any JVM, the same code can target JavaScript and native code

Java interoperability

Scala calls Java libraries directly and Java can call Scala; see Using Java from Scala

The following program shows several of those features in a dozen lines: an enum with a case that carries a value, a case class, an extension method, a higher-order pipeline and a pattern match. Every construct has a page of its own later in the section.

//> using scala 3.10.0

enum Difficulty:
  case Easy, Moderate, Hard
  case Alpine(grade: Int)

case class Trail(name: String, km: Double, ascent: Int, difficulty: Difficulty)

extension (t: Trail)
  def hours: Double = t.km / 4 + t.ascent / 600.0

@main def taste(): Unit =
  val trails = List(
    Trail("Valle Verde", 6.5, 200, Difficulty.Easy),
    Trail("Pico Norte", 11.0, 1200, Difficulty.Alpine(2)),
    Trail("Lago Azul", 8.0, 450, Difficulty.Moderate)
  )
  val long = trails.filter(_.hours > 3).map(_.name)
  println(long)
  trails.foreach: t =>
    val label = t.difficulty match
      case Difficulty.Alpine(g) => s"alpine grade $g"
      case other                => other.toString.toLowerCase
    println(f"${t.name}%-12s $label")

Saved as Taste.scala and started with scala run Taste.scala, it prints:

List(Pico Norte)
Valle Verde  easy
Pico Norte   alpine grade 2
Lago Azul    moderate

The walking-time formula is a simplified Naismith’s rule (4 km/h plus one hour per 600 m of ascent), enough for the scenario. Source: Scala 3 Book: Scala Features.

Compared with Java, the same program needs no getters, no equals/hashCode/toString boilerplate (the case class generates them) and no visitor to branch on the kind of difficulty. Compared with Kotlin, which has data classes, when and extension functions, the shape is similar; Scala’s differences are the richer type system, given/using for type-class style code and one language that spans functional and object-oriented styles without leaning on either.

Why Scala 3

Scala 3 (first released as 3.0.0 in 2021) is a major revision of the compiler and the language, not a new language. The Scala 3 Book lists ten reasons to use Scala and Scala 3 in particular:

  • FP and OOP are fused in one language.

  • The language is statically typed but often feels dynamically typed, more so in Scala 3 with union types.

  • The syntax is concise but readable.

  • Implicits, a defining feature of Scala 2, were improved and simplified in Scala 3.

  • Scala integrates seamlessly with Java, so mixed projects and the existing Java libraries are available.

  • Scala runs on the server and, through Scala.js, in the browser.

  • The standard library has dozens of ready-made functional methods that remove most hand-written loops.

  • Good practice is built in: immutability, anonymous functions, higher-order functions, pattern matching and classes that cannot be extended by default (in Scala 3 a class must be marked open to be extended outside its file, see Inheritance: Abstract, Sealed, Open & Final).

  • The ecosystem offers modern functional libraries.

  • The type system is strong.

On top of that list, the official "New in Scala 3" page groups the changes into a more principled type system (with better inference and overload resolution), a quieter syntax, and contextual abstractions that express intent (using, given, extension methods, Conversion, context functions) instead of a single mechanism, implicits. The table later on this page links each of them to the page that explains it.

Versions and release lines

Scala 3 publishes two kinds of release line, described in the 2022 compatibility plans of the Scala team:

Scala Next

receives regular minor releases (3.4, 3.5, …​) with new language features, tooling work and library changes. This is the default for applications. At the time of writing it is 3.10.0.

Scala LTS

receives patch releases focused on bug fixes, diagnostics and carefully selected quality-of-life changes, under the compatibility guarantees of the line. It is the recommended target for libraries and conservative production users. The current LTS is 3.9.0 (3 September 2026); the previous one is 3.3.x, latest 3.3.8 (10 June 2026).

The figure shows how the lines overlap.

Timeline from 2023 to 2027 of the Scala 3.3 LTS line, Scala Next 3.4 to 3.8, the 3.9 LTS line and Scala Next 3.10, with the minimum JDK of each line

The compatibility rules that make this model work are worth knowing, because they decide which compiler version a project can use:

  • Scala 3 guarantees backward output compatibility between all releases, and forward compatibility between patch releases of one minor line. A project compiled with a later minor release cannot be consumed by an earlier one: as the 3.9 announcement puts it, artifacts built with Scala 3.9 cannot be consumed by Scala 3.3 projects, so moving a library from 3.3 LTS to 3.9 LTS is a minor-version publishing decision.

  • Treat the compiler version as any other dependency: bumping a patch is a no-brainer, bumping a minor deserves the same care as any dependency minor, and you should not cross-compile between Scala 3 versions.

  • The 3.10 release is the first of the new Scala Next series. It stabilizes SIP-67, moves three SIPs behind -preview and starts removing legacy features that were deprecated for several minor releases (for example A with B for intersection types is now an error). Cross-compilation between Scala 2 and Scala 3.10 is no longer supported, so libraries that cross-build for Scala 2.13 stay on 3.9 LTS. Binary compatibility is preserved: libraries compiled with earlier Scala 3 versions keep working on 3.10.

Line Latest release at the check date Minimum JDK Remarks

Scala 3.10 (Scala Next)

3.10.0, 12 October 2026

17

first Scala Next after 3.9 LTS; removes legacy syntax; .deb and .rpm packages

Scala 3.9 (LTS)

3.9.0, 3 September 2026

17

the recommended baseline for library authors; stabilizes SIP-71 (into)

Scala 3.8

3.8.4 (3.8.0 was announced on 22 January 2026)

17

standard library compiled with Scala 3; avoid 3.8.0, which had a runtime regression fixed in 3.8.1

Scala 3.7

3.7.4

8

stabilizes named tuples (SIP-58)

Scala 3.3 (previous LTS)

3.3.8, 10 June 2026

8

kept JDK 8 compatible bytecode; maintained for one year after 3.9.0

Scala 2.13

2.13.18, 24 November 2025

8

the Scala 2 line still in wide use; see the Scala 2 note below

Scala 2.12

2.12.21, 11 December 2025

8

maintenance for sbt plugins and older code

A few releases in the table deserve a note:

  • 3.6.0 and 3.6.1 must never be used. An accident during the 3.6.0 release candidate published artifacts versioned as 3.6.0 to the immutable Maven repository; 3.6.1 was a hotfix to stop tools from picking the broken version, and 3.6.2 (10 December 2024) is effectively "3.6.0".

  • 3.8.0 had a runtime regression that could cause JVM linkage errors; the official advice is to use 3.8.1 or later.

  • 3.3 LTS to 3.9 LTS is not a patch bump. 3.9 is a new LTS baseline that also includes everything from 3.4 to 3.8, and libraries built with it cannot be consumed by 3.3 projects. Choose 3.3 only while consumers are stuck on it.

The JDK floor

Scala 3.3 LTS through 3.7 support JDK 8 and above. Starting with Scala 3.8 the minimum is JDK 17, and the 3.9 LTS and 3.10 lines keep that floor. The Scala team required it to support JDK 26 and later, which restrict the sun.misc.Unsafe functionality that the old lazy-val implementation used. The 3.3 LTS line still produces JDK 8 bytecode, and the 3.3.8 release added a -Yfuture-lazy-vals flag that activates the new lazy-val implementation for users who need to keep older JVMs but want to be safe on newer ones (it requires JDK 9 or later).

JDK 17, 21 and 25 are all good choices both for compiling and for running Scala code. The official compatibility table lists the minimum Scala versions per JDK: for JDK 25 that is 3.3.7, 3.7.1 or 3.9.0 depending on the line, for JDK 26 it is 3.3.8, 3.8.0 or 3.9.0, and for JDK 27 the table lists 3.10.0 and marks it as forthcoming. The details and the sbt and Scala CLI minimum versions are in Versions, Compatibility & JDKs.

Scala 2.13 and 2.12

Scala 2 is still maintained: 2.13 is the line most Scala 2 projects are on, and 2.12 remains for older code and sbt plugins. Scala 3 can use libraries built for 2.13 (in sbt, .cross(CrossVersion.for3Use2_13) selects such a dependency), which is how the Scala 3 ecosystem was bootstrapped. Details are in Scala 2 & Scala 3 Compatibility and Migrating from Scala 2. For new code, choose Scala 3.

Checking the version on your machine

The scala command of the 3.10.0 distribution is Scala CLI, which runs programs with the Scala version you select. The program below prints the Scala library version it was compiled against and the Java specification version it runs on, which are the two numbers to check when something is not as expected.

//> using scala 3.10.0

@main def versions(): Unit =
  println(s"Scala library: ${scala.util.Properties.versionNumberString}")
  println(s"Java runtime : ${System.getProperty("java.specification.version")}")
$ scala -version
Scala code runner version: 1.17.1
Scala version (default): 3.10.0
$ scala run Versions.scala
Scala library: 3.10.0
Java runtime : 26

The //> using scala line pins the compiler for this file. To follow the current LTS line instead, use //> using scala lts (or 3.lts, or 3.9.lts), which Scala CLI 1.17.1 resolved to 3.9.0 at the check date; //> using scala 3.3.lts selects the newest release of the previous 3.3 LTS line. Installation options are in Installing Scala. Source: Scala download page and JDK Compatibility: Scala 3.

New in Scala 3

The table lists the major additions with the release in which each became stable (or its current status) and the page that covers it. "On 3.9 LTS" says whether the feature can be used without -preview or -language:experimental flags on the LTS line; features newer than 3.3 LTS are marked with their release throughout the section.

Feature Stable in On 3.9 LTS Page

Optional braces and indentation syntax, new control syntax, creator applications (new optional), top-level definitions

3.0

yes

Optional Braces & Indentation, Packages, Imports & Top-Level Definitions

@main methods

3.0

yes

Hello World & @main Methods

Enums and generalized ADTs

3.0

yes

Enums, Algebraic Data Types & GADTs

Trait parameters, open classes, export clauses

3.0

yes

Traits & Mixins, Composition, Export & Self Types

Union and intersection types

3.0

yes

Union & Intersection Types

Opaque types

3.0

yes

Opaque Types & Value Classes

Matchable and the redesigned type hierarchy

3.0

yes

Type Hierarchy & Matchable

Polymorphic and dependent function types

3.0

yes

Dependent & Polymorphic Function Types

Type lambdas, match types

3.0

yes

Type Lambdas & Higher Kinds, Match Types

given and using, extension methods, context functions, Conversion

3.0

yes

Givens & Using Clauses, Extension Methods, Context Functions

Type class derivation with derives

3.0

yes

Type Class Derivation

Multiversal equality (CanEqual, strictEquality)

3.0

yes

Multiversal Equality

inline, compile-time operations, macros with quotes and splices

3.0

yes

Inline, Macros: Quotes & Splices

Clause interleaving (SIP-47), new context bound and given syntax (SIP-64)

3.6

yes

Generics & Bounds, Context Bounds & Deferred Givens

Named tuples (SIP-58)

3.7 (experimental in 3.5)

yes

Tuples & Named Tuples

Better fors (SIP-62) and runtimeChecked (SIP-57)

3.8

yes

For Comprehensions, Extractors & Pattern Bindings

into for implicit conversions (SIP-71)

3.9 (preview in 3.8)

yes

Conversions, into & Implicit Resolution

Strict-equality pattern matching without CanEqual (SIP-67)

3.10 (experimental before)

no, experimental

Multiversal Equality

Flexible varargs (SIP-70)

experimental

experimental

Language Evolution: SIPs, Preview & Experimental

@unroll, relaxed lambda syntax (SIP-75) and referenceable package objects

preview in 3.10

no, at most experimental

Language Evolution: SIPs, Preview & Experimental

Partial function literals with parentheses (SIP-74)

preview in 3.10.0

no

Partial Functions

Removal of legacy syntax such as A with B

3.10

no, deprecated only

Incompatibilities & Dropped Features

The full release-by-release history, with links to every announcement, is in Release History & What’s New, and the lifecycle that moves a feature from experimental to preview to stable is in Language Evolution: SIPs, Preview & Experimental. Source: New in Scala 3, Scala 3.10 released and Scala 3.9 LTS released.

Where the books are outdated

The online Scala 3 Book and the Tour of Scala describe the language as a whole and do not tie each feature to the release that introduced it, and printed books were fixed at one Scala 3 minor release. When you read them, remember:

  • They usually predate the LTS/Next model with 3.9 LTS, so "which Scala version?" has a different answer today: 3.10 for applications, 3.9 LTS for libraries, 3.3 LTS only while consumers are stuck on it.

  • They show JDK 8 or 11 as supported; since Scala 3.8 the floor is JDK 17.

  • They do not cover Scala CLI as the scala command, the official Scala Toolkit, named tuples (stable in 3.7), better fors (3.8), into (3.9), or the removal of legacy syntax in 3.10.

  • Several Scala 2 forms the books still show (implicit classes, with for intersections, wildcard _ for types) have Scala 3 replacements described in the pages linked above.