# Architecture One-Pager

*Discord Bot Platform · Solution Architecture v1.0 · Microsoft Azure · Integration Platform Architecture · 2026-10 · 19 views · 12 architecture decision records*

**Bots are untrusted consumers on the far side of a one-way boundary: entitlement is enforced before an event is produced, the shard is an address you compute, and every promise states what it loses.**

A chat service with 150 million users lets anyone register code that reacts to messages. Some bots are slow. Some are offline for days. A few are hostile. One, at any moment, is a viral slash command running on a serverless function with a cold start — and a person is staring at a spinner waiting for it. In the obvious architecture each of these problems leaks back into the chat service: a slow bot slows a message, a reconnecting fleet takes down the registry, and a revoked bot keeps reading for an hour.

The chat service commits and emits an event, and its involvement ends. Fan-out consumes events partitioned by server, filters them by the bot's intents and the server's permissions before anything is serialised, and routes each to a shard that is simply arithmetic on the server identifier. Gateway pods hold the sockets, with a bounded buffer per session and a 120-second resume window; a bot that reads too slowly is closed resumably, not allowed to grow memory. Slash commands arrive by signed HTTPS or the socket and carry a three-second acknowledgement the platform enforces, with deferral to fifteen minutes. REST actions pass a per-route-bucket limiter whose headers tell the client exactly what to do. Installations belong to the server, and revocation pushes to every node with a ten-second lease as the backstop. Reconnect storms are smeared by server-directed jitter and an identify throttle.

## What it is, and what it is not

- **Entitlement enforced at the source** — not send-everything-and-filter-in-the-client, which leaks data and spends bandwidth.
- **Shard as arithmetic** — not a routing table that becomes a hot, replicated dependency.
- **A published loss boundary at 120 seconds** — not an exactly-once claim the platform cannot keep.
- **A three-second acknowledgement** — not unbounded waiting on a stranger's endpoint.
- **Server-owned installations** — not grants tied to developer accounts that vanish.
- **State classed by how it may be lost** — not one strongly consistent store for everything.
- **Topological containment of egress** — not an SSRF validator as the only defence.

## The decisions that are the architecture

1. **The chat service never waits on a bot** (ADR-01) — Events leave over a one-way stream; bot actions return through a separate API edge.
2. **Filter before serialising, route by arithmetic** (ADR-02) — Nothing unentitled is produced, and shard placement needs no lookup.
3. **Three seconds, then a visible failure** (ADR-03) — The wait on a stranger is bounded and the expiry is shown to the user.
4. **A loss boundary that is published** (ADR-04) — Ordered replay for 120 s, explicit loss after, bounded buffers throughout.
5. **Partition by server** (ADR-05) — A hot server is one partition, not many copies.
6. **The server owns the grant** (ADR-06) — Permissions are evaluated on every call against current roles.
7. **Directed, throttled reconnects** (ADR-07) — The recovery path is cheaper than the failure path.
8. **Revocation has a deadline** (ADR-08) — Push plus a ten-second lease.
9. **Limits that can be read** (ADR-09) — Bucketed, with headers, escalating to bans only for offenders.
10. **Egress contained by topology** (ADR-11) — A separate zone with a published range.

## Why this should still be right in ten years

A bot platform outlives its first generation of bots, because developers write against the protocol and never rewrite it. These are the properties that should survive a change of scale, of cloud and of staff.

- **The trust boundary depends on no technology.** ADR-01 survives replacing Event Hubs, AKS and Azure. What would erode it is an exception for a first-party bot that blocks sending a message.
- **The shard formula is public API.** Changing it breaks every deployed bot, which is exactly why it is arithmetic and documented, not infrastructure.
- **Explicit loss boundaries age well.** Numbers change; the stance that every promise states what it drops does not.
- **Ownership follows consequence.** The server bears the risk of a bot, so the server holds the grant. That rule is independent of scale.

## Non-functional targets

Every number here is a stated assumption from the requirement, chosen to be argued with. The right-hand column names the view where the mechanism that meets it is drawn.

| Quality | Target | How it is met | View |
|---|---|---|---|
| Gateway delivery latency | p50 ≤ 120 ms, p99 ≤ 800 ms commit to socket | One filter and one shard hop; no registry call per event, because entitlements are leased. | 12 |
| Gateway availability | ≥ 99.95 % monthly | Per-shard session continuity; node loss is a resume, not an outage. | 13 |
| Interaction acknowledgement | 3 s hard; POST ≤ 300 ms p99 after click | Isolated egress, one retry in-window, enforced timer. | 11 |
| Event throughput | 400,000 events/s, 3× burst for 60 s | Server-partitioned log and arithmetic routing scale horizontally. | 12 |
| REST throughput | 90,000 requests/s, 4× burst | Stateless API pods and regional bucket counters. | 14 |
| Revocation | ≤ 10 s effective | Push invalidation with a 10 s lease backstop. | 19 |
| Region loss | RTO 5 min new sessions; registry RPO 0 | Registry replicates; sessions are rebuilt by reconnecting. | 14 |
| Reconnect storm | 500,000 sessions in 10 min, registry p99 ≤ 50 ms | Server-directed jitter and identify throttle. | 13 |

## Scope

**In scope**

- Gateway sessions, sharding, intents, resume.
- Interactions with signing, acknowledgement and deferral.
- REST with route-bucket limits and permission evaluation.
- Installation, grants, tokens and revocation.
- Developer-facing health and test tooling.
- Egress isolation for bot-supplied URLs.

**Explicitly out of scope**

- Message storage and the chat service itself.
- Voice media.
- Bot hosting and runtimes.
- A paid marketplace.
- User-facing clients.
- Abuse model training.

## What a four-week prototype should prove

Three claims are cheap to test and expensive to be wrong about.

1. Reconnect storm: kill a node holding 40,000 sessions and measure registry p99 and time-to-resume with and without the identify throttle.
2. Slow consumer: one bot reading at 1 % of event rate, measuring pod memory and the effect on neighbouring sessions at the buffer bound.
3. Revocation: revoke a grant under a registry brownout and measure the worst-case time until the session stops receiving events.

- A gateway node holding 40,000 sessions is killed during peak: every session resumes or re-identifies inside 10 minutes and registry p99 stays under 50 ms.
- One bot stops reading while its server posts 5,000 messages per second: its session closes resumably at the buffer bound, and no neighbouring session on the pod sees added latency.
- An administrator revokes a bot during a registry brownout: the bot stops receiving events inside 10 seconds, or the scenario records exactly how long it took.

## Open risks, carried rather than hidden

| Risk | If it lands | Response |
|---|---|---|
| The 120-second window is too short or too long | Too short and ordinary flaky networks force identifies; too long and memory outgrows budget. | Instrument reconnect-time distribution before fixing the number; revisit quarterly. |
| A first-party exception erodes the trust boundary | A bot that must block a message puts a stranger on the write path. | Make such a feature a separate, explicitly synchronous product with its own SLO. |
| Serverless bots miss 3 seconds at scale | A viral command shows failures the platform is blamed for. | Deferral guidance, keep-warm recommendations and per-application ack-rate visibility in the portal. |

The reasoning behind every component and technology choice is in the [Architecture Decision Record](decision-record): 12 records across 11 areas, each with the alternatives that lost and what the choice costs.
