Evidence ledger 28 sources Checked 22 Sep 2026

Evidence ledger

One row per claim in Making the client carry it: ten years of Discord's gateway contract: who published it, what grade it carries, when it was written, when the link was last checked, and the quote or figure it rests on. Nothing in the guide is cited from memory, so anything not in this table is not in the guide.

One row per claim. Every URL was fetched during the research session on 2026-09-22.

Evidence limit, stated up front. The research environment's outbound network policy allowed github.com, raw.githubusercontent.com, gitlab.com and the public package registries (hex.pm, registry.npmjs.org, pypi.org, files.pythonhosted.org, proxy.golang.org, index.crates.io). Engineering blogs, status pages, video hosts and paper archives were unreachable, including discord.com, where Discord publishes its engineering posts and its incident write-ups. This guide is therefore built entirely from the repository record and the registries: the published documentation source, its dated change log, pull requests and issue threads, library READMEs, and release timestamps. There are no blog, paper or talk sources in the mix, and that absence is stated in the guide rather than papered over.

# Org Title Tier Published Checked URL Claim I take from it Supporting quote or figure
1 Discord Developer change log (developers/change-log.mdx) adr 2017-07-19 to 2026-09-18 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx The public contract has a countable decision record: 237 dated entries over nine years and two months, 27 of them tagged Breaking Change. Parsed from the file: 237 <Update label="…"> blocks; earliest label "July 19, 2017", latest "September 18, 2026"; entries per year 2017:8, 2018:8, 2019:11, 2020:12, 2021:14, 2022:27, 2023:23, 2024:33, 2025:42, 2026:59; 27 blocks carry the tag "Breaking Change".
2 Discord Change log, "Breaking Change: Version 6" adr 2017-07-19 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx The record opens with a schema-shaped break, not a capacity-shaped one: renamed and retyped fields. "is_private removed"; "[type] is now an integer"; "recipient is now recipients"; "idle_since renamed to since".
3 Discord Change log, "Semi-Breaking Change: Very Large Bot Sharding" adr 2018-01-03 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx The first capacity-shaped contract change moves partitioning work onto the app, for apps above 100,000 guilds. "Additional sharding requirements and information for bots in over 100,000 guilds has been added. This requires a small change in numbers of shards for affected bots."
4 Discord Change log, "Gateway Intents" adr 2020-02-14 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx Declared subscriptions arrive framed as a saving for the app, not as load shedding for the platform. "Gateway Intents are a great way to specify which events you want to receive from our gateway. Go on, save yourself some bandwidth and CPU usage."
5 Discord Change log, "API and Gateway V8" adr 2020-09-24 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx Seven months after intents were optional, a version bump made them mandatory and deleted the previous opt-out. "Gateway Intents are now required"; "Removed guild_subscriptions in identify in favor of Gateway Intents"; "v6 is still the default for the time being".
6 Discord Change log, "Gateway v6 Intent Restrictions" adr 2020-10-27 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx The restrictions were then applied to the old version too, so staying on v6 stopped being an escape route. "The v6 gateway now applies the restrictions for gateway intents. This means the new chunking limitations are now in effect, regardless of intents being used."
7 Discord Change log, "Large Bot Sharding Lowered to 150,000 Guilds" postmortem 2021-03-15 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx A reported reliability failure at connection time was fixed by moving more apps into the stricter sharding regime rather than by adding capacity. "There have been reports that sessions have higher frequency of errors when starting if a bot has joined too many guilds (the gateway connection times out). To account for this we have lowered the requirement for large bot sharding down to 150,000 guilds in order to improve reliability."
8 Discord Change log, "Session-specific Gateway Resume URLs" adr 2022-08-09 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx Reconnect steering was introduced with a penalty rather than a deadline: non-adopters get disconnected sooner. "Starting on September 12, 2022, apps that aren't using the new resume_gateway_url field to resume gateway sessions will be disconnected significantly faster than normal"; "At the moment, the value of resume_gateway_url will always be wss://gateway.discord.gg to give developers more time to adopt the new field."
9 Discord Change log, "Message Content is a Privileged Intent" adr 2022-09-01 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx The largest capability withdrawal in the record, with a grace period whose price is a growth freeze. "Any app that does not have the message content intent configured … will receive empty values in fields that expose message content across Discord's APIs"; "if you opt-in to the grace period, your app will be prevented from joining any additional servers until you opt-out".
10 Discord Change log, "Introducing Rate Limit When Requesting All Guild Members" postmortem 2025-08-14 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx Bulk state hydration was metered mid-flight for the largest guilds, ahead of the announced date, for stability. "Rate Limit: 1 request per guild per bot every 30 seconds"; "A small number of applications are currently exceeding this rate limit"; "if you are the developer of an app that is requesting all guild members in very large guilds then you may start seeing this as soon as today, so we can ensure platform stability"; general rollout "October 1, 2025".
11 Discord Change log, "Changes to Privileged Intent Access for Discord Apps" adr 2026-06-10 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx The gate on the firehose was re-cut from servers to users, and made an annually renewed grant. "Previously, apps in fewer than 100 servers could access Privileged Intents by toggling them on … Starting today, the threshold is based on the number of users your app can access"; "Once your app reaches 10,000 users, you'll need to apply"; "Apps must now reapply annually for continued access".
12 Discord Change log, "Channel Obfuscation for Users and Bots" postmortem 2026-08-12 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx For nine years the contract handed every app the full channel list of every guild it joined, including channels it could not view; that is now being withdrawn. "Today, bots receive every channel in a guild, including ones they can't view, with full metadata over both the Gateway and the HTTP API"; the name becomes "___hidden___", a CHANNEL_OBFUSCATED flag (1 << 17) is set, and GET /guilds/{guild.id}/channels "will omit those channels from the response entirely".
13 Discord Change log, "Shard Param Required for Get Current User Guilds with Large Bot Sharding" adr 2026-09-15 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx The newest entry in the record extends client-side partitioning from the socket to the HTTP path. "Apps using large bot sharding are required to pass it — requests without shard now return 400 Bad Request. Valid values are 0 through max_concurrency - 1."
14 Discord Gateway documentation (developers/events/gateway.mdx) vendor checked at main 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/events/gateway.mdx Partitioning is delegated to the app by a published formula, with a hard per-connection ceiling. "Each shard can only support a maximum of 2500 guilds, and apps that are in 2500+ guilds must enable sharding"; shard_id = (guild_id >> 22) % num_shards; "num_shards does not relate to (or limit) the total number of potential sessions. It is only used for routing traffic."
15 Discord Gateway documentation, Max Concurrency and Session Start Limit vendor checked at main 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/events/gateway.mdx Admission is bucketed and budgeted: concurrency keyed by shard id, a daily session budget, and token reset as the penalty for exhausting it. rate_limit_key = shard_id % max_concurrency; "you must start them by 'bucket' in order"; "Clients are limited to 1000 IDENTIFY calls to the websocket in a 24-hour period … all active sessions for the app will be terminated, the bot token will be reset"; large bots get "max(2000, (guild_count / 1000) * 5)" per day.
16 Discord Gateway documentation, Rate Limiting and Privileged Intents vendor checked at main 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/events/gateway.mdx Metering is per connection, and the privileged subset is enforced at the handshake with a close code. "Apps can send 120 gateway events per connection every 60 seconds"; "If you pass a privileged intent in the intents parameter without configuring it in your app's settings … your Gateway connection will be closed with a (4014 close code)"; "Events associated with the GUILD_PRESENCES and GUILD_MEMBERS intents are turned off by default regardless of the API version."
17 Discord Gateway documentation, Encoding and Compression vendor checked at main 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/events/gateway.mdx The wire format is an app-side choice with app-side cost: JSON or Erlang term format, payload or transport compression, zlib or zstd. "apps can use the encoding parameter to choose whether to communicate with Discord using a plain-text JSON or binary ETF encoding"; "The currently-available transport compression options are zlib-stream and zstd-stream"; zstd requires "a zstd decompression context that stays alive for the lifetime of the gateway connection".
18 Discord Gateway events documentation, Request Guild Members vendor checked at main 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/events/gateway-events.mdx Discord names both forces behind the hydration limits in one sentence, and the limits are graded by guild size. "Due to our privacy and infrastructural concerns with this feature, there are some limitations that apply"; "if the guild is over 75k members, it will only send members who are in voice"; chunks carry "up to 1000 members per chunk"; GUILD_MEMBERS intent "is required to request the entire member list".
19 Discord Gateway events documentation, Identify structure (large_threshold) vendor checked at main 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/events/gateway-events.mdx The oldest narrowing control in the protocol is a single integer chosen by the app, defaulting to the smallest value. "large_threshold?
20 Discord "You Might Not Need a Privileged Intent" guide vendor checked at main 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/gateway/you-might-not-need-a-privileged-intent.mdx The substitute path is now taught explicitly: pull the member you need instead of subscribing to all of them. "Many developers may enable privileged intents out of habit or because a tutorial told them to, only to later discover that our API offers alternatives"; "If you know who you're looking for, you don't need to enumerate every member"; interaction payloads include the member object "with no intent required".
21 Discord PR #2127, "More serious v7 status?" (closed unmerged) adr opened and closed 2020-10-04 2026-09-22 https://github.com/discord/discord-api-docs/pull/2127 A documentation fix for the skipped v7 was rejected on brand grounds, with the confusion acknowledged by contributors. Closed unmerged the day it was opened; staff reply: "this PR does not seem warranted/necessary, was opened without discussion of its worthiness nor even a proper pull request description", defending the joke as fitting a "playful and fun brand"; a contributor: "The whole v6/v7 thing is repeatedly a cause for confusion for new developers."
22 Discord PR #4376, "Clarify Which Gateway Close Codes to Resume on" (closed unmerged) adr opened 2022-01-24, closed 2022-02-01 2026-09-22 https://github.com/discord/discord-api-docs/pull/4376 Discord deliberately refused to publish a close-code-to-recovery mapping, keeping reconnect policy one sentence wide. Staff reply on closing: "I think we dont need this, if you get a disconnect, try to resume, otherwise reconnect."
23 Discord PR #6877, "[gateway] Clarify Reconnect opcode, Document zstd-stream" (merged) source opened 2024-05-17, merged 2024-05-23 2026-09-22 https://github.com/discord/discord-api-docs/pull/6877 Two levers were documented together in 2024: the server may evict a connection at any moment, and a cheaper compression option returned. The PR "clarifies that Reconnect can come at any time, even before hello" and documents "the resurrected zstd-stream gateway compression option".
24 Discord discord-api-spec (OpenAPI 3.1) source checked at main 2026-09-22 https://github.com/discord/discord-api-spec The machine-readable contract covers only the current version and is closed to outside edits. "OpenAPI 3.1 specification for Discord's API", covering "only the most recent version (v10)"; "we do not allow public contributions to this repo"; the preview spec "is subject to breaking changes without advance notice, and should not be used within production environments".
25 Discord Manifold README source first release 2017-02-20 2026-09-22 https://raw.githubusercontent.com/discord/manifold/master/README.md The cost of fanout inside Discord's own realtime tier is a per-recipient send, and it is what the contract changes are ultimately paying down. "Send calls cost about 70 µs/op so doing them in a loop eventually gets too expensive"; "Discord runs a single GenServer per Discord server and some of these ~100,000 PIDs connected to them from many different Erlang nodes"; after deploying Manifold "We observed packets/sec drop by half".
26 Discord Manifold on Hex, release timeline source 2017-02-20 to 2026-07-07 2026-09-22 https://hex.pm/api/packages/manifold The fanout primitive is the one piece of published infrastructure that never went quiet: ten releases across nine years, the newest this year. inserted_at 2017-02-20; releases 0.1.0 (2017-02-20) through 1.7.0 (2026-07-07); 10 releases; 646,908 all-time downloads at check time.
27 Discord FastGlobal README and Hex record source single release 2017-02-20 2026-09-22 https://hex.pm/api/packages/fastglobal A hot-path workaround published once and never revised, because the runtime absorbed the idea. README: "Storing data in a single process results in overloading the process, using an ETS table gets more expensive to read as the data gets larger"; benchmark "fastglobal get 0.33 µs/op", "ets get 7.64 µs/op", "agent get 12.67 µs/op"; Hex: exactly one release, 1.0.0, 2017-02-20; 766,789 downloads.
28 Erlang/OTP ERTS 10.2 release notes (persistent_term) source OTP 21.2 (ERTS 10.2) 2026-09-22 https://raw.githubusercontent.com/erlang/otp/master/erts/doc/notes.md Twenty-two months after FastGlobal shipped, the platform added the same capability as a built-in, which is why the library stopped. "There is a new module persistent_term that implements a term storage suitable for terms that are frequently used but never or infrequently updated. Lookups are done in constant time without copying the terms. Own Id: OTP-14669 Aux Id: PR-1989".
29 Erlang/OTP PR #1989, "RFC: Add a persistent term storage" adr opened 2018-10-17, merged 2018-11-06 2026-09-22 https://github.com/erlang/otp/pull/1989 The OTP proposal names the workaround family it was replacing, which is the family FastGlobal belongs to. Discussion references "mochiglobal" and "live-compiled modules as data stores" as the patterns the feature would make unnecessary; ETS named as the alternative for frequently-updated data.
30 Discord SortedSet NIF README source first release 2019-05-10 2026-09-22 https://raw.githubusercontent.com/discord/sorted_set_nif/master/README.md When the BEAM data structure became the bottleneck, the structure moved to Rust rather than the workload moving off the BEAM. "The core data structure and algorithms are implemented in a Native Implemented Function in the Rust Programming Language"; "when the Vector needs to grow beyond it's capacity, copying Terms over to the new larger Vector proved to be a performance bottle neck"; "A default bucket size of 500 was chosen".
31 Discord SortedSet NIF on Hex, release timeline source 2019-05-10 to 2025-12-04 2026-09-22 https://hex.pm/api/packages/sorted_set_nif The Rust-in-the-BEAM component is still being changed six years later, with two releases in a single month of 2025. Releases 1.0.0 (2019-05-10), 1.1.0 and 1.2.0 (2021-07), 1.3.0 (2025-11-12), 2.0.0 (2025-12-02), 2.0.1 (2025-12-04); 307,716 downloads at check time.
32 Discord ZenMonitor README source first release 2019-02-27 2026-09-22 https://raw.githubusercontent.com/discord/zen_monitor/master/README.md The second fanout primitive is about failure notifications, not messages: one process dying must not page every watcher at once. "ZenMonitor allows for the efficient monitoring of remote processes with minimal use of ERTS Distribution"; it is "a drop-in replacement for Process.monitor/1" whose cost at scale is "an additional ETS row on the local node and additional processing time at fan-out".
33 Discord Erlpack README and npm record source npm 2017-02-17 to 2021-12-22 2026-09-22 https://registry.npmjs.org/erlpack The binary wire format offered to apps is Discord's own internal encoding, published so third parties can speak it. README: "Erlpack is a fast encoder and decoder for the Erlang Term Format (version 131) for Python and JavaScript"; npm created 2017-02-17T18:00:35.491Z, five versions, latest 0.1.4 published 2021-12-22T16:09:51.561Z.
34 Discord lilliput README and Go module versions source v1.0.0 2018-02-09, v1.5.0 2025-06-23 2026-09-22 https://proxy.golang.org/github.com/discord/lilliput/@v/list The media path shows the same instinct as the realtime path, and a six-year publication gap that closed when formats changed. README: "It aims to do as little memory allocation as possible and especially not to create garbage in Go"; module versions v1.0.0 (2018-02-09), v1.1.0 (2018-02-10), v1.2.0 (2018-05-21), then v1.3.0 (2024-09-27), v1.4.0, v1.5.0 (2025-06-23).
35 Discord Osprey README casestudy checked at main 2026-09-22 https://raw.githubusercontent.com/discord/osprey/main/README.md The anti-abuse rules engine that consumes the same event stream was open-sourced through a non-profit and adopted by two other messaging networks. "Originally developed internally at Discord to combat spam, abuse, botting, and scripting across its platform, Osprey has been open-sourced"; adopters listed as Bluesky, Discord and Matrix.org; "Osprey is an event stream decisions engine … to investigate and take automatic action on events and their properties as they happen in real-time".
36 Rapptz (discord.py) PyPI release history source 2015-08-23 to 2026-03-03 2026-09-22 https://pypi.org/pypi/discord.py/json The largest Python client stopped publishing for 432 days across exactly the window in which intents and message content were being enforced. 87 releases; 1.7.3 published 2021-06-12T16:14:40; next release 2.0.0 published 2022-08-18T03:47:52 (432 days later); latest 2.7.1 on 2026-03-03.
37 Rapptz (discord.py) discord.py 2.0.0 source artefact source 2022-08-18 2026-09-22 https://files.pythonhosted.org/packages/source/d/discord.py/discord.py-2.0.0.tar.gz The return release is a real artefact, two weeks before the message content deadline of 2022-09-01. Source distribution served for version 2.0.0; PyPI upload time 2022-08-18T03:47:52 (row 36).
38 discord.js npm release history source 2015-08-10 to 2026-09-22 2026-09-22 https://registry.npmjs.org/discord.js Each contract change lands as a major version of the largest JavaScript client, within months of the announcement. First release of each major: v12 2020-03-01 (intents documented 2020-02-14), v13 2021-08-06 (API v9), v14 2022-07-17 (message content privileged 2022-09-01); package created 2015-08-10.
39 discord.js Issue #10089, "The WebSocket rate limit has been hit, this should never happen" postmortem opened 2024-01-14, closed 2026-09-22 https://github.com/discordjs/discord.js/issues/10089 Gateway metering surfaces to app authors as an unexplained shard death, and the library, not the app, had to be fixed. Error logged: "The WebSocket rate limit has been hit, this should never happen", followed by shard destruction with close code 4008 and reconnection; follow-on logs show "Members didn't arrive in time"; resolved through library PR #10098.
40 Matrix.org Client-Server API specification, "Lazy-loading room members" adr checked at main 2026-09-22 https://raw.githubusercontent.com/matrix-org/matrix-spec/main/content/client-server-api/_index.md A second protocol solves the same hydration problem with a per-request filter that is explicitly allowed to be imprecise. "Membership events often take significant resources for clients to track"; lazy-loading is enabled by "lazy_load_members" on a RoomEventFilter; "lazy-loading is not intended to be a perfect optimisation … it is valid for the server to send redundant membership events to the client to ease implementation".
41 Bluesky Jetstream README and design document source checked at main 2026-09-22 https://raw.githubusercontent.com/bluesky-social/jetstream/main/docs/README.md A third network answers the same question with a separate filtered projection service rather than a protocol option. "It provides the same user-friendly JSON interface that allows for data filtering in a backwards-compatible manner"; design goals include "Dead-simple and cheap for us and others to operate on a single server"; non-goals include "Exactly once delivery … We do at-least-once delivery and require clients to be idempotent".
42 Discord discord/react-native (fork) source checked at main 2026-09-22 https://github.com/discord/react-native The client-side half of the same decade is carried as forks of other people's frameworks, which the repository record shows but does not explain. Repository page shows "forked from react/react-native", default branch main, 41,132 commits in history.
43 Discord rules_elixir README source checked at main 2026-09-22 https://raw.githubusercontent.com/discord/rules_elixir/main/README.md The build tooling for the BEAM tier is a fork of somebody else's Bazel rules, published with a warning. "Bazel rules for Elixir sources. Compatible with rules_erlang"; repository description on the org listing reads "Fork of rabbitmq's toolset with a mix-based approach. Unstable, unsupported."; copyright line "© 2020-2024 Broadcom".
44 Discord Access README source checked at main 2026-09-22 https://raw.githubusercontent.com/discord/access/main/README.md What Discord publishes about its internals in 2026 is operational tooling, not the data or realtime tiers. "Meet Access, a centralized portal for employees to transparently discover, request, and manage their access to all internal systems"; "Access is a React and Typescript single-page application (SPA) with a FastAPI backend that connects to the Okta API".
45 Discord Change log, "Slash Commands and Interactions" adr 2020-12-15 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx The pull-shaped substitute shipped 20 months before the push-shaped capability was fenced. "Slash Commands are here! There's a lot to cover"; documented under Application Commands, with webhook edit and delete endpoints added at the same time.
46 Discord Change log, "Deprecating Guild Creation by Apps" adr 2025-04-15 2026-09-22 https://raw.githubusercontent.com/discord/discord-api-docs/main/developers/change-log.mdx A withdrawal with a three-month runway and an automated ownership migration, which is the template the later ones follow. "The Create Guild endpoint (POST /guilds) will be restricted for applications starting July 15, 2025"; "Existing Guilds owned by bots will have their ownership transferred to a real user"; notifications sent 2025-06-15.
47 Rust community rustler crate index source 0.1.0 to 0.38.0 2026-09-22 https://index.crates.io/ru/st/rustler The Rust-to-BEAM bridge Discord's SortedSet depends on is itself a long-lived, actively versioned project, which is what makes the native-code escape hatch repeatable. Index lists 58 published versions, from 0.1.0 to 0.38.0.