> ## Documentation Index
> Fetch the complete documentation index at: https://sonamu.cartanova.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Compression

> HTTP response compression settings

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

```typescript theme={null}
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`

```typescript theme={null}
export default defineConfig({
  server: {
    plugins: {
      compress: true, // Enable with default settings
    },
  },
});
```

**Disable**:

```typescript theme={null}
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`

```typescript theme={null}
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

<Tip>
  We recommend `global: false`. Small responses or already compressed files (images, videos) don't
  need compression.
</Tip>

### threshold

Minimum response size to start compression.

**Type**: `number` (bytes)

**Default**: `1024` (1KB)

```typescript theme={null}
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

<Note>Compressing very small responses may have more overhead than benefit.</Note>

### encodings

List of compression algorithms to support.

**Type**: `string[]`

**Default**: `["gzip", "deflate"]`

```typescript theme={null}
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

<Tip>
  Brotli has a higher compression ratio but uses more CPU. We recommend pre-compressing static files
  and using gzip for dynamic responses.
</Tip>

## Basic Examples

### Recommended Settings

```typescript theme={null}
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

```typescript theme={null}
export default defineConfig({
  server: {
    plugins: {
      compress: {
        global: false,
        threshold: 1024,
        encodings: ["br", "gzip"], // Brotli preferred, gzip fallback
      },
    },
  },
});
```

### Auto Compression (All Responses)

```typescript theme={null}
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.

```typescript theme={null}
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](/en/advanced-features/compress/per-api-control)

## Practical Examples

### Standard Web API

```typescript theme={null}
import { defineConfig } from "sonamu";

export default defineConfig({
  server: {
    plugins: {
      compress: {
        global: false, // Control with @compress() decorator
        threshold: 1024, // Above 1KB only
        encodings: ["gzip"],
      },
    },
  },
});
```

**Usage**:

```typescript theme={null}
export class ArticleModel {
  @compress() // Large list response
  @api()
  static async list() {
    return this.getPuri("r").table("articles").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

```typescript theme={null}
export default defineConfig({
  server: {
    plugins: {
      compress: {
        global: false,
        threshold: 2048, // Above 2KB only (considering CDN)
        encodings: ["br", "gzip"], // Brotli preferred
      },
    },
  },
});
```

### Development vs Production

```typescript theme={null}
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

```typescript theme={null}
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
          },
        },
      },
    },
  },
});
```

<Warning>
  Increasing Brotli quality improves compression ratio but significantly increases CPU usage. Test
  before using in production.
</Warning>

## Additional Options

### gzip Level

```typescript theme={null}
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

```typescript theme={null}
export default defineConfig({
  server: {
    plugins: {
      compress: {
        global: true,
        threshold: 1024,
        encodings: ["gzip"],
        customTypes: /^text\/|json$/, // text/* and json only
      },
    },
  },
});
```

### Compression Exclusion

```typescript theme={null}
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

```bash theme={null}
# Request gzip compression
curl -H "Accept-Encoding: gzip" http://localhost:34900/api/data -i

# Check response headers
# Content-Encoding: gzip
# Content-Length: 1234

# Request Brotli compression
curl -H "Accept-Encoding: br" http://localhost:34900/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

```typescript theme={null}
// ❌ Bad: Compress images too
compress: {
  global: true,  // Compress everything
}

// ✅ Good: Control per API
compress: {
  global: false,  // Only @compress() where needed
}
```

### 2. CPU Usage

```typescript theme={null}
// ❌ 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

```typescript theme={null}
// ❌ Bad: Too low threshold
threshold: 100; // 100B - Overhead may be larger

// ✅ Good: Appropriate size
threshold: 1024; // 1KB
```

## Next Steps

After completing response compression settings:

* [compress decorator](/en/advanced-features/compress/per-api-control) - Per-API compression control
* [cache-control](/en/configuration/sonamu-config/cache-control) - Using cache with compression
* [performance](/en/troubleshooting/performance/query-optimization) - Performance optimization
