Sonamu can automatically compress HTTP responses using @fastify/compress. It supports various compression algorithms like gzip, deflate, and brotli, and you can control compression per API.
Basic Structure
import { defineConfig } from "sonamu";
export default defineConfig({
server: {
plugins: {
compress: {
global: false, // Control per API
threshold: 1024, // Compress only above 1KB
encodings: ["gzip", "br"], // Supported algorithms
},
},
},
// ...
});
compress Settings
Enable/Disable
Type: boolean | FastifyCompressOptions
export default defineConfig({
server: {
plugins: {
compress: true, // Enable with default settings
},
},
});
Disable:
export default defineConfig({
server: {
plugins: {
compress: false, // Disable compression
},
},
});
Key Options
global
Determines whether to automatically apply compression to all responses.
Type: boolean
Default: true
export default defineConfig({
server: {
plugins: {
compress: {
global: false, // Manual control per API
},
},
},
});
true: Auto-compress all responses (default)
false: Control per API with @compress() decorator
We recommend global: false. Small responses or already compressed files (images, videos) don’t need compression.
threshold
Minimum response size to start compression.
Type: number (bytes)
Default: 1024 (1KB)
export default defineConfig({
server: {
plugins: {
compress: {
threshold: 1024, // Compress only above 1KB
},
},
},
});
Recommended values:
1024 (1KB) - General web apps
512 (512B) - Compress small JSON responses too
5120 (5KB) - Compress only large responses
Compressing very small responses may have more overhead than benefit.
encodings
List of compression algorithms to support.
Type: string[]
Default: ["gzip", "deflate"]
export default defineConfig({
server: {
plugins: {
compress: {
encodings: ["gzip", "br"], // gzip and brotli only
},
},
},
});
Supported algorithms:
"gzip" - Most widely supported, fast compression
"deflate" - Similar to gzip
"br" (brotli) - High compression ratio, slower compression
Priority: Uses the first algorithm in the array that the client supports
Brotli has a higher compression ratio but uses more CPU. We recommend pre-compressing static files and using gzip for dynamic responses.
Basic Examples
Recommended Settings
import { defineConfig } from "sonamu";
export default defineConfig({
server: {
plugins: {
compress: {
global: false, // Control per API
threshold: 1024, // Above 1KB only
encodings: ["gzip"], // gzip only (fast)
},
},
},
});
Including Brotli
export default defineConfig({
server: {
plugins: {
compress: {
global: false,
threshold: 1024,
encodings: ["br", "gzip"], // Brotli preferred, gzip fallback
},
},
},
});
Auto Compression (All Responses)
export default defineConfig({
server: {
plugins: {
compress: {
global: true, // Auto-compress all responses
threshold: 512, // Above 512B
encodings: ["gzip"],
},
},
},
});
Per-API Compression Control
If you set global: false, you can control compression per API with the @compress() decorator.
import { api, compress } from "sonamu";
export class DataModel {
// Apply compression
@compress()
@api()
static async getLargeData() {
return {
// Large data...
};
}
// No compression (small response)
@api()
static async getSmallData() {
return { status: "ok" };
}
}
→ Compress Decorator Usage
Practical Examples
Standard Web API
import { defineConfig } from "sonamu";
export default defineConfig({
server: {
plugins: {
compress: {
global: false, // Control with @compress() decorator
threshold: 1024, // Above 1KB only
encodings: ["gzip"],
},
},
},
});
Usage:
export class ArticleModel {
@compress() // Large list response
@api()
static async list() {
return this.getPuri().select("*");
}
@compress() // Large detail data
@api()
static async detail(id: number) {
return this.findById(id, ["**"]);
}
@api() // Don't compress small responses
static async save(data) {
return { id: 123 };
}
}
CDN Optimization
export default defineConfig({
server: {
plugins: {
compress: {
global: false,
threshold: 2048, // Above 2KB only (considering CDN)
encodings: ["br", "gzip"], // Brotli preferred
},
},
},
});
Development vs Production
const isDev = process.env.NODE_ENV === "development";
export default defineConfig({
server: {
plugins: {
compress: isDev
? false // Development: disable compression (easier debugging)
: {
global: false,
threshold: 1024,
encodings: ["gzip"],
},
},
},
});
High Compression Settings
export default defineConfig({
server: {
plugins: {
compress: {
global: false,
threshold: 512, // Compress small responses too
encodings: ["br"], // Brotli only (highest compression ratio)
brotliOptions: {
params: {
[zlib.constants.BROTLI_PARAM_QUALITY]: 11, // Maximum quality
},
},
},
},
},
});
Increasing Brotli quality improves compression ratio but significantly increases CPU usage. Test before using in production.
Additional Options
gzip Level
import zlib from "zlib";
export default defineConfig({
server: {
plugins: {
compress: {
global: false,
threshold: 1024,
encodings: ["gzip"],
zlibOptions: {
level: zlib.constants.Z_BEST_COMPRESSION, // Maximum compression
},
},
},
},
});
gzip levels:
Z_BEST_SPEED (1) - Fast compression
Z_DEFAULT_COMPRESSION (6) - Default (recommended)
Z_BEST_COMPRESSION (9) - Maximum compression
Compress Specific Content-Types Only
export default defineConfig({
server: {
plugins: {
compress: {
global: true,
threshold: 1024,
encodings: ["gzip"],
customTypes: /^text\/|json$/, // text/* and json only
},
},
},
});
Compression Exclusion
export default defineConfig({
server: {
plugins: {
compress: {
global: true,
threshold: 1024,
encodings: ["gzip"],
removeContentLengthHeader: false,
inflateIfDeflated: false,
onUnsupportedEncoding: (encoding, request, reply) => {
reply.code(406); // Not Acceptable
return "Unsupported encoding";
},
},
},
},
});
Verifying Compression
How to verify if responses are compressed:
- Open Network tab
- Check response headers:
- Check Size:
Size: 2.5 KB (transferred)
Size: 10 KB (uncompressed)
curl Test
# Request gzip compression
curl -H "Accept-Encoding: gzip" http://localhost:1028/api/data -i
# Check response headers
# Content-Encoding: gzip
# Content-Length: 1234
# Request Brotli compression
curl -H "Accept-Encoding: br" http://localhost:1028/api/data -i
Compression Trade-offs
Benefits:
- Bandwidth savings (50-80% reduction)
- Faster transfer time (especially on slow networks)
- CDN cost savings
Drawbacks:
- Increased CPU usage
- Increased Time To First Byte (TTFB)
- Increased memory usage
Recommendations
Should compress:
- JSON responses (API)
- HTML, CSS, JavaScript
- SVG, XML
- Text files
Should not compress:
- Images (JPEG, PNG, WebP) - Already compressed
- Videos (MP4, WebM) - Already compressed
- Compressed files (ZIP, GZ) - Already compressed
- Very small responses (< 1KB)
Cautions
1. Already Compressed Files
// ❌ Bad: Compress images too
compress: {
global: true, // Compress everything
}
// ✅ Good: Control per API
compress: {
global: false, // Only @compress() where needed
}
2. CPU Usage
// ❌ Bad: Maximum Brotli quality
compress: {
encodings: ["br"],
brotliOptions: {
params: {
[zlib.constants.BROTLI_PARAM_QUALITY]: 11, // Too slow!
},
},
}
// ✅ Good: Appropriate balance
compress: {
encodings: ["gzip"], // Fast with good compression ratio
}
3. threshold Setting
// ❌ Bad: Too low threshold
threshold: 100 // 100B - Overhead may be larger
// ✅ Good: Appropriate size
threshold: 1024 // 1KB
Next Steps
After completing response compression settings: