HarperFast / HarperFast/documentation
http.compressionThreshold: docs say default 1200, shipped config sets 0 (compression off by default)
- Dominant language
- MDX
- Stars
- 9
- Forks
- 9
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 32
Description
### What's wrong
The docs state that `http.compressionThreshold` defaults to **1200** bytes, so Brotli response compression is on out of the box. Harper's shipped configuration sets it to **0**, and the runtime treats 0 as "off" — so on a default install, Brotli response compression never happens.
The root cause is not in this repo. **Harper contradicts itself**, and our docs faithfully mirror the half of it that isn't what actually ships.
### Evidence (harper `origin/main`)
| Location | Says |
| --- | --- |
| `config-root.schema.json:25-31` | property description: "Responses larger than this threshold (bytes) will be compressed... **Default: 1200**" |
| `config-root.schema.json:774` | `examples` block: `"compressionThreshold": 1200` |
| `static/defaultConfig.yaml:4` | **`compressionThreshold: 0`** — this is what gets written into a new install's config |
| `validation/configValidator.ts:329` | `compressionThreshold: number.optional()` — no default injected |
| `server/serverHelpers/contentTypes.ts:362` | `const COMPRESSION_THRESHOLD = envMgr.get(CONFIG_PARAMS.HTTP_COMPRESSIONTHRESHOLD)` — **no `\|\|` fallback**, so a configured 0 stays 0 |
| `server/serverHelpers/contentTypes.ts:373` | `canCompress = COMPRESSION_THRESHOLD && request.headers...includes('br')` — 0 is falsy, so compression is skipped entirely |
So the schema *documents* 1200, the shipped template *sets* 0, and the runtime honors 0. There is no code-level 1200 default anywhere.
Note this is specifically **`http.compressionThreshold`**. The unrelated `storage.compressionThreshold` (LMDB record compression) does have a real code default — `(storage.pageSize || 4096) - 60` at `resources/databases.ts:102` — which makes this easy to conflate when grepping.
### Affected pages in this repo
- [`reference/configuration/options.md:37`](reference/configuration/options.md#L37) - "_Default_: `1200` (bytes)"
- [`reference/http/configuration.md:111`](reference/http/configuration.md#L111) - the `http.compressionThreshold` section, plus `1200` in examples at `:123` and `:318`
- [`reference/http/overview.md:104`](reference/http/overview.md#L104) - "Compression applies when the response body exceeds the configured `compressionThreshold` (default 1200 bytes)"
- [`reference/configuration/operations.md:106`](reference/configuration/operations.md#L106) - `"compressionThreshold": 1200` in a config response example
### The question that has to be answered first
**Is `compressionThreshold: 0` in the shipped config intentional?** The docs fix depends entirely on the answer, and the two outcomes are very different:
- **If 0 is a bug in harper** - Brotli compression has been silently off for every default install. That is the real finding here, and the fix belongs in `static/defaultConfig.yaml`. Our docs then need no change beyond possibly noting the versions affected.
- **If 0 is intentional** - then harper's own schema description and examples are wrong too, and our four locations should say compression is **disabled by default** and must be explicitly enabled. In that case `config-root.schema.json` should be corrected alongside.
Either way one of the two harper locations is wrong, so this likely wants a companion harper issue; transferring or cross-linking is fine.
### Why it matters beyond a wrong number
Two things downstream depend on this:
1. Anyone following our docs believes responses over 1200 bytes are compressed. If they are not, that is a real and invisible performance difference on a default install.
2. There is a latent crash gated behind this setting. `contentTypes.ts:410-425` pipes `serializeStream`'s return value into `createBrotliCompress()` whenever `canCompress` is true, but the `application/x-msgpack` handler returns a `Buffer` (not a stream) for a plain array. `Accept: application/x-msgpack` + `Accept-Encoding: br` + an array body would throw `TypeError: stream.pipe is not a function`. That is currently unreachable **only because compression ships disabled** - so if the default is "corrected" to 1200 without fixing the pipe path first, this becomes reachable the same day. Sequencing matters. Surfaced in #655.
### Suggested fix
1. Get a ruling from whoever owns `static/defaultConfig.yaml` on whether 0 is intended.
2. Fix harper's inconsistency (either the shipped default or the schema description + examples).
3. Update the four locations above to match, in one pass so they cannot disagree with each other.
4. Track the `.pipe()` normalization separately, and land it before any change that turns compression on by default.
sent with Claude Opus 5
Contributor guide
Research direction
Start by reviewing the four cited documentation locations and confirming with the owner of Harper's static/defaultConfig.yaml whether compressionThreshold: 0 is intentional. Then verify the companion Harper inconsistency and #655's stream issue before updating all documented values consistently; done means the cross-repo decision is recorded and the four pages match the shipped behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100