A Go library providing infrastructure abstractions for cloud-native services. Each package defines a stable interface with one or more provider implementations, selected at runtime via config. Layers that touch the network — HTTP, gRPC, database, messaging — instrument with OpenTelemetry.
Module: github.com/primandproper/platform-go/v9
Go: 1.26
mainis not a release channel. Anything onmainthat has not been cut into a tagged release is considered under active development — alpha/beta, unstable, and unsupported. Treat it as such.
This repository follows a deliberately conservative release model:
- Only tagged releases are supported. If it isn't behind a version tag, it can change or break without notice, and no support or compatibility is promised for it.
-
mainmoves ahead of the latest release. New work — including breaking changes — lands onmainwell before it is deemed release-worthy. The current major module path is/v9, and the latest supported release isv8.0.0./v9is unreleased: everything onmainis subject to change until it is tagged. -
Semantic Versioning, enforced by Go's module paths. Breaking changes increment the major version and the module import path (
/v8→/v9), so a major bump can never silently break a consumer that hasn't opted in. -
No stability guarantees on unreleased APIs. Interfaces, config shapes, and package boundaries on
mainare subject to change until they ship in a release.
If you depend on this library, pin to a released tag. If you want to track upcoming work, main is fair game — just don't expect it to hold still.
go get github.com/primandproper/platform-go/v9@latestBecause breaking changes ride the major-version import path, upgrading across majors is an explicit, opt-in edit to your import paths — never a surprise from go get -u.
Interface + implementations. Every major concern is defined as an interface (e.g., cache.Cache[T], logging.Logger, secrets.SecretSource), with provider implementations in subpackages. Swap implementations via config without touching call sites. Most packages ship a noop implementation for tests and for cleanly disabling a concern.
Config structs. Each package has a config subpackage with env:-tagged structs and ValidateWithContext() (via go-ozzo/ozzo-validation). Configuration is the seam that selects an implementation. Most, but not all, also have EnsureDefaults() — packages whose defaults are expressible as envDefault: tags use those instead.
Selecting an implementation is deliberate: an unrecognized provider name returns errors.ErrUnknownProvider rather than a working-looking noop, because a typo that silently discards every message or never limits a request is a production incident that looks like a healthy process. Where a noop is genuinely wanted it has to be asked for by name.
OpenTelemetry throughout. HTTP, gRPC, database, and messaging layers emit traces and metrics. Observability primitives (logging, tracing, metrics, profiling) live under observability/.
Error handling. Uses cockroachdb/errors for rich, wrapped error context. Platform-level sentinel errors live in errors/, conventionally imported as platformerrors. Transport mappings live in errors/http and errors/grpc, which import the packages whose sentinels they map — so nothing in those packages may import them back.
Implementations are listed in parentheses; most concerns also provide a noop.
| Package | Purpose | Implementations |
|---|---|---|
database |
SQL access + instrumentation | postgres, mysql, sqlite |
cache |
Generic key/value cache (Cache[T]) |
redis, memory |
uploads |
Blob/object storage & image handling | objectstorage (S3-compatible), images |
files |
Filesystem & streaming helpers | — |
secrets |
Secret sourcing | env, gcp, ssm, kubernetes |
| Package | Purpose | Implementations |
|---|---|---|
messagequeue |
Publish/subscribe & queues | kafka, pubsub, redis, sqs |
outbox |
Transactional outbox | postgres, mysql, sqlite |
eventstream |
Server push to clients | sse, websocket |
notifications |
User notifications | async, mobile |
jobs |
Queue workers & periodic jobs | — |
email |
Transactional email | mailgun, mailjet, postmark, resend, sendgrid, ses |
| Package | Purpose | Implementations |
|---|---|---|
server |
Service servers | grpc, http |
routing |
HTTP router abstraction | chi, stdlib, httprouter, gin |
httpclient |
Instrumented HTTP client | — |
cookies |
Cookie management | — |
encoding |
Content encoding/decoding | — |
compression |
Payload compression | — |
ratelimiting |
Request rate limiting | redis |
circuitbreaking |
Circuit breaker | — |
retry |
Retry with backoff | — |
idempotency |
At-most-once effect for retried requests | http, grpc (server + client) |
| Package | Purpose | Implementations |
|---|---|---|
observability |
Logging, tracing, metrics, profiling | logging (slog, zap, zerolog); OTel tracing/metrics |
healthcheck |
Health/readiness checks | — |
version |
Build/version metadata | — |
metering |
Durable usage metering & quotas | postgres, mysql, sqlite |
webhooks |
Outbound webhook delivery | postgres, mysql, sqlite |
clock |
Injectable time | — |
config |
Config loading & env parsing | — |
| Package | Purpose | Implementations |
|---|---|---|
authentication |
Password hashing, TOTP, tokens | argon2, totp, tokens |
authorization |
Role/permission policy, enforcement | static (default), database |
audit |
Tamper-evident audit log | postgres, mysql, sqlite |
cryptography |
Cryptographic primitives | — |
random |
Secure randomness | — |
identifiers |
ID generation | — |
dataprivacy |
Subject access & erasure requests | postgres, mysql, sqlite |
| Package | Purpose | Implementations |
|---|---|---|
llm |
Large language model clients | anthropic, openai |
embeddings |
Embedding generation | — |
search |
Vector / text search | vector, text |
analytics |
Product analytics | posthog, segment, multisource |
featureflags |
Feature flagging | launchdarkly, posthog |
| Package | Purpose | Implementations |
|---|---|---|
capitalism |
Payments | stripe |
saga |
Linear durable sagas with compensations | postgres, mysql, sqlite |
distributedlock |
Distributed locking | memory, postgres, redis |
filtering |
Query filters / pagination | — |
qrcodes |
QR code generation | — |
artifacts |
Artifact handling | — |
eventcapture |
Recording domain events | — |
errors, pointer, numbers, bitmask, reflection, panicking, testutils, fake.
make setup # Install dev tools and vendor deps
make format # Format all Go code (imports, field/tag alignment, gofmt)
make lint # Run golangci-lint (Docker) + shellcheck
make test # Run tests (race detector, shuffle, failfast)
make build # Build all packages
make generate # Regenerate moq mocks after changing a mocked interface
make bench # Run benchmarks
make revendor # Clean and re-vendor dependenciesFormatting runs locally with gci, goimports, betteralign, tagalign, and gofmt. Linting runs in Docker against the golangci/golangci-lint image (42+ linters, golangci-lint v2 format).
-
stretchr/testifyis banned (assert,require, andmock), enforced bydepguard. Useshoenig/testfor assertions (testfor non-fatal,mustfor fatal) andmatryer/moqfor mocks. - Tests run in parallel by default and use subtests throughout.
- Container-backed tests use
testcontainers-go, live in-package (typicallycontainers_test.go), and gate onRUN_CONTAINER_TESTS=true. -
make testrunsCGO_ENABLED=1 go test -shuffle=on -race -vet=all -failfast ./...across every package..scripts/test.sh falseruns the suite without container tests.
Because main is a development channel and only tagged releases are supported, changes land on main freely and are stabilized before release. Follow the existing package layout (interface + config subpackage + provider implementations + noop), match the surrounding code, and keep make format lint test green.