Skip to main content
Webhooks allow your external services to be notified automatically when a Job Run reaches a terminal state (e.g., completed, failed, timed_out) or when an Event Trigger is resolved.

Delivery Models

Strait has two webhook delivery models:

Job Run Webhooks

When a run reaches a terminal state, the executor checks if the parent Job has a webhook_url configured and dispatches a signed HTTP POST. Delivery uses in-memory retry with blocking backoff (up to 3 attempts). If the worker process crashes during delivery, in-flight retries are lost.

Event Trigger Webhooks

Event trigger webhooks (configured via notify_url on wait-for-event steps) use a durable delivery model. Deliveries are persisted to the webhook_deliveries table and processed by a background polling worker (apps/strait/internal/webhook/event_notify.go). This survives process restarts — pending deliveries are picked up on the next poll cycle.

Delivery Lifecycle

  1. Terminal State Reached: When a run finishes, the executor checks if the parent Job has a webhook_url configured.
  2. Payload Construction: A WebhookPayload is assembled containing the run’s final state, result, and error (if any).
  3. Signing: If a webhook_secret is configured, the payload is signed using HMAC-SHA256 with a timestamp for replay protection.
  4. Dispatch: An HTTP POST request is sent to the webhook_url.
  5. Retry Logic: If delivery fails, Strait retries based on the response status code.
  6. Dead Letter: After exhausting retries, deliveries are marked as dead (event trigger) or silently dropped (job run).

Webhook Payload

The payload sent to your endpoint (defined in apps/strait/internal/worker/webhook.go) includes:

HMAC-SHA256 Signing

To ensure the webhook was sent by Strait, signed deliveries include:
  • X-Strait-Timestamp: Unix timestamp used in signature generation
  • X-Strait-Signature: sha256=<signature>
  • X-Webhook-Signature: compatibility header for existing consumers
Algorithm: HMAC-SHA256 using webhook_secret as key and {timestamp}.{raw-json-body} as the signed payload. The timestamp is included in the signed payload to provide replay protection — receivers should reject deliveries where the timestamp is more than 5 minutes old. Signed payload format:

Verifying Signatures (Go Example)

Retry Strategy

Job Run Webhooks

Strait attempts to deliver job run webhooks up to 3 times with an exponential backoff:
  • Attempt 1: Immediate
  • Attempt 2: 1 second delay
  • Attempt 3: 5 seconds delay

Event Trigger Webhooks

Event trigger webhooks (configured via notify_url on wait-for-event) use a persistent delivery queue that survives process restarts:
  • Max attempts: 5
  • Backoff: Exponential — 5s, 25s, 125s, 625s (capped at 30 minutes)
  • Delivery worker: Polls the database every 5 seconds for pending deliveries

Retry Rules

  • Client Errors (4xx): Delivery is considered a permanent failure; no retries are attempted. The delivery is dead-lettered immediately.
  • Server Errors (5xx) / Timeouts: Delivery is retried up to the maximum attempt limit.
  • Context Cancellation: If the system is shutting down, delivery may be aborted with a “context canceled” error.

Configuration

Job Webhooks

Webhooks are configured per job:
  • webhook_url: The destination for the POST request.
  • webhook_secret: (Optional) The key used for HMAC signing.

Event Trigger Webhooks

Event trigger webhooks are configured per trigger:
  • notify_url: Set when creating a wait-for-event step or SDK call.
  • Delivery status is tracked in the webhook_deliveries table with event_trigger_id.

Dead Letter Queue (DLQ) Management

Failed webhook deliveries are stored in the database and can be inspected and retried:
The retry endpoint resets the delivery to pending status with zero attempts and immediate next retry time. Only deliveries in failed status can be retried — attempting to retry a pending or delivered delivery returns 409 Conflict.
Always use HTTPS for your webhook URLs to protect the payload and signature in transit.