Hi everyone, I maintain Kruda, an open-source Go web framework (MIT).
I built it because I enjoy working in Go and wanted to explore how far I could push performance without making API development harder. I’d especially like feedback on the typed handler API.
You define an input struct, and Kruda binds and validates the request before calling your handler. Inputs can combine body, path parameters, and query fields. Here’s a simple JSON-body example:
type CreateUser struct {
Name string `json:"name" validate:"required,min=2"`
Email string `json:"email" validate:"required,email"`
}
type User struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
kruda.Post[CreateUser, User](app, "/users", func(c *kruda.C[CreateUser]) (*User, error) {
return &User{ID: "1", Name: c.In.Name, Email: c.In.Email}, nil
})
In a 30-field query binding and validation benchmark on Linux (HTTP/1.1), Kruda v1.8.0 reached a median of 533,210 req/s with four workers—2.06× Fiber v3.5.0, with throughput close to Actix v4.15.0. Actix led at eight workers. The full setup and results are available to reproduce.
Three decisions I’d like opinions on:
- Validation runs by default. Invalid input returns 422 with per-field errors, without calling the handler. You can disable it with
kruda.New(kruda.WithoutValidation()). Is that a useful default, or would you prefer to enable it explicitly? - Kruda has its own validator with 20 built-in rules. The tags look similar to go-playground/validator, but they aren’t fully compatible. Unknown rules produce a startup warning and are skipped; recognized rules still run. Would you prefer startup to fail instead?
- There’s an experimental, optional
cmd/bindgenstep for scalar query/path fields, defaults, and built-inmin/maxvalidation. Routes opt in explicitly. It doesn’t generate JSON/form body binding, so the example above uses the regular binding path. Would you use this, or would the extra build step put you off?
I’ve used Kruda in some production work, but not in a large project under heavy load yet. I’d appreciate hearing what feels awkward in the API, or what would stop you from trying it.
Repository and examples: GitHub - go-kruda/kruda: High-performance, type-safe Go web framework with custom async I/O transport — faster than Fiber and Actix on every benchmark route · GitHub