What Is Misk? Cash App's Kotlin Microservice Container, Explained
Series: Building Production Services with Misk — Part 1 of 24
You want to build a backend service in Kotlin. Your options usually collapse to two extremes. Spring Boot gives you everything, wired by annotation magic and classpath scanning you don’t fully control. Ktor gives you almost nothing — a delightful little server you then have to grow your own config, DI, persistence, metrics, and testing story around. Misk sits in a third place, and once you see the shape of it, the gap it fills is obvious: it’s a microservice container. This post is the orientation — what Misk is, where it sits next to Spring Boot and Ktor, and the honest answer to “should I use this?”
A quick definition up front, since you searched for one: Misk (Microservice Container in Kotlin) is an open-source service container from Cash App that wires together the common concerns of a production service — serving HTTP and gRPC endpoints, configuration, persistence, caching, queueing, distributed leasing, clustering, metrics, and testing — through Guice modules you install. It has run hundreds of microservices inside Cash App since 2018, which is the part that matters: this is not a weekend framework, it’s the thing a large payments company actually ships on.
What a “microservice container” actually is
The word container is doing real work here, and it’s not the Docker kind. Think of it the way a servlet container (Tomcat, Jetty) hosts servlets: the container owns the lifecycle, and your code plugs into it. Misk owns the process — starting and stopping a managed set of services in dependency order, standing up a Jetty server, loading config, exposing an admin dashboard — and your application is a set of modules you hand it at startup.
That’s the distinction from a framework. A framework is a library you call into and arrange yourself; Ktor is a framework. A container is a runtime your code lives inside; it has opinions about the shape of a service and provides the scaffolding so every service at the company looks roughly the same. Misk is firmly the latter. The entire entry point to a Misk app is one class, MiskApplication, handed a list of Guice modules:
fun main(args: Array<String>) {
MiskApplication(
MiskRealServiceModule(),
MiskWebModule(config.web),
// ...your modules
).run(args)
}
Everything Misk does, it does because a module is installed. Need Redis? Install RedisModule and add a RedisConfig to your YAML. Need a database? Install a JDBC or Hibernate module. Nothing you don’t install is running. That “features are modules you opt into” design is the throughline of the entire framework, and of this entire series.
Misk vs. Spring Boot vs. Ktor
Since you’re almost certainly coming from one of the other two, here’s the crisp version.
vs. Spring Boot. Both are batteries-included. The difference is how the wiring happens. Spring uses its own DI container with component scanning, @Autowired, proxies, and a lot of runtime reflection — convenient until you’re staring at a BeanCurrentlyInCreationException wondering what the container decided on your behalf. Misk uses Guice, where wiring is explicit Kotlin code in modules you can read top to bottom. There is no classpath scan deciding what’s a bean. If a dependency is bound, some module bound it, and you can find that line. For people who find Spring’s magic exhausting, this is the headline feature. (We’ll go deep on Guice in Part 3.)
vs. Ktor. Both are Kotlin-native and pleasant. The difference is how much comes in the box. Ktor is a library you compose: you pick your DI (or none), your config story, your persistence, your metrics, and you assemble them. That’s liberating for a small service and tedious for the fortieth one. Misk makes those decisions for you — config, service lifecycle, metrics, testing, an admin console — so every service starts from the same production-shaped baseline. You trade Ktor’s freedom for a container’s consistency.
The one-liner: Spring Boot hides the wiring, Ktor makes you write all of it, Misk makes the wiring explicit but does it once for the whole fleet.
The module and BOM philosophy
Misk is split into many small Gradle modules — misk-actions, misk-jdbc, misk-hibernate, misk-redis, misk-jobqueue, misk-cron, and dozens more — so your service only depends on what it uses. The core misk module is the web-server implementation; nearly everything else is an integration you add deliberately. There’s also Wisp, a sibling collection of low-dependency Kotlin modules (config, logging, feature flags, tokens) deliberately built without a Guice dependency, so they’re usable outside a Misk container.
Because the version surface is large, Misk publishes a BOM (bill of materials). You import it once and then declare Misk dependencies without versions, and the BOM keeps them consistent:
dependencies {
implementation(platform("com.squareup.misk:misk-bom:<version>"))
implementation("com.squareup.misk:misk")
implementation("com.squareup.misk:misk-actions")
// versions omitted — the BOM pins them
}
Know this before you pin anything: Misk uses calendar versioning — releases look like 2024.07.09, not 3.1.0. Pin the latest from Maven Central. The examples in this series are written against the source as of this writing and target a recent calendar release; verify signatures against your pinned version, because Misk’s API does change between releases.
When to choose Misk — and when not to
Credibility means being honest, so here’s the real guidance.
Reach for Misk when: you’re standing up more than one Kotlin service and want them to share a production shape; you value explicit DI over annotation magic; you want config, metrics, readiness, graceful shutdown, and a genuinely excellent testing story to come standard rather than be assembled; or you’re running the kind of distributed concerns (leasing, leader election, transactional job queues) that Misk has battle-tested at payments scale.
Don’t reach for Misk when: you want a tiny single-purpose service or a quick prototype — the container overhead isn’t worth it, and Ktor will be faster to stand up. Or when your team has deep Spring expertise and no appetite to learn Guice and a sparsely documented framework. Which brings us to the honest caveats.
Misk is Cash-App-shaped. Its defaults, its cloud integrations (AWS-first: SQS, S3, DynamoDB), and some of its abstractions reflect how Block builds services, not a neutral committee design. The documentation is thin relative to Spring — the source, the module READMEs, and the exemplar sample app are often the real docs, which is exactly why this series leans on reading the actual code. The community is small (hundreds of GitHub stars, not tens of thousands), so you won’t find a Stack Overflow answer for every problem. And some APIs are explicitly marked @ExperimentalMiskApi and will shift. If you need a large hiring pool and a mature ecosystem of tutorials, that’s a real cost.
None of that is disqualifying — it’s the trade you make for a framework that’s opinionated in the direction of production correctness. But you should walk in with eyes open.
Production notes & gotchas
- The docs can lag the code. Misk’s getting-started guide and the actual
exemplarapp already differ in places (the sample uses arunDevApplicationdev harness and aDeployment-based config load that the prose doc doesn’t show). Throughout this series, when the docs and the source disagree, trust the source. Clone it:git clone --depth 1 https://github.com/cashapp/misk.git. jakarta.inject, notjavax.inject. Misk has moved to the Jakarta namespace. If you paste old Guice examples usingjavax.inject.Inject, they won’t resolve. Usejakarta.inject.Inject/jakarta.inject.Singleton.misk-web(the React admin UI) is deprecated. The current admin dashboard is server-rendered withkotlinx.html+ Hotwire + Tailwind. If you find oldmisk-webReact tutorials, they’re a dead end (covered in Part 24).- Pin the BOM and read the changelog. Calendar versions move fast and the API is explicitly “subject to change.” Upgrade deliberately.
What’s next
Enough positioning. In Part 2: Your First Misk Service we’ll clone the exemplar, walk the Gradle + BOM setup and the MiskApplication entry point end to end, and get a real service running locally — the foundation every later post builds on.
Target keywords: what is misk, misk kotlin framework, misk microservice container.
Comments