Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🐦 Postbird

A reliable webhook dispatcher service written in Go. Postbird handles webhook registration, event ingestion, and guaranteed delivery with automatic retries.

Features

  • Webhook Registration - Register endpoints with custom headers, secrets, and retry policies
  • Event Ingestion - Receive events via API and queue them for delivery
  • Reliable Delivery - Automatic retries with exponential backoff and jitter
  • HMAC Signatures - Stripe/GitHub-style signature verification for security
  • Delivery Tracking - Track delivery status, attempts, response codes, and latency
  • Dead Letter Queue - Failed deliveries are moved to DLQ for manual review/replay
  • Prometheus Metrics - Built-in observability with Prometheus metrics
  • Simple API - RESTful API for managing webhooks and monitoring deliveries

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Producer   │────▢│  Queue      │────▢│  Workers    β”‚
β”‚  (API)      β”‚     β”‚  (in-memory)β”‚     β”‚  (goroutine β”‚
β”‚             β”‚     β”‚             β”‚     β”‚   pool)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
                                               β”‚
                                               β–Ό
                                        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                        β”‚  Target     β”‚
                                        β”‚  Endpoint   β”‚
                                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Quick Start

Run Locally

# Build and run
make run

# Or with Docker
make docker-up

Using the API

# Create a webhook
curl -X POST http://localhost:8080/api/v1/webhooks \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-endpoint.com/webhook",
    "description": "My webhook",
    "events": ["user.created", "order.completed"]
  }'

# Send an event
curl -X POST http://localhost:8080/api/v1/events \
  -H "Content-Type: application/json" \
  -d '{
    "type": "user.created",
    "payload": {
      "user_id": "123",
      "email": "user@example.com"
    }
  }'

# Check delivery status
curl http://localhost:8080/api/v1/deliveries/{delivery_id}

# Retry a failed delivery
curl -X POST http://localhost:8080/api/v1/deliveries/{delivery_id}/retry

API Reference

Webhooks

Method Endpoint Description
POST /api/v1/webhooks Register a new webhook
GET /api/v1/webhooks List all webhooks
GET /api/v1/webhooks/:id Get a specific webhook
PUT /api/v1/webhooks/:id Update a webhook
DELETE /api/v1/webhooks/:id Delete a webhook

Events

Method Endpoint Description
POST /api/v1/events Ingest an event

Deliveries

Method Endpoint Description
GET /api/v1/deliveries List deliveries
GET /api/v1/deliveries/:id Get delivery status
POST /api/v1/deliveries/:id/retry Retry a failed delivery

Dead Letter Queue

Method Endpoint Description
GET /api/v1/dlq List DLQ items
POST /api/v1/dlq/:id/replay Replay from DLQ

System

Method Endpoint Description
GET /health Health check
GET /metrics Prometheus metrics

Webhook Registration

{
  "url": "https://api.example.com/webhooks",
  "description": "Production webhook",
  "events": ["user.created", "user.updated"],
  "headers": {
    "X-Custom-Header": "value"
  },
  "retry_policy": {
    "max_attempts": 5,
    "initial_interval_seconds": 10,
    "max_interval_seconds": 3600
  }
}

Event Types

If events is empty or not provided, the webhook will receive all event types. Otherwise, it will only receive events matching the specified types.

Signature Verification

Postbird signs all webhook payloads using HMAC-SHA256. The signature is included in the X-Postbird-Signature header:

X-Postbird-Signature: t=1699459200,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

Verifying Signatures (Example in Go)

func verifySignature(payload []byte, secret, signature string) error {
    parts := parseSignature(signature) // Parse t= and v1= values
    timestamp := parts["t"]
    expectedSig := parts["v1"]

    // Recreate the signed payload
    signedPayload := fmt.Sprintf("%s.%s", timestamp, string(payload))

    // Compute HMAC-SHA256
    h := hmac.New(sha256.New, []byte(secret))
    h.Write([]byte(signedPayload))
    actualSig := hex.EncodeToString(h.Sum(nil))

    if !hmac.Equal([]byte(expectedSig), []byte(actualSig)) {
        return errors.New("signature mismatch")
    }

    // Check timestamp is recent (within 5 minutes)
    ts, _ := strconv.ParseInt(timestamp, 10, 64)
    if time.Since(time.Unix(ts, 0)) > 5*time.Minute {
        return errors.New("signature expired")
    }

    return nil
}

Headers Sent with Each Request

Header Description
X-Postbird-Signature HMAC-SHA256 signature
X-Postbird-Timestamp Unix timestamp
X-Postbird-Webhook-ID Webhook identifier
X-Postbird-Delivery-ID Delivery identifier
X-Postbird-Event-Type Event type
Content-Type application/json
User-Agent Postbird/1.0

Retry Strategy

Postbird uses exponential backoff with jitter:

delay = initial_interval * multiplier^attempt + jitter

Default values:

  • Initial interval: 10 seconds
  • Max interval: 1 hour
  • Multiplier: 2.0
  • Max attempts: 5

Retry schedule: 10s β†’ 20s β†’ 40s β†’ 80s β†’ 160s (capped at max_interval)

Configuration

Environment Variable Default Description
HOST 0.0.0.0 Server host
PORT 8080 Server port
DB_DRIVER sqlite Database driver
DB_DSN postbird.db?_journal_mode=WAL Database connection string
WORKER_COUNT 10 Number of delivery workers
WORKER_REQUEST_TIMEOUT 30s HTTP request timeout
QUEUE_BUFFER_SIZE 10000 In-memory queue buffer

Development

# Install dependencies
make deps

# Run tests
make test

# Run linter
make lint

# Format code
make fmt

# Build Docker image
make docker

# Run with Docker Compose
make docker-up

# View logs
make docker-logs

Project Structure

postbird/
β”œβ”€β”€ cmd/
β”‚   └── server/
β”‚       └── main.go          # Application entry point
β”œβ”€β”€ internal/
β”‚   β”œβ”€β”€ api/                 # HTTP handlers and router
β”‚   β”œβ”€β”€ config/              # Configuration
β”‚   β”œβ”€β”€ metrics/             # Prometheus metrics
β”‚   β”œβ”€β”€ queue/               # Queue interface and implementations
β”‚   β”œβ”€β”€ storage/             # Database repositories
β”‚   β”œβ”€β”€ webhook/             # Domain models and signing
β”‚   └── worker/              # Delivery workers
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ Makefile
β”œβ”€β”€ prometheus.yml
β”œβ”€β”€ go.mod
└── README.md

Roadmap

  • PostgreSQL support for production
  • Redis queue for distributed deployment
  • Web dashboard for monitoring
  • Rate limiting per webhook
  • Webhook validation (test delivery)
  • Event filtering with JSONPath
  • Batch event ingestion
  • OpenTelemetry tracing

License

MIT

About

🐦 Carrier pigeon for your webhooks | reliable delivery service written in Go

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages