Anna's Articles

Returning to Zig

From Zig to Rust to Zig again

2026-06-10 · 9 min · #computing

Zig is rising in popularity. It hasn't yet seized the space occupied by even Rust or Go, much less C, but it has been adopted by a few major projects and countless smaller ones. As such, it's becoming an important language for the future. having been interested in Zig for several years, I decided to check back in on the language and see how I feel about it today.

Why I Loved Zig

I was first introduced to Zig in 2020 by a programming mentor. They were passionate about this little new language with compile time code execution and beautiful yet simple forms of abstraction. I decided to check it out as well.

At the time, I was still deep in learning C. I enjoyed the power over my computer, but was frustrated by the dated abstractions and worse tooling. Zig, while new and unstable, was promised as a replacement for C. That hooked me. Why learn C when I could learn the next language?

I watched more of Andrew Kelley's talks. Software Should Be Perfect was formative. It shaped what I viewed what a programming language—and software in general—should look like. In that talk, Andrew emphasized the importance of fallible, explicit memory allocations, no hidden control flow, and universal reusability. Those were all values I began to look for in any programming language.

So I switched to Zig. I wrote toy programming languages, experimented with literate programming tooling, and played with Web servers. I enjoyed working with Zig. It felt nicer than C but without the footguns.

Leaving for Rust

Zig kept breaking my code. I grew tired of the churn. I was a student without much time to keep my code updated to work with the latest version of the language. This was before anyzig made it trivial to handle multiple versions of Zig on the same system. I often went months between working on particular projects. When I returned I would have to make major refactors I didn't understand to get them working again.

The Zig ecosystem was also immature. As a new programmer, I didn't have the skills to implement everything on my own. There were few libraries for anything and few examples to teach me. The standard library kept changing. Every time I thought I understood the way its abstractions worked, they would change. It didn't help that the default documentation was unstable.

So I left for Rust. At that point, Rust had been stable for years, with a strong ecosystem behind it. Learning it was a pain—I wanted to give up several times—but once I learned it, it worked. That was invaluable for me. A fast, lower-level programming language with the expressiveness I needed without the cost of instability. It also forced me to develop a mental memory model that served me well for languages with fewer built-in checks.

As a benefit, given the code didn't panic, I was able to write reusable code without hidden control flow or a garbage collector. While it did hide memory allocations and made working with C difficult, it brought me almost full circle to why Zig was appealing.

I love Rust. I enjoy working in it to this day. The abstractions bring me joy. Unfortunately, I'm concerned by some of the directions the project is going.

Why I'm Returning

Rust still isn't perfect. While it provides many of the things I was looking for in a programming language, it isn't the most ideal for making the reusable programs I want to make. FFI is difficult. Cross-compilation is irritating. Hidden, infallible memory allocations haunt me. Being shackled to LLVM it will be a long time, if ever, until it supports as many platforms as C.

Additionally, its governance still irks me. It has several giant corporate foundation members which almost certainly influence the way Rust is developed. When the biggest companies in the world are each giving you hundreds of thousands of dollars per year, you probably don't want to upset them.

Regardless of these, I was willing to accept these until the scourge of vibecoding hit the open source community. To my horror, many software projects were accepting LLM-generated code. I had thought LLMs were unpopular among developers. I figured the only people who used them were forced to by their employers.

When this happened, maintainers and users alike wrote or demanded LLM policies. Zig banned them from the project entirely. Meanwhile, Rust took its time. They did some polling and the general sentiment in the community was anti-LLM, but they weren't ready to make an official policy quite yet.

When they finally made a proposal, it included the notorious moderation policy:

No comment on this PR may mention the following topics:

It has since been removed after backlash, but the fact that this was the case at all caused me to lose trust in the Rust project going forward. I love the language, but am frustrated with the governance.

The policy itself is fine. It almost entirely restricts LLMs. It cuts down on most of the slop. It's not nearly as severe as Zig's policy, but it's workable. But this whole experience got me to explore Zig as a programming language seriously for the first time in a few years.

Zig in 2026

The first thing I noticed is that the language is still unstable. When I tried to get started with examples I found on the Web for 0.16.0, I learned they were outdated. I learned that the best way to be productive in Zig is to keep a copy of the standard library source available and get familiar with it.

I am of no illusions as to Zig's stability. Zig 0.17.0 will be released soon. It will break the build system of every project. I understand that the maintainers intend to shift towards stabilization and these breakages are part of that.

Thankfully, the language hasn't changed too much since 2020. I found that most of my instincts still held true. A few things in the library had been reworked, but the code is easy to read and I found my way around. I am confident that today's Zig code will be just as recognizable in six years.

Another thing I noticed is that Zig has a package manager now. I believe it was in development when I left. I recall using git submodules for dependency management. The built-in tooling is much nicer. Projects can define dependencies via git and tarballs. Vendoring works effortlessly. Everything just works.

There still isn't an extensive ecosystem, but that's never been what Zig was aiming for. There is no official package registry for Zig projects for a reason. We don't need another NPM or crates.io. For me, Zig has struck the perfect balance.

But Memory Unsafety!

I'm aware that Zig does not provide the same memory safety guarantees as Rust. Unfortunately, it's a tradeoff they chose to make in favor of simplicity. The complexity of Rust's affine types wasn't worth the safety benefits.

That's not to say that they have given up on safety. Zig is safer than unsafe Rust. So when you find yourself in a situation where you'd have to write unsafe Rust anyway, Zig may be a better option.

Zig is also working to make the language more safe. Their approach is focused on release modes instead of unsafe sections of code. Currently, Zig's ReleaseSafe mode crashes on failed asserts and initializes all memory. But Andrew Kelley is interested in pushing it further, shipping ReleaseSafe with something like Fil-C. While this wouldn't provide the compile-time memory safety of Rust (assuming you avoid unsafe), this wouldn't be the death spiral some suggest it to be.

Memory safety is a spectrum. There isn't one approach to memory safety that works best in all situations. Zig's is to make ReleaseSafe as safe as possible at runtime and then test and fuzz it to ensure correctness. Any unchecked illegal behavior should be found then. After its correctness is demonstrated the binary should be safe to ship in another release mode.

This approach has some drawbacks compared to Rust's model, but it's not strictly inferior, especially when Zig strives for simplicity Rust could only dream about. There are many programming languages and you can choose the one that works best for your use-case. If compile-time memory safety is worth the cost of complex type systems and long compile times, then go for it. But that's not the case for every person in every situation.

Zig's memory safety model extends to its philosophy of assertions. Instead of disabling assertions in ReleaseFast, Zig trusts that you have done the testing required to prove that your assertions are correct and those paths unreachable, allowing Zig to optimize code.

Zig demands perfection, but it gives tools to reach it.

Conclusion

So, with the standard library and release changelogs in hand, I'm prepared to tackle any software problem I face with Zig. I'll reach to my scripting language of choice when I don't want to deal with lower-level details, but Zig will be the powerhouse of my future software.

It's possible I won't stay with Zig. I may reach for Rust when I need its stability or its type system. It's possible I change my mind entirely about Zig's approach. Multiple languages can and should coexist.

But Zig represents a vision for software that resonates with me. Software that focuses on users not by ignoring software quality, but by embracing it. People deserve reliable, powerful software. This is especially true in the age of LLMs, where carefully crafted software is becoming rare and people are pressured to accept worsening slop.