GoBricks
Modern building blocks for Go microservices. GoBricks brings together configuration, HTTP, messaging, database, logging and observability primitives that teams need to ship production-grade services fast.

Table of Contents
- Why GoBricks?
- Feature Overview
- Quick Start
- Configuration
- Modules and Application Structure
- HTTP Server
- Messaging
- Database
- Observability and Operations
- Examples
- Contributing
- License
Why GoBricks?
- Production-ready defaults for the boring-but-essential pieces (server, logging, configuration, tracing).
- Composable module system that keeps HTTP, database, and messaging concerns organized.
- Mission-critical integrations (PostgreSQL, Oracle, RabbitMQ, Flyway) with unified ergonomics.
- Modern Go practices with type safety, performance optimizations, and Go 1.18+ features.
- Extensible design that works with modern Go idioms and the wider ecosystem.
Feature Overview
- Modular architecture with explicit dependencies and lifecycle hooks.
- Echo-based HTTP server with typed handlers, standardized response envelopes, and middleware batteries.
- AMQP messaging registry for RabbitMQ that orchestrates exchanges, queues, publishers, and consumers.
- Configuration loader built on Koanf that merges defaults, YAML, and environment variables.
- Database toolkit with PostgreSQL and Oracle drivers, query builders, and health checks.
- Flyway migration integration for schema evolution.
- Structured logging and observability with trace propagation, request instrumentation, and health endpoints.
- Performance optimized with modern Go type system (
any over interface{}), efficient slice operations, and reduced function complexity.
- Enterprise-grade code quality with comprehensive linting, zero warnings, and extensive test coverage.
Quick Start
Requirements
- Go 1.25+ (required for modern type aliases, generics, and slices package)
- Modern Go toolchain with module support
Install
go mod init your-service
go get github.com/gaborage/go-bricks@latest
Bootstrap an application
// cmd/main.go
package main
import (
"log"
"github.com/gaborage/go-bricks/app"
"github.com/gaborage/go-bricks/config"
)
func main() {
cfg, err := config.Load()
if err != nil {
log.Fatal(err)
}
framework, err := app.NewWithConfig(cfg, nil)
if err != nil {
log.Fatal(err)
}
// Register modules here: framework.RegisterModule(newExampleModule())
if err := framework.Run(); err != nil {
log.Fatal(err)
}
}
Configuration file
app:
name: "my-service"
version: "v1.0.0"
env: "development"
rate:
limit: 200
server:
port: 8080
database:
type: postgresql
host: localhost
port: 5432
database: mydb
username: postgres
password: password
log:
level: info
pretty: true
GoBricks loads defaults → config.yaml → config.<env>.yaml → environment variables. app.env controls the environment suffix and defaults to development.
Configuration
Accessing values
Only the essential accessors are exposed:
cfg, _ := config.Load()
host := cfg.GetString("server.host", "0.0.0.0")
port := cfg.GetInt("server.port", 8080)
pretty := cfg.GetBool("log.pretty")
Required values with validation
apiKey, err := cfg.GetRequiredString("custom.api.key")
if err != nil {
return fmt.Errorf("missing api key: %w", err)
}
Custom namespace
Custom application parameters live under custom.*:
enabled := cfg.GetBool("custom.feature.flag")
maxItems := cfg.GetInt("custom.max.items", 100)
// Convert string durations manually
rawTimeout := cfg.GetString("custom.service.timeout")
timeout, err := time.ParseDuration(rawTimeout)
// Unmarshal structured custom config
var custom struct {
FeatureFlag bool `koanf:"feature.flag"`
Service struct {
Endpoint string `koanf:"endpoint"`
Timeout string `koanf:"timeout"`
} `koanf:"service"`
}
_ = cfg.Unmarshal("custom", &custom)
See examples/params/main.go for a complete walkthrough.
Configuration Migration Guide
Breaking Change Notice: GoBricks now uses dot notation for nested configuration structures. If you're upgrading from a previous version, update your YAML configuration files:
app:
rate_limit: 200
server:
base_path: "/api/v1"
health_route: "/health"
ready_route: "/ready"
database:
service_name: "FREEPDB1" # Oracle service name
app:
rate:
limit: 200
server:
base:
path: "/api/v1"
health:
route: "/health"
ready:
route: "/ready"
database:
service:
name: "FREEPDB1" # Oracle service name
Environment variables remain the same - no changes needed:
APP_RATE_LIMIT=200 still works and maps to app.rate.limit
DATABASE_SERVICE_NAME=FREEPDB1 still works and maps to database.service.name
Code changes - Update field access in Go code:
// Current (recommended)
rateLimit := cfg.App.Rate.Limit
serviceName := cfg.Database.Service.Name
// Oracle database connection configuration:
// Use exactly one of: Service.Name, SID, or Database
oracleServiceName := cfg.Database.Service.Name // For Oracle service
oracleSID := cfg.Database.SID // For Oracle SID
oracleDB := cfg.Database.Database // For database name
Overriding via environment
Environment variables override everything using uppercase and underscores. The framework automatically converts underscore notation to dot notation for nested configuration:
# App configuration
APP_NAME=my-service
APP_RATE_LIMIT=200 # Maps to app.rate.limit
# Database configuration
DATABASE_TYPE=postgresql
DATABASE_HOST=prod-db.company.com
DATABASE_PORT=5432
# Oracle-specific configuration
DATABASE_SERVICE_NAME=FREEPDB1 # Maps to database.service.name
DATABASE_SID=ORCL
# Custom configuration
CUSTOM_FEATURE_FLAG=true # Maps to custom.feature.flag
CUSTOM_API_TIMEOUT=30s # Maps to custom.api.timeout
Modules and Application Structure
Module interface
type Module interface {
Name() string
Init(deps *ModuleDeps) error
RegisterRoutes(hr *server.HandlerRegistry, e *echo.Echo)
RegisterMessaging(registry *messaging.Registry)
Shutdown() error
}
ModuleDeps injects shared services:
type ModuleDeps struct {
DB database.Interface
Logger logger.Logger
Messaging messaging.Client
Config *config.Config
}
Registering a module
func register(framework *app.App) error {
return framework.RegisterModule(&users.Module{})
}
Init is called once to capture dependencies, RegisterRoutes attaches HTTP handlers, RegisterMessaging declares AMQP infrastructure, and Shutdown releases resources.
HTTP Server
- Based on Echo v4 with middleware stack (logging, recovery, rate limiting, CORS).
- Configurable base paths and health routes for flexible deployment scenarios.
- Request binding/validation: define request structs with tags (
path, query, header, validate).
- Response envelope ensures consistent
{data:…, meta:…} payloads.
- Typed handler signatures simplify status codes:
func (h *Handler) createUser(req CreateReq, ctx server.HandlerContext) (server.Result[User], server.IAPIError) {
user := h.svc.Create(req)
return server.Created(user), nil
}
Flexible Routing Configuration
GoBricks supports configurable base paths and health endpoints for different deployment scenarios:
server:
base:
path: "/api/v1" # All routes automatically prefixed
health:
route: "/health" # Custom health endpoint path
ready:
route: "/ready" # Custom readiness endpoint path
With this configuration:
- Module route
/users becomes /api/v1/users
- Health endpoint available at
/api/v1/health
- Ready endpoint available at
/api/v1/ready
Environment variable overrides:
SERVER_BASE_PATH="/api/v1" # Maps to server.base.path
SERVER_HEALTH_ROUTE="/status" # Maps to server.health.route
SERVER_READY_ROUTE="/readiness" # Maps to server.ready.route
Messaging
AMQP support via RabbitMQ:
- Declare exchanges and queues once using the shared registry.
- Register publishers/consumers during module initialization.
- Health / readiness hooks integrate with the main app lifecycle.
func (m *Module) RegisterMessaging(reg *messaging.Registry) {
reg.DeclareExchange("user.events", "topic")
reg.RegisterConsumer("user.events", "user.created", handler)
}
Database
PostgreSQL / Oracle support
Configure under database.* and use the provided factory to create connections. The query builder handles dialect differences (placeholders, quoting) and health checks feed into the readiness probe.
Flyway migrations
GoBricks ships with a Flyway integration that runs migrations via CLI while injecting database credentials from configuration.
migrator := migration.NewFlywayMigrator(cfg, log)
_ = migrator.Migrate(ctx, nil)
Observability and Operations
- Structured logging via Zerolog.
- Tracing propagates W3C
traceparent headers.
- Metrics capture HTTP/messaging/database timings.
- Health endpoints:
/health (liveness) and /ready (readiness with DB/messaging checks).
- Graceful shutdown coordinates servers, consumers, and background workers.
Examples
Explore the examples/ folder:
http/handlers – typed HTTP handler module
http/client – fluent HTTP client with retries and interceptors
oracle – Oracle insert with reserved column quoting
params – custom configuration namespace demo
trace-propagation – W3C tracing demonstration
Contributing
Issues and pull requests are welcome! See CONTRIBUTING.md for coding standards, tooling, and workflow.
License
MIT © Contributors
Built with ❤️ for the Go community.