Caching and memory
Athena caches Discord objects in memory using Collection (a typed Map). Defaults are fine for most bots. For large bots the cache can dominate memory;...
Athena caches Discord objects in memory using Collection (a typed Map). Defaults are fine for most bots. For large bots the cache can dominate memory; this page covers the knobs. Everything here is opt-in. With no cache option set, behaviour is exactly the historical default (unbounded in-memory caches).
For the cluster-scale Redis story, continue to Scaling to millions.
What is cached
| Cache | Scope | Default |
|---|---|---|
client.users | global | unbounded |
client.guilds | global | unbounded |
client.privateChannels | global | unbounded |
guild.members | per guild | unbounded |
guild.channels / threads / roles | per guild | unbounded |
guild.voiceStates / stageInstances | per guild | unbounded |
channel.messages | per channel | bounded by messageLimit (default 100) |
Within one process, users are not duplicated: client.users holds each user once and members/messages reference it. Duplication across separate cluster processes is inherent to multi-process sharding and only a shared store removes it (see Scaling to millions).
Free win: presence defaults
A Member no longer pre-allocates an empty clientStatus object and activities array per instance. Until a real presence update arrives, members share one frozen default. Reads return identical values, and presence updates replace it. Bots without the presence intent stop paying for empty placeholders on every cached member. This is automatic; do not mutate member.clientStatus / member.activities in place.
Config-only knobs
- Do not enable
GuildPresencesunless you use presence; it is the biggest source of churn. disableEvents: { TYPING_START: true, PRESENCE_UPDATE: true, VOICE_STATE_UPDATE: true }skips parsing events you ignore.- Lower
messageLimit, or set0to keep no messages.
Pluggable caches
Override how any cache is constructed. Unset entries keep the default.
import { Client, LRUCollection, NullCollection, User, Member, VoiceState, StageInstance } from 'athena';
new Client(token, {
cache: {
users: () => new LRUCollection(User, 100_000),
members: (guild) => new LRUCollection(Member, 50_000),
voiceStates: () => new NullCollection(VoiceState),
stageInstances: () => new NullCollection(StageInstance)
}
});LRUCollection(Class, max)keeps at mostmaxentries and evicts the least recently used. A successfulgetmarks an entry as recently used.NullCollection(Class)constructs and returns objects but stores nothing, soget/hasalways miss andsizestays 0. Use it to disable a cache you never read back. Only disable caches you do not read.
Overridable cache keys: users, guilds, privateChannels, members, channels, threads, roles, voiceStates, stageInstances, messages.
Choosing
- Small or medium bot: do nothing.
- Memory-conscious single process:
LRUCollectioncaps,NullCollectionfor unused caches, lowermessageLimit. - Huge multi-cluster bot: add a shared remote store on top; see Scaling to millions.