Production-ready Pub/Sub library and standalone service for Go
Works both as a library for embedding in your application AND as a standalone microservice with REST API.
- Reliable Message Delivery β Guaranteed delivery with exponential backoff retry
- Exponential Backoff β 30s β 1m β 2m β 4m β 8m β 16m β 30m (max)
- Dead Letter Queue (DLQ) β Automatic handling of failed messages after 5 attempts
- DLQ Statistics β Track failure reasons and resolution metrics
- Domain-Driven Design β Rich domain models with business logic
- Repository Pattern β Clean data access abstraction
- Pluggable β Bring your own Logger, Notification system, Delivery gateway
- Options Pattern β Modern Go API (2026 best practices)
- Clean Architecture β Services, Repositories, Models separation
- Battle-Tested β Production-proven in FreiCON Railway Management System
- MySQL β Full support with Relica adapters
- PostgreSQL β Full support with Relica adapters
- SQLite β Full support with Relica adapters
- Type-Safe Queries β Relica v0.14 expression API (no raw SQL)
- As Library β Embed in your Go application
- As Service β Standalone PubSub server with REST API (Fursy framework)
- Docker Ready β Production Dockerfile + docker-compose
- Cloud Native β 12-factor app, ENV config, health checks
go get github.com/coregx/pubsub@latest# Using Docker (recommended)
cd cmd/pubsub-server
docker-compose up -d
# Or build from source
go build ./cmd/pubsub-servercd cmd/pubsub-server
docker-compose up -dAccess API at http://localhost:8080
package main
import (
"context"
"database/sql"
"time"
"github.com/coregx/pubsub"
"github.com/coregx/pubsub/adapters/relica"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, _ := sql.Open("mysql", "user:pass@tcp(localhost:3306)/pubsub?parseTime=true")
repos := relica.NewRepositories(db, "mysql")
publisher, _ := pubsub.NewPublisher(
pubsub.WithPublisherRepositories(
repos.Message, repos.Queue, repos.Subscription, repos.Topic,
),
pubsub.WithPublisherLogger(logger),
)
result, _ := publisher.Publish(context.Background(), pubsub.PublishRequest{
TopicCode: "user.signup",
Identifier: "user-123",
Data: `{"userId": 123, "email": "user@example.com"}`,
})
worker, _ := pubsub.NewQueueWorker(
pubsub.WithRepositories(repos.Queue, repos.Message, repos.Subscription, repos.DLQ),
pubsub.WithDelivery(transmitterProvider, gateway),
pubsub.WithLogger(logger),
)
worker.Run(context.Background(), 30*time.Second)
}βββββββββββββββββββββββββββββββββββββββ
β Your Application β
β (or Fursy REST API for standalone) β
βββββββββββββββ¬ββββββββββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββββββββββ
β Services Layer β
β - Publisher β
β - SubscriptionManager β
β - QueueWorker β
βββββββββββββββ¬ββββββββββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββββββββββ
β Relica v0.14 Adapters β
β Type-safe expression API β
β MySQL / PostgreSQL / SQLite β
βββββββββββββββ¬ββββββββββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββββββββββ
β Database β
βββββββββββββββββββββββββββββββββββββββ
The standalone server uses Fursy framework with type-safe generic handlers and RFC 9457 Problem Details for error responses.
POST /api/v1/publish
Content-Type: application/json
{
"topicCode": "user.signup",
"identifier": "optional-dedup-key",
"data": {
"userId": 123,
"email": "user@example.com"
}
}POST /api/v1/subscribe
{
"subscriberID": 1,
"topicCode": "user.signup",
"identifier": "webhook-receiver-1"
}GET /api/v1/subscriptions?subscriberID=1DELETE /api/v1/subscriptions/123GET /api/v1/healthworker, err := pubsub.NewQueueWorker(
pubsub.WithRepositories(queueRepo, msgRepo, subRepo, dlqRepo),
pubsub.WithDelivery(transmitterProvider, gateway),
pubsub.WithLogger(logger),
pubsub.WithBatchSize(100),
pubsub.WithRetryStrategy(customStrategy),
pubsub.WithNotifications(notifService),
)SERVER_HOST=0.0.0.0
SERVER_PORT=8080
DB_DRIVER=mysql # mysql, postgres, sqlite3
DB_HOST=localhost
DB_PORT=3306
DB_USER=pubsub
DB_PASSWORD=your_password
DB_NAME=pubsub
DB_PREFIX=pubsub_
PUBSUB_BATCH_SIZE=100
PUBSUB_WORKER_INTERVAL=30
PUBSUB_ENABLE_NOTIFICATIONS=true1. PUBLISH
Publisher β Topic β Create Message
β Find Active Subscriptions
β Create Queue Items (one per subscription)
2. WORKER (Background)
QueueWorker β Find Pending/Retryable Items (batch)
β Deliver to Subscribers (via webhooks/gateway)
β On Success: Mark as SENT
β On Failure: Retry with exponential backoff
β After 5 failures: Move to DLQ
3. DLQ (Dead Letter Queue)
Failed items β Manual review
β Resolve or Delete
Attempt 1: Immediate
Attempt 2: +30 seconds
Attempt 3: +1 minute
Attempt 4: +2 minutes
Attempt 5: +4 minutes
Attempt 6: +8 minutes (moves to DLQ after this)
# Run unit tests
go test ./model/... ./retry/... . ./cmd/pubsub-server/internal/config/...
# Run with coverage
go test -cover ./model/... ./retry/... . ./cmd/pubsub-server/internal/api/...
# Integration tests (requires CGO for SQLite)
CGO_ENABLED=1 go test ./adapters/relica/...
# All tests
go test ./...| Package | Coverage |
|---|---|
model/ |
95.9% |
retry/ |
100% |
pubsub (root) |
82.4% |
config/ |
100% |
api/ (handlers) |
94.4% |
adapters/relica/ |
CI only (SQLite CGO) |
# Build image
docker build -t pubsub-server:0.2.0 -f cmd/pubsub-server/Dockerfile .
# Run with environment
docker run -d \
-p 8080:8080 \
-e DB_DRIVER=mysql \
-e DB_HOST=mysql \
-e DB_PASSWORD=secret \
pubsub-server:0.2.0- Core PubSub functionality
- Relica adapters (MySQL/PostgreSQL/SQLite)
- Publisher + SubscriptionManager services
- Standalone REST API server
- Docker support
- Relica v0.14 type-safe expression API
- Fursy v0.4 HTTP framework with generic handlers
- RFC 9457 Problem Details for error responses
- Comprehensive test suite (82-100% coverage)
- CI with MySQL/PostgreSQL service containers
- OIDC Codecov integration
- Delivery providers (HTTP webhooks, gRPC)
- Message encryption
- Rate limiting
- Prometheus metrics
- API stability guarantee
- Long-term support (3+ years)
- OpenAPI/Swagger docs
- Authentication/Authorization
Contributions welcome!
- Fork the repository
- Create feature branch (
git checkout -b feature/amazing) - Commit changes (
git commit -m 'feat: add amazing feature') - Push to branch (
git push origin feature/amazing) - Open Pull Request
See CONTRIBUTING.md for full guidelines.
MIT License β see LICENSE file for details.
- Relica v0.14 β Type-safe database query builder
- Fursy v0.4 β HTTP framework (standalone server only)
- ozzo-validation β Request validation
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Production-ready and battle-tested in FreiCON Railway Management System. Part of the CoreGX ecosystem.