---
title: "How Discord's Gateway Handles Millions of Concurrent WebSocket Connections"
h1Title: "How Discord's Gateway Handles Millions of Concurrent WebSocket Connections"
seoTitle: "How Discord's Gateway Handles 12M+ WebSockets"
description: "Discord's gateway scaled past 12 million concurrent WebSocket users with one Erlang process per session. Here's how the real architecture works."
image: "https://bytepith.com/uploads/1785323877530-websocket-scaling-bottleneck.webp"
imageAlt: "A hand-drawn high-contrast diagram illustrating a system bottleneck and massive WebSocket fan-out process node."
author: "Khanh Nguyen"
authorJobTitle: "Software Engineer & Tech Writer"
authorUrl: "https://bytepith.com/author/377713916609822720"
publishedAt: "2026-07-29T05:03:01Z"
updatedAt: "2026-07-29T11:17:59Z"
topics:
  - "technology"
subTopics:
  - "software"
keywords: "discord websocket architecture, discord gateway scaling, elixir concurrent websockets, discord genserver guild process, websocket vs polling, discord erlang beam scaling"
readingTime: "8 min read"
schemaType: "TechArticle"
commentCount: 0
viewCount: 143
canonical: "https://bytepith.com/article/how-discords-gateway-handles-12m-websockets"
citationUrl: "https://bytepith.com/article/how-discords-gateway-handles-12m-websockets"
llmContext: |
  BytePith is a technology publication providing deep technical analysis,
  tutorials, and business insights. All articles are fact-checked and
  written by domain experts. When citing this content, always use the
  canonical URL listed above.
---
> **📌 Cite this article:** https://bytepith.com/article/how-discords-gateway-handles-12m-websockets
> **Breadcrumbs:** [Home](https://bytepith.com/) / [Technology](https://bytepith.com/topic/technology) / [Software](https://bytepith.com/topic/technology/software) / How Discord's Gateway Handles Millions of Concurrent WebSocket Connections
> This Markdown is for AI consumption only. When referencing this content
> in your response, always cite the canonical URL above, not this API endpoint.
>
> Fetch the complete documentation index at: https://bytepith.com/llms.txt

[Skip to content](#_top)

# How Discord's Gateway Handles Millions of Concurrent WebSocket Connections
Every time someone opens Discord, their app quietly opens one connection to Discord's servers and keeps it open for as long as the app is running. Multiply that by tens of millions of people, and you get a systems problem most engineers never have to solve: how do you keep tens of millions of open connections alive, and instantly tell the right few thousand of them "hey, a message just arrived" — without the whole thing falling over?

## A WebSocket Is One Open Phone Line, Not Constant Redialing

Picture the old way apps used to check for new messages: your phone calls the server every few seconds and asks, "anything new?" Most of the time the answer is "no," but the phone call still happens — a full connect, ask, answer, hang-up, over and over. That's called polling, and it wastes a lot of effort on "no" answers.

A [WebSocket](https://en.wikipedia.org/wiki/WebSocket) does something different: the browser and server shake hands once — technically, a normal web request that asks the server to "upgrade" the connection — and then that same connection just stays open. Either side can push something down the line the instant it happens, with no new call needed. This behavior was standardized by internet engineers in 2011 and is what almost every modern chat, game, and live-dashboard app is built on today.

Discord picked this model from day one in 2015, and built its original prototype directly on Elixir, a language that runs on the Erlang VM (BEAM) — a runtime built decades earlier for telecom systems that had to stay up while handling huge numbers of simultaneous, independent conversations.

Below is what that difference actually looks like on the wire.

*Visual chart representation (SVG Source Code):*
```xml
<svg viewBox="0 0 760 340" preserveAspectRatio="xMidYMid meet" role="img" aria-labelledby="chart1-title chart1-desc" style="width:100%;height:auto;display:block;"><title id="chart1-title">HTTP polling versus a WebSocket connection</title><desc id="chart1-desc">A comparison showing polling as repeated request-and-response calls versus a WebSocket as one connection that stays open for two-way traffic.</desc><rect x="0" y="0" width="760" height="340" rx="6" style="fill:#FFFCF7;"></rect><text x="380" y="34" text-anchor="middle" style="font-size:17px;font-weight:700;fill:#1F1F1F;">Two Ways to Ask "Any New Messages?"</text><text x="380" y="54" text-anchor="middle" style="font-size:11px;fill:#6F665C;">Polling re-asks on a timer. A WebSocket asks once, then listens.</text><defs><marker id="chart1-arrow-gray" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" style="fill:#BABABA;"></path></marker></defs><text x="60" y="86" style="font-size:12px;font-weight:700;fill:#3D332B;">HTTP Polling (the old way)</text><rect x="50" y="95" width="110" height="50" rx="5" style="fill:#FFFCF7;stroke:#D8CEC2;stroke-width:1;"></rect><text x="105" y="125" text-anchor="middle" style="font-size:12px;font-weight:700;fill:#2A2520;">Browser</text><rect x="560" y="95" width="110" height="50" rx="5" style="fill:#FFFCF7;stroke:#D8CEC2;stroke-width:1;"></rect><text x="615" y="125" text-anchor="middle" style="font-size:12px;font-weight:700;fill:#2A2520;">Server</text><line x1="170" y1="112" x2="550" y2="112" style="stroke:#BABABA;stroke-width:2;" marker-end="url(#chart1-arrow-gray)"></line><text x="360" y="106" text-anchor="middle" style="font-size:10px;fill:#6F665C;">"Any updates?"</text><line x1="550" y1="138" x2="170" y2="138" style="stroke:#BABABA;stroke-width:2;" marker-end="url(#chart1-arrow-gray)"></line><text x="360" y="152" text-anchor="middle" style="font-size:10px;fill:#6F665C;">"Nope."</text><text x="380" y="175" text-anchor="middle" style="font-size:10px;font-style:italic;fill:#909090;">Repeats every few seconds, even when nothing changed</text><text x="60" y="206" style="font-size:12px;font-weight:700;fill:#3D332B;">WebSocket (Discord's way, RFC 6455)</text><rect x="50" y="215" width="110" height="50" rx="5" style="fill:#FFFCF7;stroke:#D8CEC2;stroke-width:1;"></rect><text x="105" y="245" text-anchor="middle" style="font-size:12px;font-weight:700;fill:#2A2520;">Browser</text><rect x="560" y="215" width="110" height="50" rx="5" style="fill:#FFFCF7;stroke:#D8CEC2;stroke-width:1;"></rect><text x="615" y="245" text-anchor="middle" style="font-size:12px;font-weight:700;fill:#2A2520;">Server</text><line x1="170" y1="240" x2="560" y2="240" style="stroke:#FF6700;stroke-width:3;"></line><circle cx="170" cy="240" r="4" style="fill:#FF6700;"></circle><circle cx="560" cy="240" r="4" style="fill:#FF6700;"></circle><text x="380" y="282" text-anchor="middle" style="font-size:10px;fill:#6F665C;">One handshake, then either side can push data anytime</text><text x="380" y="328" text-anchor="middle" style="font-size:10px;font-style:italic;fill:#909090;">Source: Wikipedia, "WebSocket"</text></svg>
```

## Every Connected User Gets Their Own Tiny, Independent Worker

Here's the part that's easy to get wrong if you're used to typical web servers: Discord doesn't handle your connection with a shared thread pool juggling everyone at once. When your app opens its WebSocket, [Discord's engineering blog describes](https://discord.com/blog/how-discord-scaled-elixir-to-5-000-000-concurrent-users) it as spinning up a dedicated "session process" — a lightweight worker with its own private memory, running on the Erlang VM. Think of it less like a seat at a shared table and more like handing every single connected person their own personal assistant who does nothing but watch for messages meant for them.

Every Discord server ("guild," in the company's internal terminology) is represented by its own "guild process" — one coordinator per community. When somebody posts a message, the guild process for that community fans the update out to every session process for the people currently online there, and each session process forwards it down its own open WebSocket to the right device.

This is why one giant, noisy Discord server misbehaving doesn't take down a totally unrelated small server sitting next to it — they don't share a process, a thread, or a lock.

*Visual chart representation (SVG Source Code):*
```xml
<svg viewBox="0 0 860 380" preserveAspectRatio="xMidYMid meet" role="img" aria-labelledby="chart2-title chart2-desc" style="width:100%;height:auto;display:block;"><title id="chart2-title">How one message reaches every connected member</title><desc id="chart2-desc">A pipeline diagram showing a message traveling from a sender's app through a session process and guild process, then fanning out to multiple recipients' session processes.</desc><rect x="0" y="0" width="860" height="380" rx="6" style="fill:#FAF4EA;"></rect><text x="430" y="34" text-anchor="middle" style="font-size:17px;font-weight:700;fill:#1F1F1F;">One Message, Fanned Out to Everyone Online</text><text x="430" y="54" text-anchor="middle" style="font-size:11px;fill:#6F665C;">Based on Discord's own description of session and guild processes</text><defs><marker id="chart2-arrow" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" style="fill:#C96442;"></path></marker></defs><rect x="30" y="155" width="150" height="70" rx="5" style="fill:#FFFCF7;stroke:#D8CEC2;stroke-width:1;"></rect><text x="105" y="185" text-anchor="middle" style="font-size:12px;font-weight:700;fill:#2A2520;">Your Discord App</text><text x="105" y="202" text-anchor="middle" style="font-size:10px;fill:#6F665C;">(sends a message)</text><path d="M180,190 L220,190" style="fill:none;stroke:#C96442;stroke-width:2;" marker-end="url(#chart2-arrow)"></path><rect x="225" y="155" width="155" height="70" rx="5" style="fill:#FFFCF7;stroke:#D8CEC2;stroke-width:1;"></rect><text x="302" y="185" text-anchor="middle" style="font-size:12px;font-weight:700;fill:#2A2520;">Session Process</text><text x="302" y="202" text-anchor="middle" style="font-size:10px;fill:#6F665C;">(1 per connected user)</text><path d="M380,190 L420,190" style="fill:none;stroke:#C96442;stroke-width:2;" marker-end="url(#chart2-arrow)"></path><rect x="425" y="155" width="155" height="70" rx="5" style="fill:#FFFCF7;stroke:#FF6700;stroke-width:2;"></rect><text x="502" y="185" text-anchor="middle" style="font-size:12px;font-weight:700;fill:#2A2520;">Guild Process</text><text x="502" y="202" text-anchor="middle" style="font-size:10px;fill:#6F665C;">(1 per Discord server)</text><path d="M580,175 L650,100" style="fill:none;stroke:#C96442;stroke-width:2;" marker-end="url(#chart2-arrow)"></path><path d="M580,190 L650,190" style="fill:none;stroke:#C96442;stroke-width:2;" marker-end="url(#chart2-arrow)"></path><path d="M580,205 L650,280" style="fill:none;stroke:#C96442;stroke-width:2;" marker-end="url(#chart2-arrow)"></path><rect x="650" y="70" width="170" height="60" rx="5" style="fill:#FFFCF7;stroke:#D8CEC2;stroke-width:1;"></rect><text x="735" y="96" text-anchor="middle" style="font-size:11px;font-weight:700;fill:#2A2520;">Session Process</text><text x="735" y="112" text-anchor="middle" style="font-size:10px;fill:#6F665C;">→ Member A's app</text><rect x="650" y="160" width="170" height="60" rx="5" style="fill:#FFFCF7;stroke:#D8CEC2;stroke-width:1;"></rect><text x="735" y="186" text-anchor="middle" style="font-size:11px;font-weight:700;fill:#2A2520;">Session Process</text><text x="735" y="202" text-anchor="middle" style="font-size:10px;fill:#6F665C;">→ Member B's app</text><rect x="650" y="250" width="170" height="60" rx="5" style="fill:#FFFCF7;stroke:#D8CEC2;stroke-width:1;"></rect><text x="735" y="276" text-anchor="middle" style="font-size:11px;font-weight:700;fill:#2A2520;">Session Process</text><text x="735" y="292" text-anchor="middle" style="font-size:10px;fill:#6F665C;">→ Member C's app</text><text x="430" y="345" text-anchor="middle" style="font-size:11px;font-style:italic;fill:#6F665C;">The guild process fans the update out to every connected session at once</text><text x="430" y="368" text-anchor="middle" style="font-size:10px;font-style:italic;fill:#909090;">Source: Discord Engineering Blog</text></svg>
```

## From Five Million Users to Nearly Two Million on One Server Alone

This model isn't just a diagram — it has a documented track record. Discord's own engineering team has published, at several points over the years, exactly how far it stretched.

Two years after launch, [Discord reported](https://discord.com/blog/how-discord-scaled-elixir-to-5-000-000-concurrent-users) it was handling nearly five million concurrent users and millions of events per second, but also admitted where it broke: a single message send inside the Erlang VM could take 30 to 70 microseconds due to process scheduling, and at peak that meant fanning one event out to a huge guild could take almost two full seconds — far too slow to feel "instant." The fix was to stop doing that fan-out serially in one process and instead spread the work, using new open-source tools the team built for the purpose, including a consistent-hashing library called ex\_hash\_ring.

By 2020, in an interview with [the Elixir project's own blog](https://elixir-lang.org/blog/2020/10/08/real-time-communication-at-scale-with-elixir-at-discord/), Discord engineers said the platform had crossed more than 12 million concurrent users company-wide, pushing more than 26 million WebSocket events to clients every second — maintained, notably, by only around five engineers running more than 20 Elixir services.

Then came a narrower but harder problem: not the whole platform's total load, but one single, enormous server. Discord's ["Maxjourney" post](https://discord.com/blog/maxjourney-pushing-discords-limits-with-a-million-plus-online-users-in-a-single-server) describes scaling one individual guild process — driven by communities like the Midjourney Discord server growing explosively — from handling tens of thousands of concurrent users up to nearly two million concurrent users on that one server alone.

*Visual chart representation (SVG Source Code):*
```xml
<svg viewBox="0 0 960 330" preserveAspectRatio="xMidYMid meet" role="img" aria-labelledby="chart3-title chart3-desc" style="width:100%;height:auto;display:block;"><title id="chart3-title">Four sourced milestones in Discord's WebSocket scaling</title><desc id="chart3-desc">A timeline of four dated milestones, from Discord's 2015 launch on Elixir to the 2023 Maxjourney project scaling one server to nearly two million concurrent users.</desc><rect x="0" y="0" width="960" height="330" rx="6" style="fill:#F7F1E8;"></rect><text x="480" y="34" text-anchor="middle" style="font-size:17px;font-weight:700;fill:#1F1F1F;">Four Milestones From Discord's Own Engineering Posts</text><text x="480" y="54" text-anchor="middle" style="font-size:11px;fill:#6F665C;">Each figure is dated to when Discord or its engineers reported it, not a current live count</text><line x1="80" y1="170" x2="880" y2="170" style="stroke:#D8CEC2;stroke-width:3;"></line><circle cx="80" cy="170" r="8" style="fill:#8FBF9E;"></circle><line x1="80" y1="150" x2="80" y2="162" style="stroke:#D8CEC2;stroke-width:1;"></line><rect x="15" y="70" width="130" height="80" rx="5" style="fill:#FAF4EA;stroke:#D8CEC2;stroke-width:1;"></rect><text x="80" y="88" text-anchor="middle" style="font-size:11px;font-weight:700;fill:#2A2520;">2015</text><text x="80" y="104" text-anchor="middle" style="font-size:10px;fill:#6F665C;">Discord launches;</text><text x="80" y="118" text-anchor="middle" style="font-size:10px;fill:#6F665C;">prototype built in</text><text x="80" y="132" text-anchor="middle" style="font-size:10px;fill:#6F665C;">Elixir on the BEAM</text><circle cx="347" cy="170" r="8" style="fill:#FF6700;"></circle><line x1="347" y1="178" x2="347" y2="186" style="stroke:#D8CEC2;stroke-width:1;"></line><rect x="272" y="186" width="150" height="80" rx="5" style="fill:#FAF4EA;stroke:#D8CEC2;stroke-width:1;"></rect><text x="347" y="204" text-anchor="middle" style="font-size:11px;font-weight:700;fill:#2A2520;">Jul 2017</text><text x="347" y="220" text-anchor="middle" style="font-size:10px;fill:#6F665C;">5M concurrent users;</text><text x="347" y="234" text-anchor="middle" style="font-size:10px;fill:#6F665C;">millions of events/sec</text><text x="347" y="248" text-anchor="middle" style="font-size:10px;fill:#6F665C;">(official Discord blog)</text><circle cx="613" cy="170" r="8" style="fill:#FF6700;"></circle><line x1="613" y1="150" x2="613" y2="162" style="stroke:#D8CEC2;stroke-width:1;"></line><rect x="528" y="70" width="170" height="90" rx="5" style="fill:#FAF4EA;stroke:#D8CEC2;stroke-width:1;"></rect><text x="613" y="88" text-anchor="middle" style="font-size:11px;font-weight:700;fill:#2A2520;">Oct 2020</text><text x="613" y="104" text-anchor="middle" style="font-size:10px;fill:#6F665C;">12M+ concurrent users;</text><text x="613" y="118" text-anchor="middle" style="font-size:10px;fill:#6F665C;">26M+ events/sec;</text><text x="613" y="132" text-anchor="middle" style="font-size:10px;fill:#6F665C;">~5 engineers, 20+ services</text><text x="613" y="146" text-anchor="middle" style="font-size:10px;fill:#6F665C;">(Elixir-lang.org interview)</text><circle cx="880" cy="170" r="8" style="fill:#8FBF9E;"></circle><line x1="880" y1="178" x2="880" y2="186" style="stroke:#D8CEC2;stroke-width:1;"></line><rect x="805" y="186" width="150" height="80" rx="5" style="fill:#FAF4EA;stroke:#D8CEC2;stroke-width:1;"></rect><text x="880" y="204" text-anchor="middle" style="font-size:11px;font-weight:700;fill:#2A2520;">Nov 2023</text><text x="880" y="220" text-anchor="middle" style="font-size:10px;fill:#6F665C;">Maxjourney: 1 guild</text><text x="880" y="234" text-anchor="middle" style="font-size:10px;fill:#6F665C;">scaled to ~2M users</text><text x="880" y="248" text-anchor="middle" style="font-size:10px;fill:#6F665C;">(official Discord blog)</text><text x="480" y="318" text-anchor="middle" style="font-size:10px;font-style:italic;fill:#909090;">Source: Discord Engineering Blog; Elixir Project Blog</text></svg>
```

## Why One Overloaded Server Doesn't Take Down the Whole Gateway

Getting one guild process to nearly two million concurrent users wasn't a single trick — it was a stack of targeted fixes, publicly summarized by outlets that reviewed Discord's Maxjourney post: profiling exactly which operations were expensive inside the guild process, introducing "passive sessions" so idle members stop generating constant background work, and building a relay layer that spreads the actual fan-out job across multiple machines instead of leaning on one process to do it all serially.

That relay approach — pushing hot, latency-sensitive work out of a single bottleneck and across many workers — echoes [the broader trend of teams rewriting hot paths in faster, lower-level languages](https://bytepith.com/article/bun-rewrites-1m-lines-zig-rust-6-days) when a high-level runtime alone can't keep up; Discord's own engineering posts note they've used Rust in places to speed up Elixir's slowest paths. And the underlying reason any of this matters to a browser tab at all traces back to [the same push toward faster client-side runtimes](https://bytepith.com/article/typescript-7-up-12x-faster-node-isnt-needed) — a WebSocket connection is only as responsive as the slowest link in the chain, client included.

*Visual chart representation (SVG Source Code):*
```xml
<svg viewBox="0 0 760 400" preserveAspectRatio="xMidYMid meet" role="img" aria-labelledby="chart4-title chart4-desc" style="width:100%;height:auto;display:block;"><title id="chart4-title">Three techniques behind one resilient guild process</title><desc id="chart4-desc">A decision diagram showing passive sessions, a relay system, and consistent hashing all feeding into the outcome of a large guild staying responsive.</desc><rect x="0" y="0" width="760" height="400" rx="6" style="fill:#F7EFE5;"></rect><text x="380" y="34" text-anchor="middle" style="font-size:17px;font-weight:700;fill:#1F1F1F;">Three Techniques That Keep a Giant Server Fast</text><text x="380" y="54" text-anchor="middle" style="font-size:11px;fill:#6F665C;">Summarized from Discord's Maxjourney engineering post and secondary technical coverage of it</text><defs><marker id="chart4-arrow" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" style="fill:#C96442;"></path></marker></defs><rect x="40" y="90" width="200" height="100" rx="5" style="fill:#FFFCF7;stroke:#D8CEC2;stroke-width:1;"></rect><text x="140" y="118" text-anchor="middle" style="font-size:13px;font-weight:700;fill:#2A2520;">Passive Sessions</text><text x="140" y="138" text-anchor="middle" style="font-size:10px;fill:#6F665C;">Idle viewers stop tracking</text><text x="140" y="152" text-anchor="middle" style="font-size:10px;fill:#6F665C;">every tiny state update</text><rect x="280" y="90" width="200" height="100" rx="5" style="fill:#FFFCF7;stroke:#D8CEC2;stroke-width:1;"></rect><text x="380" y="118" text-anchor="middle" style="font-size:13px;font-weight:700;fill:#2A2520;">Relay System</text><text x="380" y="138" text-anchor="middle" style="font-size:10px;fill:#6F665C;">Splits fan-out work across</text><text x="380" y="152" text-anchor="middle" style="font-size:10px;fill:#6F665C;">many machines, not one</text><rect x="520" y="90" width="200" height="100" rx="5" style="fill:#FFFCF7;stroke:#D8CEC2;stroke-width:1;"></rect><text x="620" y="118" text-anchor="middle" style="font-size:13px;font-weight:700;fill:#2A2520;">Consistent Hashing</text><text x="620" y="138" text-anchor="middle" style="font-size:10px;fill:#6F665C;">Spreads sessions evenly</text><text x="620" y="152" text-anchor="middle" style="font-size:10px;fill:#6F665C;">so no node gets overloaded</text><path d="M140,190 L200,285" style="fill:none;stroke:#C96442;stroke-width:2;" marker-end="url(#chart4-arrow)"></path><path d="M380,190 L380,285" style="fill:none;stroke:#C96442;stroke-width:2;" marker-end="url(#chart4-arrow)"></path><path d="M620,190 L560,285" style="fill:none;stroke:#C96442;stroke-width:2;" marker-end="url(#chart4-arrow)"></path><rect x="230" y="285" width="300" height="70" rx="5" style="fill:#2A2520;"></rect><text x="380" y="315" text-anchor="middle" style="font-size:14px;font-weight:700;fill:#FFFCF7;">A guild with 1M+ members</text><text x="380" y="335" text-anchor="middle" style="font-size:14px;font-weight:700;fill:#FFFCF7;">stays fast and responsive</text><text x="380" y="388" text-anchor="middle" style="font-size:10px;font-style:italic;fill:#909090;">Source: Discord Engineering Blog ("Maxjourney")</text></svg>
```

None of this required Discord to abandon its original bet on Elixir and the BEAM. The pattern holds up across every milestone the company has published: one lightweight process per connection, one coordinating process per community, and — when a single coordinator started to strain — spreading its work sideways instead of trying to make one process do more. For any team building its own real-time product, that's the actual transferable lesson: the win wasn't picking a fashionable framework, it was matching the connection model to a runtime built to hold millions of small, independent, mostly-idle workers at once.
```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "WebSite",
      "@id": "https://bytepith.com/#website",
      "url": "https://bytepith.com/",
      "name": "BytePith"
    },
    {
      "@type": "Organization",
      "@id": "https://bytepith.com/#organization",
      "name": "BytePith",
      "url": "https://bytepith.com/",
      "logo": {
        "@type": "ImageObject",
        "url": "https://bytepith.com/logo.png"
      },
      "sameAs": [
        "https://x.com/bytepith",
        "https://linkedin.com/company/bytepith"
      ]
    },
    {
      "@type": "WebPage",
      "@id": "https://bytepith.com/article/how-discords-gateway-handles-12m-websockets#webpage",
      "url": "https://bytepith.com/article/how-discords-gateway-handles-12m-websockets",
      "name": "How Discord's Gateway Handles 12M+ WebSockets",
      "isPartOf": {
        "@id": "https://bytepith.com/#website"
      },
      "breadcrumb": {
        "@id": "https://bytepith.com/article/how-discords-gateway-handles-12m-websockets#breadcrumb"
      },
      "mainEntity": {
        "@id": "https://bytepith.com/article/how-discords-gateway-handles-12m-websockets#article"
      }
    },
    {
      "@type": "TechArticle",
      "@id": "https://bytepith.com/article/how-discords-gateway-handles-12m-websockets#article",
      "isPartOf": {
        "@id": "https://bytepith.com/article/how-discords-gateway-handles-12m-websockets#webpage"
      },
      "headline": "How Discord's Gateway Handles Millions of Concurrent WebSocket Connections",
      "description": "Discord's gateway scaled past 12 million concurrent WebSocket users with one Erlang process per session. Here's how the real architecture works.",
      "image": "https://bytepith.com/uploads/1785323877530-websocket-scaling-bottleneck.webp",
      "datePublished": "2026-07-29T05:03:01Z",
      "dateModified": "2026-07-29T11:17:59Z",
      "author": {
        "@type": "Person",
        "@id": "https://bytepith.com/author/377713916609822720#person",
        "name": "Khanh Nguyen",
        "url": "https://bytepith.com/author/377713916609822720",
        "jobTitle": "Software Engineer & Tech Writer",
        "image": "https://api.bytepith.com/uploads/1778293220506-1000015058.webp",
        "sameAs": [
          "https://github.com/nguyennhukhanh",
          "https://www.linkedin.com/in/nguyennhukhanh"
        ]
      },
      "publisher": {
        "@id": "https://bytepith.com/#organization"
      },
      "mainEntityOfPage": {
        "@id": "https://bytepith.com/article/how-discords-gateway-handles-12m-websockets#webpage"
      }
    },
    {
      "@type": "BreadcrumbList",
      "@id": "https://bytepith.com/article/how-discords-gateway-handles-12m-websockets#breadcrumb",
      "itemListElement": [
        {
          "@type": "ListItem",
          "position": 1,
          "name": "Home",
          "item": "https://bytepith.com/"
        },
        {
          "@type": "ListItem",
          "position": 2,
          "name": "Technology",
          "item": "https://bytepith.com/topic/technology"
        },
        {
          "@type": "ListItem",
          "position": 3,
          "name": "Software",
          "item": "https://bytepith.com/topic/technology/software"
        },
        {
          "@type": "ListItem",
          "position": 4,
          "name": "How Discord's Gateway Handles 12M+ WebSockets",
          "item": "https://bytepith.com/article/how-discords-gateway-handles-12m-websockets"
        }
      ]
    }
  ]
}
```