Skip to content

pnpr + pacquet: gzip package metadata (packuments) — client requests it, server honors it #12169

Description

@zkochan

Summary

Neither pacquet nor pnpr uses gzip for package metadata (packuments). pacquet fetches packuments uncompressed from every registry — including the public npm registry — and pnpr serves them uncompressed. Packuments are the largest payloads pulled during resolution and gzip them ~5–10×, so this is a real resolution-time win that's currently left on the table, plus a behavior gap versus both real registries and the pnpm (TypeScript) client.

Current state (at 6305e955c6)

Side Behavior Effect
pnpr (server) No compression on packument responses — packument_bytes_response sets only Content-Type, and tower-http is pulled with the trace feature only (no CompressionLayer). Only /v1/files is gzipped. serves packuments raw
pacquet (client) reqwest is built without the gzip feature (hickory-dns, json, rustls, socks, stream); the client builder sets no Accept-Encoding; the packument fetch sends only Accept/Authorization/conditional headers and reads the body with .text() — no decode gets raw packuments from every registry
pnpm-TS (client) undici transparently decompresses gets gzip from real npm, raw from pnpr

Why it matters

  1. pacquet leaves a production win unclaimed. Because pacquet never sends Accept-Encoding: gzip, it pulls uncompressed packuments even from registry.npmjs.org — unlike pnpm-TS. Resolution-heavy installs transfer several× more metadata bytes than they need to.
  2. pnpr isn't a faithful registry. A real registry gzips metadata for clients that ask; pnpr never does. This is a visible divergence for the pnpm-TS client today (gzip from npm, raw from pnpr), and it makes the install-accelerator benchmark less representative once the client is gzip-aware.
  3. Subtle but important: adding gzip to pnpr alone is a no-op for pacquet — the client has to request it. The two changes only pay off together.

Proposed fix (two-sided)

  1. Client (pacquet): enable reqwest's gzip feature so it adds Accept-Encoding: gzip and transparently decompresses. Benefits pacquet against any registry. Tarballs are unaffected — .tgz responses carry no Content-Encoding: gzip, so reqwest leaves them alone and store-integrity verification is unchanged.
  2. Server (pnpr): add tower-http's CompressionLayer to the router. It skips responses that already set Content-Encoding (so the manually-gzipped /v1/files is untouched), compresses packuments + version manifests, and as a bonus shrinks the /v1/install lockfile JSON.

Together: pnpr behaves like a real registry, pacquet gets a genuine resolution-time win everywhere, and the install-accelerator benchmark stays faithful (an uncompressed pnpr would otherwise look worse than real npm once pacquet requests gzip).

Add a test asserting pnpr emits Content-Encoding: gzip for a packument when the request carries Accept-Encoding: gzip, and that pacquet decodes it.

Scope notes

  • Per the keep-pnpm-and-pacquet-in-sync rule, the pnpr-server change and the pacquet-client change are both Rust-side; the pnpm-TS client already gets gzip via undici, so no TS change is needed for parity.
  • Tarballs are already gzip-compressed artifacts — this is metadata/JSON only, no double compression.

Written by an agent (Claude Code, claude-opus-4-8).

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions