Library / SDK
101arrowz/fflate avatar
101arrowz/fflate

fflate: an 8kB JavaScript compression library for DEFLATE, GZIP, Zlib and ZIP

High performance (de)compression in an 8kB package

3,034 stars128 forksTypeScriptMIT

At a glance

What is it?
fflate is a pure JavaScript (de)compression library that ships DEFLATE, GZIP, Zlib and ZIP support in about 8kB, with synchronous and asynchronous APIs. It is a good fit when bundle size and browser compatibility matter more than streaming elegance, and a poor fit when you need Brotli.
Who is it for?
Adopt fflate when you need gzip, Zlib, DEFLATE or ZIP handling inside a JavaScript bundle and cannot afford pako's 45.6kB minified base, or when you need ZIP writing in the browser. Do not adopt it if you need Brotli, since the README's feature table lists DEFLATE, GZIP and Zlib only, and do not use the CDN build if tree shaking matters to you, because the README states tree shaking is completely unsupported from the CDN and that build is about 33kB, or 12.5kB gzipped.
Can I use it commercially?
Yes. MIT 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 147 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What fflate solves, and who ends up using it

The problem is narrow and familiar: you have bytes in a JavaScript runtime and you need them deflated or inflated, but the library that does it is larger than the rest of your page. fflate's own comparison table puts pako's base minified bundle at 45.6kB and fflate's at 8kB, with 3kB for inflate only. That gap is the entire pitch. The README describes fflate as the "fastest, smallest, and most versatile" pure JavaScript compression and decompression library in existence, and while the superlatives are the author's, the size numbers are checkable by installing the package and looking at what your bundler emits.

The audience follows from that. Frontend engineers shipping a bundle to browsers, edge or serverless functions with tight cold-start budgets, and anyone who needs to read or write a ZIP file without pulling in a Node-only dependency. The README notes that fflate is pure JavaScript and works in both the browser and Node.js, with ES Modules used throughout. It also supports GZIP, Zlib and DEFLATE data, and states that data compressed by fflate can be decompressed by other tools and vice versa, which matters more than raw speed: interoperability with the rest of the ecosystem is what makes a compression library adoptable at all.

How fflate is structured: one core, four formats, two execution modes

The repository layout is flat and readable: src/ holds the implementation, lib/ the CommonJS build, esm/ the ES Module build, umd/ the CDN bundle, and demo/ a React application. package.json declares main as ./lib/index.cjs, module as ./esm/browser.js, types as ./lib/index.d.ts, and unpkg and jsdelivr both as ./umd/index.js. There is an exports map with separate node and browser conditions, each split into import and require, plus explicit ./node and ./browser subpaths. That map is the mechanism you interact with whether you notice it or not: a bundler resolving fflate for a browser target gets esm/browser.js, and a Node process gets esm/index.mjs or lib/node.cjs depending on how it imports.

The API surface is layered by format. At the bottom are DEFLATE primitives; above them zlibSync and unzlibSync for Zlib-wrapped data, gzipSync and gunzipSync for GZIP, and decompressSync, which the README says autodetects a compressed file's format. ZIP is an add-on: the README states ZIP archiving costs an extra 3 kB. Two execution modes run through all of it. Synchronous functions like gzipSync block and return; asynchronous counterparts exist and, per the README, can utilize multiple threads in async mode. In Node that means worker threads; the package.json browser field remaps ./lib/node-worker.cjs to ./lib/worker.cjs, which is how the same async API reaches Web Workers in a browser.

The string helpers are worth knowing about because they prevent a common mistake. strToU8 converts a string to a Uint8Array, and the README shows that the default compression method for compressSync is gzip. Everything else in the library operates on Uint8Array, including Node.js Buffers, so the conversion step is where encoding bugs usually enter.

Installing fflate and compressing your first buffer

Install from npm, yarn or pnpm as the README shows. The package is named fflate and the current release is v0.8.3, published on 2026-05-16.

bash
npm i fflate # or yarn add fflate, or pnpm add fflate

Import only the functions you need. The README is explicit that importing the namespace pulls in everything, and that a single named import can save roughly 20kB off a bundle.

js
import { gzipSync } from 'fflate';

Now compress a Uint8Array. The README says the level ranges from 0 (no compression) to 9 (max compression) and that the default level is 6, so the example below is opting into maximum compression deliberately.

js
import * as fflate from 'fflate';

const massiveFile = new Uint8Array(await fetch('/aMassiveFile').then(
  res => res.arrayBuffer()
));

const notSoMassive = fflate.zlibSync(massiveFile, { level: 9 });
const massiveAgain = fflate.unzlibSync(notSoMassive);

If you are starting from a string rather than bytes, convert first with strToU8. The README notes that compressSync defaults to gzip and that mem ranges from 0 to 12, where 4 is the default.

js
const buf = fflate.strToU8('Hello world!');

const compressed = fflate.compressSync(buf, { level: 6, mem: 8 });

For GZIP specifically, gzipSync accepts a filename and an mtime, and the README says mtime can be a Date, date string, or Unix timestamp. Those two fields land in the GZIP header, so set them if downstream tooling reads the original name or modification time.

js
const gzipped = fflate.gzipSync(massiveFile, {
  filename: 'aMassiveFile.txt',
  mtime: '9/1/16 2:00 PM'
});

The CDN build and the tree-shaking trade-off

Loading fflate from a CDN is one script tag, and the README gives both UNPKG and jsDelivr URLs pinned to version 0.8.3. It also gives a Skypack ESM import for buildless setups, and a Deno variant that carries a @deno-types comment pointing at the Skypack .d.ts file. The README warns against the ?dts flag there, saying it is not necessary for Deno support.

The catch is stated plainly in the README: tree shaking is completely unsupported from the CDN, and that build is about 33kB, or 12.5kB gzipped. That is four times the 8kB headline figure. If your reason for choosing fflate over pako is size, the CDN path can quietly erase the advantage, because you ship every format and the ZIP code whether or not you call them. The README's suggested workaround is to ask the author to produce a manual build with only the features you need, which is not a self-service option. In practice, if you are buildless and size-sensitive, you either accept 12.5kB gzipped or you set up a bundler. If you do have a bundler, the ESM entry points and the sideEffects: false flag in package.json are what let dead code drop out.

Where fflate is the wrong tool

Brotli is the clearest gap. Brotli appears in the related searches people run about this project, but the README's feature table lists DEFLATE, GZIP and Zlib only, and nothing in the README describes a Brotli encoder or decoder. If your server negotiates br and you want to decode it in the browser, fflate is not the library for that job; you would need a separate Brotli implementation.

The second limitation is the API shape. fflate is built around Uint8Array in and Uint8Array out. That is the right primitive for a small library, but it means every integration point has to convert. Node streams, Web Streams, and any code that expects a string or a Buffer-shaped object all need an adapter. The README's string helpers cover the common cases and do not pretend to cover the rest.

Third, the synchronous functions block. gzipSync and its relatives are convenient and, per the README, fast, but on a large payload in a browser they occupy the main thread for the duration. The asynchronous API exists precisely for this, and the README says async mode can use multiple threads to achieve over 3x the performance of virtually any other utility. Choosing sync for a 200MB file in a UI thread is a self-inflicted freeze.

Finally, the performance claims are the author's benchmarks against pako, tiny-inflate and UZIP.js. The table shows fflate up to 25% faster on decompression and up to 50% faster on compression, but benchmark results are workload-dependent. The README also claims compression ratios often better than the original Zlib C library. Treat both as hypotheses to test on your own corpus, not as settled facts.

fflate compared with pako and UZIP.js

pako is the closest alternative and the one the README measures against. Both support DEFLATE, GZIP and Zlib, both handle streaming, and both support dictionaries and files up to 4GB. The difference is size and, per the README's table, speed: pako's base minified bundle is 45.6kB against fflate's 8kB, and fflate is listed as up to 50% faster on compression. pako does not appear in the table as supporting ZIP, ES Modules, or multi-threaded asynchronous operation, all of which fflate claims. If you already ship pako and it works, the migration is mostly a matter of swapping function names and confirming that your bundler picks the right export condition.

UZIP.js is the other meaningful comparison. It supports compression, decompression and ZIP, and the README's table lists it as up to 25% faster than pako on both compression and decompression, at 14.2kB minified. But it does not support streaming, GZIP, dictionaries, files above 4GB, or multi-threaded operation, and the table says it can hang on error. That last row is the one to weigh hardest: a decompression library that can hang on malformed input is a liability anywhere the input is not fully trusted. tiny-inflate is a different category entirely. At 3kB it is the smallest option in the table, but it decompresses only, has no ZIP or GZIP support, and is listed as up to 40% slower.

The practical split: tiny-inflate when you only ever inflate and size dominates everything; UZIP.js when you need ZIP and never touch untrusted data; pako when you want the most widely deployed option and 45.6kB is acceptable; fflate when you want the size of tiny-inflate with the feature set of pako plus ZIP.

Maintenance, licence and what an upgrade costs

The repository is not archived and the last push was on 2026-05-16, which coincides with the v0.8.3 release. The release history is sparse: v0.8.0 in May 2023, v0.8.2 in February 2024, then v0.8.3 in May 2026. That cadence suggests a library that is largely finished rather than one under continuous churn, and the CHANGELOG.md at the repository root is where the differences between those tags are recorded. Read it before upgrading, because the release notes do not describe what changed between v0.8.2 and v0.8.3.

The licence is MIT, declared in package.json and present as LICENSE at the repository root. MIT permits commercial and closed-source use with attribution and without copyleft obligations, but the usual disclaimer applies: nothing here is legal advice, and if your organisation has a policy on third-party licences, run it through that process rather than relying on a one-line summary.

Upgrade cost is low in the normal case. There is no runtime service to migrate and no data format to convert, because the README states that fflate's output interoperates with other tools in both directions. The real cost of an upgrade is the exports map. If you import from a subpath like fflate/esm/browser.js or fflate/node, a change to the exports map can break resolution in a way that a top-level import would not. Pin the version in package.json and read CHANGELOG.md before moving the pin.

Editorial conclusion

Adopt fflate when you need gzip, Zlib, DEFLATE or ZIP handling inside a JavaScript bundle and cannot afford pako's 45.6kB minified base, or when you need ZIP writing in the browser. Do not adopt it if you need Brotli, since the README's feature table lists DEFLATE, GZIP and Zlib only, and do not use the CDN build if tree shaking matters to you, because the README states tree shaking is completely unsupported from the CDN and that build is about 33kB, or 12.5kB gzipped. Before committing, verify three things against your own data: the compression level you pass (0 to 9, default 6) and the mem value (0 to 12, default 4), whether your target runtime resolves the exports map entries for node, browser, import and require, and whether your ZIP archives need the streaming ZIP path rather than the synchronous one. The last push to the repository was on 2026-05-16, so treat v0.8.3 as the current release and check whether the ZIP streaming API you plan to use is documented in the version you install.

Frequently asked questions

What is fflate?

fflate is a pure JavaScript compression and decompression library, distributed as an npm package named fflate, that supports DEFLATE, GZIP and Zlib data plus ZIP archiving, with a base minified bundle of about 8kB. It works in both the browser and Node.js and uses ES Modules.

What are the differences between fflate and JSZip?

The README does not compare fflate with JSZip, so that difference cannot be stated from the documentation. The README compares fflate against pako, tiny-inflate and UZIP.js instead, and its feature table lists ZIP support, streaming, GZIP, dictionaries, multi-threaded asynchronous operation and ES Modules for fflate.

Is zlib the same as DEFLATE?

The README treats them as separate formats that fflate handles: it lists support for DEFLATE, GZIP and Zlib data, and exposes distinct functions such as zlibSync and unzlibSync alongside the DEFLATE-level API. It does not explain the container relationship between the two, so the precise difference is not documented there.

What is deflated in zip?

The README does not define the term. It states that fflate supports DEFLATE, GZIP and Zlib data and that ZIP file archiving is available for an extra 3 kB, but it does not describe how DEFLATE relates to the contents of a ZIP archive.

what is fflate

fflate (short for fast flate) is a pure JavaScript compression and decompression library that includes support for DEFLATE, GZIP and Zlib data, and ZIP archiving for an extra 3 kB. Its base minified bundle is 8kB, or 3kB for inflate only, and it works in both the browser and Node.js.

Official sources

  1. 101arrowz/fflate on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/101arrowz-fflate.svg)](https://hysenlabs.com/projects/101arrowz-fflate)