Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ export default defineConfig({
label: "007: Rust Implementation",
slug: "docs/governance/rfc/007-rust-implementation",
},
{
label: "008: Server compression preference",
slug: "docs/governance/rfc/008-server-compression-preference",
},
],
},
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: "008: Server compression preference"
---

This RFC proposes amending the Connect protocol to have servers define the
preference for a compression algorithm among the supported set as opposed to
the client. This allows improving compression in scenarios where the client's
ordering cannot be changed, like the browser, and aligns with the commonly
accepted behavior of servers like Envoy and NGINX.

The proposed diff to the protocol specification is in [PR 322][pr322]. This
document focuses on the rationale for the change and the anticipated end user
impact.

## Current behavior

The compression algorithm to use for a request is determined by two factors:
Comment thread
anuraaga marked this conversation as resolved.
Outdated

- The list of supported compression methods configured on the server
- The list of supported compression methods in the client's `Accept-Encoding` header, e.g., `gzip, br, zstd`

Currently, it is the order in the `Accept-Encoding` header that determines which
algorithm to prefer. The server chooses the first compression method that it supports.
Comment on lines +19 to +23

@emcfarlane emcfarlane Aug 31, 2026

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.

In connect-go the response compression is chosen to match the request: https://github.com/connectrpc/connect-go/blob/51112608939254772c8e67577eb5b353741aaa7e/protocol.go#L308-L311

This seems to not be defined in the Spec.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for pointing this out! It seems most intuitive to match the request when the request is compressed. Connect-Py currently does not, since I think I was reading the spec closely when implementing that.

This seems like the right time to consolidate this behavior. I have added a note to use the request compression when provided.


Because common browsers always send `gzip, deflate, br, zstd`, and because all current Connect server implementations support `gzip` by default, it is currently impossible for
connect-web users to use the more modern and efficient `br` and `zstd` algorithms unless a Connect server disables support for `gzip`.

## Proposed behavior

We propose changing the algorithm so that servers are configured with an ordered list of compression methods,
and the first matching method present in the `Accept-Encoding` header is selected.
Comment thread
anuraaga marked this conversation as resolved.
Outdated

For example, given `Accept-Encoding: gzip, br, zstd`

- If the server is configured with `gzip, br, zstd`, then `gzip` is selected.
- If the server is configured with `br, zstd, gzip`, then `br` is selected.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Accept-Encoding: gzip, br, zstd is a precise example for what happens on the wire. I think it's confusing to use the same presentation for the server configuration. I suggest to use pseudo-code for the examples, e.g.

  • If the server is configured with compression = [gzip, br, zstd], then gzip is selected.
  • If the server is configured with compression = [br, zstd, gzip], then br is selected.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think the compression pseudo variable helps that much, I proposed an alternate wording in another comment.

Comment thread
anuraaga marked this conversation as resolved.
Outdated

Moving preference to the server will allow preferring the more efficient algorithms, finally
unlocking them for connect-web. Servers like Envoy and NGINX behave in the same way for the
same reason.

While `br` and `zstd` have come a long way and commonly have similar CPU and RAM usage to

@sudorandom sudorandom Sep 1, 2026

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.

There's something to mention here in regard to Brotli. The official reference library defaults to a compression level of 11 (out of 11). That's level uses A LOT of CPU. And so little-by-little languages are starting to switch the default, but it seems like a lot have not gotten the memo:

And with load balancers, almost none of them use the high default:

I don't think there's anything to do here immediately, but I wanted this to be known about. Defaults are super important for things like this. I suspect documentation of the server compression priority for each language is where this is useful.

From my experiments, brotli compression at level 11 uses so much CPU that the expected RPS for a typical app service will plummet.

While br and zstd have come a long way and commonly have similar CPU and RAM usage to gzip now

when configured appropriately.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yup we aligned with Envoy in connect-py

connectrpc/connect-py#97

I'm not going to complicate the prose for that here though. If we want to add compression levels to the spec, probably another PR that doesn't necessarily need an RFC (maybe)

`gzip` now, it can't be confirmed all workloads will see no regression from a change from
`gzip` to e.g., `br`. In an abundance of caution, if this RFC is approved, then this new behavior will only be introduced in Connect implementations as part of a major version. It is planned to be introduced to Connect-Go in v2, Connect-Py before v1, and Connect-ES
in v3.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I suggest that we clarify that this change applies not only to unary RPCs, but also to streaming RPCs and unary GET, and that it applies to all three protocols if an implementation supports them, not only to the Connect protocol.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point - I have added a note about it in 31e708f

[pr322]: https://github.com/connectrpc/connectrpc.com/pull/322