flate2: DEFLATE Compression for Rust With a Swappable Backend
DEFLATE, gzip, and zlib bindings for Rust
At a glance
- What is it?
- flate2 is a streaming compression library for Rust that speaks deflate, zlib and gzip through Read, BufRead and Write adapters, and it lets you choose the implementation underneath: a pure Rust default based on miniz_oxide, a zlib-rs build, the zlib C library, or zlib-ng. The backend choice interacts with the rest of your dependency graph in ways the README is unusually explicit about.
- Who is it for?
- flate2 fits a Rust project that needs deflate or gzip and wants a pure Rust default with no C toolchain, and that may later need to swap in a faster C implementation without rewriting its call sites, since the backend is a feature selection rather than an API change. It is a poor fit if you need a format other than deflate, zlib or gzip, and a poor fit if you cannot accept the backend ambiguity that comes from another crate in your graph pulling in stock zlib.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A Streaming Library, Not a compress Function
flate2 is a streaming compression and decompression library for DEFLATE based streams in Rust, and the description in the manifest is more precise than the README headline: DEFLATE compression and decompression exposed as Read, BufRead and Write streams.
The three stream traits are the whole API surface, and they are what makes the crate composable. A writer encoder means you can push bytes through it and get a compressed output without holding the whole thing in memory, and a reader decoder means the same for the other direction. The README's compression example is the shape of it:
use std::io::prelude::*;
use flate2::Compression;
use flate2::write::ZlibEncoder;
fn main() {
let mut e = ZlibEncoder::new(Vec::new(), Compression::default());
e.write_all(b"foo");
e.write_all(b"bar");
let compressed_bytes = e.finish();
}The decompression side is the mirror image, with a read::GzDecoder and a call to read_to_string.
The three supported formats are deflate, zlib and gzip, and each of them has encoder and decoder types in both the read and the write flavours, plus a multi decoder for gzip. The manifest also names the categories the crate fits, compression and api-bindings, which is an honest description of a crate that binds an algorithm to Rust's stream interfaces.
Four Backends Behind One API
The backend choice is the interesting part of the crate, and it is a Cargo feature rather than a fork.
The default is miniz_oxide, a port of miniz.c to pure Rust, and the manifest explains the reason in a comment: this implementation uses only safe Rust code and doesn't require a C compiler, and it provides good performance for most use cases while being completely portable. So the default is the choice for a project that wants no C toolchain in its build and no unsafe code in its dependency graph.
The alternatives are zlib, the widely available C library, reached through libz-sys, the high-performance zlib-ng C library through libz-ng-sys, and zlib-rs, the Rust port of zlib, which is a pure Rust implementation that uses some unsafe code.
The performance ordering in the README is specific. zlib-rs is the fastest overall, with a link to a blog post about it being faster than C, while the zlib-ng C library can be slightly faster in certain cases. The word certain is doing the work, because the answer depends on the data and on the platform, and a benchmark on one corpus does not transfer to yours.
So the choice is between portability and peak throughput, and the API does not change when you make it. That is the design goal, and it is why a project can start on the pure Rust default and move to a C backend later without touching its own code.
runtime_detection and the no_std Cost
Since version 1.1.10, the default runtime_detection feature enables runtime CPU feature detection on supported architectures. Setting default-features = false also disables it, which is why the backend examples in the README explicitly enable the feature to preserve performance.
The feature does two things. It enables std support in zlib-rs and crc32fast when those dependencies are used, and it turns on the CPU feature detection that lets the compression code use the wider instructions the processor actually has.
The no_std case is where the trade-off appears, and the README is direct about it. For no_std builds, omit runtime_detection, and CPU optimizations in those Rust dependencies then depend on features enabled at compile time, which can result in slower compression or decompression.
So the cost of a no_std build is a performance floor rather than a lost feature. The compression still works and still produces identical output, it just does not get to use the SIMD paths that the runtime detection would have selected. The default miniz_oxide dependency enables the simd feature at compile time, so the pure Rust backend is less affected by this than the zlib-rs path, and the difference in practice is smaller for the default configuration than for the optional ones.
The manifest is also where the optional dependencies are visible, with libz-sys, libz-ng-sys, zlib-rs, miniz_oxide, crc32fast and document-features all marked optional, which is how the feature flags map onto them.
The zlib-ng Compatibility Trap
This is the part of the README that saves an afternoon, and it is worth reading in full before you pick a C backend.
The first good news is that the zlib-ng feature works even if some other part of your crate graph depends on zlib. The second is that if you are already using another C or Rust library that depends on zlib and you want to avoid including both zlib and zlib-ng, you can use the zlib feature for your Rust code as well.
The trap is the compat mode. If you have C or Rust code that depends on zlib and you want to use zlib-ng through libz-sys in zlib-compat mode, there is a zlib-ng-compat feature for that. But the README warns that with the zlib-ng-compat feature, if any crate in your dependency graph explicitly requests stock zlib, or uses libz-sys directly without default-features = false, you will get stock zlib rather than zlib-ng. The advice is to use the zlib-ng feature instead, and to see the libz-sys README for the details.
In other words, the compat mode is not a guarantee. It is a request that another crate in the graph can override, silently, at link time, and the symptom is not an error but a slower build of the same library. That is the kind of problem that is invisible in a test and expensive in production, which is why the README spends a paragraph on it rather than a sentence.
The MSRV Policy Is Not the rust-version Field
The MSRV section is one of the clearest statements of policy in the Rust ecosystem, and the distinction it draws is easy to miss.
The crate supports the current and previous stable versions of the Rust compiler. The example given is that if the current stable is 1.80, the crate supports 1.80 and 1.79. Other compiler versions may work, but failures may not be treated as a flate2 bug.
Then there is the rust-version field in Cargo.toml, and the README is careful to say it is not the same thing. The value is a best-effort measured value and is indicative only, and it may change at any time. The rust-version is a best-effort measured value and is different to the MSRV. The rust-version can be incremented by a pull request in order to pass tests, as long as the MSRV continues to hold.
The consequence for users is spelled out. When the rust-version increases, the next release should be a minor version, to allow any affected users to pin to a previous minor version.
So there are two numbers, and the one that matters for a user is the MSRV, which the current and previous stable rule defines. The rust-version field is the project's own working floor, and in this manifest it is 1.67.0, well below the current stable, which is the point: the crate keeps building for old compilers even as its own metadata moves.
The Examples Directory as the API Reference
The examples directory is the largest and most systematic part of the repository, and it doubles as the API documentation.
There is one example per format per direction, and the names make the matrix obvious. For deflate there are deflateencoder-bufread, deflateencoder-read, deflateencoder-write and the matching deflatedecoder files. For gzip there is the same set plus gzmultidecoder and a gzbuilder. For zlib there is zlibencoder-bufread, zlibencoder-read and zlibdecoder-bufread, zlibdecoder-read and zlibdecoder-write, and a hello_world.txt with its hello_world.txt.gz to run them against.
The distinction the naming makes is the important one. The read flavour takes a Read and produces bytes, the BufRead flavour works with a buffered reader, and the write flavour takes writes and produces a compressed stream. Choosing between them is a question about where in your pipeline the data comes from and where it goes, and the examples answer it by showing each combination rather than by describing it.
There is also an examples/no_std/ directory, which is the concrete counterpart to the no_std paragraph in the README, and a fuzz/ directory for the fuzzing targets, plus the tests/ directory. The repository also carries an AGENTS.md and a MAINTENANCE.md, which is a newer convention in the rust-lang organisation and a sign that the project has codified how it wants itself worked on.
Dual Licensing and a Steady Release Cadence
The licence is the standard Rust dual licence, and the wording is the usual one. This project is licensed under either of the Apache License, Version 2.0, or the MIT license, at your option.
Contributions are covered by the same terms. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion is dual licensed as above, without any additional terms or conditions.
The release history is the evidence that the project is being maintained. The recent tags are 1.1.10 from 2026-08-28, 1.1.9 from 2026-02-03 with the note that it upgraded zlib-rs to version 0.6.0, and 1.1.8 from 2026-01-12. Those are patch releases, and a patch release that upgrades a backend dependency is the shape of a project that is keeping the backends current rather than adding features to the core.
The manifest itself is worth one more look. The crate is edition 2018, the keywords name gzip, deflate, zlib, zlib-ng and encoding, the authors are Alex Crichton and Josh Triplett, and the repository lives in the rust-lang organisation with the documentation on docs.rs. The repository is not archived and the last push was on 2026-10-05, so the 1.1 line is current.
Editorial conclusion
flate2 fits a Rust project that needs deflate or gzip and wants a pure Rust default with no C toolchain, and that may later need to swap in a faster C implementation without rewriting its call sites, since the backend is a feature selection rather than an API change. It is a poor fit if you need a format other than deflate, zlib or gzip, and a poor fit if you cannot accept the backend ambiguity that comes from another crate in your graph pulling in stock zlib. Before choosing zlib-ng, read the compatibility note, because the zlib-ng-compat feature silently gives you stock zlib if any crate in the graph asks for zlib directly, and note that a rust-version increase is always accompanied by a minor release, so pinning a minor version is the way to protect yourself. The crate is dual licensed under Apache-2.0 or MIT, the newest release is 1.1.10 from 2026-08-28, and the last push was on 2026-10-05.
Frequently asked questions
What is flate2 and which formats does it support?
It is a streaming compression and decompression library for DEFLATE based streams in Rust, exposing the formats as Read, BufRead and Write streams. The supported formats are deflate, zlib and gzip, and the package is published as the flate2 crate with documentation on docs.rs.
Which backend does flate2 use by default?
miniz_oxide, a port of miniz.c to pure Rust, which uses only safe Rust code and does not require a C compiler, and the manifest notes it provides good performance for most use cases while being completely portable. Other backends are available through features: zlib-rs, zlib and zlib-ng.
What does the runtime_detection feature do?
Since version 1.1.10 it is a default feature that enables runtime CPU feature detection on supported architectures, and it enables std support in zlib-rs and crc32fast when those dependencies are used. Setting default-features = false disables it, and for no_std builds it is omitted, in which case CPU optimisations depend on compile time features and can be slower.
How do I use zlib-ng without pulling in stock zlib?
Use the zlib-ng feature, which works even if another part of your crate graph depends on zlib. The zlib-ng-compat feature only works as intended if no crate in the graph explicitly requests stock zlib or uses libz-sys directly without default-features = false, otherwise you get stock zlib instead.
What is flate2's MSRV policy?
It supports the current and previous stable versions of the Rust compiler, so if the current stable is 1.80 the crate supports 1.80 and 1.79, and failures on other versions are not treated as a flate2 bug. The rust-version field in Cargo.toml is a separate, indicative, best-effort value that can be raised by a pull request, and when it rises the next release is a minor version so users can pin back.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rust-lang-flate2-rs)Was this useful?