Skip to content
Published on

Modern Scala 2026 Deep Dive - Scala 3.6, ZIO 2, Cats Effect 3, Akka 23 to Apache Pekko, Mill, sbt, Laminar

Authors

Prologue — In 2026, Scala Became a Language of Choice, Not a Language of Difficulty

Back in 2020, Scala still carried the image of "powerful but complicated." sbt was the only build tool that mattered, implicit conversions froze IDEs, and Akka was effectively synonymous with the actor model on the JVM.

The 2026 landscape is entirely different.

  • Scala 3.6 has settled in as a stable LTS. Scala 2.13 to 3 migrations are nearly automated via scala3-migrate.
  • A three-way effect-system race — Cats Effect 3.5 (Typelevel), ZIO 2.1 (John De Goes), and Kyo (Flavio Brasil) — has formed clear camps.
  • After Lightbend moved Akka to BSL in 2022, the community migrated to Apache Pekko 1.0. Same code, different governance.
  • A three-way build-tool race — sbt 1.10.5, Mill 0.12 (Lihaoyi), and scala-cli — has split by use case.
  • Scala.js frontends — Laminar 17, Tyrian, Outwatch — have grown into "TypeScript alternatives."
  • Scala Native 0.5 plus GraalVM Native Image finally make AOT compilation practical.

Scala is no longer a synonym for "functional programming on the JVM." It is a toolbox. This article maps the whole toolbox at once.

One-line summary: "What do you want to prove, where will you run it, and which paradigm does your team know?" These three questions decide 90 percent of your Scala tooling choices.


Chapter 1 · Scala 3 — How Dotty Survived

Scala 3 shipped its stable release in May 2021. The former codename Dotty (Martin Odersky, EPFL) was an eight-year refactor that rewrote the language atop a brand-new type system. Built on DOT calculus (Dependent Object Types), it formalizes every corner case of the type system.

As of 2026 there are three coexisting LTS lines.

VersionStatusHighlights
Scala 3.3 LTSLong-term supportConservative stability, library compatibility
Scala 3.5nextNamed tuples, indentation improvements
Scala 3.6 / 3.7latestCapture checking, given clarifications, Quotes refresh

Scala 2.13 is not dead either. It remains the default target for large libraries such as Spark 3.5. Bidirectional compatibility (TASTy) between Scala 2.13 and 3 lets you mix versions inside one project.

The real meaning of Scala 3 was not the syntax but the type-system cleanup. implicit was split into given / using / extension, structural types were tightened, and macros were re-designed via the Quotes API.


Chapter 2 · New Syntax in Scala 3.5 / 3.6 / 3.7 — From Named Tuples to Capture Checking

Representative new syntax.

// named tuples (Scala 3.5+) — anonymous-struct flavor
val person: (name: String, age: Int) = (name = "Yuna", age = 28)
val p2 = (name = "Min", age = 31)
val nm: String = person.name

// extension methods — successor to implicit class
extension (s: String)
  def shout: String = s.toUpperCase + "!"

"hello".shout  // "HELLO!"

// given / using — explicit form of implicit
trait Show[A]:
  def show(a: A): String

given Show[Int] with
  def show(a: Int): String = s"int:$a"

def render[A](a: A)(using s: Show[A]): String = s.show(a)

// enum — sugar over sealed trait
enum Status:
  case Active, Paused, Closed(reason: String)

// match types — type-level branching
type Elem[X] = X match
  case String => Char
  case Array[t] => t

// inline + macros — Quotes API
inline def log(inline msg: String): Unit =
  ${ logImpl('msg) }

capture checking (Scala 3.6+) puts "which external resources does this function capture" into the type. It is experimental, but it is one of the threads pointing at future effect tracking — a stepping stone toward a hypothetical Scala 4.


Chapter 3 · Scala 2.13 to 3 Migration — Automation and Its Limits

In 2026, migrating a large code base to Scala 3 follows an almost standard procedure.

  1. Run sbt-tasty-mima or mima for binary-compatibility checks.
  2. Run scalafix rule sets (Procedure.scala2, ExplicitResultTypes, etc.) to auto-rewrite.
  3. Run the scala3-migrate sbt plugin to patch implicits, default args, and type-parameter differences.
  4. Keep building under Scala 2.13 with -Xsource:3 and -Wconf enabled until warnings are zero.
  5. Switch the compiler to Scala 3 and fix remaining errors manually.
// Scala 2.13 implicit class
implicit class StringOps(val s: String) extends AnyVal {
  def shout: String = s.toUpperCase + "!"
}

// Scala 3 extension — auto-rewritten
extension (s: String)
  def shout: String = s.toUpperCase + "!"

The hard areas are macros (Scala 2 def-macros to Scala 3 Quotes API), HKT variance, and shapeless-style typeclass derivation (now replaced by Mirror). If a code base leans heavily on these three, migration cost roughly doubles.

Practical tip: migrate libraries first, applications last. Scala 3 can consume Scala 2.13 libraries, but the reverse is hard.


Chapter 4 · The Effect-System Three-Way Race — Cats Effect 3.5, ZIO 2.1, Kyo

The heart of functional Scala is the effect system. It expresses side effects (IO, concurrency, resources, errors) in types so that reasoning and testing become tractable.

LibraryCampCore abstractionCharacter
Cats Effect 3.5TypelevelIO[A], Resource[F, A], Ref[F, A]Type-class based, pairs with fs2
ZIO 2.1John De GoesZIO[R, E, A]Monolithic, 3-track R/E/A
KyoFlavio Brasilalgebraic effectsNewest, handler based

Cats Effect 3 packs every effect into a single IO type. ZIO exposes environment R, error E, and success A directly in the type. Kyo models algebraic effects (the Eff-monad family) and emphasizes handler composition.

// Cats Effect 3
import cats.effect.IO
import cats.effect.std.Console

val program: IO[Unit] =
  for
    _ <- Console[IO].println("name?")
    n <- Console[IO].readLine
    _ <- Console[IO].println(s"hi $n")
  yield ()

// ZIO 2
import zio.*

val zioProg: ZIO[Any, java.io.IOException, Unit] =
  for
    _ <- Console.printLine("name?")
    n <- Console.readLine
    _ <- Console.printLine(s"hi $n")
  yield ()

The choice is simple. Type-class friendly plus library interop picks Cats Effect. Explicit environment plus integrated libraries picks ZIO. Latest effect theory plus light footprint picks Kyo. Mixing two of them in one project is not recommended.


Chapter 5 · Cats Effect 3.5 — The Heart of the Typelevel Stack

Cats Effect (Typelevel, led by Daniel Spiewak) ships concurrency primitives — IO, Resource, Ref, Deferred, Semaphore — plus a fiber scheduler. A fiber is a cooperative concurrency unit lighter than an OS thread that can yield the JVM's native thread.

import cats.effect.{IO, Resource, ResourceApp}

object App extends ResourceApp.Forever:
  def run(args: List[String]): Resource[IO, Unit] =
    for
      _ <- Resource.eval(IO.println("start"))
      _ <- Resource.make(IO.pure(42))(_ => IO.println("close"))
    yield ()

Cats Effect's strength is type-class composition. A clean hierarchy — Sync, Async, Concurrent, Temporal, MonadCancel — lets a library demand only the minimum capability it needs. Doobie, http4s, and fs2 all sit on top of Cats Effect.

Cats Effect follows a "compose small pieces" aesthetic. That is its biggest philosophical difference from ZIO.


Chapter 6 · ZIO 2.1 — A Monolithic Integrated Stack

ZIO (John A De Goes, Ziverge) embeds the environment in the effect type itself. ZIO[R, E, A] means "consume R, fail with E, or succeed with A."

import zio.*

trait UserRepo:
  def findById(id: Long): ZIO[Any, Throwable, Option[String]]

object UserRepo:
  val live: ZLayer[Any, Nothing, UserRepo] = ZLayer.succeed {
    new UserRepo:
      def findById(id: Long) = ZIO.succeed(Some(s"user-$id"))
  }

val app: ZIO[UserRepo, Throwable, Unit] =
  for
    repo <- ZIO.service[UserRepo]
    u    <- repo.findById(1L)
    _    <- Console.printLine(u.toString)
  yield ()

object Main extends ZIOAppDefault:
  def run = app.provide(UserRepo.live)

ZIO's strength is batteries included. ZIO HTTP, ZIO Schema, ZIO JSON, ZIO Streams, ZIO Test, ZIO Config — a uniformly designed library family forms one camp. The learning curve exists, but once settled you can write the whole stack with a single mental model.

ZIO follows a "one bowl holds everything" aesthetic — the counterpoint to Cats Effect's compositional minimalism.


Chapter 7 · Kyo — The Newest Effect Library

Kyo (Flavio Brasil, ex-Twitter) models algebraic effects directly. Effects accumulate in the type and handlers process them. It is closer to Idris's effect system.

import kyo.*

def program: Int < (IO & Abort[Throwable] & Async) =
  for
    _ <- IO(println("start"))
    n <- Async.runFiber(IO(42)).await
  yield n

A < S reads as "result A, with effects S." S is a composition of effects. It is a more general shape than ZIO's R/E/A three-track.

Kyo matured rapidly in 2024–2025 and is widely discussed as "the next-generation effect library" in 2026. Its library ecosystem is still smaller than Cats Effect or ZIO, however.


Chapter 8 · Akka 23.x to Apache Pekko 1.0 — Two Roads After a License Change

In September 2022 Lightbend switched Akka 2.7 onward to BSL (Business Source License). Non-commercial use stays free; commercial use is paid. The decision shocked the open-source community.

The reply was Apache Pekko, started under the ASF. It is a fork of Akka 2.6.x with the package renamed from akka to org.apache.pekko.

ToolLicenseGovernanceStatus
Akka 23.xBSL 1.1 plus commercialLightbendActive new features
Apache Pekko 1.0Apache 2.0ASFAkka 2.6 compatible plus incremental growth

Code migration is almost a package rename.

// Akka
import akka.actor.typed.{ActorSystem, Behavior}
import akka.actor.typed.scaladsl.Behaviors

// Apache Pekko
import org.apache.pekko.actor.typed.{ActorSystem, Behavior}
import org.apache.pekko.actor.typed.scaladsl.Behaviors

val behavior: Behavior[String] = Behaviors.receive { (ctx, msg) =>
  ctx.log.info(msg)
  Behaviors.same
}

As of 2026 nearly all new projects choose Apache Pekko. Existing Akka users weigh license fees against migration cost and the trend leans toward migration.

For libraries, license is identity. This episode proved how much the open-source community values governance stability.


Chapter 9 · Actors and Streams — The Core of Apache Pekko 1.0

The two pillars of Pekko (and Akka) are typed actors and streams.

import org.apache.pekko.actor.typed.scaladsl.Behaviors
import org.apache.pekko.actor.typed.ActorSystem

enum Cmd:
  case Inc, Dec, Get(replyTo: org.apache.pekko.actor.typed.ActorRef[Int])

def counter(n: Int): org.apache.pekko.actor.typed.Behavior[Cmd] =
  Behaviors.receiveMessage {
    case Cmd.Inc => counter(n + 1)
    case Cmd.Dec => counter(n - 1)
    case Cmd.Get(r) =>
      r ! n
      Behaviors.same
  }

val sys = ActorSystem(counter(0), "demo")

Streams are a fluent DSL on top of the Reactive Streams spec.

import org.apache.pekko.stream.scaladsl.*
import org.apache.pekko.NotUsed

val source: Source[Int, NotUsed] = Source(1 to 10)
val flow: Flow[Int, Int, NotUsed]  = Flow[Int].map(_ * 2)
val sink: Sink[Int, scala.concurrent.Future[Int]] = Sink.fold(0)(_ + _)

val total = source.via(flow).runWith(sink)

Akka HTTP / Pekko HTTP, Akka Cluster / Pekko Cluster, Akka Persistence / Pekko Persistence — only the license differs. Feature parity is one-to-one.


Chapter 10 · http4s, Tapir, ZIO HTTP — A Three-Way Scala HTTP Race

The main Scala HTTP candidates are three.

LibraryCampCharacter
http4s 0.23+TypelevelHttpRoutes[F], type-safe, fs2 based
Tapir 1.xsoftwaremillDeclarative endpoints, backend adapters
ZIO HTTPZIOZIO-native, high performance

http4s is the canonical functional HTTP library.

import cats.effect.IO
import org.http4s.*
import org.http4s.dsl.io.*

val routes = HttpRoutes.of[IO] {
  case GET -> Root / "hello" / name =>
    Ok(s"hi $name")
}

Tapir declares endpoints as data and auto-generates OpenAPI, Swagger, and type-safe clients.

import sttp.tapir.*
import sttp.tapir.json.circe.*

case class User(name: String, age: Int)

val getUser = endpoint
  .get
  .in("users" / path[Long]("id"))
  .out(jsonBody[User])
  .errorOut(stringBody)

ZIO HTTP combines ZIO-native routing with strong performance. zio-http often tops benchmarks.

Choose by camp. Cats Effect stack picks http4s. ZIO stack picks ZIO HTTP. If you want backend independence, pick Tapir.


Chapter 11 · sbt 1.10.5, Mill 0.12, scala-cli — A Three-Way Build-Tool Race

For a long time sbt was effectively the only choice. In 2026 three tools coexist.

ToolAuthor / OrgStrengthWeakness
sbt 1.10.5Lightbend then communityBest compatibility, rich pluginsSteep curve, slow
Mill 0.12Li HaoyiConcise Scala DSL, fast incremental buildsFewer plugins
scala-cliVirtus LabSingle-file script friendlyNot for large projects

A build.sbt example.

// build.sbt
ThisBuild / scalaVersion := "3.6.0"
ThisBuild / organization := "example"

lazy val core = (project in file("core"))
  .settings(
    libraryDependencies ++= Seq(
      "org.typelevel" %% "cats-effect" % "3.5.4",
      "org.http4s" %% "http4s-ember-server" % "0.23.27"
    )
  )

Mill build.sc.

// build.sc
import mill._, scalalib._

object core extends ScalaModule {
  def scalaVersion = "3.6.0"
  def ivyDeps = Agg(
    ivy"org.typelevel::cats-effect:3.5.4",
    ivy"org.http4s::http4s-ember-server:0.23.27"
  )
}

scala-cli declares dependencies at the top of the file.

//> using scala 3.6.0
//> using dep org.typelevel::cats-effect:3.5.4

import cats.effect.{IO, IOApp}

object Hello extends IOApp.Simple:
  def run = IO.println("hi")

scala-cli was adopted as the official Scala runner (scala run) in 2024. For small scripts, data analysis, and teaching it is the de-facto standard. Larger projects go to sbt or Mill.


Chapter 12 · Scala.js, Laminar 17, Tyrian — Frontends Written in Scala

Scala.js compiles Scala to JavaScript. As of 2026 it is mature and webpack/vite integration is smooth.

Laminar 17 (Nikita Gazarov) is a reactive UI framework built on FRP. Signals and observables drive state.

import com.raquo.laminar.api.L.*

val name = Var("")

val app = div(
  input(
    placeholder := "your name",
    onInput.mapToValue --> name
  ),
  span(
    "hi, ",
    child.text <-- name.signal
  )
)

render(dom.document.getElementById("root"), app)

Tyrian ports the Elm Architecture (model-update-view) to Scala.js. It pairs with the Indigo game engine.

Outwatch (Cornerman) is built on observables, in the spirit of RxJS. Lampagne is a newer SSR-friendly framework.

Selection criteria:

  • "Declarative UI like React or Solid" — Laminar
  • "Unidirectional data flow like Elm" — Tyrian
  • "Familiar RxJS plus a small bundle" — Outwatch

Laminar is often called "the best frontend you can write in Scala." It is a serious alternative worth comparing against TypeScript.


Chapter 13 · Scala Native 0.5 plus GraalVM Native Image — Two Roads to AOT

The JVM starts slowly, which is fatal for CLIs and serverless. Two solutions exist.

ToolHowCharacter
Scala Native 0.5Compile directly through an LLVM backendNo JVM, C interop, small binary
GraalVM Native ImageAOT the JVM bytecodeStandard Java/Scala, needs reflection config
// Scala Native
object Hello:
  def main(args: Array[String]): Unit =
    println("hello native")
# Scala Native — direct LLVM compile
sbt nativeLink

# GraalVM Native Image — AOT from JVM bytecode
native-image -jar app.jar

Scala Native has restricted library compatibility. JVM-only libraries do not run. GraalVM runs nearly any Java library, but reflection and dynamic class loading need careful config.

To use Scala in serverless (AWS Lambda, GCP Cloud Run), one of the two is essentially required. Cold starts drop below 100 ms.


Apache Spark is written in Scala, and its API still feels most natural in Scala.

Spark versionScala targetNotes
Spark 3.5Scala 2.13 / 2.12The 2026 mainstream
Spark 4.0 (preview)Scala 2.13 / 3Connect, Spark Connect
import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder
  .appName("demo")
  .master("local[*]")
  .getOrCreate()

import spark.implicits.*

val df = Seq(("a", 1), ("b", 2)).toDF("k", "v")
df.filter($"v" > 1).show()

Apache Flink also exposes a Scala API. In 2023 Flink demoted its Scala API to best-effort, but the community sustains it.

Apache Beam has its own SDK; Spotify's Scio is the most popular Scala wrapper.

Scala 2.13 will not disappear from big data soon. Full Scala 3 support in Spark needs more time.


Chapter 15 · JSON, Schema, Codecs — circe, jsoniter-scala, upickle

JSON libraries also split into camps.

LibraryCampCharacter
circeTypelevelFunctional, type-class derivation
jsoniter-scalaPlokhotnyukMacro-generated fastest codec
upickleLi HaoyiSimple, light dependencies
ZIO JSONZIOZIO native, schema integration
// circe
import io.circe.*, io.circe.generic.semiauto.*

case class User(name: String, age: Int)

given Encoder[User] = deriveEncoder
given Decoder[User] = deriveDecoder

// jsoniter-scala
import com.github.plokhotnyuk.jsoniter_scala.macros.*
import com.github.plokhotnyuk.jsoniter_scala.core.*

given JsonValueCodec[User] = JsonCodecMaker.make

In benchmarks jsoniter-scala is the clear winner (sometimes faster than native JSON.parse). circe composes smoothly with other Typelevel libraries. upickle is lightest when you "just need JSON."


Chapter 16 · The Database Layer — Doobie 1.0, Skunk, Quill, ScalikeJDBC

Doobie 1.0 (Typelevel) — a functional wrapper over JDBC. Natural SQL on Cats Effect.

import doobie.*, doobie.implicits.*
import cats.effect.IO

case class User(id: Long, name: String)

val xa = Transactor.fromDriverManager[IO](
  driver = "org.postgresql.Driver",
  url    = "jdbc:postgresql:db",
  user   = "u",
  pass   = "p",
  logHandler = None
)

val all: IO[List[User]] =
  sql"select id, name from users".query[User].to[List].transact(xa)

Skunk (Typelevel) implements the native Postgres protocol directly on top of nio, with no JDBC. Fastest and smallest.

Quill 4.x — write queries as Scala expressions and translate them to SQL at compile time. Type-safe but with a learning curve.

ScalikeJDBC — a thin wrapper closer to plain JDBC. Pick it for familiarity.

// Quill
import io.getquill.*

val ctx = new PostgresJdbcContext(SnakeCase, "ctx")
import ctx.*

val users = quote { query[User].filter(_.age > 18) }
ctx.run(users)

Selection criteria are the camp (Cats Effect, ZIO, independent) and "do you want to write SQL directly or use a Scala expression."


Chapter 17 · Testing — Munit, ScalaTest 3.2, ZIO Test, weaver-test

Test frameworks are equally rich.

FrameworkCampCharacter
MunitScala teamConcise, JUnit compatible
ScalaTest 3.2ClassicMany styles (FunSuite, FlatSpec, ...)
ZIO TestZIOZIO native, environment injection
weaver-testdisneystreamingCats Effect native, parallel by default
// Munit
class MathSpec extends munit.FunSuite:
  test("add"):
    assertEquals(1 + 2, 3)

// ScalaTest FunSuite
class MathSuite extends org.scalatest.funsuite.AnyFunSuite:
  test("add") { assert(1 + 2 == 3) }

// weaver-test
import weaver.*

object MathSpec extends SimpleIOSuite:
  pureTest("add"):
    expect(1 + 2 == 3)

Munit is close to a default. The ZIO camp uses ZIO Test; the Cats Effect camp leans on weaver-test or Munit-CatsEffect.


Chapter 18 · Iron and refined — Constrain Values via Types

refined (fthomas) and Iron (Iltotore) add "type-level constraints to values." For instance, a type that only accepts positive integers.

// Iron (Scala 3)
import io.github.iltotore.iron.*
import io.github.iltotore.iron.constraint.numeric.*

type Age = Int :| Positive
val a: Age = 30           // OK
// val b: Age = -1         // compile error

// refined (Scala 2/3 compatible)
import eu.timepit.refined.*
import eu.timepit.refined.api.Refined
import eu.timepit.refined.numeric.*

val x: Int Refined Positive = refineMV[Positive](42)

Iron is Scala 3-only — lighter and more IDE friendly. refined has Scala 2 compatibility and pairs with ZIO Prelude and others.

Encoding API invariants in types is core to functional Scala's aesthetic.


Chapter 19 · Real Adoption — Twitter to X, Databricks, Twilio, Disney+, SoFi

Representative companies running Scala in production.

CompanyHow they use it
Twitter / XFinagle, util, Finatra. Most infrastructure in Scala. Some moved to Rust in 2023
DatabricksSpark is the company. Scala 2.12/2.13 at massive scale
TwilioParts of the messaging backend in Akka/Pekko
FoursquareLocation data processing in Scala
ING BankPayment backends on Cats Effect
SoFiFintech backends on ZIO
Disney+Streaming backend services. weaver-test originated at Disney
IagonDistributed storage, on Cats Effect
AppleParts of the Siri / iCloud backend
NetflixRecommendations and streaming pieces (historically more)

There are fewer "all Scala" companies and more "Scala in a specific domain" companies. This mirrors the maturity of other JVM languages such as Kotlin and Java 21. But in data engineering, payment backends, and distributed systems, Scala's place is solid.


Chapter 20 · Korean and Japanese Scala Communities

Korea:

  • ScalaKorea — the Korean Scala user group. Kakao, LINE, Coupang, and Woowa Brothers are the core.
  • Kakao Brain / Kakao Pay — Scala/Spark in data pipelines.
  • LINE — parts of the messaging backend in Scala/Akka, with Scala 2.13/3 coexistence.
  • Coupang — parts of data engineering.
  • Woowa Brothers — catalog and batch services in Scala.
  • NHN Cloud / Naver — Scala/Spark on top of Hadoop.

Japan:

  • ScalaMatsuri — Asia's largest Scala conference, held annually in Tokyo.
  • Scala Tokyo — the Tokyo Scala user group.
  • CyberAgent — ad backends in Scala.
  • Septeni — ad-tech domain.
  • Mercari — parts of payments and settlement.
  • DMM.com — parts of the backend.
  • NTT Communication Science Labs — academic / research use.

East-Asia Scala adoption skews toward data engineering, advertising, and payments. Both Korea and Japan center on Spark/Akka workloads, while functional libraries (Cats Effect, ZIO) spread quickly through new projects.


Chapter 21 · Scala 3 Pitfalls and Best Practices

Common traps when moving to Scala 3 for the first time.

TrapSymptomMitigation
Blindly rewriting every implicit as givenSemantics driftDistinguish using / extension / given
Leaving Scala 2 macros as-isCompile failureRewrite via Quotes API
Pulling in shapelessOverkill on Scala 3Replace with Mirror-based derivation
Enabling capture checking too earlyLibrary compatibility breaksOff on LTS, on only for new modules
Mixing sbt, Mill, and scala-cliBuild cognitive dissonancePick one
Adding new code on Akka 23License burdenWrite new code on Apache Pekko
Mixing effect campsConversion boilerplate explodesBridge Cats Effect and ZIO at the edges only
Reliance on reflective Java APIsNative Image build failsreflect-config or @reflective
Too many implicit conversionsSlow IDE, hard debuggingPrefer explicit conversion
Iron / refined everywhereLong compile timesApply only to domain invariants

Scala 3 rewards "thoughtful simplicity" even more than the tooling improvements suggest.


Chapter 22 · The Next Five Years — Scala Settles In

A look at the next five years.

  1. Scala 3.3 LTS solidifies. Nearly all new code targets 3, but Spark keeps Scala 2.13 libraries alive longer.
  2. Effect camps narrow. Cats Effect and ZIO become the stable camps, and Kyo emerges as a future-standard candidate.
  3. Apache Pekko becomes the de-facto standard. Commercial Akka licenses shrink to large enterprises only.
  4. Builds: sbt plus scala-cli as the duopoly — Mill stays the specialty pick.
  5. Scala.js frameworks like Laminar and Tyrian make full-stack Scala viable for small SaaS.
  6. Scala Native plus GraalVM normalizes serverless and CLI Scala.
  7. Scala in the AI era — data pipelines (Spark) become the standard for LLM indexing and embedding, while LLM clients emerge atop ZIO and Cats Effect.
  8. Standardization — TASTy stabilizes, macro APIs stabilize, and library API-compatibility culture matures.

Scala is no longer "a complicated functional language." It is a toolbox. And that toolbox is becoming something an everyday engineer can pick up by choice.


Epilogue — Where Should You Start

If the toolset in this article feels overwhelming, here is a learning path.

  1. Language — the official Scala 3 tutorial and the 5th edition of "Programming in Scala" (Odersky et al.).
  2. Builds — try single-file scripts with scala-cli. Then move to sbt or Mill for multi-module projects.
  3. Effects — pick Cats Effect or ZIO and write a small "Bookings"-style example.
  4. HTTP — build a REST API with http4s or Tapir.
  5. Database — connect to Postgres with Doobie or Skunk.
  6. Frontend — build a one-page SPA with Scala.js plus Laminar.
  7. Production — ship a small CLI compiled with Scala Native or GraalVM.

"What do you want to prove, where will you run it, and which paradigm does your team know?" Hold these three questions while re-reading this article, and the tool choices become surprisingly clear.

— Modern Scala 2026, fin.


References

  1. Odersky, M. et al. "Scala 3 Reference." https://docs.scala-lang.org/scala3/reference/
  2. Scala Center. "Scala 3 Migration Guide." https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html
  3. Typelevel. "Cats Effect 3 Documentation." https://typelevel.org/cats-effect/
  4. Ziverge. "ZIO 2 Documentation." https://zio.dev/
  5. Brasil, F. "Kyo Project." https://github.com/getkyo/kyo
  6. Lightbend. "Akka License Change Announcement." https://www.lightbend.com/blog/why-we-are-changing-the-license-for-akka
  7. Apache Software Foundation. "Apache Pekko." https://pekko.apache.org/
  8. http4s. "http4s Documentation." https://http4s.org/
  9. softwaremill. "Tapir Documentation." https://tapir.softwaremill.com/
  10. dream11. "ZIO HTTP." https://zio.dev/zio-http/
  11. sbt Authors. "sbt Reference Manual." https://www.scala-sbt.org/1.x/docs/
  12. Haoyi, L. "Mill Build Tool." https://mill-build.org/
  13. Virtus Lab. "scala-cli." https://scala-cli.virtuslab.org/
  14. Gazarov, N. "Laminar." https://laminar.dev/
  15. PurpleKingdomGames. "Tyrian." https://tyrian.indigoengine.io/
  16. Scala Native Team. "Scala Native 0.5." https://scala-native.org/
  17. Apache Spark. "Spark Scala API." https://spark.apache.org/docs/latest/api/scala/index.html
  18. Plokhotnyuk, A. "jsoniter-scala." https://github.com/plokhotnyuk/jsoniter-scala
  19. Typelevel. "Doobie." https://tpolecat.github.io/doobie/
  20. Typelevel. "Skunk." https://typelevel.org/skunk/
  21. Scalameta. "Munit." https://scalameta.org/munit/
  22. Disney Streaming. "weaver-test." https://disneystreaming.github.io/weaver-test/
  23. Iltotore. "Iron." https://iltotore.github.io/iron/
  24. ScalaMatsuri. "ScalaMatsuri Conference." https://scalamatsuri.org/
  25. Scala Center. "Scala Toolkit." https://docs.scala-lang.org/toolkit/introduction.html