Convoy

Convoy is an open-source, cloud-native webhooks gateway that ingests events over HTTP or straight from Kafka, SQS, Google Pub/Sub, and RabbitMQ, then reliably delivers them to subscriber endpoints with signed payloads, automatic retries, circuit breaking, and JavaScript-based transformations.

2.9K stars
182 forks
Elastic-2.0
Go

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
88 /100 Excellent
Development Activity 96
Maintenance 100
Community 56
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
81 /100 Excellent
Architecture 80
Code Quality 90
Innovation 65
Learning Curve 90

Dependency Health

Score based on the health, technical quality, freshness, and vulnerability profile of runtime dependencies. How we score it →
65 /100 Good
Library Repo Health 70
Library Technical Quality 79
Version Staleness 77
Vulnerabilities 32
Dependency Footprint 45

Convoy is an open-source webhooks gateway written in Go that gives teams a dedicated, horizontally scalable layer for ingesting, persisting, debugging, and delivering webhook events at scale. Instead of exposing internal services directly to the public internet, teams put Convoy at the edge: it accepts inbound webhooks over HTTP or pulls events straight from existing message infrastructure — Kafka topics, Amazon SQS queues, Google Pub/Sub, or RabbitMQ exchanges — normalizes them, and fans them out to one or many subscriber endpoints with cryptographically signed payloads.

Under the hood, Convoy separates ingestion from delivery: a chi-routed API server (with a companion Angular dashboard) handles project, endpoint, source, and subscription management, while a Redis-backed Asynq worker pool and scheduler process actual deliveries asynchronously, retrying failures with constant-time or exponential-backoff-with-jitter strategies and tripping a per-endpoint circuit breaker when a subscriber consistently fails. Subscriptions can run custom JavaScript transformation functions — via an embedded Goja runtime — to reshape or filter payloads before they leave the gateway, and each component (API, worker, scheduler) can scale independently.

Convoy is source-available under the Elastic License 2.0 rather than a traditional OSI-approved license: self-hosting, modifying, and running it in production is free, but reselling it as a hosted service to third parties is not permitted, and a meaningful slice of functionality — payload transformations, circuit breaking, enterprise SSO, advanced filtering, webhook analytics, mutual TLS, static IPs, and more — sits behind a license key. The unlicensed community tier caps a self-hosted instance at one organisation, two projects, and a single user.

Frain Technologies also runs a managed Convoy Cloud (getconvoy.io) for teams that would rather not operate the Postgres, Redis, and worker infrastructure themselves, positioning Convoy as a self-hostable alternative to webhook-delivery SaaS platforms for teams that need to keep event data and delivery logs under their own control.

What You Get

  • A Go API server - A chi-routed REST API (api/api.go) exposing project, endpoint, source, subscription, and event-delivery management, documented via a generated OpenAPI/Swagger spec (docs/swagger.json).
  • An Asynq/Redis worker and scheduler - A separately scalable worker pool (worker/consumer.go, worker/task/) that processes deliveries, retries, and batch-retry jobs off a Redis-backed queue (hibiken/asynq).
  • An Angular management dashboard - A dedicated frontend (web/ui/dashboard) for managing projects, endpoints, subscriptions, sources, and inspecting delivery logs.
  • A Cobra-based CLI - A single binary (cmd/) with subcommands for running the server, worker/agent, database migrations, backups, feature flags, and retries.
  • Postgres persistence with pluggable ingest sources - SQL-migration-managed Postgres storage (sql/, sql-migrate) plus ingest sources for plain HTTP, Kafka, Amazon SQS, Google Pub/Sub, and RabbitMQ.
  • Built-in delivery resilience - Per-endpoint circuit breaking, an embedded JavaScript transformation runtime, and configurable rate limiting for production-grade delivery, alongside a broader set of features gated behind an Enterprise license key.

Common Use Cases

  • Webhooks-as-a-Service backend - SaaS platforms that need to offer reliable webhooks to their own customers self-host Convoy as the delivery engine instead of building retry, signing, and monitoring logic from scratch.
  • Internal event fan-out between microservices - Platform teams route internal domain events to multiple downstream services or third-party endpoints, each with its own retry and rate-limit policy.
  • Ingesting third-party webhooks at the edge - Convoy sits in front of internal systems to receive incoming webhooks from providers so those systems never need to be exposed to the public internet.
  • Bridging message queues into webhook deliveries - Teams already publishing events to Kafka, SQS, Google Pub/Sub, or RabbitMQ use Convoy’s sources to convert those messages into signed outbound webhook deliveries without writing a custom bridge service.
  • Customer-facing webhook debugging - Support and DevRel teams embed Convoy’s portal links in their own product dashboards so end customers can self-serve webhook delivery logs and retries.

Under The Hood

Architecture Convoy’s entry point is a single Cobra-based binary (cmd/main.go) that dispatches to subcommands — server, migrate, retry, backup, bootstrap, ff (feature flags), agent, and openapi — sharing one Postgres connection and configuration layer. The HTTP surface (api/api.go, roughly 1,200 lines) is a chi router mounting /ingest, /sso, and a versioned /api/v1 tree behind middleware chains that layer authentication, pagination, and project/organisation enablement gates enforcing per-tier limits. Business logic is pulled out of handlers into one-struct-per-use-case service objects under services/ (for example CreateEndpointService, BatchRetryEventDeliveryService), each constructed with injected repository interfaces and a shared Licenser interface, which keeps handlers thin and lets every service be unit-tested against generated mocks rather than a real database. Persistence sits behind repository interfaces implemented in database/postgres/ over pgx and sqlx, decoupling services from raw SQL. Delivery is asynchronous and decoupled from ingestion: events are enqueued onto Redis via an Asynq-backed queue, consumed by a dedicated worker process’s task handlers that own retries, circuit breaking, and delivery-attempt recording — separate from the API server so each can scale independently. Licensing and entitlement checks are centralized behind a single Licenser interface with distinct paid, community, and noop implementations, so a change to that contract would need updating in every gated service and handler in a contained, greppable way rather than drifting silently.

Tech Stack Convoy is written in Go 1.26 and exposes its HTTP API through chi v5 and go-chi/render, with request validation via go-ozzo/ozzo-validation. PostgreSQL is the system of record, accessed through pgx/v5 and sqlx with schema migrations managed by sql-migrate. Redis backs the Asynq task queue plus distributed caching and locking, and redis_rate implements per-endpoint rate limiting. Webhook payload transformation runs on an embedded Goja and goja_nodejs JavaScript runtime. Observability is extensive: OpenTelemetry, Sentry, Datadog’s APM tracing, and Prometheus’s client library are all wired in. Beyond plain HTTP ingestion, Convoy can pull events directly from Kafka, Amazon SQS, Google Pub/Sub, and RabbitMQ as alternative event sources, and can archive payloads to Minio, Azure Blob, or S3-compatible storage. Auth uses JWT with an optional HashiCorp Vault client for secret storage. The CLI is built on Cobra and pflag, OpenAPI docs are generated via swag and kin-openapi, and the management dashboard is a separate Angular application. Deployment targets Docker and Kubernetes via Helm charts referenced in the project README.

Code Quality Convoy carries an extensive test suite — roughly two in five of its Go files are test files — combining standard assertion libraries, generated interface mocks for fast unit tests, golden-file snapshot comparisons, HTTP stubbing, and real-service integration tests that spin up actual Postgres, Redis, Kafka, and Minio containers rather than relying purely on mocks. Error handling favors typed sentinel errors compared with errors.Is/errors.As over string matching, and non-obvious failure-mode decisions — such as the licensing module’s explicit fail-open-on-transient-error versus fail-closed-on-definitive-negative policy — are documented inline rather than left implicit. Services are built with explicit dependency injection, which is what makes the mock-based unit tests possible. Linting is enforced through an extensive golangci-lint configuration plus a project-specific style-conventions document, and CI runs static linting, CodeQL security scanning, container vulnerability scanning, nightly dependency vulnerability scans, and a matrix of separate integration and end-to-end test workflows per backend (Kafka, RabbitMQ, SQS, Google Pub/Sub, Redis Sentinel, plus a general end-to-end suite).

What Makes It Unique What sets Convoy apart from a plain retry-and-sign webhook library is that it treats webhook delivery as a gateway problem rather than an HTTP-only one: its source model lets an outbound webhook originate from an existing Kafka topic, SQS queue, Google Pub/Sub topic, or RabbitMQ exchange, so teams already publishing to a broker get webhook fan-out without writing a bridge service. Subscriptions can carry an embedded JavaScript function that arbitrarily reshapes or filters a payload before delivery, rather than offering only fixed field-mapping rules. Circuit breaking is a first-class, per-endpoint mechanism wired directly into the delivery worker that disables and later re-enables failing endpoints automatically, rather than just capping a retry counter. None of this is research-novel — comparable commercial webhook platforms cover similar ground — but bundling multi-broker ingestion, embedded transformation scripting, and automatic circuit breaking into one self-hostable Go binary is a deliberate, coherent design choice rather than a generic CRUD webhook table.

Self-Hosting

Licensing Model Convoy is source-available under the Elastic License 2.0 (not an OSI-approved open-source license). You may freely use, modify, and self-host it, but you may not offer it to third parties as a hosted or managed service, and you may not disable or circumvent any license-key-gated functionality.

Self-Hosting Restrictions

  • Without a license key, a self-hosted instance runs in “community” mode, hard-capped to 1 organisation, 2 projects, and a single user (no multi-user/team access) — enforced in the licensing module’s community licenser.
  • JavaScript payload transformations (the embedded Goja runtime) and per-endpoint circuit breaking both ship in the open-source code but are gated behind license checks and are disabled without a license key.
  • Instance-wide ingest/API rate limiting and worker consumer-pool size are pinned to Convoy’s defaults and cannot be tuned without a license.

Enterprise Features

  • Enterprise SSO and Google OAuth login
  • Advanced webhook filtering and advanced subscriptions
  • Advanced endpoint management
  • Webhook analytics dashboard
  • Webhook retention/archiving policies
  • Mutual TLS and custom certificate authorities for endpoint auth
  • Static IPs, IP allow/deny rules, and a forward proxy option
  • Read replica database support
  • Datadog tracing and Prometheus metrics export
  • Asynq queue monitoring UI and consumer-pool tuning
  • Portal links (embeddable customer-facing delivery dashboards)
  • Endpoint URL templates and OAuth2/basic-auth endpoint authentication

Cloud vs Self-Hosted Frain Technologies also runs a managed Convoy Cloud (getconvoy.io) that includes these entitlements out of the box, so teams that don’t want to run and renew a self-hosted license key can get the full feature set without operating Postgres, Redis, and the worker fleet themselves.

License Key Required Yes, for anything beyond the community floor. A self-hosted trial can run temporarily without one (degrading gracefully back to the community tier after a 21-day grace period once it expires), but sustained access to the features above requires a license key validated against Frain Technologies’ hosted license service.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers