"Manual memory management" is exactly what the label says, it's "manual".
What you usually do is group all allocated items with the same max lifetime in an arena allocator created somewhere up the call stack, and then defer-free the entire arena instead of each individual item. In real world code there's hardly a situation where each item requires its own lifetime tracking, instead they are usually lumped together with other items of a similar lifetime.
Zig's GeneralPurposeAllocator also helps to catch typical memory-related issues at runtime (like leaks and dangling access), e.g. see:
https://github.com/ziglang/zig/blob/master/lib/std/heap/gene...
Tagged-index-handles are also always an option to achieve spatial and temporal runtime memory safety at a higher level:
https://floooh.github.io/2018/06/17/handles-vs-pointers.html