Problem
Some server endpoints need fresh Discord member identity data (username, display_name, avatar_url) to render dashboard views such as tickets.
The current tickets/open fallback resolves missing identities with live Discord member lookups (GET /guilds/{guild.id}/members/{user.id}) during the request. On a server with 95 tickets / 64 unique users missing identity, that makes the endpoint take ~17s locally.
Recent profiling on GET /v2/server/923764211845312533/tickets/open shows:
total_ms=17377
discord_ms=15819
open_tickets_ms=845
links_ms=215
players_ms=396
auth_users_ms=98
missing_identity_users=64
discord_lookup_attempted=64
discord_lookup_succeeded=42
This confirms the bottleneck is not Mongo; it is the repeated live Discord member lookups. Even when done concurrently in Go, the Discord client buckets this route, so requests are effectively serialized.
Why not store identity on ticket creation?
We explicitly do not want to persist discord_username, discord_display_name, or discord_avatar_url as the source of truth on ticket creation because those fields can change over time.
We still want:
- fresh member info when available,
Not on server when the user is no longer in the guild,
- and no per-request burst of dozens of Discord member REST calls.
Proposed solution
Add a shared external Discord member cache backed by Valkey so both the bot and the API/dashboard can use the same member identity source.
High-level idea:
- The bot hydrates and maintains guild member identity in Valkey (startup + ongoing updates from member events).
- The API reads from that shared cache for ticket/link/other server endpoints.
- API falls back gracefully when a member is absent from cache (e.g. short-lived stale/miss strategy), without turning every dashboard request into dozens of live Discord REST calls.
- Cache negative lookups for short periods as well so repeated
Unknown Member users do not hammer Discord.
Potential implementation direction:
- key shape like
discord:guild_member:{guild_id}:{user_id}
- fields:
user_id, guild_id, username, display_name, avatar_url, nick, fetched_at
- optional short-lived negative cache for not-on-server users
- API should prefer cache over live Discord lookup for read endpoints
- bot becomes the main producer/updater of member cache
Useful reference
disgo supports custom/external cache approaches; see example:
Expected outcome
Endpoints like tickets/open should stop spending ~15s+ in Discord member lookup fallback and instead return quickly while still showing current user info (or Not on server when appropriate).
Problem
Some server endpoints need fresh Discord member identity data (
username,display_name,avatar_url) to render dashboard views such as tickets.The current
tickets/openfallback resolves missing identities with live Discord member lookups (GET /guilds/{guild.id}/members/{user.id}) during the request. On a server with 95 tickets / 64 unique users missing identity, that makes the endpoint take ~17s locally.Recent profiling on
GET /v2/server/923764211845312533/tickets/openshows:total_ms=17377discord_ms=15819open_tickets_ms=845links_ms=215players_ms=396auth_users_ms=98missing_identity_users=64discord_lookup_attempted=64discord_lookup_succeeded=42This confirms the bottleneck is not Mongo; it is the repeated live Discord member lookups. Even when done concurrently in Go, the Discord client buckets this route, so requests are effectively serialized.
Why not store identity on ticket creation?
We explicitly do not want to persist
discord_username,discord_display_name, ordiscord_avatar_urlas the source of truth on ticket creation because those fields can change over time.We still want:
Not on serverwhen the user is no longer in the guild,Proposed solution
Add a shared external Discord member cache backed by Valkey so both the bot and the API/dashboard can use the same member identity source.
High-level idea:
Unknown Memberusers do not hammer Discord.Potential implementation direction:
discord:guild_member:{guild_id}:{user_id}user_id,guild_id,username,display_name,avatar_url,nick,fetched_atUseful reference
disgosupports custom/external cache approaches; see example:Expected outcome
Endpoints like
tickets/openshould stop spending ~15s+ in Discord member lookup fallback and instead return quickly while still showing current user info (orNot on serverwhen appropriate).