Products Consulting About Blog Contact Us Česky
arrow_back Back to blog

Mise vs SDKMAN: Why I'm Switching After Years of .sdkmanrc

Mise vs SDKMAN: Why I'm Switching After Years of .sdkmanrc

A colleague mentioned Mise today. I’ve been a loyal SDKMAN user for years — .sdkmanrc in every project, sdk use java 21.0.2-tem committed to muscle memory. It works, it’s reliable, I’ve never had a reason to look elsewhere.

Then I actually looked at what Mise does, and I’m not sure I can go back.

The Problem with One Tool per Language

SDKMAN manages JDKs (and Gradle, Maven, and a few other JVM tools). It does that well. But my projects don’t just need Java:

  • Java 21 (Temurin)
  • Node 22 (for the frontend build)
  • Terraform (for infrastructure)
  • Python 3.12 (for scripts)

So I have SDKMAN for Java, nvm for Node, pyenv for Python, and tfenv for Terraform. Each has its own config file, its own shell hooks, its own way of pinning versions. My .zshrc loads four version managers, each adding latency to every new shell.

Mise replaces all of them with one tool and one config file:

TOML
# .mise.toml
[tools]
java = "temurin-21"
node = "22"
python = "3.12"
terraform = "1.9"

That’s it. One file in the repo root. Everyone on the team gets the same versions. No “works on my machine” because someone forgot to run sdk install.

What Mise Does Better

Speed

SDKMAN uses shell scripts. Every new terminal loads SDKMAN’s init script, which adds noticeable latency. Mise is written in Rust and modifies PATH directly instead of using shims. The overhead is ~5ms on shell startup vs. ~120ms for shim-based tools like asdf. SDKMAN falls somewhere in between, but it’s not in Mise’s league.

One Config for Everything

Instead of .sdkmanrc + .nvmrc + .python-version + .terraform-version, you have a single .mise.toml. It supports all 500+ tools from the asdf plugin ecosystem, plus its own curated backends.

Environment Variables

Mise doubles as a direnv replacement. You can set project-specific environment variables in the same config:

TOML
[tools]
java = "temurin-21"

[env]
SPRING_PROFILES_ACTIVE = "local"
DATABASE_URL = "jdbc:postgresql://localhost:5432/myapp"

No more .env files that accidentally get committed.

Tasks

Mise can also replace make and npm scripts:

TOML
[tasks.dev]
run = "java -jar build/libs/app.jar"
depends = ["build"]

[tasks.build]
run = "./gradlew build -x test"
Bash
mise run dev   # builds first, then runs

Is this necessary? No. But it’s nice to have project tasks defined alongside tool versions in one place.

The Migration Path

Here’s the part that convinced me: Mise reads .sdkmanrc natively. It maps SDKMAN’s vendor strings to its own format — 21.0.2-tem becomes temurin-21.0.2. Your existing .sdkmanrc files just work.

The migration is gradual:

  1. Install Mise: curl https://mise.run | sh
  2. Add to your shell: eval "$(mise activate zsh)"
  3. Your existing .sdkmanrc files are picked up automatically
  4. When you’re ready, convert to .mise.toml for the full feature set

You don’t have to uninstall SDKMAN immediately. Both can coexist while you transition.

What SDKMAN Still Does Better

Fair is fair:

  • JVM ecosystem breadth — SDKMAN supports more JDK distributions (GraalVM, Liberica NIK, Bisheng) that Mise doesn’t have yet
  • JVM-specific tooling — SDKMAN manages Gradle, Maven, Micronaut CLI, Quarkus CLI, and other JVM tools natively. With Mise, some of these require asdf plugins
  • Community — SDKMAN has years of JVM community trust and a larger user base in the Java world
  • Candidatessdk list java with its table of available distributions is a great discovery experience

If your world is purely JVM and you never touch Node/Python/Terraform, SDKMAN is still excellent. The case for Mise strengthens as your toolchain diversifies.

The Comparison

SDKMANMise
LanguagesJVM ecosystem500+ tools (Java, Node, Python, Go, Rust, Terraform…)
Config file.sdkmanrc.mise.toml (also reads .sdkmanrc)
Shell startup~50-100ms~5ms
Env varsNoYes (replaces direnv)
TasksNoYes (replaces make)
Written inBashRust
JDK distributionsExtensiveGood (missing GraalVM, Liberica NIK)
WindowsVia Git Bash/WSLNative (for non-asdf backends)

Bottom Line

SDKMAN solved a real problem and solved it well. I’ve used it for years without complaints. But Mise is what SDKMAN would look like if you designed it today — polyglot, fast, and aware that modern projects use more than one language.

If your .zshrc loads three version managers, Mise is a straightforward upgrade. If you’re happy with SDKMAN and only write Java — keep it. There’s no reason to switch for the sake of switching.

But if a colleague mentions Mise, try it. I did, and my shell is 200ms faster and my project root has one config file instead of four.


Cover photo by Patrick on Unsplash.

More from the Blog