Caching
Limits, identity-preserving snapshots, sweeps, and how guild/channel caches stay aligned.
The client keeps structures in memory so you do not REST-fetch everything on every event. Managers are the day-to-day API; client.cache exposes limits, stats, and sweeps.
Mental model
| Cache | Access | Notes |
|---|---|---|
| Guilds | client.guilds | READY / GUILD_CREATE upserts |
| Channels | client.channels and guild.channels | Same object, two indexes |
| Users | client.users | Shared across guilds |
| Members | guild.members | Per guild; partial snapshots merge only |
| Roles / emojis / stickers | guild.roles / .emojis / .stickers | Per guild |
| Messages | per-channel maps via gateway handlers | Bounded; FIFO when full |
Deleting or FIFO-evicting a guild removes its channels from the global index and clears those channels’ message caches. Users are not mass-deleted (they are shared).
Configuring limits
Defaults (DEFAULT_CACHE_LIMITS):
| Bucket | Default |
|---|---|
guilds | 200 |
users | 10_000 |
channels | 5_000 |
messages | 50 (per channel) |
members | 5_000 (per guild) |
roles / emojis / stickers | unbounded (0) |
Semantics:
| Value | Meaning |
|---|---|
| positive number | Max entries (FIFO on insert of a new key) |
0 or Infinity | Unbounded |
false (messages only) | Message cache disabled |
import { Client } from '@fluxerjs/core';
const client = new Client({
cache: {
guilds: 100,
channels: 2_000,
messages: 20, // per channel
// messages: false, // disable message caching
roles: 500, // optional per-guild caps
},
});
client.cache.limits; // resolved numbers (`Infinity` when unbounded)Breaking clarification: cache.messages: 0 is now unbounded (same as other buckets). Pass messages: false to turn message caching off. Passing 0 emits a one-time warning.
Get / fetch / resolve / force
- get — cache only;
undefinedif missing - fetch — REST, then update cache
- resolve — get, else fetch (when the manager supports it)
- force —
guilds.fetch(id, { force: true })re-fetches and_patches metadata in place (nested caches kept)
const cached = client.guilds.get(guildId);
const guild = cached ?? (await client.guilds.fetch(guildId));
await client.guilds.fetch(guildId, { force: true });
const member =
guild.members.get(userId) ?? (await guild.members.resolve(userId));Identity and patching
READY and available GUILD_CREATE reuse cached Guild / Channel / Role / emoji / sticker instances when the id (and channel type) match. Nested collections are synced with prune for roles/channels/emojis/stickers; members are merge-only (partial lists are common).
References stay valid across reconnects and outage recovery unless:
- the channel type changes (instance is replaced)
- the guild/channel is FIFO-evicted or permanently deleted
- you call
client.destroy()
*Update events still provide an old snapshot when something was cached.
Sweeps and stats
client.cache.stats();
// { guilds, channels, users, members, messages, messageChannels, roles, emojis, stickers }
client.cache.sweepMessages((msg) => Date.now() - Date.parse(msg.timestamp) > 3_600_000);
client.cache.sweepMembers((member, guildId) => member.id !== client.user.id);
client.cache.sweepUsers();
client.cache.sweepChannels((ch) => !('guildId' in ch));
client.cache.sweepGuilds((g) => !g.available);Aliases kept for compatibility: client.sweepMessages, client.sweepMembers, client.users.sweep, guild.members.sweep.
See examples/cache-bot.js for a runnable long-running pattern.
Reconnect / unavailable
- RESUMED — cache is kept as-is
- Identify READY — guilds upsert in place (same object identity when still cached)
- Unavailable (
GUILD_DELETEwithunavailable: true) — guild stays cached withavailable === false; the next available GUILD_CREATE recovers the same guild instance and syncs nested caches - Permanent GUILD_DELETE — guild removed; channels + message caches cascade away
When to fetch anyway
Fetch when correctness beats a round trip: bans, messages older than the per-channel cap, or roles/channels after an outage if the recovery snapshot omitted them. For “is this user in the server right now,” fetchMember beats a stale cache.
Troubleshooting
| Symptom | Check |
|---|---|
| Memory keeps growing | Lower limits; periodic sweepMessages / sweepMembers; confirm messages is not 0 if you meant “off” (false) |
| “Orphan” channels after leaving a guild | Permanent delete and FIFO eviction cascade; if you only marked unavailable, channels stay on purpose |
Channel missing from guild.channels but present on client.channels | Should not happen after sync — report if you see it; both indexes are written together |
Held Guild reference looks stale after reconnect | Confirm you did not hit FIFO eviction; identity is preserved only while the guild remains cached |