Rust — why Tauri picked Rust
Rust — why Tauri picked Rust
Tauri is a framework for building desktop and mobile apps, with a core runtime written in Rust. This post covers Rust's origins and core concepts, and "why Rust in particular", on a factual basis. It is not a deep dive into Rust itself.
1. About Rust
Graydon Hoare at Mozilla started Rust as a personal project in 2006, and Mozilla began backing it publicly in 2010. 1.0 shipped in May 2015. In February 2021 the Rust Foundation was founded with AWS, Google, Huawei, Microsoft, and Mozilla as founding members, and stewardship of the language and tooling shifted to the foundation. Licensed under MIT / Apache-2.0 dual.
Design goals — memory safety, concurrency safety, zero-cost abstractions. To deliver memory safety without a GC, the compiler statically checks an ownership system.
2. Ownership, Borrow, Lifetime
Core rules (summary from chapter 4 of the official The Rust Programming Language):
- Every value has exactly one owner.
- When the owner goes out of scope, the value is freed immediately.
- Values can be borrowed (
&Timmutable reference,&mut Tmutable reference). At any moment, only one mutable reference is allowed, or multiple immutable references — never both.
fn main() {
let s = String::from("hello");
let len = take_len(&s); // borrow
println!("{s} {len}"); // still usable
}
fn take_len(s: &String) -> usize { s.len() }
Once ownership moves, the original is no longer usable. The compiler refuses.
A lifetime is a notation that tells the compiler how long a reference lives. Most are inferred, but explicit annotations are sometimes required in function signatures:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
These rules block data races at compile time. Issues common in C/C++ — use-after-free, double-free, concurrent mutation — are caught at build time.
3. The result
- No GC — no GC pauses, making Rust a candidate for embedded, real-time, even OS kernels.
- Single static binary —
cargo build --releasebundles dependencies statically into one executable (dynamic linking is also possible when needed). - C ABI compatibility — Rust can call C libraries directly and produce
.so/.dll/.dylibfiles callable from C.
4. Cargo
Rust's build and package tool. One tool covers all of:
- Dependency resolution (
Cargo.toml,Cargo.lock) - Build, test, and doc generation (
cargo build,test,doc) - Workspaces (monorepo mode)
- Crate publishing (
crates.io)
It occupies the same slot as JS's npm or Python's uv, all in one place.
5. Other paths (system language choices)
| Language | First release | Position |
|---|---|---|
| C | 1972 | Systems, OS, drivers. Standard ABI. |
| C++ | 1985 | Superset of C with OO and templates. |
| Go | 2009 (Google) | A system-level language with a GC. Emphasizes simplicity and a concurrency model (goroutines). |
| Rust | 2010, 1.0 in 2015 | Memory safety without a GC. |
| Zig | 2016, Andrew Kelley | Explicit memory management, comptime. Emphasizes seamless C integration. |
| Swift | 2014, Apple | ARC-based. Mostly Apple platforms. |
The choice is a tradeoff. Go has a gentle learning curve and a GC. Rust offers strong safety guarantees at the cost of a steep curve. Zig emphasizes a simpler compiler and comptime metaprogramming.
6. Why Tauri picked Rust
Tauri is a desktop and mobile app framework first released in 2020. 1.0 shipped in June 2022 and 2.0 in October 2024. Licensed under MIT / Apache-2.0.
Core architecture — WebView host + Rust core:
- UI layer — uses a system-installed WebView to render HTML/CSS/JS (WebView2 on Windows, WKWebView on macOS, WebKitGTK on Linux).
- Core layer — Rust handles window management, the event loop, OS API calls, and bundling.
- Bridge — Rust functions exposed via
#[tauri::command]are called from JS throughinvoke("name", args).
Why Rust fits this slot well:
- Small binaries — no GC runtime and natural static linking produce shipped binaries in the single-digit MB range (Electron bundles Chromium, often resulting in 100+ MB).
- Direct OS API access — safe wrappers over Win32, Cocoa, GTK, Android NDK, iOS objc-c interfaces (
windows-rs,core-foundation,jni-rs, etc.). - Race-free concurrency — the compiler enforces safety across multithreaded IPC, file I/O, and OS event handling.
- C/C++ library reuse — pull in native SQLite, libsodium, OpenSSL via FFI directly.
- Supply chain security — cargo + crates.io's lockfile model is often cited as different from npm's hoisting risks.
This choice also has costs. The learning curve is steep, and dynamic plugin models are harder. Tauri absorbs this through the plugin system (tauri-plugin-*) and a capabilities (permissions) model.
7. Common patterns
Install:
# Windows (PowerShell, winget)
winget install Rustlang.Rustup
# macOS, Linux
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Common after install
rustup default stable
rustup update
cargo --version
rustup manages toolchains. A per-project rust-toolchain.toml keeps the team on the same version.
Tauri commands:
pnpm tauri dev # dev build + WebView launch
pnpm tauri build # release bundle
Internally cargo build runs. src-tauri/Cargo.toml is the Rust-side manifest.
Exposing a command:
// src-tauri/src/lib.rs
#[tauri::command]
fn add(a: i32, b: i32) -> i32 { a + b }
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![add])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
// frontend
import { invoke } from "@tauri-apps/api/core"
const sum = await invoke<number>("add", { a: 1, b: 2 })
8. Common pitfalls
First-build time — cargo compiles the dependency tree from scratch. Several minutes is common. Subsequent builds are incremental.
MSVC vs GNU toolchain (Windows) — the default is x86_64-pc-windows-msvc, which requires Visual Studio Build Tools. Worth noting what rustup default stable-msvc actually means.
WebView differences across OSes — WebView2, WKWebView, and WebKitGTK do not share the same CSS/JS support range. Linux is often cited as the most divergent.
What unsafe means — Rust's safety guarantees hold only outside of unsafe { ... } blocks. The convention is to isolate FFI touchpoints inside such blocks.
Panic handling — a panic in the Rust core terminates the app. Recover via Result<T, E> and have command handlers return Result so the JS side can catch it.
Closing thoughts
Rust's ownership system is a new branch of memory safety without a GC. Tauri picked Rust for the core because of the combined effect of small binaries, direct OS API access, race-free concurrency, C/C++ reuse, and supply chain security. The learning curve is steep, but operational stability is high. As long as you keep WebView differences across OSes in mind, one codebase can target both desktop and mobile.
Next
- (end of languages)
Rust official site, The Rust Programming Language (book), Rust GitHub, Rust Foundation, Tauri official site, Tauri GitHub, Go, and Zig are the references.