Zig:C
A new foundation for systems programming with no hidden control flow. No destructors, no exceptions, no operator overloads, no preprocessor — what you read is what the CPU runs. Eleven years and still pre-1.0, yet it already carries Bun, TigerBeetle, Ghostty.
still pre-1.0 · ship-when-ready
JS runtime · written in Zig
2-year ZSF pledge · 2025-10
every alloc is visible
What is Zig
Zig is a systems language meant to share C's role while refusing C's traps. It is not a "safe Rust" or a "friendly C++" — its design goal is that reading the source tells you exactly what runs: no destructors, no exceptions, no operator overloading, no macros. Every allocation routes through an explicit Allocator.
Same tier as C. Manual memory, readable assembly, fits kernel / embedded / DB-internals work.
No destructors, exceptions, RAII, or operator overloading. The semantics of a line are exactly what's written — Zig's central design tenet.
Run arbitrary Zig at compile time. Generics, reflection, metaprogramming are not separate languages — comptime covers all of it.
@cImport consumes C headers natively; zig cc is a cross-platform C compiler and toolchain — more ergonomic than stock GCC / Clang.
// Classic C bug: forgot to free
char* read_file(const char* path) {
FILE* f = fopen(path, "r");
if (!f) return NULL;
char* buf = malloc(1024);
if (fread(buf, 1, 1024, f) < 0)
return NULL; // leaks buf and f!
fclose(f);
return buf;
}fn readFile(a: std.mem.Allocator, path: []const u8) ![]u8 {
const f = try std.fs.cwd().openFile(path, .{});
defer f.close(); // closes on every exit
const buf = try a.alloc(u8, 1024);
errdefer a.free(buf); // only on error path
_ = try f.readAll(buf);
return buf;
}History : Timeline
What started in 2015 as Andrew Kelley's side project and is still pre-1.0 by 0.16 in 2026 — yet Bun, TigerBeetle and Ghostty have all bet core systems on it. Eleven years, traced.
- 2015·12
Andrew Kelley starts Zig
December: Andrew Kelley pushes the first commit of Zig to GitHub. He was building an embedded audio engine called GenesisDAW at the time and had grown tired of C's undefined behavior, the C preprocessor, and the build system tax — so he set out to design a language "worthy of replacing C."
- 2016·02
First public unveiling
Andrew first presents Zig at small hackaday-style meetups: no hidden control flow (no RAII, no exceptions, no operator-overloaded silent allocations) plus
comptime(arbitrary Zig code at compile time as metaprogramming). The room's reaction: "isn't this just better C?" — his answer: "Yes. That's exactly the point." - 2017·08
0.1.0 — self-hosting begins
0.1.0 ships in August. The Zig compiler started in C++; by this point it could mostly bootstrap itself. The same year Andrew starts working on Zig full-time, funded by Patreon donations from individuals.
- 2019·09
zig ccarrives0.5.0 bundles LLVM clang directly into the
zigbinary:zig ccis a drop-in cross-platform C compiler — and a cross-compilation toolchain by default. One command on macOS produces a Linux ARM64 binary. This single trick recruited a wave of "I just need to compile some C" users to Zig. - 2020·06
ZSF founded
The Zig Software Foundation registers as a US 501(c)(3) non-profit. Andrew becomes its chair. Zig stops being "just a GitHub repo" — it now has a bank account, a board, and the ability to take grants and pay engineers.
- 2021
Bun begins — a JS runtime in Zig
Stripe engineer Jarred Sumner decides to write a faster Node.js alternative in Zig: Bun. Zig was at 0.8 then. His bet: "Zig's comptime plus easy C++ interop with JavaScriptCore lets a two-person team build something that competes with V8/Node."
- 2022·07
Bun goes public + TigerBeetle endorsement
July: Bun 0.1 ships publicly — "a Node alternative written in Zig, 3× faster cold start" goes viral on Twitter. The same year TigerBeetle (financial-grade distributed OLTP database) announces it's full-stack Zig. Together these silenced half of the "is Zig a toy?" debates.
- 2023·08
0.11 — async temporarily removed
0.11 removes the
async/awaitkeywords from the language: the team admits the previous stackless-coroutine design was flawed and would rather cut it than ship it broken to 1.0. The community split — but admiration won out: "a language willing to publicly say its own design was wrong." - 2024·09
Ghostty 1.0 made public
Mitchell Hashimoto (founder of HashiCorp / Terraform) reveals Ghostty, a terminal emulator he had quietly built in Zig over three years. Native macOS / Linux GUI, GPU-accelerated, config-as-code. The HN front page exploded. Mitchell: "Zig lets me share one core between Apple frameworks on macOS and GTK on Linux."
- 2025·10
Synadia + TigerBeetle pledge $512K
Synadia (the company behind NATS) and TigerBeetle jointly pledge $512,000 to the Zig Software Foundation over two years. The largest industry donation ZSF has ever received — signaling Zig isn't surviving on individual Patreon any more; it has cash flow to pay a real core team.
- 2025·11
Anthropic acquires Bun
Anthropic acquires Bun. Jarred Sumner joins Anthropic; Bun continues development as part of the Claude Code stack. The first time a Zig-built project becomes core infrastructure inside a major AI company.
- 2026·04
0.16 ships — still pre-1.0
April 14: 0.16.0 ships. Zig remains pre-1.0: breaking changes allowed every release, but the core language has stabilized. The 1.0 roadmap is now explicit — finish the new IO model, the async rework, the package manager, and the self-hosted backend first. The team would rather be late than ship a flawed 1.0.
Language Essentials : ZigAlphabet
Zig isn't a kitchen sink. The whole language stands on the eight primitives below — and comptime alone replaces what other languages call templates, generics, reflection, and macros.
comptime metaprogramming
Run arbitrary Zig code at compile time. Generics, reflection, templates — all expressed in one syntax. No second meta-language.
fn List(comptime T: type) type {
return struct {
items: []T,
len: usize,
};
}
const L = List(u32);
// L is a struct type, generated at compile timeError union !T
Errors are part of the type system. No exceptions, no hidden traps. Any fallible function returns !T.
fn parseInt(s: []const u8) !u32 {
if (s.len == 0) return error.Empty;
return @intFromString(s);
}
const n = try parseInt("42");
// `try` unwraps or propagates the errordefer / errdefer
No destructors. Cleanup is declared explicitly at the call site. errdefer runs only on the error path — graceful "half-constructed" handling.
const file = try open("x.txt");
defer file.close();
const buf = try alloc.alloc(u8, 1024);
errdefer alloc.free(buf);
// freed only if the rest failsExplicit allocators
No built-in heap. Every allocating function takes an Allocator parameter — arena / GP / page / fixed-buffer, your call. The caller owns the policy.
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const alloc = gpa.allocator();
const list = try std.ArrayList(u32).init(alloc);
// allocator is a value, not a globalNo hidden control flow
A call is a call — no destructors, no exceptions, no operator overloads. What you read is what runs.
// Zig: a + b is integer add. Period.
const c = a + b;
// C++: a + b might call op+ which
// might allocate, throw, log, or worse.
// Zig allocations are always literally:
try alloc.create(T)@cImport + zig cc
Zig consumes C headers directly. zig cc is also a cross-platform C toolchain — compile a macOS source to Linux ARM64 in one command.
const c = @cImport({
@cInclude("sqlite3.h");
});
var db: ?*c.sqlite3 = null;
_ = c.sqlite3_open("x.db", &db);
// shell:
// zig build-exe x.zig -target aarch64-linuxpacked struct + bit fields
No C-style "implementation-defined" alignment. packed struct gives you bit-exact memory layout — perfect for network protocols and hardware registers.
const RGB = packed struct {
r: u5,
g: u6,
b: u5,
}; // exactly 16 bits
const px = RGB{ .r = 31, .g = 0, .b = 0 };Less is more
Zig has fewer than 50 keywords. You can read the full language reference in one evening. Yet each primitive — allocators, error unions, comptime, packed structs — scales all the way to production code.
"Zig's goal isn't to be the most powerful language — it's to be the one you can trust the most." — Andrew Kelley
Why Zig : WhyZig
Zig is not for people who want a "safer Rust." It is for people who want systems code that they can actually read. Simple isn't easy — but simple lets you stare at the source and say "I know exactly what this does."
No hidden allocations
Read one line and you know if it allocates. All allocations route through an explicit Allocator — perf incidents have nowhere to hide.
const x = try alloc.create(T);
// allocations are always visibleSource you can actually read
No destructors, no exceptions, no operator overloading, no preprocessor. The control flow you read is the control flow the CPU executes.
// what you see = what runs
defer file.close();
// no surprise hookscomptime unifies generics + reflection
No second meta-language for templates or traits. comptime just runs ordinary Zig code to generate types, validate shapes, build tables. Metaprogramming has never been this readable.
comptime var i: u8 = 0;
inline while (i < 8) : (i += 1) { ... }Cross-compilation out of the box
zig build-exe x.zig -target aarch64-linux. Zig bundles LLVM and libc — no sysroot, no cross-toolchain install. Bun ships its docker images this way.
$ zig build-exe app.zig
--target=aarch64-linux
// done. zero extra setupErrors are values, not exceptions
!T marks fallibility in the signature. The caller either trys to propagate or catches to handle — the compiler won't let you forget.
const v = parse(s) catch 0;
// or `try parse(s)` to propagateRespect for C
Zig aims to fill C's role, not preach against it. @cImport reads C headers natively; zig cc beats GCC on UX. Zig is C's ally, not its rival.
const c = @cImport({
@cInclude("png.h");
});
// C headers, zero glueBuilt for critical paths
TigerBeetle bet a financial-grade OLTP DB on Zig. Bun bet a 100k+-user JS runtime on Zig. Ghostty bet a cross-platform GUI terminal on Zig. None of them blew up.
// TigerBeetle: 100% Zig
// Bun: ~770k LoC Zig
// Ghostty: ~140k LoC ZigBuild system is also Zig
build.zig is not Make, CMake, or Bazel — it's just Zig code. One syntax, one type system, source to build graph with no second language.
// build.zig
pub fn build(b: *std.Build) void { ... }An ecosystem before 1.0
Zig is at 0.16, still allowing breaking changes per release. Yet Bun / TigerBeetle / Ghostty / Roc / pg_turso / mach run in production today. Stability comes from engineering discipline, not a version label.
// 0.16 (2026-04)
// 1.0 — when it's ready, not beforeWho's Using : Production
Zig isn't 1.0 yet — but the projects below have already bet core systems on it. Bun (JS runtime), TigerBeetle (financial OLTP DB), Ghostty (cross-platform terminal) — none of these are toys.
The Bun · TigerBeetle · Ghostty Era : Zig in Prod
In the 2010s "Zig" was something only HN fringe nerds wrote. The wind flipped in 2025: Anthropic bought Bun, TigerBeetle is running financial data, Ghostty became developers' favorite terminal overnight — Zig-built projects entered the core stack of an AI company for the first time.
"Zig lets me look at 5,000 lines and say "I know exactly what this does." That's not possible in C++, where operator overloads, constructors / destructors and template instantiation hide the real control flow somewhere off the page. Zig refuses to hide. The cost is a bit of verbosity; the payoff is that a year later I can still maintain it.
In 2026 when the Bun team posted their experimental Zig→Rust port plan, they disclosed roughly 770,000 lines of Zig across 1,600 files. The single largest Zig codebase in production today.
TigerBeetle is a financial-grade distributed OLTP DB doing millions of accounting ops per second. Storage engine, raft consensus, client wire protocol — all Zig. October 2025 they jointly pledged $512K to ZSF with Synadia.
The largest industry donation ZSF has ever received. Two-year, $512,000 pledge — for the first time the foundation can pay a real core team rather than running on Andrew's personal Patreon.
Bun
Stripe engineer Jarred Sumner started Bun as a one-person project in 2021 — picking Zig for "comptime plus C++ interop with JavaScriptCore." Acquired by Anthropic in November 2025. Today Bun powers parts of the Cursor / Midjourney / Claude Code generation of AI tools.
- ~770k lines of Zig · 1,600 files
- 3× Node's cold-start · custom TLS / DNS / HTTP
- 89k+ GitHub stars · de-facto Node alternative on npm
Footnote: in 2026 the Bun team published an experimental Zig→Rust port plan. Jarred's own line: "we haven't decided. We're just trying. There's a very high chance all this code gets thrown out completely."
// A Bun hot-path looks roughly like this
pub fn readBody(
self: *Request,
a: std.mem.Allocator,
) ![]u8 {
const len = self.contentLength orelse
return error.NoLength;
const buf = try a.alloc(u8, len);
errdefer a.free(buf);
_ = try self.socket().readAll(buf);
return buf;
}
// explicit allocator + try + errdefer
// the same shape across 5,000 core linesProjects already running on Zig
Ghostty · Mitchell Hashimoto
HashiCorp / Terraform founder Mitchell Hashimoto quietly built a cross-platform, GPU-accelerated terminal emulator in Zig over three years; the 2024 unveiling owned HN's front page. Mitchell on picking Zig: "I needed one core to drive both macOS AppKit and Linux GTK — Zig's C interop made that possible."
In 2025 Ghostty became a non-profit, and libghostty was extracted as a standalone open Zig module — dozens of projects, commercial ones included, now depend on it. What started as one author's side project grew into infrastructure.
Mitchell again: "Zig doesn't surprise me with delight every day. But it never surprises me with horror either. For systems software, that's the correct trade."
// Ghostty: one Zig core driving two GUI stacks
const Surface = switch (builtin.os.tag) {
.macos => @import("apple/Surface.zig"),
.linux => @import("gtk/Surface.zig"),
else => @compileError("unsupported"),
};
pub fn draw(s: *Surface) !void {
// same logic across platforms
try s.renderer().flush();
}
// comptime switch · zero runtime costIn one line: Zig's current position isn't "may one day replace C." It is "already running on production critical paths" — the language is just modest enough not to call itself 1.0 yet.
vs Rust / C : Zig vs Rust vs C
Three "systems" languages, three worldviews. Rust bets on memory safety enforced by the type system, C bets on maximum freedom for the programmer, Zig bets on no hidden control flow. The table below makes it clear that Zig isn't competing with Rust — they're not actually trying to do the same thing.
| C | Rust | Zig | |
|---|---|---|---|
| Memory safety | Programmer discipline only | Borrow checker, statically guaranteed | Explicit alloc + ReleaseSafe sanitizers |
| Error handling | errno / return codes / docs | Result<T, E> | !T |
| Generics / metaprog | Macros + void* + prayer | traits + const fn + macros | comptime handles all of it |
| Hidden control flow | setjmp / signals | Drop / panic / Deref impls | None (core promise) |
| Compile-time alloc | None | const fn, restricted | comptime runs the full language |
| C interop | It is C | bindgen + unsafe + cargo build.rs | @cImport reads C headers natively |
| Cross compile | Install a pile of sysroots + toolchains | cargo --target | zig build-exe -target ... works out of the box |
| Build system | Make / CMake / Autotools / ... | Cargo (universal) | build.zig — itself just Zig code |
| Ecosystem maturity | 50 years | Took off in 2015 | Pre-1.0 |
| LLM-friendliness | UB-prone · models easily slip | Strict compiler, rich diagnostics | No hidden flow → models read it cleanly |
| Learning curve | A week to start, a lifetime of footguns | Steep, a month or two | Gentle — read the reference in one evening |
| Design philosophy | Maximum freedom | Type system as guardrail | What you read is what runs |
Outlook : TheRoadToOne
"Eleven years and still not 1.0" is Zig's most-mocked stat. Yet across those eleven years, companies have bet financial databases, a JS runtime, and a cross-platform terminal on it in production. 1.0 isn't a marketing milestone — it's the moment promises are paid in full.
The road from 0.16 to 1.0
0.16 (April 2026) is the version where Andrew publicly committed to driving toward 1.0. Remaining hard problems: a new unified IO model (sync / async on one substrate), a self-hosted backend (kicking the hard LLVM dependency), and finishing the package manager. The team's line: "1.0 isn't about hitting a deadline, it's about delivering a promise."
Rust took 5 years from 0.x to 1.0; Zig has spent 11. The trade-off is that by the moment Zig hits 1.0, every production-touching design has already been beaten on by production — not patched after the fact.
The new IO model
After cutting async in 2024, the team went back to the drawing board. The new design: every function takes an Io parameter — exactly like Allocator. The same business logic runs on blocking, non-blocking, or coroutine schedulers, picked at the call site. Radical, but consistent with the language's grain.
Self-hosted backend
Today release-mode Zig still goes through LLVM. The team is writing native x86_64 / aarch64 backends — debug builds will skip LLVM entirely and compile an order of magnitude faster. A massive dev-loop win.
Bun · post-Anthropic
November 2025: Anthropic acquires Bun. Jarred Sumner joins. Bun keeps shipping inside Claude Code's stack — meaning Anthropic's AI tool chain has Zig in the basement. The Bun team also pushed an experimental Zig→Rust port; Jarred's line: "we haven't decided. We're just trying."
$512K + the ZSF payroll
October 2025: Synadia + TigerBeetle pledge $512K. Stacked on top of Bun and Patreon, ZSF now pays a real core team rather than relying on "Andrew alone." Governance has crossed into institutional territory.
"Readable" in the AI era
In the era of LLM-written code, Zig's "no hidden control flow" turns out to be an asset: a model reading Zig doesn't have to imagine "this implicitly destructs" or "this might throw." The code looks like what runs. Andrew hasn't marketed this; the community has — Zig as an LLM-friendly systems language.