Nucleus
Compare

Why Nucleus

How Nucleus compares with Electron, Tauri, and vanilla Compose Multiplatform for building desktop apps in Kotlin.

Kotlin already runs on Android, on iOS through Kotlin/Native, and on the web through Kotlin/JS and Wasm. On the desktop you can render a Compose window, but reaching the operating system has meant compiling native libraries per platform, wiring JNI or FFM bridges, and learning a different native API for each OS. Nucleus lets you build the whole desktop app in Kotlin — UI, business logic, OS calls, and packaging — in a single process.

This page compares that approach with Electron, Tauri, and vanilla Compose Multiplatform (CMP).

Comparison

NucleusElectronTauriCMP default
Language(s)KotlinJS + Node (+ C++ for natives)JS + RustKotlin
UI techCompose + Skia GPUChromium (Blink + V8)OS WebViewCompose + Skia GPU
OS APIs40+ Kotlin modules, single processNode child_process / native modulesRust commands over IPCLimited (Tray, Notification, no decorated window)
Packaging formats18 (DMG, PKG, Exe, MSI, NSIS, NSIS Web, Portable, AppX, DEB, RPM, AppImage, RawAppImage, Pacman, Snap, Flatpak, ZIP, TAR, 7Z)5–7 via electron-builder5 via tauri-bundler6 (DMG, PKG, MSI, EXE, DEB, RPM)
Auto-updateBuilt-in (updater-runtime)electron-updaterTauri Updater pluginNone
Cold start~0.2 s (GraalVM) · ~1.0 s (JVM+AOT)2–3 s< 1 s1–2 s
RAM idle30–120 MB*200–500 MB~87 MB*200 MB
Binary size40 MB (GraalVM) · 60 MB (JVM)*150–200 MB5–20 MB80–120 MB
Native window decorationsYes — Liquid Glass, Fluent, Yaru, JewelLimited (Chromium chrome)Yes (OS chrome)Limited
ModelOne language end-to-endTwo runtimes, IPC bridgeWeb frontend + Rust backendOne language, fewer built-ins

Measured: startup, RAM, and process count

We built the same Hello-World window in four stacks and measured each one identically on the same Windows 11 machine — wall-clock time from process launch to the first window handle, and the private working set (the figure Task Manager shows) once the window settled.

Hello-WorldStackCold startWarm startRAM (private WS)Processes
Nucleus (Tao)GraalVM native image~0.17 s~0.10 s~30 MB1
WinUI 3.NET 9 + Windows App SDK~0.20 s~0.28 s~32 MB1
FlutterDart AOT + Skia~0.28 s~0.28 s~33 MB1
TauriRust + WebView2~0.74 s~0.12 s~87 MB7

Two results worth calling out:

  • Task Manager under-reports WebView2 apps. The Tauri process itself shows ~4 MB — but the real footprint (~87 MB) lives in six separate msedgewebview2.exe processes that Task Manager lists elsewhere. Nucleus runs as a single self-contained process, so the number you see is the number it costs, and there's no reliance on a system-installed WebView.
  • Nucleus lands in the same ~30 MB class as native WinUI 3 and Flutter — while staying pure Kotlin/Compose — and uses roughly a third of Tauri's memory. Native/AOT is what buys both the low RAM and the sub-0.2 s start.

macOS

Same protocol on a macOS 26 machine (Apple silicon) — wall-clock time from process launch to the first on-screen window, and total RSS across every process the app spawns once the window settled. RSS includes shared framework pages, so these figures are not directly comparable with the Windows private-working-set column — compare within the table.

Hello-WorldStackCold startWarm startRAM (RSS, all processes)Processes
Nucleus (Tao)GraalVM native image~0.32 s~0.20 s~115 MB1
SwiftUInative reference~0.14 s~0.14 s~78 MB1
FlutterDart AOT + Skia~0.79 s~0.17 s~100 MB1
TauriRust + WKWebView~0.91 s~0.19 s~173 MB4
  • The WKWebView story mirrors WebView2. The Tauri main process shows ~97 MB, but WebKit renders in three separate helper processes (WebContent, GPU, Networking) that add another ~76 MB — all counted in the table.
  • Nucleus sits between the native SwiftUI reference and Tauri — ~35 % less RAM than Tauri and a cold start nearly 3× faster, in a single process.

One language across the stack

Electron and Tauri split the stack across languages. You write the UI in JavaScript, the native parts in Rust, C++, or Swift, and connect them through an IPC bridge. Nucleus keeps the whole stack in Kotlin — UI, business logic, OS calls, and packaging — with the same call graph, memory model, and debugger.

When you need to drop down to a platform — embed a SwiftUI view, call into Win32 directly, or use a Linux-only D-Bus interface — the Tao backend exposes NativeView, and native-access provides typed FFI without leaving Kotlin source.

When to choose each tool

  • Electron — the largest ecosystem and hiring pool. Choose it when shipping speed and JavaScript familiarity matter more than RAM, binary size, or native look and feel.
  • Tauri — the smallest binaries in this comparison. Choose it when you accept the platform-specific WebView and the Rust/JavaScript context switch.
  • vanilla CMP — the foundation Nucleus builds on. Choose it when you want Compose without the additional surface Nucleus adds, and you're prepared to write your own packaging, signing, updater, and decorated-window code.
  • Nucleus — choose it when you want one language across the stack, native window decorations, the JVM ecosystem in-process, and a packaging pipeline that covers 18 formats and four stores.

Notes

The performance numbers above are typical for a Hello-World class app. Real-world cold start and RAM scale with what your app loads. Nucleus has two runtime targets: GraalVM native image for cold start and binary size, and JVM + AOT cache for throughput. See performance for details.

In the comparison table, the Electron figures are drawn from public benchmarks. The Nucleus, WinUI 3, Tauri, and JVM numbers — including Tauri's RAM — were measured first-hand on a single Windows 11 machine (warm runs unless noted); see the Measured section above. *Nucleus RAM was measured on Windows 11 with a Hello World build; binary size is the NSIS installer with maximum compression.

What's next