Experiments
An experiment is an instance-wide rollout. For each account, Fluxer works out whether the account is in the rollout and which settings the account receives. The single route on this page resolves every experiment the server defines and returns them in one envelope, together with the polling cadence they share. This server defines domain_migration, plutonium_page, channel_threads, and voice_p2p. Only domain_migration and voice_p2p are configured by an operator. plutonium_page and channel_threads are on for every account.
Every assignment is advice. A client that ignores one behaves as it does with the rollout off, and no route and no Gateway event reports what a client actually ran.
Experiment assignments object
Section titled “Experiment assignments object”One resolution of every defined experiment against one account. Every field is present on every response.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| poll_interval_seconds | integer | Seconds to wait before revalidating, from 60 through 86400 |
| poll_jitter_percent | integer | The largest random offset added to or subtracted from the wait, as a percentage of the wait, from 0 through 50 |
| assignments | assignment map object | One entry for each experiment the server defines |
Every account on the instance receives the same poll_interval_seconds and poll_jitter_percent. One request refreshes every experiment.
Assignment map object
Section titled “Assignment map object”One entry per experiment. The envelope reports this object even when it is empty.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| domain_migration? | domain migration assignment object | The caller’s web domain migration assignment |
| plutonium_page? | Plutonium page assignment object | The caller’s Plutonium page assignment |
| channel_threads? | channel threads assignment object | The caller’s channel threads assignment |
| voice_p2p? | peer-to-peer voice assignment object | The caller’s peer-to-peer voice assignment |
Ignore unknown experiments and treat a missing experiment as off.
Domain migration assignment object
Section titled “Domain migration assignment object”One resolution of the instance web domain migration rollout against one account. This server version writes the key on every response.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| enabled | boolean | Whether the caller’s web client moves to the new web origin |
A caller is drawn by the operator’s account or guild allowlist, by having premium when the operator includes premium users, or by the sampled share of the account population. When the operator lists rollout countries, the sampled share only draws a caller whose request comes from a listed country. enabled is false in every other case, the rollout being off included.
Only the official web client acts on this assignment, and only on its legacy origins. Every other client ignores it. The logged-out share and the instance-wide switch are published in the instance discovery document instead, because a client that holds no credential cannot read this route.
Plutonium page assignment object
Section titled “Plutonium page assignment object”The Plutonium page state for one account. This server version writes the key on every response, always with enabled true.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| enabled | boolean | Whether the caller’s client shows the full Plutonium page in place of the Plutonium settings tab, always true |
The rollout is complete and has no operator setting. The key stays for clients that still read it.
The assignment only changes what the client shows. An enabled client replaces the Plutonium settings tab with a full Plutonium page, makes app pages linkable in chat, and uses a minimal gift purchase modal. The server applies no part of it on its own.
Channel threads assignment object
Section titled “Channel threads assignment object”The channel threads state for one account. This server version writes the key on every response.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| active | boolean | Always true, whatever client capability the caller declares |
| config_version | integer | A non-negative version number, the same for every account |
The key stays for clients that still read it. Threads, forum channels, and media channels need the channel_threads client capability.
Peer-to-peer voice assignment object
Section titled “Peer-to-peer voice assignment object”One resolution of the instance peer-to-peer voice rollout against one account. This server version writes the key on every response.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| enabled | boolean | Whether the caller may start a peer-to-peer voice call |
| max_participants | integer | Most participants a peer-to-peer call holds (2-4) |
A caller is drawn by the operator’s account or guild allowlist, by having premium when the operator includes premium users, or by the sampled share of the account population. When the operator lists rollout countries, the sampled share only draws a caller whose request comes from a listed country. enabled is false in every other case, the rollout being off included.
A selected client may ask for a peer-to-peer connection when it starts a voice call, and shows the peer-to-peer setting of a guild voice channel. It offers a peer-to-peer call in a direct message or group direct message only when the channel has at most max_participants members, the caller included. max_participants is the same for every account, selected or not, and a join past it is refused as full. The assignment does not decide who joins. While the rollout is on, any account that agrees to a direct connection may join a peer-to-peer call that is already running. The server checks the rollout again when a call starts, so a client that ignores this assignment gains nothing.
Request country
Section titled “Request country”Fluxer resolves the country of each request to this route from the client address. An account can receive a different assignment from another network when an operator lists rollout countries. A request whose country is unknown matches no listed country.
Get experiment assignments
Section titled “Get experiment assignments”GET/v1/experimentsResolves every defined experiment for the caller and returns an experiment assignments object. The response is derived per account, so it is never shared between accounts.
Response body
Section titled “Response body”Experiment assignments object.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | response body | The envelope was resolved |
| 304 | empty | The request sent a matching If-None-Match |
Request headers
Section titled “Request headers”| Field | Type | Description |
|---|---|---|
| If-None-Match? | string | An ETag from an earlier response to this route |
A client sends the ETag it last received. Fluxer compares it against the tag of the envelope it just resolved and answers 304 with no body on a match. * matches any current tag. A weak comparison is used, so a W/ prefix on either side does not defeat the match.
Response headers
Section titled “Response headers”| Field | Type | Description |
|---|---|---|
| ETag | string | A strong tag over the envelope body, sent on 200 and on 304 |
| Cache-Control | string | The literal value private, no-cache |
| Vary | string | The literal value Authorization, replaced by Origin where the cross-origin policy echoed an allowed origin |
The ETag changes when the response changes, which includes a change of request country. Treat it as an opaque value.
ETag is listed in Access-Control-Expose-Headers and If-None-Match in Access-Control-Allow-Headers, so a cross-origin client reads the tag and revalidates with it.
Polling
Section titled “Polling”A client reads this route once per session and then again every poll_interval_seconds, offset by a random amount up to poll_jitter_percent of that interval in either direction. It sends the last ETag on every request after the first. A client MUST NOT poll faster than the lower end of that jitter range.
Until the first successful response, use 300 seconds with 15 per cent jitter.
Rate limit
Section titled “Rate limit”60 requests per 10 seconds for each authenticated user, on the default bucket.