KEY TAKEAWAYS
- GitHub recommends a 2XX response within 10 seconds and asynchronous processing. Its delivery result describes acknowledgment, not whether your background work finished.[1]
- GitHub does not automatically redeliver failed deliveries. A requested redelivery keeps the original X-GitHub-Delivery value; use that identity to trace existing work, not as an automatic guarantee against duplicate effects.[1][2]
- Our proposed recovery rule: reconcile an existing effect, recover an accepted job, or establish that repetition is safe before redelivery. Missing records leave the outcome unresolved.
Start with the work already in progress
Before clicking Redeliver on a failed GitHub webhook, find out whether the receiver already accepted it. A receiver can enqueue a job and then lose its HTTP reply. A worker can complete the intended action while GitHub still shows a failed delivery. Sending the webhook again may then start the same work twice. These are possible failure paths, not incidents measured for this guide.
GitHub recommends responding with a 2XX HTTP status within 10 seconds. If the receiver takes longer, GitHub terminates the connection and considers the delivery a failure. Its suggested queue architecture lets the receiver acknowledge the webhook while processing continues in the background.[1] This makes a successful acknowledgment compatible with unfinished work, and a timeout compatible with work already accepted.
GitHub also recommends redelivering missed webhooks after a server comes back up, and documents manual and scripted recovery options.[1][2] The checks here add an application-level decision for integrations that can create consequential effects, such as sending a customer notification or starting an external operation. They do not say that GitHub prohibits redelivery. A harmless, repeatable action may need less investigation than an action whose duplicate matters.
Use the guide with access to the relevant GitHub delivery, receiver records, queue status and a permitted application or provider result lookup. Name one integration recovery owner who can authorize the chosen path. If those inputs are unavailable, the useful result is a documented hold and next evidence check, not a guessed retry.
Trace one delivery through three checkpoints
X-GitHub-Delivery is the delivery header used to identify the GitHub event delivery; its value stays the same on requested redelivery.[1] Retain that value alongside the webhook's source scope, intended target, event type and relevant payload. Link it to the application's job ID and any downstream operation ID. A job ID identifies background work; an operation ID identifies the intended external action. Neither is supplied automatically by the delivery header.
| Checkpoint | Evidence to inspect | What it cannot establish alone |
|---|---|---|
| GitHub acknowledgment | The delivery GUID, attempt time, HTTP result and stated failure reason. | Whether the receiver saved a job or the intended action happened. |
| Receiver and queue | The scoped delivery record, accept/enqueue state, linked job ID and current worker state. | Whether an external provider accepted or completed the action. |
| Downstream result | An authoritative application/provider record correlated to the exact target and intended payload, including accepted versus completed state. | Whether an unrelated record is this action, or whether an empty lookup means no action occurred. |
- Locate the original delivery in the correct webhook and preserve its result and failure reason. Read X-GitHub-Event and the payload's action when that event has one; GitHub recommends checking both before processing.[1]
- Follow the same delivery value into the receiver record. Find the linked queue job and inspect whether it is pending, running, finished or terminally rejected under the application's own definitions.
- Follow the job's intended action into the permitted downstream lookup. Match the source scope, target and payload, not just a similar timestamp. Distinguish an accepted operation from a completed result.
- Select the branch below from the combined evidence. If a log is expired, a queue lookup is inaccessible or a provider record cannot be uniquely matched, leave the outcome unresolved. An empty search is not a final no-effect status.
For receiver design, document the boundary between acceptance, durable enqueueing and the 2XX response. Decide what a duplicate receipt returns and how it recovers an existing job. Sending 2XX does not create durability by itself, and recording a delivery as merely 'seen' does not prove that its work was accepted. These are proposed design checks, not guarantees made by GitHub's queue recommendation.
Check authenticity separately from duplicate handling
GitHub says to validate the webhook signature before processing the delivery further. With a configured webhook secret, X-Hub-Signature-256 contains an HMAC-SHA256 signature with the prefix sha256=. Preserve the payload and headers before verification and use a constant-time comparison, not a plain == comparison. If no secret is configured, that signature header will be absent.[3] This guide does not configure a secret or supply a tested receiver adapter.
A valid signature checks the sender and payload integrity. It does not show that this is the first receipt, that the application supports the event/action, or that the intended effect succeeded. Each receipt, including a redelivery, needs the receiver's normal authenticity and applicability checks before business handling. A failed verification also does not settle what an earlier attempt may already have done.
GitHub recommends using X-GitHub-Delivery to identify unique deliveries, and requested redelivery preserves it.[1] Our proposed duplicate-handling check is broader: the application should recognize the same scoped delivery and payload atomically, return or reconcile its existing state, and control downstream repetition where needed. Check retention and provider propagation explicitly. The header alone neither enforces an external provider's idempotency contract nor promises exactly-once work. A receiver that discards every previously seen GUID must also define how an authorized recovery of terminally rejected work can proceed without bypassing its safety checks.
Choose a recovery path from the combined status
| Combined status | Decision | Evidence needed to finish |
|---|---|---|
| The exact intended effect already exists or is accepted. | Reconcile that result. Do not create a second effect merely to obtain a successful webhook acknowledgment. | The existing operation's authoritative result, or its documented next completion check if it is still accepted/in progress. |
| The receiver durably accepted a job that is pending or running. | Continue or repair that job through the authorized queue path. Webhook redelivery is not a worker-retry mechanism. | The same job's progress and its correlated downstream result. Queue repair must still respect any external effect already attempted. |
| The exact intended action has a definitive no-effect result. | Consider an authorized redelivery after fixing the receiver and checking the conditions below. | A final status contract proving no effect and no remaining runnable or late work, followed by the new receiver/job/result trace. |
| The original outcome is unresolved. | Hold automatic redelivery and repeat mutation while the recovery owner gathers evidence. A verified duplicate-prevention contract can support a different decision. | A correlated authoritative result, definitive no-effect evidence, or an applicable repetition-safety contract; not an empty or expired lookup. |
A repetition-safety contract must cover this action, source/account scope, payload, concurrent attempts and recovery interval, including an external provider when necessary. Receiver-side message suppression is not enough if a worker can still repeat an external write. This is a proposed standard for accepting that contract, not a capability established by the four GitHub pages.
Before redelivery, confirm that the receiver fault is repaired; signature and event/action handling are ready; any old runnable work is accounted for; and the same delivery can enter the intended recovery path without creating another effect. Check the documented GitHub window and the operator's access for that webhook type. Obtain the actual operator's authorization. The editorial examples here authorize no production action.
Four fictional deliveries, four completed decisions
All identifiers, states and decisions in this section are fictional and unexecuted. D-demo values are short teaching labels standing in for real X-GitHub-Delivery GUIDs; J-demo labels identify jobs and E-demo labels identify external effects. Assume a receiver with signature validation and supported event/action checks, plus authorized status lookups that correlate the exact source, target and payload. The application status semantics stated in each case are assumptions, not standard GitHub fields.
| Delivery case | Assumed evidence | Completed decision |
|---|---|---|
| D-demo-1: failed acknowledgment, accepted effect | The receiver saved D-demo-1 and enqueued J-demo-1 before its reply missed the deadline. The provider's authoritative lookup links the exact action to accepted E-demo-1, whose completion is still pending. | The integration recovery owner records E-demo-1 and follows its documented completion lookup. No second create or blind webhook redelivery is approved. The GitHub failure did not erase accepted work. |
| D-demo-2: acknowledged, still queued | GitHub shows 2XX. The receiver durably links D-demo-2 to J-demo-2. The queue contract confirms J-demo-2 is pending, not lost; no completed effect is yet evidenced. | The queue owner restores the existing worker path for J-demo-2 under its recovery rules. The recovery owner keeps the result open until that job's downstream outcome is reconciled. No new webhook is submitted to repair the worker. |
| D-demo-3: definitive no-effect | The application/provider contract reports the exact action as final rejected-before-effect. No job remains runnable and the contract rules out a late effect. The receiver fault is fixed, the delivery is within the documented window, and duplicate handling permits the authorized recovery. | An authorized repository admin approves one documented redelivery of the original GUID. The planned completion check follows that receipt to its job and effect. This is a fictional approval decision, not a claimed redelivery or successful recovery. |
| D-demo-4: genuinely unknown | GitHub reports a timeout. Receiver evidence is incomplete, the queue record is unavailable and the provider search is empty without final no-effect semantics. | The integration recovery owner holds automatic redelivery and repeat mutation. Next action: restore permitted queue-status access and request an authoritative lookup for the retained original action. If neither resolves it, keep the hold; do not relabel an empty search as rejection. |
D-demo-3 relies on positive, final no-effect evidence and the absence of possible late work under a stated contract. Removing those assumptions would move it to the unresolved branch. D-demo-2 is a different problem: the job exists, so recovery belongs to the queue and worker rather than another webhook receipt. D-demo-1 still needs a completion check because accepted is not necessarily completed.
Use the redelivery option for the actual webhook type
GitHub does not automatically redeliver failed deliveries. Its guide documents redelivery for deliveries that occurred in the past 3 days.[2][4] That is a GitHub redelivery window, not the retention lifetime of your queue or provider records. An older or missing delivery record does not prove that its action never happened. Investigate repeated delivery failures using their stated failure reason rather than sending the same request indefinitely.[2]
| Webhook type | Documented access | Documented recovery surface |
|---|---|---|
| Repository | Repository admin access. | GitHub web interface or REST API. |
| Organization | Organization owner. | GitHub web interface or REST API. |
| GitHub App | App owner or designated app manager. | GitHub web interface or REST API. |
| GitHub Marketplace | App owner or designated app manager for that app. | The listing's web interface. The failed-delivery guide says delivery-data API endpoints are unavailable. |
| GitHub Sponsors | Owner of the sponsored account. | The account's sponsorship dashboard. The failed-delivery guide says delivery-data API endpoints are unavailable. |
For a repository webhook, the documented UI path is repository Settings → Webhooks → the selected webhook → Recent deliveries → the original delivery GUID → Redeliver.[4] Use it only after the application's recovery decision and the operator's authorization. Requested redelivery keeps X-GitHub-Delivery unchanged.[1] Organization and App webhooks have their own settings paths; do not assume repository-admin access applies to them.
GitHub's failure guide also describes writing scripts to find and redeliver failed deliveries.[2] A script is user-authored automation, not a built-in GitHub retry schedule. This article supplies no API command, credential setup or production script, and neither connects an account nor executes redelivery.
Close the recovery on the work result
After an authorized recovery, read the receiver, queue and downstream records again. Preserve the original delivery identity, the recovery attempt, the existing or new job linkage, the correlated operation result and the reason for the decision. A fresh 2XX closes the acknowledgment question; it does not close unfinished background work. A queued job also needs its own completion or final failure evidence.
- Close as completed only when the intended result is authoritatively correlated to the delivery and payload, with no unresolved work capable of a conflicting duplicate under the integration's contract.
- If the provider has accepted the operation but not completed it, retain its operation identity and the documented next status check. Do not replace it with a second create to make the dashboard look successful.
- If recovery fails again, keep the actual failure reason, the recovery owner and the next permitted check. If the effect remains unknown, retain that uncertainty and the hold rather than reporting success or nonexecution.
The sources establish GitHub's delivery guidance, stable redelivery header, signature handling and documented recovery options. They are four pages from one publisher, not independent runtime corroboration. No receiver, queue, external operation or recovery experiment was run for this guide, and no reliability or business improvement was measured. Use your integration's actual status and duplicate-handling contracts to settle the application decisions.
Sources & scope
A practical guide based on four official GitHub Docs pages retrieved 11 October 2026 KST. Their publication and update dates are unknown. Application recovery rules below are proposals, not extra GitHub requirements or a tested integration. All worked cases are fictional and unexecuted. The article date identifies this prepared edition; it is not evidence of production activation.
- GitHub Docs: Best practices for using webhooks ↗
Official primary guidance retrieved 11 October 2026 KST: 10-second acknowledgment recommendation, asynchronous queueing, event/action checks, missed-delivery recovery and stable X-GitHub-Delivery on requested redelivery. Publication/update dates unknown; not a tested implementation.
- GitHub Docs: Handling failed webhook deliveries ↗
Official primary guidance retrieved 11 October 2026 KST: no automatic GitHub redelivery, manual/user-authored script options, repeated-failure investigation and Marketplace/Sponsors delivery-data API limits. Publication/update dates unknown.
- GitHub Docs: Validating webhook deliveries ↗
Official primary guidance retrieved 11 October 2026 KST: validate before further processing, configured-secret HMAC-SHA256, X-Hub-Signature-256 and constant-time comparison with unchanged payload/headers. Publication/update dates unknown; source examples were not executed.
- GitHub Docs: Redelivering webhooks ↗
Official primary guidance retrieved 11 October 2026 KST: past-3-days redelivery window, webhook-type access rules, web-interface paths and repository/organization/App REST alternatives. Publication/update dates unknown; no redelivery was performed.
Publication history
- — Initial prepared edition: documented GitHub facts, proposed receiver/queue/result recovery decisions and four fictional completed case decisions. Production activation requires separate release evidence.
Have a correction or a different perspective? Contact Palanthos.