
Product
Socket Firewall Now Blocks Malicious VS Code and Open VSX Extensions
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.
@fastify/compress
Advanced tools
Adds compression utils to the Fastify reply object and a hook to decompress requests payloads.
Supports gzip, deflate, brotli, and zstd (Node.js 22.15+/23.8+).
ℹ️ Note: In large-scale scenarios, use a proxy like Nginx to handle response compression.
⚠ Warning: Since
@fastify/compressversion 4.x, payloads compressed with thezipalgorithm are not automatically uncompressed. This plugin focuses on response compression, andzipis not in the IANA Table of Content Encodings.
npm i @fastify/compress
| 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.
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:
zstd (Node.js 22.15+/23.8+)brgzipdeflate* (no preference — @fastify/compress will use gzip)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.
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'),
// Disable compression but keep decompression enabled (default behavior for globalDecompression is true)
{ globalCompression: false }
)
// Disable decompression but keep compression enabled
await fastify.register(
import('@fastify/compress'),
{ globalDecompression: 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/compressplugin together with@fastify/staticplugin,@fastify/compressmust be registered (with global hook) before registering@fastify/static.
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.compressThis 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.
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 })
app.get('/', (req, reply) => {
reply
.type('text/plain')
.compress(fs.createReadStream('./package.json'))
})
await app.listen({ port: 3000 })
It's also possible to pass a Fetch API Response object or a Web ReadableStream. The plugin will automatically extract the body stream from the Response or convert the Web stream to a Node.js Readable behind the scenes.
import fastify from 'fastify'
const app = fastify()
await app.register(import('@fastify/compress'), { global: true })
app.get('/', async (req, reply) => {
const resp = new Response('Hello from Fetch Response')
reply.compress(resp)
})
app.get('/', async (req, reply) => {
return new Response('Hello from Fetch Response')
})
app.get('/', (req, reply) => {
const stream = new ReadableStream({
start (controller) {
controller.enqueue(new TextEncoder().encode('Hello from Web ReadableStream'))
controller.close()
}
})
reply.header('content-type', 'text/plain')
reply.compress(stream)
})
The minimum byte size for response compression. Defaults to 1024.
await fastify.register(
import('@fastify/compress'),
{ threshold: 2048 }
)
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') }
)
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.'
}
}
)
Response compression can be disabled by an x-no-compression header in the request.
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')))
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'] }
)
// Example with zstd support (Node.js 22.15+/23.8+)
await fastify.register(
import('@fastify/compress'),
// Prefer zstd, fallback to brotli, then gzip
{ encodings: ['zstd', 'br', 'gzip'] }
)
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
}
});
Content-Length header removal with removeContentLengthHeaderBy 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'))
)
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:
zstd (Node.js 22.15+/23.8+)brgzipdeflateIf 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.
The plugin supports compressing the following payload types:
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.
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) => {
// ...
})
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'] }
)
// Example with zstd support for request decompression (Node.js 22.15+/23.8+)
await fastify.register(
import('@fastify/compress'),
// Support zstd, brotli and gzip for request decompression
{ requestEncodings: ['zstd', 'br', 'gzip'] }
)
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.
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.'
}
}
}
)
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
}
}
}
)
Past sponsors:
Licensed under MIT.
The 'compression' package is an Express middleware that provides similar functionality to @fastify/compress, enabling gzip and deflate compression for HTTP responses. It is widely used in Express applications and offers a straightforward API for enabling compression. Compared to @fastify/compress, it is more tailored for Express rather than Fastify.
The 'koa-compress' package is a middleware for Koa applications that provides HTTP compression using gzip, deflate, and Brotli. It offers similar functionality to @fastify/compress but is designed specifically for Koa, making it a better fit for Koa-based applications.
FAQs
Fastify compression utils
The npm package @fastify/compress receives a total of 410,524 weekly downloads. As such, @fastify/compress popularity was classified as popular.
We found that @fastify/compress demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 18 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.

Research
More than 140 Mastra npm packages were compromised in a supply chain attack that used a typosquatted dependency to deliver a cross-platform infostealer during installation.

Research
/Security News
A new npm package tests AI malware scanners with prompt injection, safety-triggering comments, context flooding, and obfuscated JavaScript.