Skip to content
AgileLogics
5 min read

Shipping Scala to Production

Prerequisites: Building web services

Packaging

// illustrative
// project/plugins.sbt
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.11.1")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.3.1")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.4")

// build.sbt
enablePlugins(JavaAppPackaging, DockerPlugin)
dockerBaseImage := "eclipse-temurin:21-jre"
dockerExposedPorts := Seq(8080)
Command Produces
sbt assembly one "fat" JAR with all dependencies
sbt stage a folder with start scripts and JARs
sbt Docker/publishLocal a Docker image
scala package . --assembly a runnable JAR with Scala CLI

Continuous integration

# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with: { distribution: temurin, java-version: 21, cache: sbt }
      - uses: sbt/setup-sbt@v1
      - run: sbt scalafmtCheckAll compile test

Configuration and operations

  • Configuration — read settings from environment variables with defaults (pureconfig, ciris), and fail fast at startup on bad config.
  • JVM settings — set heap limits relative to the container (-XX:MaxRAMPercentage=75) and choose a garbage collector (G1 by default; ZGC for low latency).
  • Observability — structured JSON logs, metrics, and distributed tracing via OpenTelemetry.
  • Health checks — liveness and readiness endpoints for Kubernetes.

Keeping a codebase healthy

  • Compile with strict warnings (-Wunused:all, -Werror in CI) and use scalafmt and Scalafix.
  • Keep dependencies current with Scala Steward, which opens update pull requests automatically.
  • Model the domain with case classes, enums, and opaque types; keep side effects at the edges; test the pure core thoroughly.
  • Pick one style for the team — "direct style" Scala, Cats Effect, or ZIO — and apply it consistently.

What's next

Try the Advanced Projects, then read What You Should Know Now — and What's Next for where to go from here.