zlib-rs: a stable API and 30M downloads


2026-01-27 Author: Folkert de Vries zlib-rs data compression

Since the first release in April 2024, zlib-rs has come a long way. It has seen major adoption over the last year, and, we're proud to say, is now feature complete. We've released zlib-rs 0.6, the first version with a stable and complete API.

With this milestone, we now fully deliver on the promise of our Data compression initiative: real alternatives to C/C++ counterparts that reduce attack surface through memory safety and provide on-par performance.

Features and promises are nice, but seeing adoption grow is the cherry on the cake: zlib-rs recently crossed 30M downloads, 25M+ in the last year, and is on track to become the default implementation in flate2, which is expected to further boost usage.

This blog post is a quick round-up of the latest release, 0.6. The full release notes are here.

Stable API

The zlib-rs crate now has a stable API. It hides away most of the internals, but exposes enough for flate2 and rustls. Generally we recommend to use zlib-rs via flate2 in applications, but for low-level libraries using zlib-rs directly is now an option.

Additionally flate2 now uses the zlib-rs CRC32 checksum implementation when zlib-rs is used. Our implementation is faster, and it saves a dependency.

C-compatible API

The libz-rs-sys crate is a C-compatible API built on top of zlib-rs. It can be compiled into a drop-in compatible C library.

ABI changes

All exported functions now use extern "C" instead of extern "C-unwind".

This is a change we've wanted to make for a while, but held off on because we had rust crates using libz-rs-sys. Now that they instead use zlib-rs directly, we can focus more on C users in the libz-rs-sys crate.

Normally, when rust functions panic, they start unwinding the stack. That is only valid when the caller anticipates that the callee might unwind. For rust functions this case is handled, but when exporting a function, the caller is likely not written in rust, and does not support stack unwinding.

If the callee does unwind into an unsuspecting caller, behavior is undefined. Although libz-rs-sys should not panic, causing UB when we somehow do is a massive footgun. So now we use extern "C", which will instead abort the program at the FFI boundary.

Support for gz* functions

We've added functions like gzread, gzwrite and many others to the libz-rs-sys API. These were already available in libz-rs-sys-cdylib, and have now been promoted. They are still behind the gz feature, so enable that if you need these functions. Most of the gz* functions were implemented by @brian-pane.

In addition, we've implemented several other missing functions (like inflateBack), so that we're now fully compatible with the zlib and zlib-ng public API.

Thank yous

For completing this final milestone we thank all the contributors, specifically @brian-pane, and the Sovereign Tech Fund for investing in the API stabilization.

What's next

Although the public API is now complete, a project like this is never truly done. There are always new optimization ideas to try, versions to update, and obscure edge cases to support.

The biggest remaining items is that technically the API is only complete when using nightly rust. The gzprintf and gzvprintf functions are c-variadic, and c-variadic function definitions are currently unstable. I hope to stabilize #[feature(c_variadic)] in the next ~6 months.




All news and blogs