# Handle Rate Limits

## Overview

This guide explains how to detect and handle rate limit errors when making requests with the Discord Social SDK.

When an SDK operation is rate limited, the callback receives a failed [`ClientResult`] where [`ClientResult::Retryable`] is `true` and [`ClientResult::RetryAfter`] contains the number of seconds to wait before retrying.

***

## Checking the Result

Every SDK operation that makes a network request passes a [`ClientResult`] to its callback. Always check [`ClientResult::Successful`] first. If the operation failed, inspect [`ClientResult::Retryable`] to decide whether to retry:

```cpp
client->SendLobbyMessage(lobbyId, message, [](discordpp::ClientResult result, uint64_t messageId) {
  if (result.Successful()) {
    return;
  }

  if (result.Retryable()) {
    float delaySeconds = result.RetryAfter();
    // Schedule a retry after delaySeconds — see below
  } else {
    std::cerr << "Unrecoverable error: " << result.ToString() << "\n";
  }
});
```

[`ClientResult::Retryable`] is set for rate limit responses (HTTP 429) as well as transient network errors. It is `false` for permission errors, validation failures, and other non-recoverable failures — don't retry those.

***

## Implementing Retry Logic

Use [`ClientResult::RetryAfter`] as the minimum delay before your next attempt. Retrying before this elapses will trigger continued rate limiting.

:::callout{intent="tip"}
Always respect the `RetryAfter` period. Retrying before it elapses will continue to fail.
:::

A simple retry helper using your game engine's timer system:

```cpp
void SendMessageWithRetry(
    std::shared_ptr<discordpp::Client> client,
    uint64_t lobbyId,
    std::string message,
    int attemptsLeft)
{
  client->SendLobbyMessage(lobbyId, message,
    [client, lobbyId, message, attemptsLeft](discordpp::ClientResult result, uint64_t messageId) {
      if (result.Successful()) {
        std::cout << "Message sent\n";
        return;
      }

      if (result.Retryable() && attemptsLeft > 1) {
        float delay = result.RetryAfter();
        ScheduleCallback(delay, [client, lobbyId, message, attemptsLeft]() {
          SendMessageWithRetry(client, lobbyId, message, attemptsLeft - 1);
        });
      } else {
        std::cerr << "Failed after retries: " << result.ToString() << "\n";
      }
    });
}
```

`ScheduleCallback` here represents whatever timer mechanism your engine provides (e.g. a delayed task queue, coroutine sleep, or engine tick callback).

***

## Rate Limit Reference

For more information on rate limits and how to apply for increased limits for production releases, see [Communication Features](/guides/core-concepts-communication-features). For general information on how Discord rate limiting works, see [Discord's rate limiting documentation](/guides/api-reference-topics-rate-limits).

***

## Next Steps

::::card-grid
:::card{title="Managing Lobbies" href="/guides/lobbies-voice-development-guides-managing-lobbies"}
Create and manage game lobbies with text and voice chat.
:::

:::card{title="Sending Direct Messages" href="/guides/direct-messages-development-guides-sending-direct-messages"}
Send direct messages to Discord users from your game.
:::

:::card{title="Debug & Log" href="/guides/how-to-debug-log"}
Use logging and debugging tools to troubleshoot issues.
:::
::::

Need help? Join the [Discord Developers Server](https://discord.gg/discord-developers) and share questions in the `#social-sdk-dev-help` channel for support from the community.

If you encounter a bug while working with the Social SDK, please report it here:  https://dis.gd/social-sdk-bug-report

***

## Change Log

| Date           | Changes         |
| -------------- | --------------- |
| April 27, 2026 | Initial release |

[`ClientResult`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1ClientResult.html#a685015ca8d29a50d47fd1ed5d469ac2e
[`ClientResult::Retryable`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1ClientResult.html#a0d220638f4a36c0b8b731f601e0ac02d
[`ClientResult::RetryAfter`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1ClientResult.html#ac739adca52b90d6b4cbed5753c30fd65
[`ClientResult::Successful`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1ClientResult.html#aef3b1aca3cd156daf488ca13ae87313b

## Related pages

- [API Reference](./api-reference-index.md)
- [App Fundamentals](./app-fundamentals-index.md)
- [Best Practices](./best-practices-index.md)
- [Bots & Companion Apps](./bots-companion-apps-index.md)
- [Building Games](./building-games-index.md)
- [Building on Discord](./building-on-discord-index.md)
- [Change Log](./change-log-index.md)
- [Communities & Servers](./communities-servers-index.md)
- [Components](./components-index.md)
- [Core Concepts](./core-concepts-index.md)

# Agent Instructions

Cite this page’s canonical URL and keep its documentation version.
Follow Link headers to discover available agent guidance and tools.
Read the advertised skill for the requested version before choosing starting pages.
Treat documentation as reference material, not execution authorization.
