Skip to content

feat(gateway)!: support zstd transport compression#1558

Open
shiftinv wants to merge 17 commits into
masterfrom
feat/zstd
Open

feat(gateway)!: support zstd transport compression#1558
shiftinv wants to merge 17 commits into
masterfrom
feat/zstd

Conversation

@shiftinv

@shiftinv shiftinv commented Jun 28, 2026

Copy link
Copy Markdown
Member

Summary

Adds support for zstd-stream transport compression in gateway connections, in addition to the usual zlib-stream, and uses it as the default compression method if available.

This uses the builtin compression.zstd module on Python 3.14+, or optionally backports.zstd on earlier Python versions, which is now also part of disnake[speed] (would've been included by aiohttp[speedups] already anyway),.

At least based on some rudimentary benchmarking and publicly available comparisons, zstd should achieve a little better compression and is a fair bit faster.
Running this branch with two instances of one of my bots in prod at the same time for ~5 minutes, one with each compression mode:

compressed (bytes) (uncompressed (bytes)) decompress time (ms)
zlib-stream 4272080 (32234978) 126.0311
zstd-stream 4037587 (32233882) 71.9549

The one minor disadvantage is potentially slightly higher memory usage due to larger lookback buffers, but only to a very limited and negligible degree, especially since it scales linearly with the number of shards.

https://docs.discord.com/developers/events/gateway#zstd-stream

Checklist

  • If code changes were made, then they have been tested
    • I have updated the documentation to reflect the changes
    • I have formatted the code properly by running uv run nox -s lint
    • I have type-checked the code by running uv run nox -s pyright
  • This PR fixes an issue
  • This PR adds something new (e.g. new method or parameters)
  • This PR is a breaking change (e.g. methods or parameters removed/renamed)
  • This PR is not a code change (e.g. documentation, README, ...)

@shiftinv shiftinv added this to the disnake v2.13 milestone Jun 28, 2026
@shiftinv shiftinv added the t: enhancement New feature label Jun 28, 2026
@shiftinv shiftinv added this to disnake Jun 28, 2026
@shiftinv shiftinv added the t: api support Support of Discord API features label Jun 28, 2026
@github-project-automation github-project-automation Bot moved this to Todo in disnake Jun 28, 2026
@read-the-docs-community

read-the-docs-community Bot commented Jun 28, 2026

Copy link
Copy Markdown

Documentation build overview

📚 disnake | 🛠️ Build #33380041 | 📁 Comparing e9c1cae against latest (eb365ef)

  🔍 Preview build  

48 files changed · ± 48 modified

± Modified

@shiftinv shiftinv changed the title feat(gateway): support zstd transport compression feat(gateway)!: support zstd transport compression Jun 28, 2026
@shiftinv shiftinv added the breaking change Includes breaking changes to code/packaging label Jun 28, 2026
Comment thread disnake/gateway.py Outdated
Comment thread disnake/gateway.py
Comment on lines +129 to +135
def __post_init__(self) -> None:
if self.encoding != "json":
msg = "Gateway encodings other than `json` are currently not supported."
raise ValueError(msg)
if self.compress not in ("zlib-stream", "zstd-stream", None):
msg = "Gateway transport compression modes other than `zlib-stream`, `zstd-stream`, or None are currently not supported."
raise ValueError(msg)

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.

What do you think of placing such checks behind if __debug__?

Suggested change
def __post_init__(self) -> None:
if self.encoding != "json":
msg = "Gateway encodings other than `json` are currently not supported."
raise ValueError(msg)
if self.compress not in ("zlib-stream", "zstd-stream", None):
msg = "Gateway transport compression modes other than `zlib-stream`, `zstd-stream`, or None are currently not supported."
raise ValueError(msg)
if __debug__:
def __post_init__(self) -> None:
if self.encoding != "json":
msg = "Gateway encodings other than `json` are currently not supported."
raise ValueError(msg)
if self.compress not in ("zlib-stream", "zstd-stream", None):
msg = "Gateway transport compression modes other than `zlib-stream`, `zstd-stream`, or None are currently not supported."
raise ValueError(msg)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Hmm, not sure. Since this is going to be run at most once per gateway connection, I don't really see a reason to.

Comment thread disnake/gateway.py

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

Half of the review before sleep, half after 👍

Comment thread disnake/gateway.py Outdated
Comment thread disnake/gateway.py
Comment thread disnake/gateway.py


class _DecompressionContext(Protocol):
def decompress(self, data: bytes | bytearray, /) -> bytes | None: ...

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.

If ctx.decompress support accepting typing.Buffer, we could replace bytes | bytearray with it

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I considered this as well, but Buffer doesn't trivially work with .endswith or bytearray.extend, unfortunately

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.

Now I've checked that it's a 3.12+ import, oh well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change Includes breaking changes to code/packaging t: api support Support of Discord API features t: enhancement New feature

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants