Best Practices
Overview
This page consolidates best practices for building production Discord bots with discord.go.
Token Security
- Load tokens from environment variables, not config files.
- Never commit tokens to version control.
- Use
ConfigFromEnvoros.Getenv("DISCORD_TOKEN"). - Rotate tokens if exposed.
Context Usage
- Use
context.WithTimeoutfor all REST calls. - Use
context.WithCancelfor long-running operations. - Never use
context.Background()for unbounded network calls. - Use the context-accepting variants (
RequestGuildMembersContext,JoinVoiceChannelContext) for gateway operations.
Command Design
- Use guild command sync during development for fast iteration.
- Switch to global command sync for production.
- Add descriptions to all commands and options.
- Use middleware for permission checks and validation.
- Set cooldowns on commands that should be rate-limited.
Event Handling
- Keep handlers fast; defer slow work to goroutines.
- Set
WithMaxHandlerConcurrencyto bound goroutine creation. - Handle panics via the error handler.
- Use collectors for button/select/menu flows with timeouts.
- Use
Router.ModalPrefixfor dynamic modal IDs (e.g.supreq_modal_<id>). - Use
ctx.ReplyEphemeralComplexfor ephemeral responses with embeds/components. - Use
msg.FirstEmbed()instead ofmsg.Embeds[0]to avoid index panics. - Use
snowflake.MustParsefor config constants,snowflake.Parsefor untrusted input. - Use
snowflake.ID.IsZero()instead ofid == 0for readability. - Use
permissions.Permission.String()for channel permission overwrites.
REST Usage
- Reuse a single
rest.Client; do not create new clients per request. - Use bulk endpoints instead of individual calls.
- Set audit log reasons with
rest.WithReason. - Check for
*rest.APIErrorto handle API-specific errors. - Do not bypass the rate limiter with raw HTTP calls.
Caching
- Use the memory cache for development.
- Implement a TTL or LRU cache for long-running bots.
- Do not rely on cache for critical data; fall back to REST.
- Treat cache as eventually consistent.
Sharding
- Use auto-detection (
WithShards(0)) for growing bots. - Monitor per-shard latency.
- Do not change shard count without restarting.
- Respect
max_concurrencyfrom thegateway/botresponse.
Voice
- Join via the main gateway first, then create the voice client.
- Use DAVE end-to-end encryption when available.
- Send Opus frames at 20ms intervals.
- Close the voice client on shutdown.
Error Handling
- Use
errors.Asto check forAPIErrorandCaptchaError. - Classify errors as retryable or fatal before retrying.
- Log structured fields for observability.
- Do not retry on 401/403; check credentials instead.
Security
- Use
interactions.VerifyRequestfor interaction verification. - Use
interactions.Serveras anhttp.Handlerthat verifies signatures and timestamps automatically. - Generate and verify OAuth2 state parameters using
oauth2.GenerateState(). - Use HTTPS for all webhook endpoints.
- Rate-limit incoming interaction endpoints.
- Store bot tokens in environment variables, not config files.
- Use
SetToken,SetBearerToken, orSetBotTokento configure credentials. The token is stored in an unexported field and cannot be read by external code. bot.Startvalidates token format and returnsErrInvalidTokenfor malformed tokens.
Deployment
- Use
client.RunContext(ctx)for service-managed lifecycle. - Monitor gateway latency and REST latency.
- Set
GOMAXPROCSappropriately for your container. - Use graceful shutdown to drain event handlers.