Zig's ELF linker is no longer a toy — and it's coming for LLD

4 min read 2 sources explainer
├── "Zig's self-hosted ELF linker has crossed a maturity threshold and can now replace LLD for most Linux targets"
│  ├── Zig Dev Blog (ziglang.org devlog) → read

The devlog argues that with parallelized relocations, a non-quadratic merge-section algorithm, and working in-place incremental updates, the self-hosted linker now handles the vast majority of x86_64-linux and aarch64-linux binaries without LLD. The team is explicitly removing the 'not yet usable for anything serious' caveat that accompanied earlier releases.

│  └── kristoff_it (Hacker News, 194 pts) → read

By submitting the devlog and surfacing it to 194 points, kristoff_it amplifies the position that this is a milestone release worth the developer community's attention. The framing treats the linker work as a long-awaited graduation from experimental status.

├── "Incremental linking, not raw throughput, is the breakthrough that matters for developer workflows"
│  └── top10.dev editorial (top10.dev) → read below

The editorial emphasizes the 30–80ms incremental relink times versus 1.5–3 second cold LLD links as the most consequential change, framing in-place section rewrites as the real productivity win. It argues that link time dominates incremental rebuild latency on non-trivial C++/Rust projects, so a working incremental mode reshapes the inner dev loop more than parallelism alone would.

└── "This work has implications beyond Zig — it pressures the broader LLD-dominated toolchain ecosystem"
  └── top10.dev editorial (top10.dev) → read below

The editorial situates Zig's linker against LLD (the default for Clang, Rust, and the modern toolchain world) and mold (which proved 4–10x speedups were possible on Chromium-class workloads). By benchmarking against LLD 18 and mold 2.32 on real targets like ripgrep and SQLite, Zig is positioning its linker as a serious competitor in a space where link time has become the dominant build-latency factor.

What happened

The Zig devlog entry for 2026-05-30 landed quietly and then promptly hit 194 points on Hacker News. The headline: the self-hosted ELF linker, which has been the long pole in Zig's tent for years, just crossed a threshold. As of the 0.16-dev cycle, Zig can link the vast majority of x86_64-linux and aarch64-linux binaries without invoking LLD at all, and it does so with first-class incremental linking and parallelized relocation resolution.

The specific changes in this devlog: a rewrite of the relocation engine to process relocations in parallel across input sections, a new merge-section algorithm that deduplicates string tables and constant pools without the quadratic blowup the old path had, and — most consequentially — a working in-place update mode that rewrites only the changed sections of an output binary rather than emitting a new one from scratch. Kelley's notes claim incremental relinks in the 30–80ms range for binaries where a cold LLD link takes 1.5–3 seconds. The devlog includes benchmarks against LLD 18 and mold 2.32 on a handful of real-world targets: ZLS itself, a stripped-down ripgrep, and a Zig-compiled SQLite.

For context, this is the same linker that, eighteen months ago, the Zig team was openly describing as "not yet usable for anything serious." The 0.13 release shipped it behind a flag with the explicit warning that LLD was still the default for a reason. That asterisk is being removed.

Why it matters

Linkers are one of those pieces of infrastructure that nobody thinks about until they dominate your build time, and then you think about nothing else. LLD is the default backend for Clang, Rust, and most of the modern toolchain world, and "link time" is the single largest contributor to incremental rebuild latency on any non-trivial C++/Rust project. mold proved in 2021 that you could go meaningfully faster by aggressively parallelizing — Rui Ueyama benchmarked mold at 4–10x LLD on Chromium-class workloads — but mold is a drop-in replacement, not a compiler-aware linker. It doesn't know which sections are dirty between builds because the compiler doesn't tell it.

The Zig approach is different and arguably more interesting: because the compiler and the linker live in the same process and share data structures, the linker can be told exactly which functions changed. The compiler emits per-decl object sections, the linker keeps a section map across builds, and an incremental rebuild touches only the dirty ranges in the output ELF. This is closer to what hotpatch systems like Live++ do for game development than to traditional batch linking. It's also closer in spirit to what Jai has been demoing for years and what the Mojo team has gestured at — except Zig actually shipped it and you can apt-get a binary today.

The HN thread (194 points, ~200 comments) is the usual mix, but two threads of reaction stand out. First, Rust folks asking the obvious question: when does this become a Rust backend? The answer, per Kelley in a reply: "it already kind of is, if you build rustc with `-C linker=zig`." Several commenters reported using `zig cc` and `zig ld` as a cross-compilation toolchain for Rust workspaces, and the new ELF backend means that path no longer falls back to LLD for the link step. Second, the mold comparison. Kelley is careful to note that mold is still faster on cold links for very large binaries — Chromium-scale — but Zig wins on incremental, which is the metric that actually shows up in your iteration loop.

There's also a quieter implication the devlog doesn't spell out. The reason Zig has been able to do this — and the reason Rust, with vastly more engineering hours, hasn't — is that Zig made the architectural choice early to treat the linker as a compiler pass rather than a separate program. That decision looked weird in 2020. It looks prescient now.

What this means for your stack

If you're shipping Zig code, the practical advice is: stop passing `-fLLD` and let the default backend run. The devlog notes a handful of edge cases that still fall back to LLD (specifically, some LTO configurations and a few exotic relocation types on aarch64), but the common path is now self-hosted.

If you're shipping Rust or C++, the more interesting question is whether you should be using `zig cc` as your build driver. The pitch has been around for a while — Loris Cro wrote it up in 2021 — but the value proposition was mostly "easier cross-compilation." That's still true, and it's a real win for anyone shipping musl static binaries or doing aarch64-from-x86 builds. The new pitch is that `zig cc` plus the self-hosted linker is, for incremental rebuilds, faster than your current toolchain even if you're not cross-compiling. It costs you nothing to test on a side branch: replace `cc` with `zig cc` in your Makefile and time a few iterations. The worst case is you learn it doesn't help your specific workload.

The one place to be cautious: production release builds. Zig's linker is new code, and new linker code finds new linker bugs. Use it for dev loops; gate your release pipeline on whichever linker your distro packages until 0.16 stable ships and a few months of bug reports accumulate. This is the same advice anyone gave for mold in 2022, and mold turned out fine.

Looking ahead

The broader story here is that the toolchain layer of systems programming is being rewritten, in the open, by small teams that are willing to violate the layering assumptions LLVM was built on. mold did it for linking-as-batch-job. Zig is doing it for linking-as-compiler-pass. Cranelift is doing it for codegen-as-library. None of these are research projects anymore — they're shipping, and the cumulative effect is that the 30-year-old assumption that "the linker is a separate program you call at the end" is finally cracking. The 5-second link is starting to look as quaint as the 30-second compile.

Hacker News 221 pts 95 comments

Zig ELF Linker Improvements Devlog

→ read on Hacker News
Devblogs 66 pts

ELF Linker Improvements in Zig

→ read on Devblogs
bpavuk · Hacker News

I am so used to thinking that Zig, Rust, and the likes are only viable in niches where C is viable, but no. not anymore at least - once this linker and incremental compilation on other targets land, Zig will become THE C replacement and that will let me iterate at the speed of JS or Python with perf

onlyrealcuzzo · Hacker News

I've been building a memory safe language that transpiles to Zig with a Go-like runtime that can run interpreted (no GC) or compiled - high-level that feels like Ruby but with incremental typing like TypeScript.The Zig team between 0.16 and this has really made me glad I chose Zig as the target

librasteve · Hacker News

There has been some speculation about porting the Raku backend (Meta-Object Aware Runtime Virtual Machine - MOARVM)from C to Zig. For example the wider set of Zig Hash options could be a big optimization.Since you ask, the front end is self hosting in NQP and with the ripening RakuAST project increa

teabee89 · Hacker News

This is the promise that blew my mind the first time I heard about Zig years ago. So happy to see this become reality!

derefr · Hacker News

So, this linker does fast incremental linking, which is great for development iteration speed.But I assume that any kind of incremental linking, is mutually exclusive with link-time optimization? I.e. you'd never want to use this option for a release build?

// share this

// get daily digest

Top 10 dev stories every morning at 8am UTC. AI-curated. Retro terminal HTML email.