https://github.com/go-kruda/kruda
High-performance, type-safe Go web framework with custom async I/O transport — 847K RPS plaintext
https://github.com/go-kruda/kruda
epoll generics go golang high-performance http microservice rest-api type-safe web-framework
Last synced: 3 days ago
JSON representation
High-performance, type-safe Go web framework with custom async I/O transport — 847K RPS plaintext
- Host: GitHub
- URL: https://github.com/go-kruda/kruda
- Owner: go-kruda
- License: mit
- Created: 2026-02-22T17:48:04.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-03-27T02:24:53.000Z (10 days ago)
- Last Synced: 2026-03-27T05:04:26.585Z (9 days ago)
- Topics: epoll, generics, go, golang, high-performance, http, microservice, rest-api, type-safe, web-framework
- Language: Go
- Homepage: https://pkg.go.dev/github.com/go-kruda/kruda
- Size: 25.5 MB
- Stars: 17
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
# Kruda
Fast by default, type-safe by design.
[](https://go.dev)
[](https://pkg.go.dev/github.com/go-kruda/kruda)
[](https://github.com/go-kruda/kruda/actions/workflows/test.yml)
[](https://codecov.io/gh/go-kruda/kruda)
[](LICENSE)
## Why Kruda?
- Typed handlers `C[T]` — body + param + query parsed into one struct, validated at compile time
- Auto CRUD — implement `ResourceService[T]`, get 5 REST endpoints
- Built-in DI — optional, no codegen, type-safe generics
- Pluggable transport — Wing (Linux, epoll+eventfd), fasthttp, or net/http
- Minimal deps — Sonic JSON (opt-out via `kruda_stdjson`), pluggable transport
- AI-friendly — typed API + 21 examples = AI generates correct code on first try
## Quick Start
```bash
go get github.com/go-kruda/kruda
```
```go
package main
import (
"github.com/go-kruda/kruda"
"github.com/go-kruda/kruda/middleware"
)
func main() {
app := kruda.New()
app.Use(middleware.Recovery(), middleware.Logger())
app.Get("/ping", func(c *kruda.Ctx) error {
return c.JSON(kruda.Map{"pong": true})
})
app.Listen(":3000")
}
```
## Typed Handlers
```go
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
})
```
## Auto CRUD
```go
kruda.Resource[User, string](app, "/users", &UserCRUD{db: db})
// Registers: GET /users, GET /users/:id, POST /users, PUT /users/:id, DELETE /users/:id
```
## Dependency Injection
```go
c := kruda.NewContainer()
c.Give(&UserService{})
c.GiveLazy(func() (*DBPool, error) { return connectDB() })
c.GiveNamed("write", &DB{DSN: "primary"})
app := kruda.New(kruda.WithContainer(c))
app.Get("/users", func(c *kruda.Ctx) error {
svc := kruda.MustResolve[*UserService](c)
return c.JSON(svc.ListAll())
})
```
## Error Mapping
```go
app.MapError(ErrNotFound, 404, "resource not found")
kruda.MapErrorType[*ValidationError](app, 422, "validation failed")
```
## Coming from Another Framework?
| Concept | Kruda | Gin | Fiber | Echo | stdlib |
|---------|-------|-----|-------|------|--------|
| App | `kruda.New()` | `gin.Default()` | `fiber.New()` | `echo.New()` | `http.NewServeMux()` |
| Route | `app.Get("/path", h)` | `r.GET("/path", h)` | `app.Get("/path", h)` | `e.GET("/path", h)` | `mux.HandleFunc("GET /path", h)` |
| Typed handler | `kruda.Post[In, Out](app, "/path", h)` | — | — | — | — |
| Group | `app.Group("/api")` | `r.Group("/api")` | `app.Group("/api")` | `e.Group("/api")` | — |
| Middleware | `app.Use(mw)` | `r.Use(mw)` | `app.Use(mw)` | `e.Use(mw)` | — |
| Context | `*kruda.Ctx` | `*gin.Context` | `*fiber.Ctx` | `echo.Context` | `http.ResponseWriter, *http.Request` |
| JSON response | `return &obj, nil` | `c.JSON(200, obj)` | `c.JSON(obj)` | `c.JSON(200, obj)` | `json.NewEncoder(w).Encode(obj)` |
| Path param | `c.Param("id")` | `c.Param("id")` | `c.Params("id")` | `c.Param("id")` | `r.PathValue("id")` |
| Query param | `c.Query("q")` | `c.Query("q")` | `c.Query("q")` | `c.QueryParam("q")` | `r.URL.Query().Get("q")` |
| Body binding | `c.Bind(&v)` or `C[T].In` | `c.ShouldBindJSON(&v)` | `c.BodyParser(&v)` | `c.Bind(&v)` | `json.NewDecoder(r.Body).Decode(&v)` |
| Auto CRUD | `kruda.Resource[T, ID](app, "/path", svc)` | — | — | — | — |
| DI | `Container.Give()` / `MustResolve[T](c)` | — | — | — | — |
> Full migration guides: [Gin](docs/guide/coming-from-gin.md) · [Fiber](docs/guide/coming-from-fiber.md) · [Echo](docs/guide/coming-from-echo.md) · [stdlib](docs/guide/coming-from-stdlib.md)
## Benchmarks
Measured with `wrk -t4 -c256 -d5s` on Linux i5-13500 (8P cores), GOGC=400.
| Test | Kruda (Go) | Fiber (Go) | Actix (Rust) | vs Fiber | vs Actix |
|------|--:|--:|--:|--:|--:|
| plaintext | **846,622** | 670,240 | 814,652 | +26% | +4% |
| JSON | **805,124** | 625,839 | 790,362 | +29% | +2% |
| db | **108,468** | 107,450 | 37,373 | +1% | +190% |
| fortunes | 104,144 | **106,623** | 45,078 | -2% | +131% |
Wing transport uses raw `epoll` + `eventfd` on Linux — bypasses both fasthttp and net/http. macOS defaults to fasthttp.
- See [`bench/reproducible/`](bench/reproducible/) for full source code of all 3 frameworks and reproduction steps
## Documentation
- [API Reference (pkg.go.dev)](https://pkg.go.dev/github.com/go-kruda/kruda)
- [Examples](examples/) — 21 runnable examples
- [Contributing](CONTRIBUTING.md)
- [Security Policy](SECURITY.md)
- [Benchmark Charts](https://go-kruda.github.io/kruda/benchmarks/)
## AI Integration
Kruda includes a built-in [MCP](https://modelcontextprotocol.io/) server for AI coding assistants (Claude Code, Cursor, Copilot).
```bash
# Install CLI
go install github.com/go-kruda/kruda/cmd/kruda@latest
# New projects — .mcp.json included automatically
kruda new myapp
# Existing projects
kruda mcp init # generates .mcp.json + .cursor/mcp.json
kruda mcp --test # verify it works
```
| Tool | Description |
|------|-------------|
| `kruda_new` | Scaffold a new project |
| `kruda_add_handler` | Generate a typed handler with `C[T]` pattern |
| `kruda_add_resource` | Generate a CRUD `ResourceService` |
| `kruda_list_routes` | Scan source code and list all registered routes |
| `kruda_suggest_wing` | Suggest Wing Feather hints for routes |
| `kruda_docs` | Look up Kruda docs and code examples |
## Security
See [SECURITY.md](SECURITY.md) for our responsible disclosure policy.
### Security Hardening (Recommended)
```go
import (
"os"
"time"
"github.com/go-kruda/kruda"
"github.com/go-kruda/kruda/middleware"
"github.com/go-kruda/kruda/contrib/jwt"
"github.com/go-kruda/kruda/contrib/ratelimit"
)
app := kruda.New(
kruda.WithBodyLimit(1024 * 1024), // 1MB body limit
kruda.WithReadTimeout(10 * time.Second),
)
// Rate limiting — 100 req/min per IP
app.Use(ratelimit.New(ratelimit.Config{
Max: 100, Window: time.Minute,
TrustedProxies: []string{"10.0.0.1", "10.0.0.2"},
}))
// Stricter limit on auth endpoints
app.Use(ratelimit.ForRoute("/api/login", 5, time.Minute))
// JWT authentication on protected routes
api := app.Group("/api").Guard(jwt.New(jwt.Config{
Secret: []byte(os.Getenv("JWT_SECRET")),
}))
```
### Contrib Modules
| Module | Install | Description |
|--------|---------|-------------|
| [contrib/jwt](contrib/jwt/) | `go get github.com/go-kruda/kruda/contrib/jwt` | JWT sign, verify, refresh (HS256/384/512, RS256) |
| [contrib/ws](contrib/ws/) | `go get github.com/go-kruda/kruda/contrib/ws` | WebSocket upgrade, RFC 6455 frames, ping/pong |
| [contrib/ratelimit](contrib/ratelimit/) | `go get github.com/go-kruda/kruda/contrib/ratelimit` | Token bucket / sliding window rate limiting |
| [contrib/session](contrib/session/) | `go get github.com/go-kruda/kruda/contrib/session` | Session middleware with pluggable store |
| [contrib/compress](contrib/compress/) | `go get github.com/go-kruda/kruda/contrib/compress` | Response compression (gzip, deflate) |
| [contrib/etag](contrib/etag/) | `go get github.com/go-kruda/kruda/contrib/etag` | ETag response caching |
| [contrib/cache](contrib/cache/) | `go get github.com/go-kruda/kruda/contrib/cache` | Response cache (in-memory, Redis) |
| [contrib/otel](contrib/otel/) | `go get github.com/go-kruda/kruda/contrib/otel` | OpenTelemetry tracing |
| [contrib/prometheus](contrib/prometheus/) | `go get github.com/go-kruda/kruda/contrib/prometheus` | Prometheus metrics |
| [contrib/swagger](contrib/swagger/) | `go get github.com/go-kruda/kruda/contrib/swagger` | Swagger UI HTML |
### Pre-release Checklist
Run vulnerability scan before every release:
```bash
# Install govulncheck (one-time)
go install golang.org/x/vuln/cmd/govulncheck@latest
# Scan root module
govulncheck ./...
# Scan Wing transport module
cd transport/wing && govulncheck ./...
```
Kruda core has minimal external dependencies (Sonic JSON, fasthttp). Use `kruda_stdjson` build tag to switch to stdlib JSON. Upgrade to the latest Go patch release for security fixes.
**Minimum Go version for zero stdlib vulnerabilities:** go1.25.8+
## Contributing
Contributions welcome. Please read the [Contributing Guide](CONTRIBUTING.md) before submitting a PR.
## License
[MIT](LICENSE)