Replace Polling with Signed Webhooks for Hosting Events
Learn how to replace polling loops with signed webhooks for hosting event automation. Implement HMAC verification, timestamp tolerance, and replay protection.
You are probably polling your hosting platform's API every few minutes to check for new orders, failed payments, or server status changes. That loop wastes resources, adds latency, and can miss events between checks. Signed webhooks push events to you the moment they happen, but you must verify them to avoid spoofing and replay attacks. This guide shows you how to switch from polling to signed webhooks, with HMAC verification, timestamp tolerance, and replay protection.
Why replace polling loops with webhooks?
Polling is a pull model: you ask the API repeatedly for changes. Webhooks are push: the platform sends an HTTP POST to your endpoint when an event occurs. Polling every minute means 1,440 requests per day per endpoint, most returning nothing new. Webhooks eliminate that waste and reduce event latency from minutes to seconds. For hosting automation, that matters when a new order should trigger immediate provisioning, or a payment failure should suspend service without delay.
How do signed webhooks work?
A signed webhook includes a cryptographic signature in the request headers, generated by the sender using a shared secret. You verify the signature to confirm the payload came from the expected source and was not altered. The typical flow:
- The platform creates a JSON payload describing the event.
- It computes an HMAC (Hash-based Message Authentication Code) using a secret key and the payload.
- It sends the payload and signature in headers, often with a timestamp.
- Your endpoint recomputes the HMAC and compares it to the received signature.
- If they match and the timestamp is recent, you process the event.
This prevents attackers from forging events or replaying old ones.
How to verify HMAC signatures correctly
HMAC verification is straightforward but easy to get wrong. Use a constant-time comparison to avoid timing attacks. Here is a step-by-step approach:
- Extract the signature and timestamp from the headers (e.g.,
X-SignatureandX-Timestamp). - Reconstruct the signed string. Common patterns:
timestamp + '.' + payloador just the payload. Check your provider's documentation. - Compute the HMAC using SHA-256 and your secret key.
- Compare the computed signature with the received one using a constant-time function.
- If they match, proceed to timestamp validation.
Never use a simple string equality check; use a function like hash_equals() in PHP or hmac.compare_digest() in Python.
Example: HMAC verification in Python
import hmac
import hashlib
def verify_signature(payload, secret, received_signature, timestamp):
signed_payload = f"{timestamp}.{payload}".encode()
expected = hmac.new(secret.encode(), signed_payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, received_signature)
What timestamp tolerance should you use?
Timestamp tolerance limits how old a request can be. If an attacker captures a valid request, they could replay it later. By rejecting requests with timestamps outside a small window (e.g., 5 minutes), you reduce that risk. Choose a tolerance that balances clock skew and security. Too tight (e.g., 30 seconds) may cause false rejections if your server clock drifts. Too loose (e.g., 1 hour) gives attackers a larger window. A common choice is 5 minutes. Always use UTC timestamps and ensure your server time is synchronized via NTP.
How to implement replay protection
Timestamp tolerance alone is not enough; an attacker could replay a request within the tolerance window. To prevent replay, track processed event IDs or signatures. Options:
- In-memory cache: Store recent event IDs in a set with a TTL equal to the tolerance window. Simple but not shared across multiple servers.
- Database: Insert event IDs into a table with a unique constraint. If insertion fails, it's a replay. Works across servers but adds latency.
- Redis: Use a Redis set with expiry. Fast and shared.
Whichever you choose, ensure the storage is atomic and handles concurrency. For high-volume hosting events, Redis is a good fit.
Best practices for webhook endpoints
Your endpoint must be reliable and secure. Follow these guidelines:
- Respond quickly: Return 200 OK within a few seconds. If processing takes longer, queue the event and process asynchronously.
- Use HTTPS: Never accept webhooks over plain HTTP.
- Validate payload structure: Even after signature verification, check that required fields exist and have expected types.
- Log failures: Log signature mismatches and processing errors for debugging.
- Handle retries: Webhook senders often retry on failure. Ensure your endpoint is idempotent.
Putting it all together
Replacing polling with signed webhooks requires three security layers: HMAC verification, timestamp tolerance, and replay protection. Implement them carefully, and you will reduce load, improve latency, and keep your automation secure. If you are building a hosting automation platform, consider using a solution that provides signed webhooks out of the box. For example, Teculiar includes webhook support with HMAC signatures as part of its automation platform. You can also check our pricing page for details.
What to do next
- Audit your current polling loops and identify events that could be webhook-driven.
- Set up a secure endpoint with HMAC verification and timestamp checks.
- Implement replay protection using Redis or a database.
- Test with your provider's webhook simulator and monitor for failures.
Start by replacing one high-frequency polling loop with a webhook, then expand as you gain confidence.