Skip to content

perf(server): Switch cache compression from deflate to Brotli#1410

Merged
yamadashy merged 6 commits into
mainfrom
perf/use-brotli-for-cache-compression
Apr 5, 2026
Merged

perf(server): Switch cache compression from deflate to Brotli#1410
yamadashy merged 6 commits into
mainfrom
perf/use-brotli-for-cache-compression

Conversation

@yamadashy

@yamadashy yamadashy commented Apr 5, 2026

Copy link
Copy Markdown
Owner

Switch the in-memory cache compression algorithm from deflate to Brotli (quality level 4) to reduce memory footprint on Cloud Run.

Benchmark results (308KB input)

Method Size Speed vs deflate
deflate (default) 6.6 KB 0.62 ms
brotli q=4 4.1 KB 0.28 ms 38% smaller, 2x faster
brotli q=11 3.5 KB 14.30 ms 48% smaller, 23x slower

Brotli q=4 provides the best balance: better compression than deflate while actually being faster.

Checklist

  • Run npm run test
  • Run npm run lint

Open with Devin

Use Brotli (quality 4) instead of deflate for in-memory cache compression.
Brotli q=4 achieves ~38% better compression ratio than deflate while being
faster (0.28ms vs 0.62ms per operation), reducing cache memory footprint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

⚡ Performance Benchmark

Latest commit:1bdb18c [autofix.ci] apply automated fixes
Status:✅ Benchmark complete!
Ubuntu:1.52s (±0.04s) → 1.51s (±0.01s) · -0.01s (-0.6%)
macOS:1.10s (±0.20s) → 1.07s (±0.18s) · -0.03s (-2.4%)
Windows:2.01s (±0.62s) → 2.28s (±0.64s) · +0.27s (+13.6%)
Details
  • Packing the repomix repository with node bin/repomix.cjs
  • Warmup: 2 runs (discarded), interleaved execution
  • Measurement: 20 runs / 30 on macOS (median ± IQR)
  • Workflow run
History

5493da9 perf(server): Reduce Brotli window size to lower per-call memory

Ubuntu:1.53s (±0.04s) → 1.51s (±0.02s) · -0.01s (-0.9%)
macOS:1.19s (±0.20s) → 1.22s (±0.21s) · +0.03s (+2.4%)
Windows:1.95s (±0.04s) → 1.94s (±0.05s) · -0.01s (-0.5%)

f98b14d refactor(server): Extract Brotli quality level into named constant

Ubuntu:1.50s (±0.04s) → 1.49s (±0.03s) · -0.01s (-0.7%)
macOS:0.86s (±0.05s) → 0.88s (±0.07s) · +0.02s (+1.9%)
Windows:1.82s (±0.04s) → 1.82s (±0.04s) · -0.00s (-0.1%)

7abc77e refactor(server): Use BROTLI_MODE_TEXT and remove redundant Buffer allocation

Ubuntu:1.49s (±0.02s) → 1.50s (±0.03s) · +0.01s (+0.5%)
macOS:1.15s (±0.27s) → 1.19s (±0.25s) · +0.04s (+3.5%)
Windows:1.84s (±0.05s) → 1.85s (±0.05s) · +0.01s (+0.4%)

3ba995c perf(server): Switch cache compression from deflate to Brotli

Ubuntu:1.53s (±0.02s) → 1.53s (±0.03s) · -0.01s (-0.6%)
macOS:1.39s (±0.23s) → 1.38s (±0.21s) · -0.01s (-1.0%)
Windows:2.28s (±0.43s) → 2.23s (±0.49s) · -0.04s (-2.0%)

@coderabbitai

coderabbitai Bot commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b4dbd73b-1606-4735-a301-527d524cf1c0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Replaced zlib compression (inflate/deflate) with Brotli compression (brotliDecompress/brotliCompress) in the cache utility. Updated the get() method to use Brotli decompression and the set() method to use Brotli compression with quality parameter set to 4. Error handling and JSON serialization/deserialization logic remain unchanged.

Changes

Cohort / File(s) Summary
Compression Algorithm Update
website/server/src/domains/pack/utils/cache.ts
Replaced zlib inflate/deflate with Brotli compress/decompress. Added Brotli quality parameter configuration (BROTLI_PARAM_QUALITY set to 4) in the set() path. Cache TTL checks and error handling remain structurally identical.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: switching cache compression from deflate to Brotli, which is the primary modification in the changeset.
Description check ✅ Passed The description includes detailed benchmark results, clear rationale for the change, and completes the repository's checklist with both test and lint items marked as done.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/use-brotli-for-cache-compression

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

gemini-code-assist[bot]

This comment was marked as resolved.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Apr 5, 2026

Copy link
Copy Markdown

Deploying repomix with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1bdb18c
Status: ✅  Deploy successful!
Preview URL: https://188b8d1e.repomix.pages.dev
Branch Preview URL: https://perf-use-brotli-for-cache-co.repomix.pages.dev

View logs

@claude

claude Bot commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Code Review — PR #1410

Overall: Approve — Clean, well-scoped change. Low risk, correct implementation, credible benchmarks.

Findings

1. Extract Brotli quality level into a named constant (Suggestion)

The magic number 4 in the params object would be clearer as a module-level constant:

const BROTLI_QUALITY = 4; // Balanced speed/ratio for in-memory cache

This makes the tuning choice explicit and easier to find/adjust later.

2. No tests for cache.ts (Pre-existing gap, not introduced by this PR)

Details

There are no test files for the cache module (website/server/ has no test infrastructure at all). While this PR doesn't make the gap worse, a compression algorithm swap is exactly the kind of change a round-trip unit test would catch regressions for. Recommend a follow-up issue to add tests covering:

  • Compress/decompress round-trip correctness
  • TTL expiry behavior
  • Error handling (corrupt entry → delete + return undefined)
  • dispose() cleanup

3. Performance assessment (No concerns)

Details

The benchmark claims (Brotli q=4: 38% smaller, 2x faster than deflate) are consistent with published compression literature. Brotli at lower quality levels avoids the full Huffman pass and benefits from a superior static dictionary. The choice of q=4 over the default q=11 (which would be 23x slower) is correct for a latency-sensitive cache path.

One minor note: under high concurrency, Brotli's compressor state at q=4 uses ~4 MB per active context vs. smaller for deflate. For a Cloud Run deployment with moderate traffic this is negligible, but worth knowing if traffic patterns change significantly.

4. Security (No concerns)

The cache is write-then-read within the same process — no path for untrusted compressed data to reach decompressAsync. No new attack vectors.

5. Deployment (No concerns)

Cache is purely in-memory with 60s TTL. Server restarts clear it. No rolling-deploy compatibility issues since old deflate entries can't survive a restart. The catch block in get() also gracefully handles any hypothetical format mismatch by deleting the entry.

6. Conventions (All pass)

Commit message, PR title, PR body, checklist, and code style all conform to project conventions.


🤖 Generated with Claude Code

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

…location

Apply gemini-code-assist suggestion: enable text mode for better compression
of JSON cache data and pass string directly to brotliCompress.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Follow-up Review — Incremental Findings

The previous review covered the main points well. Here are additional observations not yet mentioned:

1. PR description says "60s TTL" but actual usage is 600s (10 minutes) (Minor — docs accuracy)

Details

The RequestCache constructor defaults to ttlInSeconds = 60, but sharedInstance.ts line 6 constructs it with new RequestCache<PackResult>(600) — a 10-minute TTL. The PR description references "60s TTL" which is misleading. Not a code bug, but worth correcting in the description since the longer TTL means more entries accumulate in memory, making the 38% size reduction more impactful than the description suggests.

2. Consider tuning BROTLI_PARAM_LGWIN for lower per-call memory (Optional micro-optimization)

Details

The default Brotli window size is 22 (4 MB look-back). For typical cached payloads (tens to hundreds of KB of JSON), a smaller window like 19 (512 KB) would be sufficient and reduces per-compression-call memory allocation. Given the stated goal of reducing Cloud Run memory footprint, this is worth considering alongside the quality setting:

[zlib.constants.BROTLI_PARAM_LGWIN]: 19,

No blocking issues found. The change is correct, well-scoped, and safe to merge.


🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@yamadashy

Copy link
Copy Markdown
Owner Author

Addressed the named constant suggestion in f98b14d. 🤖

yamadashy and others added 3 commits April 6, 2026 02:09
Set BROTLI_PARAM_LGWIN to 19 (512KB) instead of default 22 (4MB).
No impact on compression ratio for typical cache payloads, while
reducing memory allocation per compression call.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Smaller window size (512KB) degrades compression ratio significantly
for large repositories (26% worse at 7.7MB), which are the payloads
that benefit most from compression. Revert to default 4MB window.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Code Review — PR #1410 (Third Pass)

Overall: Approve — Previous reviews covered the core analysis well, and the owner addressed both actionable suggestions (named constant, LGWIN tuning). This pass focuses on what's new or unaddressed.

New Findings

1. Final diff state vs commit history discrepancy (Informational)

The PR has 4 commits, but gh pr diff shows only 3 commits' worth of changes — BROTLI_PARAM_LGWIN / BROTLI_WINDOW_SIZE from commit 5493da9 is absent from the cumulative diff. This may be a rebase artifact or intentional revert. If the LGWIN change was intentionally dropped, the commit history is misleading; if it should be included, the diff is incomplete. Worth confirming the intended final state.

2. BROTLI_WINDOW_SIZE naming (Minor — only if LGWIN is retained)

Details

The constant holds a log₂ exponent (19), not a byte count. The comment clarifies this, but the name BROTLI_WINDOW_SIZE could mislead a future reader into thinking it's a size value. BROTLI_LGWIN (matching the Node.js constant name) would be more precise. Very minor — not blocking.

Previously Raised — Still Open

  • No tests for cache.ts: Pre-existing gap, not introduced here, but the algorithm swap makes a round-trip test more valuable. Recommend a follow-up issue.
  • PR description says "60s TTL": Actual usage is new RequestCache<PackResult>(600) (10 minutes). The longer TTL means more entries in memory at steady state, making the 38% size reduction more impactful than described.

No Concerns

  • Security: No new attack surface. Data is internally generated and bounded upstream.
  • Performance: Brotli q=4 benchmarks are credible and consistent with published literature. The default window (22/4MB) is appropriate for varying payload sizes.
  • Conventions: Commit messages follow Conventional Commits. The server scope is reasonable for website/server/ code.
  • Deployment: In-memory cache with no persistence — zero rolling-deploy risk.

🤖 Generated with Claude Code

@yamadashy yamadashy merged commit 129cfbe into main Apr 5, 2026
20 of 21 checks passed
@yamadashy yamadashy deleted the perf/use-brotli-for-cache-compression branch April 5, 2026 17:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant