go-core is a reusable Go backend foundation for production-minded services. It provides common runtime building blocks for configuration, lifecycle management, transport wrappers, logging, metrics, tracing, database access, messaging, migrations, resilience, and error handling.
The project is intentionally infrastructure-focused. It is not a service template, product domain, or toy demo. Consuming services own their business logic, persistence models, API contracts, deployment topology, and operational policy.
Module path:
github.com/yogayulanda/go-core
- Consistent service bootstrap and graceful shutdown.
- Environment-driven configuration with validation.
- gRPC and HTTP/gRPC-Gateway server wiring.
- Request IDs, recovery, auth metadata/JWT verification, and middleware/interceptor behavior.
- Structured logging with sensitive-field redaction.
- Prometheus metrics and OpenTelemetry tracing hooks.
- SQL database initialization, migrations, and transaction helpers.
- Kafka publishing/consuming and outbox helpers.
- Redis and Memcached cache initialization.
- Resilience helpers for timeout, retry, circuit breaker, and HTTP clients.
- Stable application error contracts for transport-safe responses.
go-core keeps infrastructure concerns separated by package:
app/owns application container setup, dependency initialization, and lifecycle hooks.config/loads and validates environment-based runtime configuration.server/grpc/provides gRPC server construction, interceptors, recovery, auth, and metrics.server/gateway/provides HTTP/gRPC-Gateway setup, envelopes, health/readiness/version/metrics endpoints, pprof, CORS, signature validation, and panic recovery.database/opens configured SQL databases through GORM.dbtx/provides explicit SQL transaction propagation helpers.migration/wraps Goose migration execution and optional startup auto-run.messaging/provides Kafka publisher/consumer abstractions.messaging/outbox/provides driver-aware SQL outbox helpers.logger/defines structured technical logging contracts and redaction.observability/contains tracing, metrics, request ID, and transaction ID helpers.errors/defines application error taxonomy and gRPC/HTTP mapping.cache/,httpclient/,resilience/,security/, andversion/cover supporting runtime concerns.
The intended service shape remains conventional Go:
- Transport handlers translate requests into service calls.
- Service/domain code owns business rules.
- Repository code owns persistence access.
go-coresupplies shared runtime, transport, observability, and infrastructure glue.
- Go 1.24+
- gRPC and grpc-gateway
- GORM with SQL Server support and DSN composition helpers for MySQL/PostgreSQL/SQL Server
- Goose migrations
- Kafka via
segmentio/kafka-go - Redis and Memcached clients
- Prometheus metrics
- OpenTelemetry tracing
- Zap logging
- JWT verification with static RSA public key or JWKS
- Resty-based resilient HTTP client
Requirements:
- Go 1.24 or newer
make- Optional:
golangci-lintfor linting - Optional:
k6for load-gate scripts
Clone and verify:
git clone https://github.com/yogayulanda/go-core.git
cd go-core
go mod download
make test
make vetInstall the linter used by the repository:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.8
make lintRun the standard local gate:
make checkRun the stronger release-oriented local gate:
make quality-gateConfiguration is loaded from environment variables. For local development, copy .env.example to .env and adjust values for your local dependencies.
Core variables:
SERVICE_NAMEAPP_ENVLOG_LEVELLOG_TIMEZONESHUTDOWN_TIMEOUTGRPC_PORTHTTP_PORTGRPC_TLS_ENABLED,GRPC_TLS_CERT_FILE,GRPC_TLS_KEY_FILEHTTP_TLS_ENABLED,HTTP_TLS_CERT_FILE,HTTP_TLS_KEY_FILE
Database variables:
DB_LISTDB_<NAME>_DRIVERDB_<NAME>_DSNDB_<NAME>_HOSTDB_<NAME>_PORTDB_<NAME>_NAMEDB_<NAME>_USERDB_<NAME>_PASSWORDDB_<NAME>_PARAMSDB_<NAME>_REQUIRED
Optional runtime dependencies:
- Redis:
REDIS_ENABLED,REDIS_ADDRESS,REDIS_PASSWORD,REDIS_DB - Memcached:
MEMCACHED_ENABLED,MEMCACHED_SERVERS,MEMCACHED_TIMEOUT - Kafka:
KAFKA_ENABLED,KAFKA_BROKERS,KAFKA_CLIENT_ID,KAFKA_USERNAME,KAFKA_PASSWORD - Migrations:
MIGRATION_AUTO_RUN,MIGRATION_DB,MIGRATION_DIR,MIGRATION_LOCK_ENABLED - Tracing:
OTEL_EXPORTER_OTLP_ENDPOINT,OTEL_EXPORTER_OTLP_INSECURE,OTEL_EXPORTER_OTLP_CA_CERT_FILE,TRACE_SAMPLING_RATIO - Auth:
INTERNAL_JWT_ENABLED,INTERNAL_JWT_PUBLIC_KEY,INTERNAL_JWT_JWKS_ENDPOINT,INTERNAL_JWT_ISSUER,INTERNAL_JWT_AUDIENCE - HTTP signatures:
AUTH_SIGNATURE_ENABLED,AUTH_SIGNATURE_MASTER_KEY
See docs/CONFIGURATION_PROFILES.md for grouped configuration guidance.
package main
import (
"context"
"log"
"os"
"os/signal"
"syscall"
coreapp "github.com/yogayulanda/go-core/app"
coreconfig "github.com/yogayulanda/go-core/config"
coremigration "github.com/yogayulanda/go-core/migration"
coreserver "github.com/yogayulanda/go-core/server"
coregateway "github.com/yogayulanda/go-core/server/gateway"
coregrpc "github.com/yogayulanda/go-core/server/grpc"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/grpc"
)
func main() {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
cfg, err := coreconfig.Load(coreconfig.WithDotEnv(".env"))
if err != nil {
log.Fatal(err)
}
if err := cfg.Validate(); err != nil {
log.Fatal(err)
}
if err := coremigration.AutoRunUp(cfg); err != nil {
log.Fatal(err)
}
application, err := coreapp.New(ctx, cfg)
if err != nil {
log.Fatal(err)
}
grpcServer, err := coregrpc.New(application)
if err != nil {
log.Fatal(err)
}
grpcServer.Register(func(s *grpc.Server) {
// Register service implementations here.
})
gatewayServer, err := coregateway.New(application, func(ctx context.Context, mux *runtime.ServeMux) error {
// Register grpc-gateway handlers here.
return nil
})
if err != nil {
log.Fatal(err)
}
if err := coreserver.Run(ctx, application, grpcServer, gatewayServer); err != nil {
log.Fatal(err)
}
}External responses should be predictable and safe. Internal details belong in logs and traces, not client payloads.
- Use
errors.AppErrorand the builder APIs for application-visible failures. - Keep validation details explicit and structured.
- Sanitize unknown/internal transport errors to stable public messages.
- Preserve richer technical context through structured logs and observability signals.
The repository provides additive observability primitives rather than a mandatory platform:
- structured service, DB, event, and transaction-oriented logs
- sensitive key redaction for common secret fields
- Prometheus metrics for HTTP, gRPC, service operations, DB operations, messaging, outbox, and transaction-oriented flows
- OpenTelemetry tracing bootstrap and transport wrappers
- health, readiness, metrics, version, and optional pprof endpoints
app/ Application container and lifecycle
cache/ Redis and Memcached helpers
config/ Environment configuration loading and validation
database/ SQL database initialization
dbtx/ SQL transaction propagation helpers
docs/ Architecture, operations, reliability, and release docs
errors/ Application error contract and transport mapping
examples/ Focused integration examples
httpclient/ Resilient outbound HTTP client
logger/ Structured logging contracts and redaction
messaging/ Kafka abstractions and outbox support
migration/ Goose migration helpers
observability/ Metrics, tracing, request ID, transaction ID
resilience/ Timeout, retry, and circuit breaker helpers
scripts/ Quality, smoke, load, and failure-drill scripts
security/ Auth metadata and JWT verification helpers
server/ gRPC, gateway, and startup orchestration
templates/ Reference package templates
version/ Build/version metadata
- Prefer pragmatic, idiomatic Go over framework-heavy abstractions.
- Keep repository behavior as the source of truth; docs should describe actual implementation.
- Make boundaries explicit between transport, service/domain logic, repositories, and infrastructure.
- Keep operational behavior readable in code, logs, metrics, and release evidence.
- Add abstractions only when they remove real duplication or clarify ownership.
- Treat validation honestly: fail fast for required runtime dependencies and surface actionable configuration errors.
- Avoid hidden magic, speculative rewrites, and product-specific business logic in the foundation.
Useful starting points:
docs/ARCHITECTURE.mddocs/SERVICE_BOOTSTRAP.mddocs/CONFIGURATION_PROFILES.mddocs/ERROR_HANDLING.mddocs/OBSERVABILITY.mddocs/MESSAGING_PATTERN.mddocs/RELIABILITY.mddocs/SECURITY.mddocs/VERSIONING.mdMIGRATION.md
Architecture diagram placeholder:
Client -> Gateway/gRPC -> Handler -> Service -> Repository -> Database
| | |
| | +-> Outbox/Kafka
| +-> Logger/Metrics/Tracing
+-> Middleware/Interceptors/Auth/Recovery
CI should remain the fast baseline:
make test
make vet
make lintRelease candidates should use the stronger local/release checks where applicable:
make quality-gate
BASE_URL=https://staging.example.com make smoke-gate
BASE_URL=https://staging.example.com TARGET_PATH=/health make load-steadyUse docs/PRODUCTION_SIGNOFF.md and docs/RELEASE_EVIDENCE_TEMPLATE.md when preparing a production service release that consumes this module.
Set build metadata with -ldflags when building a service that exposes /version:
go build -ldflags "\
-X 'github.com/yogayulanda/go-core/version.Version=1.0.0' \
-X 'github.com/yogayulanda/go-core/version.Commit=$(git rev-parse HEAD)' \
-X 'github.com/yogayulanda/go-core/version.BuildDate=$(date -u +%Y-%m-%dT%H:%M:%SZ)'"- Keep compatibility and migration guidance clear for public releases.
- Continue tightening docs around service bootstrap and operational behavior.
- Expand examples only when they reflect real implementation patterns.
- Avoid adding product-specific assumptions to the foundation.
See CONTRIBUTING.md.
See SECURITY.md for responsible disclosure guidance.
Apache License 2.0. See LICENSE.