Skip to content

storage/gcp: compress entry bundles with gzip - #1213

Draft
patflynn wants to merge 1 commit into
transparency-dev:mainfrom
patflynn:gcp-gzip-bundles
Draft

patflynn wants to merge 1 commit into
transparency-dev:mainfrom
patflynn:gcp-gzip-bundles

Conversation

@patflynn

@patflynn patflynn commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Store entry bundles (tile/entries/* and tile/data/*) in GCS with Content-Encoding: gzip to reduce storage and egress bandwidth by ~55-60%.

Details & Safety

  • Selective compression: Only entry bundles (setEntryBundle) are compressed with gzip (Content-Encoding: gzip). Checkpoints and Merkle hash tiles (tile/<level>/*) remain uncompressed.
  • HTTP & gRPC GCS client compatibility:
    • The HTTP GCS client (gcs.NewClient) transparently decompresses Content-Encoding: gzip objects (setting r.Attrs.Decompressed = true and clearing r.Attrs.ContentEncoding).
    • The gRPC GCS client (gcs.NewGRPCClient, used by TesseraCT) does not perform decompressive transcoding and returns the raw compressed bytes with r.Attrs.ContentEncoding == "gzip" and r.Attrs.Decompressed == false.
    • gcsStorage.getObject checks r.Attrs.ContentEncoding == "gzip" && !r.Attrs.Decompressed and gunzips before returning, ensuring all internal callers (updateEntryBundles, antispam, deduplication, migration, and 412 precondition-failed idempotent write recovery) always receive uncompressed logical bytes regardless of client transport.
  • Backward-compatible with existing logs: Pre-existing uncompressed entry bundles (including partial bundles grown across the rollout boundary) have empty Content-Encoding and continue to be read without change.
  • External HTTP readers: Clients sending Accept-Encoding: gzip receive compressed bytes directly from GCS/CDN; clients omitting Accept-Encoding: gzip receive decompressed bytes via GCS decompressive transcoding.

Store entry bundles (tile/entries/* and tile/data/*) in GCS with
Content-Encoding: gzip to reduce storage and egress bandwidth by ~55-60%.

- Compress entry bundle payloads with gzip in gcsStorage.setObject and set
  w.ContentEncoding = "gzip" while keeping checkpoints and hash tiles
  uncompressed.
- Transparently gunzip in gcsStorage.getObject when
  r.Attrs.ContentEncoding == "gzip" && !r.Attrs.Decompressed so both the
  HTTP GCS client (which auto-decompresses via decompressive transcoding)
  and the gRPC GCS client (which returns raw compressed bytes) always
  return uncompressed logical bytes to internal callers (updateEntryBundles,
  antispam, deduplication, migration, and 412 precondition-failed
  idempotency checks).
- Remain fully backward-compatible with pre-existing uncompressed entry
  bundles in GCS.
@patflynn
patflynn requested a review from a team as a code owner October 7, 2026 16:27
@patflynn
patflynn requested a review from phbnf October 7, 2026 16:27

@phbnf phbnf 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.

Specs say that we should do this, so we should certainly do it! Maybe we need an issue to also make sure that we do this on POSIX? I can't remember what / if current CT operators have done something about this already.

However, I wonder what the CPU impact would be both for writes and reads. Should we test this? I'd like to make sure that this change won't cause unexpected CPU surges.

Comment thread storage/gcp/gcp.go
// returns an error if the named object exists _and_ contains different data to what's
// passed in here.
if err := s.objStore.setObject(ctx, objName, bundleRaw, &gcs.Conditions{DoesNotExist: true}, logContType, logCacheControl); err != nil {
if err := s.objStore.setObject(ctx, objName, bundleRaw, &gcs.Conditions{DoesNotExist: true}, logContType, logCacheControl, bundleContEnc); err != nil {

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.

Might be worth popping a comment explaining that if a client doesn't set Accept-Encoding, then GCS (I think?) will decompress data.

@patflynn
patflynn marked this pull request as draft October 7, 2026 16:50

This branch has not been deployed

No deployments
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.

2 participants