go-api-boot
Production-Ready Go API Framework
Batteries‑included Go framework for building production‑grade gRPC + HTTP APIs – with generics, MongoDB ODM, cloud utilities, zero‑config HTTPS, Temporal workers, and a one‑line bootstrap CLI.
📑 Table of Contents
Overview
go‑api‑boot eliminates the repetitive plumbing required to ship modern API services in Go. With a single CLI command you get:
- A fully wired gRPC server that also serves gRPC‑Web and REST gateways – no Envoy sidecars or extra proxies.
- Temporal workflow support for long-running background jobs.
- Generic ODM for MongoDB with multi‑tenant support.
- Opinionated middlewares (JWT auth, logging, panic recovery) that you can opt out of per‑method.
- A relocatable cloud toolkit (Azure / GCP) for signed URLs, blob storage, secret resolution, etc.
- Zero-configuration HTTPS – serve valid TLS certificates on day 0.
- Built-In Dependency injection wiring customized for gRpc services, temporal workers, config, mongo client, and cloud abstractions.
The result: you write business logic, not boilerplate.
Key Features
🚀 gRPC & gRPC‑Web
First‑class gRPC & gRPC‑Web – serve browsers natively without Envoy.
🗄️ Generic ODM for MongoDB
Type‑safe generic multi-tenant Object Model with async helpers.
🔍 Vector & Text Search
Built‑in support for Atlas Vector Search and Atlas Search.
🔐 JWT Auth & Middleware
Observability, logging, panic recovery pre‑wired.
☁️ Cloud Providers
Interchangeable Azure / GCP helpers for storage & secrets.
🔒 Zero‑Config SSL
Automatic Let's Encrypt certificates with exponential back‑off.
⏰ Temporal Workflow Support
Run long-lived, fault-tolerant background jobs with native Temporal integration.
🔧 Bootstrap CLI
Scaffold full service, models, repos, services, Dockerfile, build scripts.
Quick Start
Bootstrap a New Service
# Install the CLI once $ go install github.com/SaiNageswarS/go-api-boot/cmd/go-api-boot@latest # Scaffold a new service in ./quizService $ go-api-boot bootstrap github.com/yourname/quizService proto
Generated layout:
quizService/ ├── cmd/... # main.go and build scripts ├── db/ # repositories ├── generated/ # proto stubs (via build script) ├── services/ # business logic ├── Dockerfile # multistage build └── config.ini # config
Running Locally
# Generate proto code & build binary $ ./build.sh # Export secrets (or use .env / Azure Key Vault) $ export MONGO_URI=mongodb://localhost:27017 $ export ACCESS_SECRET=supersecret $ export DOMAIN=api.example.com # required for SSL # (optional) use cloud cache for certs $ export SSL_BUCKET=my-cert-bucket # bucket / container name # Start the server – gRPC :50051, HTTP :8081 (HTTPS if --ssl) $ ./build/quizService
Core Modules
Server
// main.go
package main
func main() {
// Load secrets and config
dotenv.LoadEnv()
// load config file
var ccfg *config.AppConfig
config.LoadConfig("config.ini", ccfg) // loads [dev] or [prod] section based on env var - `ENV=dev` or `ENV=prod`
mongo, _ := odm.GetClient()
// Pick a cloud provider – all implement cloud.Cloud
cloudFns := cloud.ProvideAzure(ccfg) // or cloud.ProvideGCP(cfg)
// load secrets from Keyvault/SecretManader
cloudFns.LoadSecretsIntoEnv(context.Background())
boot, _ := server.New().
GRPCPort(":50051"). // or ":0" for dynamic
HTTPPort(":8080").
EnableSSL(server.CloudCacheProvider(cfg, cloudFns)).
// Dependency injection
Provide(cfg).
Provide(mongo).
ProvideAs(cloudFns, (*cloud.Cloud)(nil)).
// Register gRPC service impls
RegisterService(server.Adapt(pb.RegisterLoginServer), ProvideLoginService).
Build()
ctx, cancel := context.WithCancel(context.Background())
// catch SIGINT ‑> cancel
_ = boot.Serve(ctx)
}gRPC, gRPC‑Web, and optional REST gateway on the same port. Middleware registry (unary + stream) to plug in OpenTelemetry, Prometheus, etc.
ODM (MongoDB)
Generic CRUD
// Model
type Profile struct {
ID string `bson:"_id"`
Name string `bson:"name"`
}
func (p Profile) Id() string { return p.ID }
func (p Profile) CollectionName() string { return "profile" }
// Query
client, err := odm.GetClient(ccfg)
profile, err := async.Await(odm.CollectionOf[Profile](client, tenant).FindOneById(context.Background(), id))Additionally use helpers like HashedKey to generate _id, NewModelFrom[T any](proto interface) to copy values from proto to the model.
Creating & Ensuring Indexes
// In your setup code
if err := odm.EnsureIndexes[Profile](ctx, mongoClient, tenant); err != nil {
log.Fatalf("failed to ensure indexes: %v", err)
}This idempotent helper safely creates all indexes advertised by your models:
- Implement
Indexedfor classic indexes. - Implement
SearchIndexedfor text search (TermSearchIndexSpec). - Implement
VectorIndexedfor vector search (VectorIndexSpec).
Vector Search
type Article struct {
ID string `bson:"_id"`
Title string `bson:"title"`
Content string `bson:"content"`
Embedding bson.Vector `bson:"embedding"` // 768-dim vector
}
func (a Article) Id() string { return a.ID }
func (a Article) CollectionName() string { return "articles" }
// Specify vector index on field "embedding"
func (m Article) VectorIndexSpecs() []odm.VectorIndexSpec {
return []odm.VectorIndexSpec{{
Name: "contentVecIdx", Path: "embedding", Type: "vector", NumDimensions: 768,
Similarity: "cosine",
}}
}embedding := getEmbedding(...) // []float32
params := odm.VectorSearchParams{
IndexName: "contentVecIdx",
Path: "embedding",
K: 5,
NumCandidates: 20,
}
results, _ := async.Await(repo.VectorSearch(ctx, embedding, params))
for _, hit := range results {
fmt.Println(hit.Doc, hit.Score)
}Text Search
type Article struct {
ID string `bson:"_id"`
Title string `bson:"title"`
Content string `bson:"content"`
Embedding bson.Vector `bson:"embedding"` // 768-dim vector
}
func (a Article) Id() string { return a.ID }
func (a Article) CollectionName() string { return "articles" }
// Specify term index on field "content" and "title".
func (m Article) TermSearchIndexSpecs() []odm.TermSearchIndexSpec {
return []odm.TermSearchIndexSpec{{
Name: "contentTextIdx", Paths: []string {"content", "title"},
}}
}params := odm.TermSearchParams{
IndexName: "contentTextIdx",
Path: []string {"content", "title"},
Limit: 10,
}
results, _ := async.Await(repo.TermSearch(ctx, "golang guides", params))
for _, hit := range results {
fmt.Println(hit.Doc, hit.Score)
}Auth & JWT
func (s *LoginService) AuthFuncOverride(ctx context.Context, method string) (context.Context, error) {
return ctx, nil // public endpoint
}HS256 by default – override via env vars or secrets manager. Skip auth per‑method.
Cloud Abstractions
var cloudFns cloud.Cloud = cloud.ProvideAzure(ccfg) filePath, err := cloudFns.DownloadFile(context, bucket, key)
Switch provider with one line – signatures stay identical. Cloud access Secrets such as ClientId, TenantId, ClientSecret for Azure or ServiceAccount.json for GCP are loaded from environment variables.
Zero‑Config SSL/TLS
boot, _ := server.New().
GRPCPort(":50051").HTTPPort(":8080").
EnableSSL(server.DirCache("certs")) // local cache
Build()There are two ways to persist the Let's Encrypt certificates:
- Local autocert.DirCache("certs") – good for single-node dev / on-prem.
- Distributed cache with SslCloudCache – perfect for Docker / Kubernetes where the container filesystem is ephemeral.
ACME challenge handled internally, exponential back‑off for cloud IP propagation. Just expose port 80 and 443 in your container spec.
Temporal Workers
import (
"github.com/SaiNageswarS/go-api-boot/server"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/worker"
)
boot, _ := server.New().
GRPCPort(":50051").
HTTPPort(":8080").
WithTemporal("MY_TASK_QUEUE", &client.Options{
HostPort: "temporal:7233", // or "localhost:7233" if running locally
}).
// ProvideIndexerActivities is a function whose dependencies will be injected
RegisterTemporalActivity(ProvideIndexerActivities).
RegisterTemporalWorkflow(IndexPdfFileWorkflow).
Build()
boot.Serve(context.Background())go-api-boot provides first-class support for running Temporal workers alongside your gRPC/HTTP services using the same dependency injection system.
CLI Reference
| Command | Description |
|---|---|
| bootstrap <modulePath> <protoDir> | Scaffold a new project |
| repository <ModelName> | Generate model + repository in `db/` |
| service <ServiceName> | Generate skeleton gRPC service |
Run with -h for full flags.
Examples
Contributing
PRs and issues are welcome!
- Fork ➡️ hack ➡️ PR.
- Run
make test lint– zero lint errors. - Add unit / integration tests for new features.
License
Apache‑2.0 – see LICENSE for details.