Wait for the number of seconds in the Retry-After header, then retry. Cap the attempts, add jitter, and fix the cause by sending fewer, larger calls. Both Slack and Jira Cloud document HTTP 429 with Retry-After, so one retry helper can serve both.
What 429 means
HTTP 429 Too Many Requests says you are calling faster than the service allows. Slack's rate limit page says that if you exceed a limit on its HTTP APIs, including incoming webhooks, it returns 429 with a Retry-After header holding the seconds until you may try again. It recommends designing for roughly one request per second for a given call, noting short bursts are tolerated. Incoming webhooks are listed at one per second with short bursts allowed.
Atlassian's Jira Cloud rate limiting page says that when any limit is exceeded Jira returns 429, and tells apps to respect the Retry-After header and use backoff. It also describes burst limits per endpoint, so you can be throttled even with hourly quota left, and requests to other endpoints are unaffected.
A retry helper
post_with_retry() {
url="$1"; data="$2"; tries=0
while [ "$tries" -lt 4 ]; do
code=$(curl -s -o /dev/null -D headers.txt -w '%{http_code}' \
-X POST -H 'Content-Type: application/json' --data "$data" "$url")
if [ "$code" != "429" ]; then echo "$code"; return 0; fi
wait=$(grep -i '^retry-after:' headers.txt | tr -dc '0-9')
sleep "${wait:-5}"
tries=$((tries+1))
done
return 1
}
Treat a success as any 2xx, and fail the step if the helper returns non zero so the problem is visible.
Rules for a good retry
- Honour Retry-After when present. Fall back to a short default when it is not.
- Add jitter so parallel jobs do not retry in lockstep.
- Cap the number of attempts and the total wait. A job stuck sleeping for an hour is worse than a failed one.
- Retry only on 429 and on server errors. Do not retry a 400 or 403, because repeating a bad request will not fix it.
- Make the call safe to repeat. A retry after a timeout can double create a ticket. See searching before you create.
Our post on webhook retry schedule, backoff and jitter explains the receiving side of the same ideas.
Fix the cause, not only the symptom
Hitting 429 usually signals a design problem:
| Cause | Better design |
|---|---|
| One chat message per finding | One summary message per run |
| One ticket per finding | One ticket per work item, see grouping |
| Many jobs posting in parallel | A final job that collects results and posts once |
| Polling an API in a tight loop | Use a webhook or a longer interval |
A scan that finds 400 items should produce one message and a handful of tickets, not 400 calls.
Test the failure path
Point the helper at a local test server that always returns 429 with a Retry-After of 1 and confirm the job gives up after the cap and fails clearly. Many teams test the happy path only and discover the unhappy one in an incident.
Quick check
Should I retry forever on 429?
No. Cap attempts and total wait, then fail the step so someone notices.
Is the Retry-After value always present?
Both vendors document it, but write a default delay in case a proxy strips it.
Sources
Safeguard's policies and gates reduce noise before it reaches chat or tickets, and you can try the free scan at gold.safeguard.sh/scan.
Last reviewed: 19 October 2026.