svckit

module
v0.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2026 License: Apache-2.0

README

svckit

Go Reference License

A Go microservice toolkit built on standard-library contracts.

svckit is the set of building blocks a service needs before it does anything useful: configuration, logging, resilient connections to Postgres, Redis and RabbitMQ, a signed event bus, HTTP middleware, health checks, secrets and graceful shutdown. It grew out of a 17-service platform and was extracted once the pieces had stopped changing shape.

Design

Standard-library contracts, frameworks as adapters. Everything here is written against net/http, database/sql, log/slog and context.Context — never against a web framework or an ORM. Middleware is func(http.Handler) http.Handler. The database layer hands back *sql.DB. Logging ships slog.Handler implementations rather than a logger type.

The practical consequence: the core module depends on no web framework and no ORM. Chi and the Go 1.22+ http.ServeMux consume the middleware natively — chi.Use takes exactly func(http.Handler) http.Handler. Gin needs translation, so it gets its own module. GORM or Ent bind to the *sql.DB in about ten lines.

Adapters are separate modules, so importing svckit never pulls in a framework you did not choose, and a project pinned to a different framework version is unaffected by what an adapter requires.

Where the abstraction stops. Some things are not worth hiding: go-redis, Prometheus and RabbitMQ appear as themselves. Small interfaces at the edges (Publisher, Subscriber, Store, IdentityProvider) keep alternatives possible without pre-building them.

Install

go get github.com/dobrevit/svckit

Optional modules — take only what you use:

go get github.com/dobrevit/svckit/testkit  # test harness (Docker, testcontainers)
go get github.com/dobrevit/svckit/chix     # chi router adapter
go get github.com/dobrevit/svckit/ginx     # Gin framework adapter
Using it from chi

Nothing to adapt — chi consumes the middleware directly:

r := chi.NewRouter()
r.Use(chix.Route())                        // label metrics by route template
r.Use(middleware.Tracing())
r.Use(middleware.Metrics("orders"))
r.Use(middleware.RequestLogging("orders"))

chix.Route() is the only piece that needs a shim: chi knows the matched pattern only after routing, and without it every path parameter becomes its own Prometheus label value.

Using it from Gin

Gin has its own handler type, context and response writer, so each middleware needs translating — that is what ginx is:

router := gin.New()
router.Use(ginx.Route())
router.Use(ginx.TracingMiddleware())
router.Use(ginx.PrometheusMiddleware("orders"))
router.Use(ginx.LoggingMiddleware())

ginx.Use adapts any func(http.Handler) http.Handler into a gin.HandlerFunc, covering anything it does not wrap explicitly.

Packages

Package What it does
app Service runtime: wires config, database, messaging, health and shutdown; decorates your http.Handler and serves it
amqpcluster RabbitMQ publisher and subscriber with multi-node failover
audit Audit-event emitter over the event bus
auth JWT issue and validate, net/http authentication middleware, identity on the request context
buildinfo Version metadata injected at build time via ldflags
debug pprof endpoints behind an environment gate
env Typed environment-variable readers with defaults
eventbus Signed publish/subscribe, broadcast, dead-letter handling and a handler dispatcher
health Health and readiness reporting over *sql.DB and the event bus
httpclient HTTP client with circuit breaker, retries, tracing and metrics
httpx Response envelopes, bounded JSON decoding, clamped pagination
lifecycle Goroutine and server lifecycle management with graceful shutdown
logging log/slog handlers: human-readable lines or JSON, configured from the environment
middleware CORS, tracing, rate limiting, request logging, Prometheus metrics, service-key auth
pgcluster Postgres cluster with writer detection, read balancing, health checks and a circuit breaker
rediscluster Redis cluster client with health checking and load balancing
secrets Secret resolution over environment variables, Vault or Kubernetes Secrets
testkit Test harness: suites, mocks, assertions and container fixtures (separate module)
chix chi router adapter — route-template labelling (separate module)
ginx Gin adapter — middleware, response helpers, pagination (separate module)

Quick start

package main

import (
	"log"
	"net/http"

	"github.com/dobrevit/svckit/app"
)

func main() {
	a, err := app.New("orders",
		app.WithDatabase(),
		app.WithOptionalEventPublisher(),
	)
	if err != nil {
		log.Fatalf("bootstrap failed: %v", err)
	}
	defer a.Close()

	mux := http.NewServeMux()
	mux.HandleFunc("GET /orders/{id}", handleGetOrder)

	// Handler adds tracing, metrics and request logging, and serves
	// /health, /ready, /metrics and the profiling endpoints in front of
	// your routes.
	a.Run(a.Handler(mux))
}

Migrations stay yours: app.WithMigration(func(db *sql.DB) error { ... }) takes goose, Atlas or anything else that accepts a *sql.DB.

Testing

The unit tier needs nothing running:

go test -race -short ./...

The integration tier needs Postgres, Redis and RabbitMQ, and is gated behind a build tag so a plain go test ./... never reaches it:

docker compose up -d
go test -race -tags integration ./...

compose.yaml in this repository starts the three services on the ports the tests expect. Override any of them with REDIS_TEST_URL, POSTGRES_TEST_URL or RABBITMQ_TEST_URL.

Status

v0.x — the API may still move. The packages are in production use, but the names and shapes are not yet frozen; that happens at v1.0.0. Changes are recorded in CHANGELOG.md.

Contributing

See CONTRIBUTING.md for the workflow and the design stance that shapes review feedback. Contributions require a signed CLA; the bot prompts you on your first pull request.

Security

Please report vulnerabilities privately rather than through an issue — SECURITY.md has the process and what to expect.

License

Apache License 2.0 — see LICENSE.

Directories

Path Synopsis
Package amqpcluster connects to a RabbitMQ cluster rather than a single broker: publishers and subscribers hold connections to every configured node, fail over when one goes away, and reconnect in the background.
Package amqpcluster connects to a RabbitMQ cluster rather than a single broker: publishers and subscribers hold connections to every configured node, fail over when one goes away, and reconnect in the background.
Package appkit is the service runtime: one constructor that wires the infrastructure a service would otherwise hand-roll in main() — logging, database cluster, event publisher/subscriber, audit client, event signing, health checks, the standard middleware stack and graceful shutdown.
Package appkit is the service runtime: one constructor that wires the infrastructure a service would otherwise hand-roll in main() — logging, database cluster, event publisher/subscriber, audit client, event signing, health checks, the standard middleware stack and graceful shutdown.
Package audit emits audit events onto the event bus.
Package audit emits audit events onto the event bus.
Package auth authenticates HTTP requests and carries the caller's identity on the request context.
Package auth authenticates HTTP requests and carries the caller's identity on the request context.
Package buildinfo carries the version metadata a binary was built with.
Package buildinfo carries the version metadata a binary was built with.
chix module
Package debug gates Go's runtime profiling endpoints behind an environment switch, so profiling is available while investigating a service and absent in normal operation.
Package debug gates Go's runtime profiling endpoints behind an environment switch, so profiling is available while investigating a service and absent in normal operation.
Package env provides typed helpers for reading configuration from environment variables with defaults.
Package env provides typed helpers for reading configuration from environment variables with defaults.
Package eventbus is the generic RabbitMQ event system: the BaseEvent envelope, topic publisher/subscriber with signing, fanout broadcast, per-type dispatch with real outcome metrics, and DLQ support.
Package eventbus is the generic RabbitMQ event system: the BaseEvent envelope, topic publisher/subscriber with signing, fanout broadcast, per-type dispatch with real outcome metrics, and DLQ support.
ginx module
Package health reports whether a service and its dependencies are working.
Package health reports whether a service and its dependencies are working.
Package httpclient is an HTTP client for calling other services.
Package httpclient is an HTTP client for calling other services.
Package httpx provides small, framework-neutral helpers for JSON HTTP handlers: a standard error envelope, safe error responses that never echo internal error strings to clients, bounded JSON decoding, and clamped pagination parsing.
Package httpx provides small, framework-neutral helpers for JSON HTTP handlers: a standard error envelope, safe error responses that never echo internal error strings to clients, bounded JSON decoding, and clamped pagination parsing.
Package lifecycle manages the goroutines and servers a process owns, so shutdown is orderly rather than abrupt.
Package lifecycle manages the goroutines and servers a process owns, so shutdown is orderly rather than abrupt.
Package logging provides log/slog handlers with an established human-readable line format:
Package logging provides log/slog handlers with an established human-readable line format:
Package middleware provides HTTP middleware as func(http.Handler) http.Handler, the form the standard library and every stdlib-compatible router understand.
Package middleware provides HTTP middleware as func(http.Handler) http.Handler, the form the standard library and every stdlib-compatible router understand.
Package pgcluster connects to a PostgreSQL cluster over database/sql.
Package pgcluster connects to a PostgreSQL cluster over database/sql.
Package rediscluster connects to a set of Redis nodes with health checking and load balancing across the healthy ones.
Package rediscluster connects to a set of Redis nodes with health checking and load balancing across the healthy ones.
Package secrets resolves secrets by logical path, independently of where they are stored.
Package secrets resolves secrets by logical path, independently of where they are stored.
testkit module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL