# You Must Fix Your Asserts

**URL:** <https://ziggit.dev/t/you-must-fix-your-asserts/15827>\
**Category:** Media\
**Created:** [May 31, 2026, 1:21pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827 "2026-05-31T13:21:38Z")\
**Posts on this page:** 12\
**Page:** 2

<div class="post-metadata">

**Author:** ![jmctagger](https://ziggit.dev/letter_avatar_proxy/v4/letter/j/8dc957/32.png) [@jmctagger](https://ziggit.dev/u/jmctagger)\
**Post date:** [June 1, 2026, 2:41pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827/21 "2026-06-01T14:41:04Z")

</div>

> [@npc1054657282](#):
>
> I’m not quite sure what ‘disabling assertions in a production environment’ means.

I was wondering, too… but I think it means, at the simplest level, building ReleaseFast instead of ReleaseSafe, so that you get a crash rather than UIB. I _could_, however, also mean comptime-if’ing condition checking explicitly, to guarantee NO (side-effect) code is run at all if your `builtin.mode` is such-and-such.

---

<div class="post-metadata">

**Author:** ![jmctagger](https://ziggit.dev/letter_avatar_proxy/v4/letter/j/8dc957/32.png) [@jmctagger](https://ziggit.dev/u/jmctagger)\
**Post date:** [June 1, 2026, 2:55pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827/22 "2026-06-01T14:55:05Z")

</div>

> [@ericlang](#):
>
> `do_something() catch unreachable` can produce slower code than `do_something() catch @panic(...)`

Is this solely the fault of the one extra indirection (in assembly) that @pzittlau mentioned above? If so, this certainly seems to encourage use of `@panic()`, in particular, if you always intend these “asserts” to be never be disabled in production. If, otoh, you intend to use `ReleaseFast`, then it would still make sense to use `unreachable` for the performance _gain_ that _could_ come from optimized compilation given the `unreachable` hint (at the expense of possible UIB). (That is, that performance gain could outweigh the small hit for the extra indirection; though, you wouldn’t know by how _much_ without explicit testing or assy inspection…)

---

<div class="post-metadata">

**Author:** ![jumpnbrownweasel](https://ziggit.dev/user_avatar/ziggit.dev/jumpnbrownweasel/32/263_2.png) [@jumpnbrownweasel](https://ziggit.dev/u/jumpnbrownweasel)\
**Post date:** [June 1, 2026, 3:12pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827/23 "2026-06-01T15:12:43Z")

</div>

> [@spiffyk](#):
>
> a failed assertion `fork` the program into a second process, and immediately `abort` that new process

In the db I worked on in the past, a failed assertion would cause the process to print stack traces and exit. The error exit would be noticed by a very small/reliable parent process, which would restart it; if restarts occurred multiple times within a certain time interval, it would give up to avoid flooding the logs. The advantage of doing it in the parent process is that the child process may crash for reasons other than an assertion failure.

---

<div class="post-metadata">

**Author:** ![spiffyk](https://ziggit.dev/user_avatar/ziggit.dev/spiffyk/32/7202_2.png) [@spiffyk](https://ziggit.dev/u/spiffyk)\
**Post date:** [June 1, 2026, 3:23pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827/24 "2026-06-01T15:23:39Z")

</div>

Knot Resolver actually does both nowadays. They do the forking thing I mentioned earlier, and there is a manager daemon that (among other things) restarts crashed `kresd` processes.

One addendum to the forking mechanism: a single `kresd` process may have multiple DNS queries in flight at any given point in time. There are many asserts in the codebase that would realistically only affect a single query when they happen, making it much better to fail that particular query (usually by sending a `SERVFAIL` response to the client) and keep the other ones running. If the whole process were to crash, all queries that were in flight at that point would fail. Combine that with DNS running over UDP in many cases and you get a less than stellar user experience in the form of DNS resolution delays.

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [June 1, 2026, 3:38pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827/25 "2026-06-01T15:38:08Z")

</div>

Don’t know why but in my (and one other coders chess engine in ZIg) we noticed that the  
`io print catch unreachable` (just let the thing crash) produced a slower engine overall than panic.  
Of course this is not too much context, but after we both changed it, it produced a higher “nodes-per-second”.

---

<div class="post-metadata">

**Author:** ![charlie](https://ziggit.dev/user_avatar/ziggit.dev/charlie/32/1930_2.png) [@charlie](https://ziggit.dev/u/charlie)\
**Post date:** [June 1, 2026, 4:15pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827/26 "2026-06-01T16:15:31Z")

</div>

is the “debug” in the struct’s name a mistake/typo? cannot figure out why the words “debug” and “prod” are in the same sentence; debug objects have no business in prod/release iirc.

---

<div class="post-metadata">

**Author:** ![Justus2308](https://ziggit.dev/user_avatar/ziggit.dev/justus2308/32/5305_2.png) [@Justus2308](https://ziggit.dev/u/Justus2308)\
**Post date:** [June 1, 2026, 4:47pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827/27 "2026-06-01T16:47:06Z")

</div>

The extra indirection is only a thing if `unreachable` is lowered to a call to `std.lang.panic` which is only the case for `Debug` and `ReleaseSafe` modes. Otherwise it’s literally assumed to be unreachable by the chosen compiler backend.  
Even for `ReleaseSafe`, you’d only ever need to follow that one extra indirection if you plan to crash your program right after anyway so it shouldn’t impact the ‘happy path’ at all.

My guess is that the performance difference is caused by the LLVM optimizer prefering `@panic` over `unreachable` in that specific case for whatever reason.

---

<div class="post-metadata">

**Author:** ![alanza](https://ziggit.dev/user_avatar/ziggit.dev/alanza/32/6006_2.png) [@alanza](https://ziggit.dev/u/alanza)\
**Post date:** [June 1, 2026, 8:48pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827/28 "2026-06-01T20:48:25Z")

</div>

> [@jmctagger](#):
>
> > [@npc1054657282](#):
> >
> > I’m not quite sure what ‘disabling assertions in a production environment’ means.
> 
> I was wondering, too… but I think it means, at the simplest level, building ReleaseFast instead of ReleaseSafe, so that you get a crash rather than UIB. I _could_, however, also mean comptime-if’ing condition checking explicitly, to guarantee NO (side-effect) code is run at all if your `builtin.mode` is such-and-such.

I’d encourage you and @npc1054657282 to read the linked blog post again to check your understanding.

**“disabling assertions in a production environment”** means using a language like C or Rust, where asserts are implemented via macros which are therefore deleted from the compiled code in release builds. In Zig, the closest thing would be something like using `comptime if (builtin.mode != .ReleaseFast) std.debug.assert(...)` and then releasing `ReleaseFast` builds of your software.

**“leaving assertions in”** means—in the case of Zig—just using plain old `catch unreachable` and `std.debug.assert` in your code as ~~God~~ Andrew intended.

---

<div class="post-metadata">

**Author:** ![npc1054657282](https://ziggit.dev/user_avatar/ziggit.dev/npc1054657282/32/5790_2.png) [@npc1054657282](https://ziggit.dev/u/npc1054657282)\
**Post date:** [June 1, 2026, 9:15pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827/29 "2026-06-01T21:15:16Z")

</div>

> [@alanza](#):
>
> I’d encourage you and @npc1054657282 to read the linked blog post again to check your understanding.

I’m sorry, I got confused while reading the article because I feel that the ‘disabling assertions in the production environment’ mentioned in the text is not much different from the actual effect of assertions under the current ReleaseFast.

After thinking it over again, this article might be a response to the difference discussed earlier on the forum regarding whether side effects inside assertions would be retained. Overall, I feel that there isn’t a very big difference, and I feel this comment ‘disabling asserts in prod’ never clearly conveyed what it intended to express from the beginning.

---

<div class="post-metadata">

**Author:** ![alanza](https://ziggit.dev/user_avatar/ziggit.dev/alanza/32/6006_2.png) [@alanza](https://ziggit.dev/u/alanza)\
**Post date:** [June 1, 2026, 9:37pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827/30 "2026-06-01T21:37:11Z")

</div>

Ah, I see. I think you must have missed something. One _big_ difference that Loris alludes to in the blog post is that when code is present during compilation, the compiler knows about it. That is, when assertions are _retained_ in production, the compiler can use them as information when optimizing.

If those same assertions are removed (be it through `comptime if` or macros), the compiler cannot make the same assumptions. The entire point of the article (please read it again with this in mind) is that this is strictly worse than leaving them in.

---

<div class="post-metadata">

**Author:** ![npc1054657282](https://ziggit.dev/user_avatar/ziggit.dev/npc1054657282/32/5790_2.png) [@npc1054657282](https://ziggit.dev/u/npc1054657282)\
**Post date:** [June 1, 2026, 9:40pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827/31 "2026-06-01T21:40:50Z")

</div>

Thank you, now I understand this point, and assertions are indeed very valuable for performance optimization.

---

<div class="post-metadata">

**Author:** ![lufe](https://ziggit.dev/letter_avatar_proxy/v4/letter/l/b782af/32.png) [@lufe](https://ziggit.dev/u/lufe)\
**Post date:** [June 1, 2026, 9:44pm UTC](https://ziggit.dev/t/you-must-fix-your-asserts/15827/32 "2026-06-01T21:44:05Z")

</div>

> [@npc1054657282](#):
>
> I feel that the ‘disabling assertions in the production environment’ mentioned in the text is not much different from the actual effect of assertions under the current ReleaseFast.

What helped me understand these questions around zig’s assert, is that in zig to think of the assertion being made by you, the programmer, to the zig compiler. The zig compiler always uses them:

- in safe modes it will complain if you lied to it
- in release modes it will take your assertion for granted and may use it for optimization

In contrast, in C for example I think of an assertion as being made by the compiler. However, it only does so in debug builds. In release builds the assertions are completely stripped out before the compiler can even see them.

[Previous page](https://ziggit.dev/t/you-must-fix-your-asserts/15827.md?page=1)
