Skip to main content
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

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:

Browser Developer Tools

  1. Open Network tab
  2. Check response headers:
    Content-Encoding: gzip
    
  3. 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

Performance Impact

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: