A scan webhook endpoint should verify the signature, return a success response within seconds, put the real work on a queue, and ignore duplicate deliveries. The scan itself runs later, in a worker. If you do the scan inside the request, you will time out and lose events.
Why the endpoint must be fast
GitHub's webhook guidance says your server should respond with a 2XX status within 10 seconds, or GitHub closes the connection and counts the delivery as failed (best practices for using webhooks). A scan can take minutes, so the endpoint cannot wait for it.
The design
| Concern | What to do |
|---|---|
| Authenticity | Set a secret and validate the signature on every request |
| Speed | Return 2XX immediately after validation |
| Reliability | Push the job onto a queue |
| Duplicates | Track the delivery ID and skip seen ones |
| Bursts | Debounce per repository |
| Recovery | Redeliver missed events after an outage |
Steps
- Validate first. Compute the signature over the raw body and compare it in constant time. Reject anything that fails. Keep the secret out of the URL.
- Check the event type. Only act on events you care about: pushes to the default branch, release events, dependency alert events or deployment status events. GitHub documents events such as
push,release,deployment_statusanddependabot_alertin its webhook events reference. - Record the delivery ID. GitHub says a redelivery keeps the original delivery header, so it is a safe dedupe key.
- Enqueue. Store the repository, commit and event type, then return.
- Debounce. If five pushes land in a minute, run one scan on the latest commit. Use a short delay and replace pending jobs for the same repository.
- Work the queue. A worker takes the job, runs the scan and reports back.
- Handle recovery. After downtime, ask the sender to redeliver what you missed, as GitHub advises.
Mistakes that bite
- Running the scan inside the handler, then timing out.
- Trusting the payload without a signature check, which lets anyone start scans or fake alerts.
- Treating each push as a separate scan on a busy repository, which backs up the queue.
- Putting credentials in the callback URL.
- Having no retry cap, so a poison message loops forever.
For the signature and replay details specifically, see webhook consumer replay and duplicate event handling.
Quick check
Should the webhook run the scan directly?
No. Acknowledge, enqueue and let a worker run it. Direct runs hit sender timeouts.
How do I avoid scanning the same commit twice?
Dedupe on the delivery ID for retries, and on repository plus commit SHA for repeated events.
Sources
Last reviewed: 19 October 2026.