npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aeolun/compress

v8.0.6

Published

Fastify compression utils

Readme

@fastify/compress

CI NPM version neostandard javascript style

Adds compression utils to the Fastify reply object and a hook to decompress requests payloads. Supports gzip, deflate, and brotli.

ℹ️ Note: In large-scale scenarios, use a proxy like Nginx to handle response compression.

⚠ Warning: Since @fastify/compress version 4.x, payloads compressed with the zip algorithm are not automatically uncompressed. This plugin focuses on response compression, and zip is not in the IANA Table of Content Encodings.

Install

npm i @fastify/compress

Compatibility

| Plugin version | Fastify version | | ---------------|-----------------| | >=8.x | ^5.x | | >=6.x <8.x | ^4.x | | >=3.x <6.x | ^3.x | | ^2.x | ^2.x | | >=0.x <2.x | ^1.x |

Please note that if a Fastify version is out of support, then so are the corresponding versions of this plugin in the table above. See Fastify's LTS policy for more details.

Usage - Compress replies

This plugin adds two functionalities to Fastify: a compress utility and a global compression hook.

Currently, the following encoding tokens are supported, using the first acceptable token in this order:

  1. br
  2. gzip
  3. deflate
  4. * (no preference — @fastify/compress will use gzip)
  5. identity (no compression)

If an unsupported encoding is received or the 'accept-encoding' header is missing, the payload will not be compressed. To return an error for unsupported encoding, use the onUnsupportedEncoding option.

The plugin compresses payloads based on content-type. If absent, it assumes application/json.

Supported payload types

The plugin supports compressing the following payload types:

  • Strings and Buffers
  • Node.js streams
  • Response objects (from the Fetch API)
  • ReadableStream objects (from the Web Streams API)

Global hook

The global compression hook is enabled by default. To disable it, pass { global: false }:

await fastify.register(
  import('@fastify/compress'),
  { global: false }
)

If only compression or decompression is required, set the globalCompression or globalDecompression config flags to false respectively (both are true by default).

await fastify.register(
  import('@fastify/compress'),
  // only decompress compressed incoming requests
  { globalCompression: false }
)

Fastify encapsulation can be used to set global compression but run it only in a subset of routes by wrapping them inside a plugin.

ℹ️ Note: If using @fastify/compress plugin together with @fastify/static plugin, @fastify/compress must be registered (with global hook) before registering @fastify/static.

Per Route options

Different compression options can be specified per route using the compress options in the route's configuration. Setting compress: false on any route will disable compression on the route even if global compression is enabled.

await fastify.register(
  import('@fastify/compress'),
  { global: false }
)

// only compress if the payload is above a certain size and use brotli
fastify.get('/custom-route', {
  compress: {
    inflateIfDeflated: true,
    threshold: 128,
    zlib: {
      createBrotliCompress: () => createYourCustomBrotliCompress(),
      createGzip: () => createYourCustomGzip(),
      createDeflate: () => createYourCustomDeflate()
    }
  }, (req, reply) => {
    // ...
  })

reply.compress

This plugin adds a compress method to reply that compresses a stream or string based on the accept-encoding header. If a JS object is passed, it will be stringified to JSON.

ℹ️ Note: When compressing a Response object, the compress middleware only extracts and compresses the body stream. It will handle compression-related headers (like Content-Encoding and Vary) but does not copy other headers or status from the Response object - these remain the responsibility of your application or Fastify's built-in handling.

The compress method uses per-route parameters if configured, otherwise it uses global parameters.

import fs from 'node:fs'
import fastify from 'fastify'

const app = fastify()
await app.register(import('@fastify/compress'), { global: false })

// Compress a file stream
app.get('/file', (req, reply) => {
  reply
    .type('text/plain')
    .compress(fs.createReadStream('./package.json'))
})

// Compress a Response object from fetch
app.get('/fetch', async (req, reply) => {
  const response = await fetch('https://api.example.com/data')
  reply
    .type('application/json')
    .compress(response)
})

// Compress a ReadableStream
app.get('/stream', (req, reply) => {
  const response = new Response('Hello World')
  reply
    .type('text/plain')
    .compress(response.body)
})

await app.listen({ port: 3000 })

Compress Options

threshold

The minimum byte size for response compression. Defaults to 1024.

ℹ️ Note: The threshold setting only applies to string and Buffer payloads. Streams (including Node.js streams, Response objects, and ReadableStream objects) are always compressed regardless of the threshold, as their size cannot be determined in advance.

await fastify.register(
  import('@fastify/compress'),
  { threshold: 2048 }
)

customTypes

mime-db determines if a content-type should be compressed. Additional content types can be compressed via regex or a function.

await fastify.register(
  import('@fastify/compress'),
  { customTypes: /x-protobuf$/ }
)

or

await fastify.register(
  import('@fastify/compress'),
  { customTypes: contentType => contentType.endsWith('x-protobuf') }
)

onUnsupportedEncoding

Set onUnsupportedEncoding(encoding, request, reply) to send a custom error response for unsupported encoding. The function can modify the reply and return a string | Buffer | Stream | Error payload.

await fastify.register(
  import('@fastify/compress'),
  {
    onUnsupportedEncoding: (encoding, request, reply) => {
      reply.code(406)
      return 'We do not support the ' + encoding + ' encoding.'
    }
  }
)

Disable compression by header

Response compression can be disabled by an x-no-compression header in the request.

Inflate pre-compressed bodies for clients that do not support compression

Optional feature to inflate pre-compressed data if the client does not include one of the supported compression types in its accept-encoding header.

await fastify.register(
  import('@fastify/compress'),
  { inflateIfDeflated: true }
)

fastify.get('/file', (req, reply) =>
  // will inflate the file  on the way out for clients
  // that indicate they do not support compression
  reply.send(fs.createReadStream('./file.gz')))

Customize encoding priority

By default, @fastify/compress prioritizes compression as described here. Change this by passing an array of compression tokens to the encodings option:

await fastify.register(
  import('@fastify/compress'),
  // Only support gzip and deflate, and prefer deflate to gzip
  { encodings: ['deflate', 'gzip'] }
)

brotliOptions and zlibOptions

Compression can be tuned with brotliOptions and zlibOptions, which are passed directly to native node zlib methods. See class definitions.

  server.register(fastifyCompress, {
    brotliOptions: {
      params: {
        [zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT, // useful for APIs that primarily return text
        [zlib.constants.BROTLI_PARAM_QUALITY]: 4, // default is 4, max is 11, min is 0
      },
    },
    zlibOptions: {
      level: 6, // default is typically 6, max is 9, min is 0
    }
  });

Manage Content-Length header removal with removeContentLengthHeader

By default, @fastify/compress removes the reply Content-Length header. Change this by setting removeContentLengthHeader to false globally or per route.

  // Global plugin scope
  await server.register(fastifyCompress, { global: true, removeContentLengthHeader: false });

  // Route-specific scope
  fastify.get('/file', {
    compress: { removeContentLengthHeader: false }
  }, (req, reply) =>
    reply.compress(fs.createReadStream('./file.gz'))
  )

Usage - Decompress request payloads

This plugin adds a preParsing hook to decompress the request payload based on the content-encoding request header.

Currently, the following encoding tokens are supported:

  1. br
  2. gzip
  3. deflate

If an unsupported encoding or invalid payload is received, the plugin throws an error.

If the request header is missing, the plugin yields to the next hook.

Global hook

The global request decompression hook is enabled by default. To disable it, pass { global: false }:

await fastify.register(
  import('@fastify/compress'),
  { global: false }
)

Fastify encapsulation can be used to set global decompression but run it only in a subset of routes by wrapping them inside a plugin.

Per Route options

Specify different decompression options per route using the decompress options in the route's configuration.

await fastify.register(
  import('@fastify/compress'),
  { global: false }
)

// Always decompress using gzip
fastify.get('/custom-route', {
  decompress: {
    forceRequestEncoding: 'gzip',
    zlib: {
      createBrotliDecompress: () => createYourCustomBrotliDecompress(),
      createGunzip: () => createYourCustomGunzip(),
      createInflate: () => createYourCustomInflate()
    }
  }
}, (req, reply) => {
    // ...
  })

requestEncodings

By default, @fastify/compress accepts all encodings specified here. Change this by passing an array of compression tokens to the requestEncodings option:

await fastify.register(
  import('@fastify/compress'),
  // Only support gzip
  { requestEncodings: ['gzip'] }
)

forceRequestEncoding

By default, @fastify/compress chooses the decompression algorithm based on the content-encoding header.

One algorithm can be forced, and the header ignored, by providing the forceRequestEncoding option.

If the request payload is not compressed, @fastify/compress will try to decompress, resulting in an error.

onUnsupportedRequestEncoding

The response error can be customized for unsupported request payload encoding by setting onUnsupportedEncoding(request, encoding) to a function that returns an error.

await fastify.register(
  import('@fastify/compress'),
  {
     onUnsupportedRequestEncoding: (request, encoding) => {
      return {
        statusCode: 415,
        code: 'UNSUPPORTED',
        error: 'Unsupported Media Type',
        message: 'We do not support the ' + encoding + ' encoding.'
      }
    }
  }
)

onInvalidRequestPayload

The response error can be customized for undetectable request payloads by setting onInvalidRequestPayload(request, encoding) to a function that returns an error.

await fastify.register(
  import('@fastify/compress'),
  {
    onInvalidRequestPayload: (request, encoding, error) => {
      return {
        statusCode: 400,
        code: 'BAD_REQUEST',
        error: 'Bad Request',
        message: 'This is not a valid ' + encoding + ' encoded payload: ' + error.message
      }
    }
  }
)

Gotchas

Handling Unsupported Payload Types

When @fastify/compress receives a payload type that it doesn't natively support for compression (excluding the types listed in Supported payload types), the behavior depends on the compression method:

  • Using reply.compress(): The plugin will attempt to serialize the payload using Fastify's serialize function and then compress the result. This provides a best-effort approach to handle custom objects.

  • Using global compression hook: To prevent breaking applications, the plugin will pass through unsupported payload types without compression. This fail-safe approach ensures that servers continue to function even when encountering unexpected payload types.

Acknowledgments

Past sponsors:

License

Licensed under MIT.