v1.1.0Declarative config, service calls & hot reload

Gin, with the boring parts done.

Request binding, error mapping, config, repositories, tracing and workers: the code every production API ends up writing, already written. Handlers are plain functions that return (T, error). No annotations, no DI container, no code generation.

go get -u github.com/klass-lk/ginboot
Or push to GitHub and run it on AWS Lambda with Ginboot Cloud, free to start

Controllers, not boilerplate

A handler is a function that takes a request and returns a value and an error. Ginboot does the binding, status codes, tracing and JSON around it, and the same binary runs as an HTTP server or a Lambda function.

main.go
package main

import (
	"log"

	"github.com/klass-lk/ginboot"
	"github.com/klass-lk/ginboot/example/internal/controller"
)

func main() {
	// Loads ginboot.yml / application.yml and .env automatically
	server := ginboot.New()
	cfg := server.Config()

	server.SetBasePath(cfg.Ginboot.Server.BasePath)
	server.RegisterController("/posts", controller.NewPostController(svc))

	// Runs as HTTP locally, as an API Gateway proxy on AWS Lambda
	if err := server.Start(cfg.Ginboot.Server.Port); err != nil {
		log.Fatal(err)
	}
}
post_controller.go
package controller

import "github.com/klass-lk/ginboot"

func (c *PostController) Register(group *ginboot.ControllerGroup) {
	group.GET("/:id", c.GetPost)

	protected := group.Group("")
	protected.POST("", c.CreatePost)
}

// Handlers return (DTO, error) — Ginboot handles binding,
// status codes and JSON serialisation for you.
func (c *PostController) GetPost(ctx *ginboot.Context) (model.Post, error) {
	return c.postService.GetPostById(ctx.Param("id"))
}

func (c *PostController) CreatePost(ctx *ginboot.Context, req model.Post) (model.Post, error) {
	post, err := c.postService.CreatePost(req)
	if err != nil {
		return model.Post{}, ginboot.NewApiError(400, "invalid post")
	}

	// Fire-and-forget call to another service, traced end to end
	_ = ctx.CallServiceAsync("notification-service", "/notifications/send", post)

	return post, nil
}

Familiar from either side

Ginboot adds structure without hiding Go. Nothing is generated and nothing is injected behind your back, so a stack trace leads to code you wrote.

Batteries included

Everything a production Go service needs is already there, and each piece is optional. Use what helps and keep writing plain Gin for the rest.

Ginboot Cloud

Push to GitHub. Run on AWS Lambda.

Your Ginboot service already runs on Lambda. Ginboot Cloud takes care of the rest: builds, environments, API Gateway and dashboards. You don't write any Terraform or YAML pipelines.

  • Every push builds once. Test it in preprod, then promote that exact build to production
  • Request, error and latency metrics from API Gateway and Lambda, with no instrumentation
  • OpenTelemetry logs and traces from your Ginboot app, per request
  • Deploy, promote and roll back from Claude Code, Cursor or VS Code over MCP
Hosted
$0platform fee

Runs in our AWS account. A monthly allowance is included, then you pay for usage.

Your AWS
$49/ month per org

Runs in your own account and AWS bills you directly. No Ginboot charges on traffic.

No AWS account needed to start. Connect yours whenever you like.