nurago is a collection of independent Go packages for building backend services: retries and exponential backoff, HTTP client and server, OpenTelemetry and Prometheus instrumentation, structured logging and log redaction, Argon2id password hashing, JWT, Redis, Valkey, Kafka, AWS S3 and SQS, SQL connection and transaction handling, caching, validation, and configuration loading.
Each package is imported on its own and pulls only the dependencies it reaches, so adopting one does not commit you to the rest. Most reach none at all.
Previously named gogen: same library, same packages, new name. The old
github.com/tecnickcom/gogenmodule path is deprecated and no longer resolves fromv1.146.0onwards. See /docs/migration-from-gogen/ for the migration.
Why “nurago”? From nuraghe + Go: the Bronze Age Sardinian stone towers, built without mortar, around 7,000 of which still stand after 3,500 years.
Table of contents
Start Here
- Install:
go get github.com/tecnickcom/nurago
- GitHub: https://github.com/tecnickcom/nurago
- API reference: https://pkg.go.dev/github.com/tecnickcom/nurago
- Package catalog: /packages/
- Guides: /docs/
- For AI coding assistants: /docs/ai-assistants/ and /llms.txt
- Licence: MIT, for the whole module
Import the packages you need, individually:
import (
"github.com/tecnickcom/nurago/pkg/backoff"
"github.com/tecnickcom/nurago/pkg/redact"
)
Why nurago
There is no runtime to adopt and no application skeleton to inherit from. Your handlers implement no interface of ours. Each package works on its own, next to whatever the service already uses.
Importing pkg/backoff adds no AWS SDK, Kafka, Redis, or OpenTelemetry code to your build, even though other packages in this module require them. Go resolves dependencies per package, so what you pay for is what your imports reach. 40 of the 70 packages reach no external module at all. See /docs/dependency-footprint/.
The module is at v1 and the exported API of every pkg/ package is stable: no breaking change is made to an exported symbol within v1. Releases are frequent, because dependency updates and additive changes ship as soon as they are ready. A high patch number reflects that cadence, and says nothing about API churn.
Packages that take configuration share one shape: a New constructor with a variadic opts ...Option parameter and WithXxx option functions.
Still evaluating? /comparison/ covers where nurago sits next to a framework, a hand-rolled internal library, and the standard library alone, including the cases where one of those is the better fit.
What It Covers
The full catalog is at /packages/; the capability index, area by area, is at /features/.
- Service bootstrap and lifecycle: context, logging, metrics, signal handling, and bounded graceful shutdown in one call, plus the HTTP server, health endpoint, and pprof mounting. See /docs/getting-started/.
- Observability:
log/slogwith syslog-range severities and a zerolog backend, a backend-agnostic metrics contract with OpenTelemetry, Prometheus, and StatsD implementations, request-scoped trace IDs, and secret redaction. See /docs/observability/. - Resilience: retries with jittered exponential backoff, an HTTP retrier that honours
Retry-Afterand replays request bodies, periodic scheduling, and a caching DNS dialer. See /docs/resilience/. - Security: Argon2id password hashing (RFC 9106) with an optional pepper layer, Have I Been Pwned k-anonymity checks, HMAC-only JWT, and AES-GCM encryption. See /docs/security/.
- Data and messaging: SQL connection lifecycle and transaction control flow, MySQL distributed locking, Redis, Valkey, Kafka, S3, and SQS clients that all expose the same health-check method. See /docs/data-and-messaging/.
- Utilities: generic map and slice operations, fixed-point decimals, JSON-friendly time types, prefix tries, pagination, declarative filtering, string metrics, random identifiers, and validation.
Quick Start
A minimal service that wires the lifecycle and serves two operational routes. Bootstrap creates the context, logger, and metrics client, calls your bind function, then blocks until SIGINT or SIGTERM and waits for registered workers to finish within the shutdown budget.
package main
import (
"context"
"log"
"log/slog"
"net/http"
"sync"
"time"
"github.com/tecnickcom/nurago/pkg/bootstrap"
"github.com/tecnickcom/nurago/pkg/httpserver"
"github.com/tecnickcom/nurago/pkg/logutil"
"github.com/tecnickcom/nurago/pkg/metrics"
)
// binder supplies your own routes. The operational routes are separate.
type binder struct{}
func (b *binder) BindHTTP(_ context.Context) []httpserver.Route {
return []httpserver.Route{
{
Method: http.MethodGet,
Path: "/hello",
Description: "Says hello.",
Handler: func(w http.ResponseWriter, _ *http.Request) {
_, _ = w.Write([]byte("hello"))
},
},
}
}
func main() {
shutdownWG := &sync.WaitGroup{}
shutdownCh := make(chan struct{})
bind := func(ctx context.Context, l *slog.Logger, m metrics.Client) error {
srv, err := httpserver.New(
ctx,
&binder{},
httpserver.WithServerAddr(":8080"),
httpserver.WithEnableDefaultRoutes(httpserver.PingRoute, httpserver.StatusRoute),
httpserver.WithRequestTimeout(30*time.Second),
httpserver.WithShutdownTimeout(10*time.Second),
httpserver.WithShutdownSignalChan(shutdownCh),
httpserver.WithShutdownWaitGroup(shutdownWG),
httpserver.WithLogger(l),
)
if err != nil {
return err
}
srv.StartServer()
return nil
}
err := bootstrap.Bootstrap(
bind,
bootstrap.WithLogConfig(logutil.DefaultConfig()),
bootstrap.WithShutdownTimeout(30*time.Second),
bootstrap.WithShutdownWaitGroup(shutdownWG),
bootstrap.WithShutdownSignalChan(shutdownCh),
)
if err != nil {
log.Fatal(err)
}
}
Every package page carries a runnable example of its own, and more are on pkg.go.dev. The full walkthrough is at /docs/getting-started/.
Scaffolding a New Service
The repository also generates a complete web service from a configuration file, so a new project starts with the lifecycle, configuration, routing, health endpoint, Docker build, and API tests already wired:
git clone https://github.com/tecnickcom/nurago.git
cd nurago
cp project.cfg myproject.cfg # edit the name, owner, and paths
make project CONFIG=myproject.cfg
The generated project is written under target/. See /docs/service-scaffolding/.
Requirements
- Go 1.26.0 or later (the minimum declared in
go.mod; any newer release works) - No CGO. The Kafka client is pure Go and needs no system
librdkafkainstallation.
Some packages need the dependency they wrap to be reachable at runtime (a MySQL server for mysqllock, a Redis or Valkey server, a Kafka broker, AWS credentials for the S3 and SQS clients, the Have I Been Pwned API for passwordpwned). Each package page states what it needs.
Using nurago with AI Coding Assistants
Language models read this documentation too, on someone’s behalf. The project publishes machine-readable indexes for them:
- /llms.txt: the condensed index of the site and of all 70 packages, in the llms.txt format.
- llms.txt in the repository: the same index pointing at the reference documentation.
- Context7: the repository is indexed for MCP-based documentation retrieval, so an assistant can pull current nurago documentation into its context instead of recalling it.
/docs/ai-assistants/ has the prompt snippets, the rules that keep generated code idiomatic for this library, and the pitfalls worth pinning (the deprecated gogen import path in particular).
Feedback and Contributions
Bug reports and feature requests are welcome as GitHub issues. Code contributions are limited to project collaborators: please open an issue to discuss a change rather than sending an unsolicited pull request. CONTRIBUTING.md and CODE_OF_CONDUCT.md have the details.
Security vulnerabilities should be reported according to SECURITY.md, not through a public issue.
If this project is useful to you, please consider supporting development via GitHub Sponsors. The Sponsor page has the tiers and how logo placement works.