- Published on
Modern Zig 2026 — Zig 0.14, Andrew Kelley, Bun, TigerBeetle, Ghostty, comptime, Zon, Roc Deep Dive
- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 1. Zig in 2026 — Andrew Kelley vision and industrial adoption
- 2. Zig 0.14 (March 2025) — compilation speed and async on hold
- 3. Zig 0.15 / Zig 1.0 roadmap
- 4. Bun runtime — the biggest validation of Zig
- 5. TigerBeetle — distributed accounting database
- 6. Ghostty — Mitchell Hashimoto terminal
- 7. Zig build system (build.zig) and Zon manifest
- 8. Zig as C cross-compiler — why other projects use Zig
- 9. Zig vs Rust — the differences
- 10. comptime — the killer feature of Zig
- 11. Allocator-aware programming
- 12. ZLS (Zig Language Server)
- 13. Roc — the functional alternative
- 14. Korea / Japan — adoption at builders, Cybozu Zig experiment
- 15. Who should pick Zig — systems / embedded / C replacement
- 16. References
1. Zig in 2026 — Andrew Kelley vision and industrial adoption
As of May 2026, Zig is still not 1.0. The latest release is 0.14 from March 2025. But do not be fooled by the "0.x" label. Serious products like Bun, TigerBeetle, and Ghostty are already shipping in Zig, and thousands of C/C++ projects swap out their cross-compiler with a single zig cc invocation.
Zig core identity is one solo BDFL — Andrew Kelley — backed by the Zig Software Foundation. The opposite of Rust transitioning from Mozilla to a foundation and distributing governance: Zig is intentionally one person taste deeply etched into a language. The consequences:
- A C-like simple surface, paired with
comptime— powerful compile-time meta-programming - No hidden control flow — no operator overloading, no RAII, no hidden allocator
- Explicit memory management, allocator passed as a function argument
zig cc/zig c++— Zig bundles LLVM and works as a serious C/C++ cross-compilerbuild.zig— replaces Make/CMake/Bazel; the build graph is written in Zig itself
Industrial adoption is "still small but very serious". Bun share of npm traffic, TigerBeetle traction in fintech ledgers, Ghostty quietly eating macOS-developer terminal share — those three alone prove Zig is not a toy.
This article starts from Andrew Kelley design philosophy, then walks through what 0.14 actually delivers, the 0.15 / 1.0 roadmap, and Bun / TigerBeetle / Ghostty before getting into comptime, allocators, the build system, zig cc, ZLS, and Roc — the reasons (and traps) for taking Zig seriously in May 2026.
2. Zig 0.14 (March 2025) — compilation speed and async on hold
Zig 0.14 shipped on March 5, 2025. Key changes:
- Progress on the native x86 backend — work to skip LLVM for debug builds. Reports of debug compile times nearly halving in some projects.
- Simpler
@importdependency tree — the module system feels more intuitive. std.Build(build system) API churn —build.zigtaste shifted again. Migrating from 0.13 to 0.14 means walking through signature changes likestep.addArgs.async/awaitstill removed — async features pulled out in 0.11 still are not back in 0.14. Andrew said "we will redesign the stackless coroutine model", and whether that redesign lands before 1.0 is the big open question.
Code-level feel of 0.14:
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var list = std.ArrayList(u8).init(allocator);
defer list.deinit();
try list.appendSlice("Hello, Zig 0.14!\n");
try std.io.getStdOut().writeAll(list.items);
}
trypropagates errors;deferruns on scope exit- You construct
std.heap.GeneralPurposeAllocatordirectly and extract the interface viaallocator() - Every collection takes an
allocator— no hidden alloc
The big-picture story of 0.14: the compiler is making itself faster. Exactly the opposite vector from Rust catching flak for rustc compile times.
3. Zig 0.15 / Zig 1.0 roadmap
As of May 2026, 0.15 has not shipped yet. Things expected or being discussed between 0.14 and 0.15:
- Native x86 backend as default — bypassing LLVM in debug builds becomes the default. Release builds still go through LLVM.
- Async/await redesign — Andrew proposed a new "I/O-driven concurrency" model. The core idea: not stackless coroutines, but async via an explicit
ioargument. Roughlyfn read(io: *Io, ...) []u8. A library opts into async only when it consents. std.Io— the standard interface for async I/O. Still in flux.- Stronger incremental compilation
- Package manager (Zon) stabilization —
build.zig.zonbecame the standard in 0.14; 0.15 polishes it further
When will Zig 1.0 land? Nobody can pin it down. Andrew officially says "1.0 ships when we can credibly promise stability". Conservative read: 2027. Optimistic: late 2026. Serious users like Bun / TigerBeetle / Ghostty are already shipping on 0.x — they are not waiting for 1.0; they migrate their code with every release.
4. Bun runtime — the biggest validation of Zig
Bun is a JavaScript runtime built by Jarred Sumner. Its core positioning is "Node.js replacement", and the engine is written almost entirely in Zig. Through 2024–2025, Bun 1.x shipped, 1.1 and 1.2 followed, and Node compatibility now lands near 99%. In 2026, Bun is the single largest industrial proof that Zig can ship serious infrastructure software.
Why Bun chose Zig:
- Compile speed — a JS runtime pulls massive C++ dependencies (JSC, V8), and Zig packages them cleanly inside its build system
zig ccfor cross-compiling C/C++ deps — Bun builds macOS/Linux/Windows binaries from one host- Allocator control — alloc/free is hand-tuned in the JS runtime hot path
- comptime — boilerplate for
bun:ffi,bun:sqliteis generated at compile time
A simplified slice of Bun-style code:
// Bun-style HTTP server hot path (simplified)
pub fn handleRequest(
arena: *std.heap.ArenaAllocator,
socket: *Socket,
req: *Request,
) !void {
var response_buffer = std.ArrayList(u8).init(arena.allocator());
try writeStatusLine(&response_buffer, 200);
try writeHeaders(&response_buffer, req);
try socket.writeAll(response_buffer.items);
}
- Arena allocator — memory is bundled per request; when the response is done the arena releases everything at once. malloc/free calls are nearly zero
- Explicit error propagation —
tryrethrows all I/O errors upward - No hidden alloc — even
ArrayListrequires an explicitinit(allocator)
What Bun shows: a small team (under 10 people) can build Node-class infrastructure in Zig. That is dramatically less code than Rust would need, and dramatically safer than C.
5. TigerBeetle — distributed accounting database
TigerBeetle, led by Joran Dirk Greef, is a financial distributed database. Written 100% in Zig with a single clear purpose: process double-entry accounting transactions at OLTP speed. Its target is the ledger backend of fintech and payment systems.
Why TigerBeetle is interesting:
- NASA Power of 10 rules plus the TIGER STYLE coding guide — 70-line function limit, no recursion, dynamic alloc only at startup, explicit bounds on every loop, assertions everywhere
- Deterministic simulation testing — VOPR (Viewstamped Operation Replication), their own consensus, fault-injected and simulated billions of times
- Single binary, zero dependency — one
zig buildand you have a single binary - Performance — targeting one million transactions per second per node
A snippet in TIGER STYLE:
fn transfer(ledger: *Ledger, from: AccountId, to: AccountId, amount: u64) !void {
assert(from != to);
assert(amount > 0);
const from_account = try ledger.lookup(from);
const to_account = try ledger.lookup(to);
assert(from_account.balance >= amount); // explicit precondition
from_account.balance -= amount;
to_account.balance += amount;
try ledger.commit();
}
assertsits in the code like comments — debug builds enforce invariants- All alloc happens at startup; the hot path has zero alloc
- Functions are short and do one thing
TigerBeetle is the industrial proof that Zig is viable for mission-critical software. A fintech ledger is a domain where being off by one cent can sink a company, and they bet on Zig.
6. Ghostty — Mitchell Hashimoto terminal
Ghostty is a GPU-accelerated terminal emulator built by Mitchell Hashimoto (the Vagrant / Terraform guy). The 1.0 release shipped in December 2024, and by 2026 it is a first-class citizen on both macOS and Linux.
Why Ghostty chose Zig:
- Cross-platform native UI — Swift on macOS, GTK4 on Linux. The core logic in between is Zig
- Comptime-generated terminal sequence parser — VT100 / xterm escape sequences become compile-time lookup tables
- Zero-copy rendering — direct GPU texture writes, so alloc must be hand-managed
- Mitchell personal pick — that the Terraform-in-Go author landed on "next is Zig" was an event itself
A pattern Ghostty highlights:
const Cell = struct {
char: u21,
fg: Color,
bg: Color,
attrs: packed struct(u8) {
bold: bool,
italic: bool,
underline: bool,
_reserved: u5,
},
};
packed struct(u8)— explicit bit layout. What you would do in C with macros and comments, the language understands directlyu21— exactly 21 bits, the perfect width for a Unicode code point
Ghostty is also proof that GUI apps can be built in Zig. New systems languages typically stall on GUI, and Mitchell answered: "core in Zig, platform chrome native".
A deeper comparison lives in a separate post (2026-05-16 terminal shell tools).
7. Zig build system (build.zig) and Zon manifest
Zig does not use an external build tool. Make, CMake, Bazel, Cargo disappear — replaced by one file: build.zig. That means the build script is also Zig code.
A typical build.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 = "myapp",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
b: *std.Build— the build-graph builder objectb.standardTargetOptions— automatically accepts options like-Dtarget=x86_64-linux-gnu- Build is code, not data — for-loops, if-branches, dynamic dependencies all possible
Zon manifest — build.zig.zon
Zig Object Notation, introduced in 0.11. JSON-like, but written in Zig syntax.
.{
.name = "myapp",
.version = "0.1.0",
.minimum_zig_version = "0.14.0",
.dependencies = .{
.httpz = .{
.url = "https://github.com/karlseguin/http.zig/archive/abc123.tar.gz",
.hash = "1220abcdef...",
},
},
.paths = .{ "src", "build.zig", "build.zig.zon" },
}
.hashis required — content-addressed; a dependency change halts the build- No central registry — no npm/crates.io equivalent. Every dependency is a direct URL reference
- This is intentional — Andrew said "package managers are too large a security surface"
Tradeoffs:
- Pro: dependency graphs cannot explode; nobody pulls a left-pad-style stunt
- Con: discoverability suffers — finding "the Zig version of lodash" means searching the wild
8. Zig as C cross-compiler — why other projects use Zig
The strongest tool that ships with zig is zig cc / zig c++. Not a wrapper — a first-class C/C++ compiler that bundles LLVM.
# Build a macOS aarch64 binary from a Linux x86_64 host
zig cc -target aarch64-macos main.c -o main
# Cross-compile to Windows x86_64
zig cc -target x86_64-windows-gnu main.c -o main.exe
Why this matters:
- glibc version pinning —
-target x86_64-linux-gnu.2.17for RHEL 7 compatibility - libc bundled — Zig ships musl, glibc, mingw sources along with itself
- One install — installing Zig gives you cross-compilers for every target
Industrial usage:
- uv (Python package manager, by Astral) — uses
zig ccto build wheels - TigerBeetle — one
zig buildproduces every platform binary on a single host - Bun — uses it for dependency compilation as noted above
- gcc / clang replacement — folks like Drew DeVault have replaced toolchains in their projects
The key message: you end up using Zig the tool even when you do not use Zig the language. Cross-compilation alone is reason enough.
9. Zig vs Rust — the differences
By 2026, "Rust vs Zig" is already tribal. Both claim to be the C/C++ successor, but they feel very different.
| Axis | Rust | Zig |
|---|---|---|
| Memory safety | Borrow checker (compile-time enforced) | Allocator-aware + runtime checks |
| Generics | Trait + monomorphization | comptime |
| Compile speed | Infamously slow | Fast and getting faster (native backend) |
| Async | async/await (stabilized) | Removed, redesign in progress |
| Standard library | Huge | Small (intentionally) |
| Build tool | cargo | build.zig |
| 1.0 | May 2015 | TBD (late 2026 ~ 2027) |
| Governance | Foundation plus teams | Andrew Kelley plus ZSF |
| Learning curve | Very steep | Steep, but different shape |
The "no borrow checker, is it safe?" answer for Zig:
- Allocator is explicitly passed — function signatures spell out who owns the memory
- Runtime safety checks — debug builds auto-panic on out-of-bounds, integer overflow, null deref
defer/errdefer— not RAII, but deterministic cleanup- GeneralPurposeAllocator leak detection — leaks are caught in debug builds
Andrew Kelley said: "Rust borrow checker gives up too much freedom for safety; Zig chooses explicitness and simplicity". Both are correct. The right answer depends on domain.
10. comptime — the killer feature of Zig
comptime is the core differentiator of Zig. Arbitrary Zig code runs at compile time, and the results can be used as types and constants.
10.1 Generics are just functions
fn List(comptime T: type) type {
return struct {
items: []T,
len: usize,
pub fn append(self: *@This(), item: T) void {
// ...
}
};
}
const IntList = List(i32);
const StrList = List([]const u8);
Tis acomptimeparameter — the type itself is passed as a valueListis a function; calling it returns a type- Same work as C++ templates and Rust generics — but first-class inside the language
10.2 Compile-time code execution
const lookup_table = comptime blk: {
var t: [256]u8 = undefined;
for (&t, 0..) |*v, i| {
v.* = @intCast(i * 2 % 256);
}
break :blk t;
};
comptime blk: { ... }— this block runs at compile time and the result is baked in- At runtime,
lookup_tableis just 256 bytes of data - What you would handle in C with macros or external scripts, Zig handles in the same language
10.3 Code that inspects itself
fn serialize(value: anytype, writer: anytype) !void {
const T = @TypeOf(value);
const info = @typeInfo(T);
switch (info) {
.Int => try writer.print("{}", .{value}),
.Bool => try writer.print("{}", .{value}),
.Struct => |s| {
inline for (s.fields) |field| {
try serialize(@field(value, field.name), writer);
}
},
else => @compileError("unsupported type"),
}
}
@typeInfointrospects a typeinline forunrolls at compile time@compileErrorraises a compile-time failure
This is the work that Rust does through proc-macro plus serde plus syn — done at the language level in Zig. No external macros.
11. Allocator-aware programming
The Zig memory model fits in one sentence: "every function that uses memory must take an allocator as a parameter".
pub fn readFile(allocator: std.mem.Allocator, path: []const u8) ![]u8 {
const file = try std.fs.cwd().openFile(path, .{});
defer file.close();
const stat = try file.stat();
const buffer = try allocator.alloc(u8, stat.size);
errdefer allocator.free(buffer);
_ = try file.readAll(buffer);
return buffer;
}
- Allocator is passed explicitly — the caller knows what alloc is used
defercloses the fileerrdeferfrees the buffer only on error
Standard-library allocators:
| Allocator | Purpose |
|---|---|
std.heap.GeneralPurposeAllocator | Debug builds detect leak / double-free |
std.heap.page_allocator | Direct OS pages |
std.heap.c_allocator | malloc / free |
std.heap.ArenaAllocator | Free everything in one shot |
std.heap.FixedBufferAllocator | Pre-allocated buffer |
std.testing.allocator | Tests, leak detection enforced |
The arena pattern is the workhorse:
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const alloc = arena.allocator();
// Every alloc in this scope is freed in one shot via arena.deinit()
const a = try alloc.alloc(u8, 100);
const b = try alloc.alloc(u8, 200);
// No individual free needed for a or b
Bun HTTP request handling and TigerBeetle transaction processing both run on the arena pattern. Fewer alloc calls means consistently faster average performance.
12. ZLS (Zig Language Server)
ZLS is the community LSP for Zig (not the official one). By 2026, it is first-class in VS Code, Neovim, Helix, and Zed.
What ZLS provides:
- Goto definition / find references
- Autocomplete (covers comptime results to a degree)
- Inlay hints — inferred types inline
- Diagnostics — invokes the Zig compiler to surface errors live
- Rename refactoring
Watch out for:
- ZLS must match the Zig version. ZLS for 0.14 and ZLS for 0.13 are distinct
- comptime inference has limits — especially with
anytypeparameters - Even at 0.14, ZLS still hangs occasionally — not Rust-analyzer-level stable yet
Config (.zls.json):
{
"enable_inlay_hints": true,
"enable_argument_placeholders": false,
"warn_style": true,
"enable_autofix": true
}
13. Roc — the functional alternative
Roc is a functional systems language by Richard Feldman (from the Elm community). Strangely, it is often mentioned alongside Zig. Why:
- The Roc compiler is written in Zig
roc buildalso bundles LLVM — same approach as Zig- Functional, no GC, ML-family syntax — Haskell aesthetics plus Zig execution model
- Andrew Kelley publicly cheers it on
A taste of Roc:
greet : Str -> Str
greet = \name -> "Hello, \(name)!"
main =
Stdout.line! (greet "World")
- Functional, pattern matching, type inference
!marks effects — same impulse as Haskell IO- No GC; reference counting plus opportunistic in-place mutation
In 2026, Roc is still pre-1.0. But there is real space for "a serious ML-family language built on Zig", and for people who lean functional it is attractive. A case study in the diversity of the Zig ecosystem.
14. Korea / Japan — adoption at builders, Cybozu Zig experiment
14.1 Korea — Builder (SaaS) adoption
Korean SaaS builder companies (Notion-style or Webflow-style tools) have been experimenting with Zig in their core rendering engines since 2025.
- Reason 1: WASM target — Zig supports WASM as a first-class target, and the resulting binaries are often smaller than Rust
- Reason 2:
zig ccbrings existing C/C++ dependencies into WASM — less reliance on emscripten - Reason 3: it fits small core teams in startups — onboarding is cheaper than Rust
Of course, it is still small. JS/TS dominates. But in "WASM-target hot paths", Zig adoption is rising.
14.2 Japan — Cybozu Zig experiment
Cybozu (groupware company behind Kintone) publicly shared an experiment migrating modules from Go to Rust to Zig. Findings:
- Rust: safe but blocked by compile speed and learning curve
- Zig: faster compiles, and engineers coming from Go could read it within a few days
- Downside: it is pre-1.0, so every compiler upgrade means code edits — the question is whether that cost is acceptable
Some Fujitsu and NTT infrastructure teams also adopted zig cc alone to simplify build pipelines — the "not the language, but the tool" pattern.
15. Who should pick Zig — systems / embedded / C replacement
Take Zig seriously in these domains:
- Build-system replacement for a C/C++ project — anyone tired of Make/CMake.
zig buildpluszig cccleans it up - CLI tools that need cross-compilation — the Bun pattern
- Embedded / OS / firmware — anywhere you need
no std, exact bit layout, allocator control - WASM-target hot paths — the builder case
- Mission-critical financial backends — TigerBeetle, assuming you have TIGER-STYLE discipline
Where to avoid:
- Plain web backends (CRUD) — Go, Node, Rust are much faster to ship
- Data science / ML — Python ecosystem dominates
- Full GUI apps — keep only the core in Zig, use native for chrome (Ghostty pattern)
- Long-term stability critical — 1.0 is not out. Every version bump may demand migration
One-line conclusion: Zig in 2026 is "a serious language in a serious experimental stage". Bun, TigerBeetle, and Ghostty shipping before 1.0 is the proof. Do not wait for 1.0 — try it in a low-stakes corner, then decide.
16. References
- Zig official site: https://ziglang.org/
- Zig 0.14 release notes: https://ziglang.org/download/0.14.0/release-notes.html
- Zig Software Foundation: https://ziglang.org/zsf/
- Andrew Kelley blog: https://andrewkelley.me/
- Zig language reference: https://ziglang.org/documentation/master/
- Zig build system guide: https://ziglang.org/learn/build-system/
- Zon package manifest: https://ziglang.org/learn/build-system/#zig-package-manager
- Bun: https://bun.sh/
- Bun on GitHub: https://github.com/oven-sh/bun
- TigerBeetle: https://tigerbeetle.com/
- TigerBeetle design docs: https://docs.tigerbeetle.com/
- TIGER STYLE coding guide: https://github.com/tigerbeetle/tigerbeetle/blob/main/docs/TIGER_STYLE.md
- Ghostty: https://ghostty.org/
- Ghostty on GitHub: https://github.com/ghostty-org/ghostty
- ZLS (Zig Language Server): https://github.com/zigtools/zls
- Roc language: https://www.roc-lang.org/
- uv (Astral, uses zig cc): https://docs.astral.sh/uv/
- "Can Zig replace C/C++" Andrew Kelley talks: https://www.youtube.com/results?search_query=andrew+kelley+zig
- Bun internal Zig usage articles: https://bun.sh/blog
- Zig community Discord: https://discord.gg/zig