TL;DR: Firing webhooks synchronously ties your API response time to an external server's health. StakCMS dispatches webhooks to a Redis queue, enforcing HMAC SHA256 signatures and logging exact failure reasons to prevent silent integration drops.
The Synchronous Trap
A webhook is just an HTTP POST to an external server. It’s easy to write: $client->post($url, $payload). It’s also a fantastic way to accidentally take down your own application. If you fire webhooks synchronously during an API request, and the receiving server (like a massive Vercel build pipeline) takes 10 seconds to respond, your API response to your user hangs for 10 seconds. If the external server 500s, your internal database transaction might roll back.
The Asynchronous Decoupling
In StakCMS, we decoupled webhooks entirely from the HTTP lifecycle. When an action occurs (like a form submission), we don't POST anything. We drop a DispatchWebhookJob into Redis and immediately return a 201 Created to the user.
// DispatchWebhookJob.php
public function handle()
{
$body = [
'event' => $this->event,
'data' => $this->payload,
];
$headers = ['Content-Type' => 'application/json'];
// We strictly enforce HMAC SHA256 signatures
if ($this->webhook->secret) {
$headers['X-Webhook-Signature'] = hash_hmac('sha256', json_encode($body),
$this->webhook->secret);
}
try {
$response = $client->post($this->webhook->url, ['headers' => $headers, 'json' => $body]);
// Log success to webhook_calls table } catch (RequestException $e) {
// Log exactly why it failed so the user isn't guessing in the dark
$status = $e->hasResponse() ? $e->getResponse()->getStatusCode() : 0;
}
}



