Skip to content
Latchkey

Discord webhook HTTP 429 rate limit in CI

Discord rate limits per webhook and returns HTTP 429 with a JSON body containing retry_after (seconds) and {"message":"You are being rate limited."}. In CI this triggers when a matrix build posts many messages to the same webhook in a short burst.

What this error means

A Discord notify step returns HTTP 429 with a retry_after value. Some messages post, others fail, correlated with parallel jobs sharing one webhook.

Discord API
< HTTP/1.1 429 Too Many Requests
{"message": "You are being rate limited.", "retry_after": 1.462, "global": false}

Common causes

Many jobs post to one webhook

A matrix or fan-out that fires a webhook per job exceeds the per-webhook limit in a short window.

Immediate retries ignore retry_after

Retrying without waiting the returned retry_after keeps the webhook throttled.

How to fix it

Wait for retry_after before retrying

  1. Parse retry_after from the 429 body.
  2. Sleep that many seconds.
  3. Retry the post once.
Terminal
ra=$(jq -r '.retry_after // 2' /tmp/body)
sleep "$ra"
# retry the POST once

Post one summary from a final job

Aggregate results and notify once instead of per matrix leg.

.github/workflows/ci.yml
notify:
  needs: [build]
  if: always()
  runs-on: ubuntu-latest
  steps:
    - run: ./scripts/discord-summary.sh

How to prevent it

  • Send a single aggregated message per workflow run.
  • Honor retry_after before retrying any 429.
  • Avoid sharing one webhook across many concurrent jobs.

Frequently asked questions

What causes "Discord 429 rate limit"?
A matrix or fan-out that fires a webhook per job exceeds the per-webhook limit in a short window.
How do I fix Discord 429 rate limit?
Wait for retry_after before retrying

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card