Quick answer: Discord rate-limits UpdateActivity to ~1/15s. Debounce your calls; update only on real state changes (level, match phase), not every frame.

A multiplayer game updates Discord Rich Presence with current map. Players switch maps fast in a lobby; presence stuck on previous map for 15 seconds. Rate limit caught up.

Debounce Pattern

DateTime _lastUpdate;
DiscordSDK.UpdateActivity _pendingActivity;

void ScheduleUpdate(Activity newActivity) {
    _pendingActivity = newActivity;
    var now = DateTime.UtcNow;
    if ((now - _lastUpdate).TotalSeconds >= 15) {
        DoUpdate();
    }
    // otherwise wait; timer will pick it up
}

void Tick() {
    if (_pendingActivity != null && (DateTime.UtcNow - _lastUpdate).TotalSeconds >= 15) {
        DoUpdate();
    }
}

Last write wins. If state changes 5 times within 15s, only the most recent is sent.

Update Only on Change

Avoid sending the same activity twice. Compare to last sent:

if (newActivity.Equals(_lastSent)) return;
ScheduleUpdate(newActivity);
_lastSent = newActivity;

Saves unnecessary API calls and avoids wasted rate-limit budget.

State Granularity

For most games, update on:

Don’t update on every score tick or HP change — players don’t need that granularity in friends’ profiles.

Discord SDK Lifecycle

Call Discord.RunCallbacks() each frame; it’s the SDK’s pump. Without this, UpdateActivity won’t actually be sent.

Verifying

Change maps rapidly in a test build. Presence updates once per 15s with the latest map. Friends see the latest state when they look. No errors in Discord log.

“Rich Presence is for visibility, not telemetry. Debounce and update meaningfully.”

For lobby join/invite buttons via Rich Presence, those events are exempt from the 15s throttle — safe to set when state changes.