Service Name: Webhook Delivery Service Criticality: Tier-1 (High Availability, 99.99% Target) P99 Latency SLA: < 100ms Ingestion
If an incident or alert is triggered, use these fast-path diagnostic endpoints to isolate the root cause:
curl -s http://webhook-service.internal/healthExpected Output:
{ "status": "UP", "queueSize": 0 }curl -s http://webhook-service.internal/statsCheck queueSize and successRate. If queueSize is climbing (> 1000) and successRate is dropping (< 95%), a downstream receiver or network partition is likely causing delivery failures.
curl -s http://webhook-service.internal/logs | grep -E '"status":"FAILED"|"status":"RETRYING"'- Symptom:
webhook_queue_size_currentis sustained above 500. - Root Cause: Downstream client webhook endpoints are offline, rate-limiting requests (HTTP 429), or experiencing extreme latencies, clogging the background processor thread.
- Remedy Actions:
- Increase horizontal scale (increase replica count of the webhook containers) to expand total delivery concurrency.
- Increase the maximum attempts limit temporarily or lower the HTTP timeout value from 5s to 2s to prune slow connections faster.
# Example to scale replicas in Kubernetes kubectl scale deployment webhook-delivery-service --replicas=10
- Symptom: Webhook process crashes with "Out of Memory" or CPU utilization is constantly at 100%.
- Root Cause: Memory leak in the in-memory queue or too many pending retries under extreme ingestion spikes.
- Remedy Actions:
- Terminate container and force restart to release leaked memory buffer.
- Implement rate limiting on ingestion endpoints to protect the memory boundaries.
- Deploy a permanent out-of-process persistent queue (like Redis or RabbitMQ) if traffic spikes are consistently exceeding the memory boundaries.
To maintain high security, shared webhook secrets must be rotated every 180 days, or immediately upon key compromise:
Generate a secure, cryptographically random key:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Output example: b98b816a13d9cfc892809e20a2e39958e2bfb73be5c6138be6e3557e49c7bc29To prevent breaking integrations during rotation:
- Configure the Webhook Service to temporarily sign payloads with both the old secret and the new secret.
- Provide the new secret key to the subscriber.
- Once the subscriber updates their webhook receiver to verify using the new secret, remove the old secret from the active signing list.
To ensure the safety of the off-chain system, the SSRF (Server-Side Request Forgery) engine must be audited after any networking or DNS upgrades:
- Verify that the URL parser correctly flags subnets by running integration tests.
- Inspect server firewalls, ensuring egress traffic is strictly barred from routing to cloud provider private IP ranges and internal Kubernetes API service accounts.
When a webhook permanently fails after exhausting its retry budget, or is rejected by the SSRF shield, it is moved to the dead letter queue instead of being dropped. webhook_dead_letter_queue_size_current climbing or webhook_dead_letter_enqueued_total increasing indicates persistent downstream failures.
curl -s http://webhook-service.internal/deadletter
# {"count": 3, "deadLetters": [ { "id": "...", "reason": "MAX_ATTEMPTS_EXHAUSTED", ... } ]}
# Inspect a single entry to see the failure reason and last error
curl -s http://webhook-service.internal/deadletter/<job-id>- Verify the downstream endpoint is healthy (
curl/GET /healthon the receiver). - Confirm the stored
errorMessageis a transient failure (5xx, timeout) and not a request you should not re-send (e.g. 4xx contract violations).
# Push a single dead letter back onto the active queue with a fresh retry budget
curl -X POST http://webhook-service.internal/deadletter/<job-id>/requeue
# { "status": "REQUEUED", "jobId": "<new-job-id>" }The requeued message is re-signed and passes through the full security + retry pipeline again.
# Remove a single entry
curl -X DELETE http://webhook-service.internal/deadletter/<job-id>
# Purge the entire queue (requires explicit confirmation)
curl -X DELETE http://webhook-service.internal/deadletter?confirm=true- Bounded retention: The DLQ holds up to 1,000 entries in memory; the oldest entry is evicted (and counted as
webhook_dead_letter_discarded_total) when capacity is exceeded. - Durability: The DLQ is in-memory. For transactions that must survive service restarts, deploy the out-of-process persistent queue pattern (Redis/RabbitMQ) as the backing store.