Fastify plugin providing compression and decompression utilities for HTTP responses and requests.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Automatic and manual response compression functionality with intelligent algorithm selection, content-type filtering, and configurable compression thresholds.
When global: true is set (default), all routes automatically compress responses based on client Accept-Encoding headers and configured criteria.
// Automatic compression is enabled via plugin registration
// No additional API calls needed - handled by onSend hooksCompression Criteria:
x-no-compression header present in requestUsage Examples:
const fastify = require('fastify')({ logger: true });
// Enable automatic compression globally
await fastify.register(require('@fastify/compress'), {
global: true,
threshold: 1024,
encodings: ['br', 'gzip', 'deflate']
});
// This route will automatically compress large responses
fastify.get('/api/data', async (request, reply) => {
// Large JSON response will be automatically compressed
return {
data: Array.from({ length: 1000 }, (_, i) => ({ id: i, value: `item-${i}` }))
};
});
// Prevent compression with header
fastify.get('/api/no-compress', async (request, reply) => {
// Client can prevent compression by sending x-no-compression header
return { message: 'This won\'t be compressed if x-no-compression header present' };
});Use the reply.compress() method for explicit control over response compression.
/**
* Manually compress a response payload
* @param payload - Data to compress and send
*/
interface FastifyReply {
compress(payload: CompressiblePayload): void;
}
type CompressiblePayload =
| Buffer
| NodeJS.TypedArray
| ArrayBuffer
| string
| Iterable<Buffer | string>
| AsyncIterable<Buffer | string>
| Stream;Usage Examples:
// Manual compression with different payload types
fastify.get('/api/manual', async (request, reply) => {
const data = { message: 'Hello World', timestamp: Date.now() };
// Compress and send JSON data
reply.compress(data);
});
// Manual compression with buffer
fastify.get('/api/buffer', async (request, reply) => {
const buffer = Buffer.from('Large text content'.repeat(100));
// Compress and send buffer
reply.compress(buffer);
});
// Manual compression with stream
fastify.get('/api/stream', async (request, reply) => {
const { Readable } = require('stream');
const stream = Readable.from(function* () {
for (let i = 0; i < 1000; i++) {
yield `data chunk ${i}\n`;
}
}());
// Compress and send stream
reply.compress(stream);
});The plugin automatically determines which responses should be compressed based on Content-Type headers.
Default Compressible Types Pattern:
/^text\/(?!event-stream)|(?:\+|\/)json(?:;|$)|(?:\+|\/)text(?:;|$)|(?:\+|\/)xml(?:;|$)|octet-stream(?:;|$)/uBuilt-in Compressible Types:
text/* (except text/event-stream)*/*+json, */json*/*+text, */text*/*+xml, */xmlapplication/octet-streamUsage Examples:
// Route with different content types
fastify.get('/api/json', async (request, reply) => {
reply.type('application/json');
return { data: 'compressible JSON' }; // Will be compressed
});
fastify.get('/api/text', async (request, reply) => {
reply.type('text/plain');
return 'This is compressible text'; // Will be compressed
});
fastify.get('/api/binary', async (request, reply) => {
reply.type('application/pdf');
return pdfBuffer; // Won't be compressed (not in default pattern)
});
// Override content-type detection per route
fastify.get('/api/custom', {
compress: {
customTypes: (contentType) => contentType.startsWith('application/pdf')
}
}, async (request, reply) => {
reply.type('application/pdf');
return pdfBuffer; // Will be compressed due to custom type function
});The plugin selects compression algorithms based on client Accept-Encoding headers and configured preferences.
Default Algorithm Priority:
zstd (Node.js 22.15+/23.8+)br (Brotli)gzipdeflateidentity (no compression)Usage Examples:
// Configure algorithm preferences
await fastify.register(require('@fastify/compress'), {
encodings: ['br', 'gzip', 'deflate'] // Skip zstd, prefer Brotli
});
// Client Accept-Encoding examples:
// "gzip, deflate, br" -> selects 'br' (highest priority available)
// "gzip, deflate" -> selects 'gzip' (deflate has lower priority)
// "deflate" -> selects 'deflate' (only option available)
// "*" -> selects 'gzip' (default for wildcard)
// "identity" -> no compressionConfigure minimum payload sizes to trigger compression, avoiding overhead for small responses.
/**
* Compression threshold configuration
*/
interface ThresholdOptions {
/** Minimum payload size in bytes to trigger compression (default: 1024) */
threshold?: number;
}Usage Examples:
// Global threshold
await fastify.register(require('@fastify/compress'), {
threshold: 2048 // Only compress responses >= 2KB
});
// Route-specific threshold
fastify.get('/api/data', {
compress: {
threshold: 512 // Compress responses >= 512 bytes for this route
}
}, async (request, reply) => {
return largeDataObject;
});
// Small responses won't be compressed
fastify.get('/api/ping', async (request, reply) => {
return { status: 'ok' }; // Too small, won't be compressed
});Handle content that's already compressed, with optional inflation for non-supporting clients.
/**
* Pre-compressed content handling options
*/
interface PreCompressedOptions {
/** Inflate pre-compressed content for clients that don't support compression */
inflateIfDeflated?: boolean;
}Usage Examples:
// Enable inflation for pre-compressed content
await fastify.register(require('@fastify/compress'), {
inflateIfDeflated: true
});
// Route serving pre-compressed content
fastify.get('/api/precompressed', async (request, reply) => {
// Content is already gzip compressed
const precompressedBuffer = getPrecompressedData();
// Plugin detects compression and handles appropriately:
// - If client supports gzip: sends as-is with Content-Encoding: gzip
// - If client doesn't support gzip: inflates and sends uncompressed
return precompressedBuffer;
});The plugin automatically manages compression-related HTTP headers.
Automatic Header Handling:
Content-Encoding header to selected algorithmVary: accept-encoding headerContent-Length header (configurable)/**
* Header management options
*/
interface HeaderOptions {
/** Remove Content-Length header when compressing (default: true) */
removeContentLengthHeader?: boolean;
}Usage Examples:
// Keep Content-Length header (not recommended)
await fastify.register(require('@fastify/compress'), {
removeContentLengthHeader: false
});
// Headers automatically set by plugin:
fastify.get('/api/data', async (request, reply) => {
return largeObject;
// Response headers will include:
// Content-Encoding: gzip (or br, deflate, etc.)
// Vary: accept-encoding
// Content-Length header removed (default behavior)
});Handle both buffer payloads and streaming responses with appropriate compression.
Usage Examples:
const { Readable } = require('stream');
const fs = require('fs');
// Compress streaming file response
fastify.get('/api/download', async (request, reply) => {
const fileStream = fs.createReadStream('large-file.json');
// Plugin automatically detects stream and applies streaming compression
reply.compress(fileStream);
});
// Compress generated streaming content
fastify.get('/api/generated', async (request, reply) => {
const dataStream = Readable.from(async function* () {
for (let i = 0; i < 10000; i++) {
yield JSON.stringify({ id: i, data: `item-${i}` }) + '\n';
// Allow other operations
if (i % 100 === 0) await new Promise(resolve => setImmediate(resolve));
}
}());
reply.type('application/x-ndjson');
reply.compress(dataStream);
});Override global compression settings on a per-route basis.
/**
* Route compression configuration
*/
interface RouteOptions {
/** Route-specific compression options, or false to disable */
compress?: RouteCompressOptions | false;
}
type RouteCompressOptions = Pick<FastifyCompressOptions,
| 'brotliOptions'
| 'customTypes'
| 'encodings'
| 'inflateIfDeflated'
| 'onUnsupportedEncoding'
| 'removeContentLengthHeader'
| 'threshold'
| 'zlib'
| 'zlibOptions'
>;Usage Examples:
// Route with custom compression settings
fastify.get('/api/high-compression', {
compress: {
encodings: ['br'], // Only use Brotli
threshold: 100, // Compress even small responses
brotliOptions: {
params: {
[require('zlib').constants.BROTLI_PARAM_QUALITY]: 11 // Maximum compression
}
}
}
}, async (request, reply) => {
return await getDataForHighCompression();
});
// Route with compression disabled
fastify.get('/api/no-compress', {
compress: false
}, async (request, reply) => {
return { message: 'Never compressed' };
});
// Route with custom content type matching
fastify.get('/api/custom-types', {
compress: {
customTypes: /^application\/(pdf|zip)/ // Compress PDF and ZIP files
}
}, async (request, reply) => {
reply.type('application/pdf');
return pdfBuffer;
});