Skip to content

Lakta

An opinionated Go microservice framework. Modules, DI, and lifecycle management — batteries included.

Automatic init ordering

Declare what your module provides and needs. The runtime resolves initialization order via topological sort — no manual wiring.

Context-carried DI

The injector lives on the context. Access any registered type from gRPC handlers, HTTP handlers, or Temporal activities with a single lakta.Invoke[T](ctx) call.

Batteries included

First-class modules for gRPC, HTTP (Fiber), PostgreSQL, OpenTelemetry, health checks, and Temporal workflows — all wired consistently.

Graceful lifecycle

Async and sync start phases run concurrently. SIGTERM triggers reverse-order shutdown with a 30-second deadline. Config hot-reload is built in.

func main() {
if err := lakta.NewRuntime(
config.NewModule(
config.WithConfigDirs(".", "./config"),
config.WithArgs(os.Args[1:]),
),
tint.NewModule(),
slog.NewModule(),
otel.NewModule(),
health.NewModule(),
grpcclient.NewModule(
grpcclient.WithName("data"),
grpcclient.WithClient(v1.NewDataServiceClient),
),
fiberserver.NewModule(
fiberserver.WithDefaults(fiber.Config{ReadTimeout: 30 * time.Second}),
fiberserver.WithRouter(registerRoutes),
),
).Run(); err != nil {
os.Exit(1)
}
}
func registerRoutes(app *fiber.App) {
app.Get("/orders/:id", func(c fiber.Ctx) error {
client, err := lakta.Invoke[v1.DataServiceClient](c.Context())
if err != nil {
return err
}
resp, err := client.GetOrder(c.Context(), &v1.GetOrderRequest{Id: c.Params("id")})
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(resp.GetOrder())
})
}