DEV Community

Motzumoto
Motzumoto

Posted on AI-assisted

Your Discord bot's member cache is lying to you. Mine never timed out a single member.

I set largeThreshold: 50 in my Discord bot's client config. The comment next to it said it saved memory with no functional loss. That was wrong, and it took a log search to find out how wrong.

What the setting really does

largeThreshold is the large_threshold field in Discord's gateway IDENTIFY payload. It is the member count above which the gateway stops sending offline members when a guild loads. Above it, a guild counts as "large" and the initial guild payload only carries members who are online.

Nothing fills the gap later. My only full-roster fetch ran from the guild-join event, and that event only fires for brand new guilds. Guilds the bot was already in at startup never got it. So after every restart, the member cache held the online members plus whoever the bot had seen since.

That means this line is not doing what it looks like:

for (const member of guild.members.values()) { ... }
Enter fullscreen mode Exit fullscreen mode

It does not iterate every member. It iterates the members who happen to be online or recently active.

How I found it

I have a verification timeout sweep. If a member does not finish verification in time, the bot acts on them. I searched 200MB of production logs for the line it writes when it actions someone: verification timeout action applied. It appeared zero times. It had never once actioned anyone.

Two of the four servers using the gate were above the threshold, at 532 and 54 members. The 54 member server was only affected because I had set the threshold to 50. At Discord's default of 250 it would have worked.

The fix

Do not treat the cache as a roster. There are two honest options:

  1. Keep a durable record of who needs checking. I added a pending_verification table and made it the source of candidates.
  2. Call the full member fetch explicitly before you iterate, and report a "not cached" count, so that "nobody matched" is distinguishable from "most of the server was never looked at".

The threshold itself is a real memory optimisation and I kept it. The mistake was letting several features read the cache as if it were complete.

The trap inside the trap

The sweep's happy path returns early and quietly when it finds no candidates. So the absence of log output proved nothing for weeks. A check that stays silent when it finds nothing cannot tell you that it is blind.

Takeaways

  1. Before you walk a guild's members, ask whether you need the offline ones. If yes, the cache is the wrong source.
  2. Make sweeps report what they examined, not only what they did.
  3. Comments that claim "no functional loss" deserve a test.

I build Akiko, a Discord bot with AI chat that remembers you, plus economy, music, moderation and a web dashboard. Free to add: https://i.hep.gg/akiko

Top comments (0)