Why We Chose Zig Over Rust
The case for Zig's explicit simplicity over Rust's complexity in building sovereign systems.
Why We Chose Zig Over Rust
Everyone asks: “Why not Rust?”
Rust is memory-safe. Rust is fast. Rust has a massive ecosystem.
We chose Zig anyway.
The Rust Tax
Rust is an excellent language. For certain problems, it’s the best tool available.
But Rust comes with tax:
| Tax | Cost |
|---|---|
| Compile times | Minutes, not seconds |
| Binary size | 500KB+ minimum (std) |
| Cognitive load | Borrow checker fights |
| Build complexity | Cargo, crates.io, features |
| Async complexity | Pin, Box, lifetimes everywhere |
For sovereign infrastructure, these taxes compound.
What We Need
Our requirements for Libertaria:
- Deterministic builds – Reproducible across platforms
- Small binaries – Kenya Rule (<10MB, ideally <1MB)
- Fast compile – Iterate quickly
- No hidden allocations – Explicit memory management
- C interop – Zero-cost FFI for crypto libraries
- Readable code – Auditable by humans
Rust can do all of these. But Zig does them simply.
Zig’s Simplicity
const std = @import("std");
pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit();
const allocator = gpa.allocator(); const slice = try allocator.alloc(u8, 100); defer allocator.free(slice);
// No hidden allocations. Ever.}Compare to Rust:
use std::alloc::{GlobalAlloc, Layout, System};
fn main() { unsafe { let layout = Layout::from_size_align(100, 1).unwrap(); let ptr = System.alloc(layout); // ... use ptr ... System.dealloc(ptr, layout); }}Rust requires unsafe for explicit allocation. Zig makes it the default.
Comptime vs. Macros
Rust macros are powerful. They’re also complex:
macro_rules! vec { ($($x:expr),*) => { { let mut temp_vec = Vec::new(); $(temp_vec.push($x);)* temp_vec } };}Zig comptime:
fn makeArray(comptime T: type, comptime size: usize) [size]T { var arr: [size]T = undefined; // ... fill arr ... return arr;}Comptime is just Zig code that runs at compile time. No special syntax. No macro_rules.
The Build System
Rust: Cargo.toml, features, workspaces, proc-macros.
Zig:
const std = @import("std");
pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{ .name = "libertaria", .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, });
b.installArtifact(exe);}That’s it. No crates.io dependency hell. No feature flags.
When Rust Wins
We’re not Rust haters. Use Rust when:
- You need absolute memory safety (no unsafe allowed)
- You’re building for a team with Rust expertise
- The ecosystem has critical libraries
- Compile times don’t matter
For us, explicit over safe is the right tradeoff.
The Real Reason
Rust optimizes for “prevent all bugs.”
Zig optimizes for “make all costs visible.”
We want visibility. We want to see every allocation, every system call, every edge case.
Sovereign infrastructure demands transparency.
Zig: The last language you’ll need to learn.
#zig #rust #systems #technical