Scalatra review: a tiny Scala web framework for engineers who want routes, not a platform
Tiny Scala high-performance, async web framework, inspired by Sinatra
At a glance
- What is it?
- Scalatra is a Sinatra-style Scala web framework published to Maven Central as scalatra-javax and scalatra-jakarta. It is small, servlet-based, and best suited to teams that want explicit HTTP handling rather than a full application platform.
- Who is it for?
- Adopt Scalatra when you want a small, servlet-based Scala layer over HTTP and are comfortable managing the surrounding stack yourself. Do not adopt it if you need a batteries-included platform with an ORM, DI container and documented upgrade path, because the README does not describe one.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly Scala, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Scalatra is, and the team it fits
Scalatra describes itself in the README as "a tiny, Sinatra-like web framework for Scala." That sentence is the whole pitch. The framework gives you a servlet subclass, HTTP verb methods, and route blocks. It does not give you an ORM, a dependency injection container, a build tool, or a deployment model. Those are decisions you make elsewhere.
The target reader is a Scala developer who already knows how a servlet container works and wants route definitions that read like the HTTP they represent. The README's example is four lines: import org.scalatra, extend ScalatraServlet, call get("/"), return markup. There is no configuration file, no application bootstrap class, and no module list to assemble before the first request.
That minimalism is the point. Frameworks that ship a full stack also ship opinions about persistence, configuration and lifecycle. Scalatra ships almost none, which means the surface you learn is small and the surface you maintain is small. The cost is that everything outside routing is your problem, and the README does not pretend otherwise.
How routing and the servlet model actually fit together
A Scalatra application is a servlet. The README's example extends ScalatraServlet and registers a get("/") block; the framework maps that block to the servlet's HTTP handling, so the container's request lifecycle is the framework's request lifecycle. There is no separate server abstraction between your route and the container.
That design has a visible consequence in the repository layout. The top level contains core/, jetty/, json/, forms/, swagger/, metrics/, cache/, auth/, twirl/, scalatest/ and specs2/ as separate directories. Those are integration modules, not a monolith: you add the ones you need and leave the rest out of your dependency list. The README's artifact coordinates reflect the same split at the packaging level, with scalatra-javax and scalatra-jakarta as distinct publications of the same framework.
The README also links to Scalatra Guides for "documentation on all aspects of the framework" and to a separate repository of example applications. The guides are where the mechanism lives; the README itself is a pointer. If you evaluate Scalatra only from the README you will see routing and nothing else, which understates the framework and overstates how much you can learn from the front page.
Installing Scalatra and serving a first route
The README sends new users to the installation and first-project pages on scalatra.org, and states that the latest version is 3.2.+, published to Maven Central. There is no sbt plugin, no CLI and no project generator mentioned in the README, so installation means adding a library dependency to an existing sbt build.
Pick the artifact that matches your target platform. The README gives both coordinates:
// for javax
libraryDependencies += "org.scalatra" %% "scalatra-javax" % "3.2.+"
// for jakarta
libraryDependencies += "org.scalatra" %% "scalatra-jakarta" % "3.2.+"The javax and jakarta split matters because the servlet API namespace changed between Java EE and Jakarta EE. Choosing the wrong one produces compile errors against the servlet classes rather than a runtime failure, which is at least a fast signal. After the dependency resolves from Maven Central, the first real use is the README's own example, a servlet with one route:
import org.scalatra._
class ScalatraExample extends ScalatraServlet {
get("/") {
<h1>Hello, world!</h1>
}
}You should see the markup rendered when the route is served by your container. The README does not show how to start that container, which is a deliberate omission: the jetty/ directory exists in the repository, but the README does not document a run command, so wiring the servlet into a server is left to the installation and first-project guides or to your own container setup.
The servlet dependency is the framework's real boundary
Because a Scalatra application is a servlet, it inherits servlet semantics. That is an advantage when you are deploying into an existing servlet container or a WAR-based pipeline, since the framework adds nothing your operations team has to learn. It is a limitation when your deployment target is not servlet-shaped.
The README does not document an alternative server model, a rollback procedure, or a migration path between the javax and jakarta artifacts. If you are already running jakarta-namespace servlets, the scalatra-jakarta artifact is the one the README points at; if you are on javax, the other. Switching later is not described anywhere in the README, so treat the choice as something to get right before you build on it.
There is also no version pinning guidance beyond the 3.2.+ range. A floating patch range is convenient for staying current and inconvenient for reproducible builds, and the README does not discuss the trade-off. The repository does contain a version.sbt and a .scala-steward.conf, which suggests dependency updates are handled through tooling, but the README does not explain that workflow to users.
None of this is a defect in a small framework. It is the boundary you accept when you choose one. Scalatra does routing and HTTP handling; your build, your container and your upgrade discipline stay yours.
Scalatra versus Play, and when Http4s fits better
The comparison people reach for is Scalatra against Play. Play is a full framework: it owns the build integration, the server, the configuration format and the development workflow. Scalatra owns routing and not much else, and expects you to bring the rest. If you want a single documented path from project creation to production, Play's approach removes decisions that Scalatra leaves open. If you want to keep your existing sbt build, your container and your libraries, Scalatra stays out of the way.
Http4s is a different axis. It is built on a functional streaming model rather than the servlet model, so the request and response types are pure values you compose, not objects tied to a container's lifecycle. That gives you composability and a different testing story at the cost of a steeper conceptual entry point. Scalatra's route blocks are imperative and immediately familiar to anyone who has used Sinatra; Http4s asks you to think in terms of the underlying effect and streaming abstractions first. Neither is strictly better. They optimize for different things: Scalatra for a small surface over a servlet, Http4s for a composable functional pipeline.
The repository's swagger/ and json/ directories show where Scalatra extends: API documentation and JSON handling are optional modules, not core. Play bundles comparable concerns into the framework itself. That difference in default scope is the honest way to choose between them.
Maintenance, licensing and what the repository tells you
The repository is not archived, and the last push was on 2026-09-22. That is recent enough that the project is not dormant, but the README does not describe a release cadence, a support window, or a deprecation policy, and no recent releases were retrieved for this review. Do not read the last push date as a commitment to backward compatibility.
The LICENSE file is present at the top level, but the repository metadata reports the licence as NOASSERTION, meaning the automated classifier could not identify a standard licence from the file. That is a fact about the metadata, not about the terms. If you are adopting Scalatra in a commercial setting, read LICENSE directly and have your own process confirm the terms; this review cannot tell you what they are.
Upgrade cost is the harder question. The README documents the 3.2.+ line and the javax/jakarta artifact split, and nothing about migrating between them. There is a compat/ directory in the repository, which suggests compatibility work exists, but the README does not explain what it contains or how it is used. Plan for the possibility that a major version change means reading the guides and the source rather than following a migration document.
Where Scalatra is the wrong tool
Scalatra is the wrong choice if you need the framework to answer questions the README does not answer. There is no documented rollback story, no documented upgrade procedure between the javax and jakarta artifacts, and no documented release schedule. A team that needs a vendor-style support contract or a published compatibility matrix will not find one described here.
It is also the wrong choice if you want the framework to decide your persistence, templating and dependency injection. The repository splits those into optional modules (json/, forms/, twirl/, cache/, auth/, metrics/), and the README does not present a default combination. You will be assembling a stack, and you will own the result.
Finally, if your runtime is not servlet-based, the core abstraction works against you. The framework's identity is the servlet subclass, and the README offers no alternative. Choosing Scalatra and then fighting the servlet model is a sign you wanted a different framework.
Editorial conclusion
Adopt Scalatra when you want a small, servlet-based Scala layer over HTTP and are comfortable managing the surrounding stack yourself. Do not adopt it if you need a batteries-included platform with an ORM, DI container and documented upgrade path, because the README does not describe one. Before committing, verify the exact 3.2.+ artifact resolves from Maven Central for your javax or jakarta target, and check whether your deployment container expects a servlet or a Netty-style stack.
Frequently asked questions
How do I add Scalatra to an sbt project?
Add either "org.scalatra" %% "scalatra-javax" % "3.2.+" or "org.scalatra" %% "scalatra-jakarta" % "3.2.+" to libraryDependencies, depending on whether your target uses the javax or jakarta servlet namespace. Both artifacts are published to Maven Central.
Does Scalatra include Swagger support?
The repository contains a swagger/ directory, which indicates Swagger integration is maintained as a separate module rather than being part of the core framework. The README does not document how to enable it; the Scalatra Guides are the place the README points for module documentation.
What is the difference between scalatra-javax and scalatra-jakarta?
They are two publications of the same framework targeting different servlet API namespaces, javax and jakarta. The README lists both coordinates under the 3.2.+ version and does not describe a migration path between them.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/scalatra-scalatra)