// 2015 — 2026 · Andrew Kelley · Zig Software Foundation

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.

0.16latest, April 2026
still pre-1.0 · ship-when-ready
100k+Bun GitHub stars
JS runtime · written in Zig
$512KSynadia + TigerBeetle
2-year ZSF pledge · 2025-10
0hidden allocations
every alloc is visible
comptime!Tdefererrdefer@cImporttrypackedAllocatorzig ccno hidden@TypeOfbuild.zig
scroll
01

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.

Low-level systems

Same tier as C. Manual memory, readable assembly, fits kernel / embedded / DB-internals work.

No hidden flow no-hidden

No destructors, exceptions, RAII, or operator overloading. The semantics of a line are exactly what's written — Zig's central design tenet.

comptime metaprog

Run arbitrary Zig at compile time. Generics, reflection, metaprogramming are not separate languages — comptime covers all of it.

C interop with-C

@cImport consumes C headers natively; zig cc is a cross-platform C compiler and toolchain — more ergonomic than stock GCC / Clang.

file.cC
// 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;
}
file.zigZig
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;
}
02

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.

  1. 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."

  2. 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."

  3. 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.

  4. 2019·09

    zig cc arrives

    0.5.0 bundles LLVM clang directly into the zig binary: zig cc is 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.

  5. 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.

  6. 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."

  7. 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.

  8. 2023·08

    0.11 — async temporarily removed

    0.11 removes the async / await keywords 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."

  9. 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."

  10. 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.

  11. 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.

  12. 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.

03

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.

A

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 time
B

Error 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 error
C

defer / 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 fails
D

Explicit 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 global
E

No 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)
F

@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-linux
G

packed 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

04

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 Allocatorperf incidents have nowhere to hide.

const x = try alloc.create(T);
// allocations are always visible

Source 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 hooks

comptime 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 setup

Errors 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 propagate

Respect 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 glue

Built 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 Zig

Build 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 before
05

Who'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.

06

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.

— Andrew KelleyCreator of Zig / Chair of ZSF · paraphrased from interviews
770k
Lines of Zig in Bun's repo

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.

100%
TigerBeetle: 100% Zig

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.

$512K
Synadia + TigerBeetle pledge

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.

SPOTLIGHT

Bun A JavaScript runtime in Zig

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
  • 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 lines

Projects already running on Zig

Bun
JS/TS runtime · ~770k LoC Zig
TigerBeetle
Financial OLTP DB · 100% Zig
Ghostty
M. Hashimoto terminal emulator
Roc
Functional lang · compiler in Zig
mach
Zig game / GPU framework
Limbo (Turso)
SQLite-compatible rewrite
pg_turso
Postgres extension · Zig
http.zig
High-perf community HTTP lib
zls
Zig Language Server
Uber
Uses zig cc as cross-toolchain
River
Wayland tile compositor · Zig
Buzz
Dynamic lang · VM in Zig
Capy
Zig cross-platform GUI lib
zigly
Fastly Compute@Edge SDK
TLS in Zig
Bun rolls its own TLS stack
libghostty
Reusable Ghostty terminal core
SPOTLIGHT 2

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 cost

In 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.

07

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.

CRustZig
Memory safetyProgrammer discipline onlyBorrow checker, statically guaranteedExplicit alloc + ReleaseSafe sanitizers
Error handlingerrno / return codes / docsResult<T, E>!T
Generics / metaprogMacros + void* + prayertraits + const fn + macroscomptime handles all of it
Hidden control flowsetjmp / signalsDrop / panic / Deref implsNone (core promise)
Compile-time allocNoneconst fn, restrictedcomptime runs the full language
C interopIt is Cbindgen + unsafe + cargo build.rs@cImport reads C headers natively
Cross compileInstall a pile of sysroots + toolchainscargo --targetzig build-exe -target ... works out of the box
Build systemMake / CMake / Autotools / ...Cargo (universal)build.zig — itself just Zig code
Ecosystem maturity50 yearsTook off in 2015Pre-1.0
LLM-friendlinessUB-prone · models easily slipStrict compiler, rich diagnosticsNo hidden flow → models read it cleanly
Learning curveA week to start, a lifetime of footgunsSteep, a month or twoGentle — read the reference in one evening
Design philosophyMaximum freedomType system as guardrailWhat you read is what runs
08

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.

HOT · 2026-04

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.

Zig 0.1 → 0.1611 yrs
Rust 0.1 → 1.05 yrs
IO

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.

BACKEND

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

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."

FUNDING

$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.

AI

"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.