Relay Troubleshooting

Webhooks show “failed” and are not delivered

Is your endpoint publicly accessible? Relay runs from edge servers. Internal or private-network URLs will fail. Test with curl -X POST -d '{"test":true}' https://your-endpoint.com.

Is your endpoint returning 4xx? Relay does not retry 4xx responses. Check for missing auth, IP allowlists, or incorrect paths.

Is DNS resolving? Verify DNS records exist and SSL certificates are valid and not expired.

Retries exhaust quickly

Default retry strategy: 3 attempts with exponential backoff (1s, 2s, 4s). Total window is about 7 seconds.

Serverless cold starts may cause the first request to timeout. Keep webhook receiver endpoints warm or return 200 immediately and process asynchronously.

Relay shows success but my app did not process the webhook

Silent failures. If your handler returns 200 before processing, failures after the response are invisible to Relay. Return 5xx on processing errors so Relay retries.

Async processing. If you return 200 immediately and queue work, failures in your queue are outside Relay’s visibility. Implement your own retry for queued jobs.

Signature verification fails on valid webhooks

Are you signing the raw body? Use the raw request body string, not parsed-and-re-serialized JSON. In Express, use express.raw({ type: 'application/json' }).

Correct concatenation format: timestamp + payload where timestamp comes from the X-Solenoid-Timestamp header and payload is the raw body string.

Correct algorithm: HMAC-SHA256. The secret is your API key.

Timestamp skew: Reject timestamps more than 5 minutes old to prevent replay attacks.

Webhooks arrive out of order

Relay provides at-least-once delivery but does not guarantee ordering. Retries and network variance can reorder deliveries. Use timestamps or sequence numbers in your payload to detect and handle out-of-order events.

Same webhook received multiple times

Duplicates are expected under at-least-once delivery. A network timeout can cause a retry even if the first delivery succeeded. Deduplicate by tracking the X-Solenoid-Signature and X-Solenoid-Timestamp header pair or by including an idempotency key in your payload.

Getting more help