Using Brotli with Node.js

· 2 min read

Brotli is a compression algorithm developed by Google, able to compress data even smaller than gzip can.

Compressing can be helpful in many scenarios; the most notable being serving your website assets in a much smaller format.

But there are times when we may want to use brotli programmatically, such as NodeJS.

For example, I needed to store large strings into Redis; Redis is an in-memory database, and of course, space is limited, and every byte counts.

I was willing to pay a small CPU-related price for saving space and network transfer payloads (which Firebase, of course, bills me for).

Therefore, I started researching for the most effective way of compressing the data before writing to Redis, so that:

  • the string would occupy less space
  • the network cost and speed would be lower

Brotli, which is built-in into Node, seemed like a good choice. Let’s see how to use it.

Compressing

NodeJS comes with utilities for compressing/decompressing Brotli since versions v11.7.0, v10.16.0.

Like many other APIs, Node comes with async and sync versions. For simplicity, we’ll show the sync versions.

We need to turn the input data structure into a string when compressing.

import { brotliCompressSync } from 'zlib';

// let's assume this is an object or
// string you want to store
// such as a JSON object
const data = [];

const compressed = brotliCompressSync(JSON.stringify(data)).toString('base64');

// do something with "compressed"

The above can become a small utility function:

export function compressWithBrotli(data: unknown) {
  return brotliCompressSync(JSON.stringify(data)).toString('base64');
}

Decompressing

For decompressing a Brotli base64 string and turning it back into its JSON representation we will need a few more steps:

  • First, we turn the compressed string into a Buffer
  • We then decompress using the built-in utility brotliDecompressSync
  • We check if the value is truthy, and if so, parse the string using JSON.parse
import { brotliDecompressSync } from 'zlib';

export function decompressWithBrotli(data: string) {
  const buffer = Buffer.from(data, 'base64');

  const value = brotliDecompressSync(buffer).toString('utf-8');

  return value ? JSON.parse(value) : undefined;
}

We can now use the utility functions compressWithBrotli and decompressWithBrotli to compress our text on the fly.

If you want to use the async versions of the API, use the variants brotliCompress and brotliDecompress.