Skip to content
Open
Show file tree
Hide file tree
Changes from all 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,54 @@
---
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 response is determined by two factors:

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

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.

Good catch. This needs to be specified in protocol.md. It currently says that servers should not do that. I'll suggest a change.

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.

Oops I had updated the RFC here but forgot to update the protocol.md PR, updated it

006519b

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.

Just to clarify, I'm not sure if they should do this behavior. But the current connect-go does, and I wanted clarification so implementations are consistent.


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 if the client has not compressed
the request.

For example, given this header from a client: `Accept-Encoding: gzip, br, zstd`

- If the server's list of supported compression methods is `[gzip, br, zstd]`, then the server selects `gzip` as the compression method.
- If the server's list of supported compression methods is `[br, zstd, gzip]`, then the server selects `br` as the compression method.

If the request is compressed, including a `Content-Encoding` header with a valid compression algorithm, that algorithm must be
used without consulting `Accept-Encoding`.

The above matching should be used for all RPCs, including unary and streaming, and non-Connect protocol RPCs. The header names
may be different but should otherwise select a compression in the same way.

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.

Comment thread
timostamm marked this conversation as resolved.
[pr322]: https://github.com/connectrpc/connectrpc.com/pull/322