Serving the Application
Run a functional web server.
Serving the Application is a free Scala for Backend Engineering & Functional Programming lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Scala for Backend Engineering & Functional Programming learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Ember Server
http4s runs your HttpApp[F] on a backend. The default modern choice is Ember, a pure-Scala server built on cats-effect and fs2, available as org.http4s.ember.server.EmberServerBuilder.
Older apps may use Blaze, but Ember is the recommended path going forward.
// build.sbt
// "org.http4s" %% "http4s-ember-server" % http4sVBuilding the Server
EmberServerBuilder.default[F] gives a builder you configure fluently: bind host and port, attach the app, then call .build to get a Resource[F, Server].
Using a Resource guarantees the socket is released on shutdown.
import com.comcast.ip4s._
import org.http4s.ember.server.EmberServerBuilder
EmberServerBuilder.default[IO]
.withHost(ipv4"0.0.0.0")
.withPort(port"8080")
.withHttpApp(app)
.buildip4s Literals
Ember uses ip4s types for type-safe networking. The ipv4"..." and port"..." interpolators validate at compile time, so an invalid address or out-of-range port will not compile.
Import com.comcast.ip4s._ to access them.
import com.comcast.ip4s._
val host = host"localhost"
val p = port"8080"Resource Lifecycle
The server is a Resource because it owns a socket that must open and close cleanly. resource.use(_ => ...) keeps it running for the duration of the inner effect.
Use IO.never to run until the process is interrupted.
server.use(_ => IO.never).voidIOApp Entry Point
An http4s app's main class extends IOApp, which provides a managed cats-effect runtime. You implement run returning IO[ExitCode].
IOApp handles thread pools, signal handling, and graceful shutdown for you.
import cats.effect.{IO, IOApp, ExitCode}
object Main extends IOApp {
def run(args: List[String]): IO[ExitCode] = ???
}A Complete Main
Putting it together: build the server resource, then use it with IO.never so the process stays alive, returning ExitCode.Success.
This is the canonical http4s entry point.
def run(args: List[String]): IO[ExitCode] =
EmberServerBuilder.default[IO]
.withPort(port"8080")
.withHttpApp(app)
.build
.use(_ => IO.never)
.as(ExitCode.Success)Composing Resources
Real apps acquire more than a server: a DB pool, an HTTP client, config. Compose them in a single for-comprehension over Resource so all are released in reverse order.
Pass the acquired clients into route construction.
for {
client <- EmberClientBuilder.default[IO].build
app = buildApp(client)
srv <- serverResource(app)
} yield srvGraceful Shutdown
Because the server lives in a Resource, cancelling the fiber (for example on SIGTERM under IOApp) runs the finalizer that stops accepting connections and closes the socket.
Ember drains in-flight requests within a configurable shutdown timeout.
EmberServerBuilder.default[IO]
.withShutdownTimeout(30.seconds)
.withHttpApp(app)
.buildServer Middleware
Wrap the final HttpApp with server middleware before handing it to the builder. Common ones are Logger, CORS, GZip, and ErrorHandling.
Order matters: the outermost wrapper sees the request first and the response last.
import org.http4s.server.middleware._
val finalApp = Logger.httpApp(true, false)(
CORS.policy.withAllowOriginAll(app)
)Configuration
Read host, port, and secrets from the environment with a config library such as ciris or pureconfig, returning the config as part of a Resource or effect.
Avoid hardcoding ports so the same binary runs across environments.
val port = sys.env.get("PORT")
.flatMap(Port.fromString)
.getOrElse(port"8080")Health and Observability
Expose a liveness route like GET /health returning 200 so orchestrators can probe the process. Add request logging and metrics middleware for visibility.
Keep health checks cheap and dependency-free so they reflect process, not downstream, status.
val health = HttpRoutes.of[IO] {
case GET -> Root / "health" => Ok("UP")
}Quick Check
Recall why the server is modeled as a Resource.
Recap
You served the app with EmberServerBuilder, bound it using ip4s literals, and ran it from an IOApp with build.use(_ => IO.never).
You composed resources, wrapped middleware, read config from the environment, added a health route, and relied on Resource for graceful shutdown.
Frequently asked questions
Is the “Serving the Application” lesson free?
Yes — the full text of “Serving the Application” is free to read here on the web, and the Scala for Backend Engineering & Functional Programming course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Scala for Backend Engineering & Functional Programming course, upgrade to CoddyKit PRO.
What will I learn in “Serving the Application”?
Run a functional web server. You practise Scala for Backend Engineering & Functional Programming with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Scala for Backend Engineering & Functional Programming?
No prior experience is required. Scala for Backend Engineering & Functional Programming on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Serving the Application” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Scala for Backend Engineering & Functional Programming lesson?
Yes. Every Scala for Backend Engineering & Functional Programming lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Routes and HttpRoutes
- Requests and Responses
- JSON Endpoints
- Serving the Application