Skip to content

perf: compress api responses in the bundled Caddy - #1908

Merged
joshunrau merged 1 commit into
mainfrom
perf/compress-api-responses
Nov 10, 2026
Merged

joshunrau merged 1 commit into
mainfrom
perf/compress-api-responses

Conversation

@gdevenyi

@gdevenyi gdevenyi commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

A deployment that uses the bundled Caddy now sends API responses compressed (zstd or gzip). Before, the API and the bundled Caddy sent all responses at full size. This is a mitigation for #1714, not its fix: on an instance with 19,099 records the dashboard's record list did not arrive in the web client's 10 s limit, and the dashboard showed "Reconnecting…" continuously.

Changes

  • The bundled Caddy compresses responses from /api/* whose Content-Type is application/json or application/x-msgpack, when the client sends Accept-Encoding. Other content types and the /storage/* and web routes are not changed.

Decisions

  • An explicit match is given, in place of a plain encode zstd gzip. The default match list of encode does not include application/x-msgpack, which is the type of the instrument records list (MsgpackInterceptor). A plain encode thus compresses the small responses and not the largest one. The cost is that a new response type on the API is not compressed until it is added to the list.
  • Compression is done in Caddy, not in the API with @fastify/compress. The alternative also covers deployments that do not use the bundled Caddy, but it adds a dependency and uses the API's one event loop for the compression work.

Risks

  • A deployment that has its own copy of the Caddyfile does not get this change until the operator updates the copy.
  • Compression uses CPU time in the Caddy container for each large response. Accepted: the body sizes that matter here are megabytes, and the web image already does the same for static files.

Notes

Tested in caddy:2.7-alpine (the image in docker-compose.yaml) with this Caddyfile and a mock api upstream that serves a 1.62 MB JSON body of 20,000 small records:

Response Content-Type Accept-Encoding Bytes on the wire
application/x-msgpack zstd, gzip 28,692
application/x-msgpack gzip 107,231
application/x-msgpack identity 1,617,780
application/json; charset=utf-8 zstd, gzip 28,692
application/octet-stream zstd, gzip 1,617,780

With a plain encode zstd gzip in the same image, the application/x-msgpack response stays at 1,617,780 bytes. The body in the test was JSON text with a msgpack label, so the ratio for real msgpack bodies will be lower. The effect on the instance in #1714 is not measured.

Adversarial review

Reviewed at commit c715c2c. pnpm check: green. The three steps of pnpm check (lint, unit tests with coverage, end-to-end tests) ran green in the CI job lint-and-test on this commit, not on a local machine.

Findings

CLEAN

Attestation

I, Claude Fable 5.2, attest that the review block above reports the adversarial review as it ran on the commit named, with every finding it returned.

🤖 Generated with Claude Code

https://claude.ai/code/session_01W53iUShuoPRdGy8vrks2nm

The api does not compress its responses. The default match list of encode omits
application/x-msgpack, the type of the instrument records list. Mitigates #1714.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W53iUShuoPRdGy8vrks2nm
@gdevenyi
gdevenyi requested a review from joshunrau as a code owner November 10, 2026 14:22
Copilot AI balanced review requested due to automatic review settings November 10, 2026 14:22

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@gdevenyi

Copy link
Copy Markdown
Contributor Author

An alternative to this would be to add compression into the API endpoint in node.

@github-actions

Copy link
Copy Markdown

This pull request was closed because its body does not meet .agents/skills/opening-pr/SKILL.md:

  • ### Findings is neither CLEAN nor numbered findings.

Fix the body with gh pr edit <number> --body-file <path>, then gh pr reopen <number>.

@github-actions github-actions Bot closed this Nov 10, 2026
@gdevenyi gdevenyi reopened this Nov 10, 2026
@github-actions

Copy link
Copy Markdown

This pull request was closed because its body does not meet .agents/skills/opening-pr/SKILL.md:

  • ### Findings is neither CLEAN nor numbered findings.

Fix the body with gh pr edit <number> --body-file <path>, then gh pr reopen <number>.

@github-actions github-actions Bot closed this Nov 10, 2026
@gdevenyi gdevenyi reopened this Nov 10, 2026
@github-actions

Copy link
Copy Markdown

This pull request was closed because its body does not meet .agents/skills/opening-pr/SKILL.md:

  • ### Findings is neither CLEAN nor numbered findings.

Fix the body with gh pr edit <number> --body-file <path>, then gh pr reopen <number>.

@github-actions github-actions Bot closed this Nov 10, 2026
@joshunrau joshunrau reopened this Nov 10, 2026
@joshunrau
joshunrau merged commit c38a420 into main Nov 10, 2026
15 of 18 checks passed
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.

3 participants