Relay your webhooks
Event catalog, guaranteed delivery, HMAC signatures, dead letter queues, rate limiting — out of the box.
go get github.com/xraph/relayEverything you need for webhook delivery
Relay handles the hard parts — retries, signatures, dead letters, rate limits — so you can focus on your business logic.
Event Catalog
Type-safe event registration with schema validation. Define your event types once, reference them everywhere.
r.Catalog().RegisterEventType( "order.created", relay.WithSchema(orderSchema), relay.WithDescription("New order placed"),)Guaranteed Delivery
Configurable retry schedules with exponential backoff. No event is lost, ever.
relay.WithRetrySchedule( 5*time.Second, "text-fd-muted-foreground/60 italic">// 1st retry 30*time.Second, "text-fd-muted-foreground/60 italic">// 2nd retry 2*time.Minute, "text-fd-muted-foreground/60 italic">// 3rd retry 15*time.Minute, "text-fd-muted-foreground/60 italic">// 4th retry 1*time.Hour, "text-fd-muted-foreground/60 italic">// 5th retry)Dead Letter Queue
Failed deliveries are captured automatically. Inspect, debug, and replay them on demand.
items, _ := r.DLQ().List(ctx, dlq.WithEventType("order.created"), dlq.WithLimit(10),)r.DLQ().Replay(ctx, items[0].ID)HMAC Signatures
Every payload is signed with HMAC-SHA256. Receivers verify authenticity with a single call.
valid := relay.VerifySignature( payload, header.Get("X-Relay-Signature"), endpoint.Secret,)Rate Limiting
Per-endpoint token bucket rate limiting protects downstream services from being overwhelmed.
relay.WithRateLimit( 100, "text-fd-muted-foreground/60 italic">// requests per second time.Second, "text-fd-muted-foreground/60 italic">// window)Pluggable Stores
Ship with in-memory for dev, swap to PostgreSQL for production. Bring your own store with a simple interface.
r, _ := relay.New( relay.WithStore(postgres.New(db)), relay.WithWorkers(8), relay.WithLogger(slog.Default()),)From event to endpoint. Automatically.
Relay orchestrates the entire webhook delivery lifecycle — validation, fan-out, delivery, retries, and dead-letter routing.
Schema Validation
Every event is validated against its registered schema before delivery. Malformed payloads never reach your endpoints.
Smart Fan-Out
Events are distributed to all subscribed endpoints in parallel. Each endpoint has independent retry and rate-limit policies.
Decision Matrix
2xx = delivered. 429/5xx = retry with backoff. 4xx = dead letter. 410 = auto-disable endpoint.
Simple API. Production power.
Send your first webhook in under 20 lines. Verify signatures on the receiver side with standard crypto.
1package main2 3import (4 "log/slog"5 "github.com/xraph/relay"6 "github.com/xraph/relay/store/memory"7)8 9func main() {10 r, _ := relay.New(11 relay.WithStore(memory.New()),12 relay.WithWorkers(4),13 relay.WithLogger(slog.Default()),14 )15 16 "text-fd-muted-foreground/60 italic">// Register an event type17 r.Catalog().Register("order.created")18 19 "text-fd-muted-foreground/60 italic">// Register an endpoint20 r.Endpoints().Create(ctx, relay.Endpoint{21 URL: "https:">//api.acme.co/webhooks",22 EventTypes: []string{"order.created"},23 })24 25 "text-fd-muted-foreground/60 italic">// Send an event26 r.Send(ctx, relay.Event{27 Type: "order.created",28 Payload: orderJSON,29 })30}1package main2 3import (4 "crypto/hmac"5 "crypto/sha256"6 "encoding/hex"7 "io"8 "net/http"9)10 11func webhookHandler(w http.ResponseWriter, r *http.Request) {12 body, _ := io.ReadAll(r.Body)13 signature := r.Header.Get("X-Relay-Signature")14 15 "text-fd-muted-foreground/60 italic">// Verify HMAC-SHA256 signature16 mac := hmac.New(sha256.New, []byte(secret))17 mac.Write(body)18 expected := hex.EncodeToString(mac.Sum(nil))19 20 if !hmac.Equal([]byte(signature), []byte(expected)) {21 http.Error(w, "invalid signature", 401)22 return23 }24 25 "text-fd-muted-foreground/60 italic">// Process the verified webhook26 processEvent(body)27 w.WriteHeader(200)28}Start delivering webhooks
Add production-grade webhook delivery to your Go service in minutes. Relay handles retries, signatures, dead letters, and rate limiting out of the box.
go get github.com/xraph/relay