keel is a Go microservice framework that provides opinionated, batteries-included infrastructure for building production microservices.
New service from zero to running: under 5 minutes. Independently verified by Claude Sonnet in Cursor.
v0.1 — opinionated, batteries-included framework. Modular architecture planned for v0.2.
go get github.com/glodb/keelMost Go microservice projects repeat the same wiring: HTTP server, database connections, messaging, caching, observability — from scratch, every time. Keel provides a single opinionated core so you register your service and start writing business logic immediately.
Built in 2017. Battle-tested across 8 years and multiple production systems handling millions of daily requests.
- Service registry + factory pattern (
servicehandler.Register→Boot(env, service)→Run()/Stop()) - Service types you can OR together:
HTTP,SOCKET,SIMPLE,TCP - Graceful shutdown on SIGINT/SIGTERM (HTTP + socket drain)
- Panic recovery everywhere —
SafeGo,RecoverFromPanic,InitializerWithRecovery - Multi-service single binary — isolated
NewGINServer()/NewControllers()graphs (no shared global state)
- Layered JSON config: global
config/<env>.json+ per-serviceservices/<svc>/config/<env>.json - Env var overrides win over JSON
- Programmatic config —
NewConfig()+LoadFromBytes()+SetGlobalInstance()(no files needed) - Typed accessors —
GetString/GetInt/...withOr/OKvariants - Config validation at startup (
configvalidator)
- Three drivers: MongoDB, MySQL, PostgreSQL with pooled connections
- Rich ops:
Add/AddMany,Update/UpdateOne/UpdateMany,FindOne/Find/FindCursor,FindOneAndUpdate/Delete,Delete/DeleteOne/DeleteMany,BulkWrite,Distinct,Aggregate,Count,RawQuery - Soft delete built-in (
SoftDeleteOne/Many→_deletedcollections,deletedAt/deletedBy) - Index management (
EnsureIndex, unique + partial filters) - Pagination in 3 flavors:
Paginate,SqlPaginate,AggregatePaginate+ array pagination - DB migrations (
MigrationModels+ runner) - Cross-controller access —
GetController(MONGO, "name")
- Pub/Sub and RPC request/reply
- Topic registry (registered / publishable / subscribed / RPC-subscribed)
- Batched event publisher with queue-subscribe
- Socket.IO — connect/disconnect/error/message callbacks, custom events (typed + raw)
- Rooms, broadcast to room / user / all
- Shared-HTTP-port or standalone mode
- Gin HTTP with middleware tiers (
open/auth/base) via middleware registry - Auto OpenAPI/Swagger — generated
openapi.json+ Swagger UI (non-PROD) - Built-in
/health+ version endpoints on every HTTP service - Custom validators with human-readable translated messages
- API validation built-in
- Circuit breaker (closed/open/half-open)
- Health checks — readiness/liveness/startup, with DB/cache/breaker probes
- Distributed tracing — OpenTelemetry/Jaeger (toggleable via
useTracing) - pprof profiling endpoints (toggle)
- Structured logging (zap)
- Structured errors —
AppErrorwith codes + trace/span IDs
- FCM push, email (gomail), WhatsApp, activity sender
- Common
NotificationSenderinterface with semaphore-limited concurrency
- Meilisearch full-text search integration
- Distributed Redis lock (
redislock) - Secure cookies (
gorilla/securecookie) - Crypto/utils — AES encrypt/decrypt, XID generation, OAuth2 Google client, BSON helpers
- Generic data structures —
Set[T],Queue[T] - Redis cache built-in
A keel service has three parts: register, implement, boot.
package myservice
import "github.com/glodb/keel/settings/servicehandler"
func init() {
servicehandler.Register("myservice", func() servicehandler.ServiceBase {
return &MyService{}
})
}type MyService struct{}
func (s *MyService) Run() error {
// start your HTTP handlers, NATS subscribers, etc.
return nil
}
func (s *MyService) Stop() {
// graceful shutdown
}package main
import (
"flag"
"log"
_ "myapp/myservice"
"github.com/glodb/keel"
)
func main() {
env := flag.String("env", "DEV", "deployment environment")
svc := flag.String("con", "MYSERVICE", "service name")
flag.Parse()
if err := keel.Boot(*env, *svc); err != nil {
log.Fatal(err)
}
}keel loads config from JSON files at startup:
- Global config:
config/<env>.json - Service config:
services/<servicename>/config/<env>.json
Environment variables override JSON values.
| Package | Purpose |
|---|---|
settings/configmanager |
Configuration loading |
settings/servicehandler |
Service registration and lifecycle |
settings/logger |
Structured logging (zap) |
settings/metrics |
Prometheus metrics |
settings/cachesettings |
Redis cache + distributed lock |
settings/searchsettings |
Meilisearch integration |
settings/notificationsettings |
FCM, email, WhatsApp notifications |
settings/tracing |
OpenTelemetry distributed tracing |
settings/circuitbreaker |
Circuit breaker |
settings/errors |
Structured error types |
database/basefunctions |
Mongo/MySQL/PostgreSQL CRUD helpers |
httpHandler |
Gin-based HTTP server + Swagger |
settings/socket.io |
Socket.IO server |
Importing github.com/glodb/keel pulls in the full dependency set (Mongo, MySQL, PostgreSQL, Redis, NATS, Firebase, Twilio, Stripe, OpenTelemetry, etc.). This is intentional for a batteries-included framework. Opt-in sub-package splitting is on the roadmap for v0.2.
👉 keel-code — a complete working example service
See docs/ops.md for Docker run commands and deployment notes.
Why Gin? Stable, well-tested HTTP routing. Making it optional is planned for v0.2.
Why init() registration? Zero boilerplate for the common case. Constructor pattern (keel.New()) is in progress for v0.2.