Rivaas — Go API Framework with Built-in Observability

2 min read Original article ↗

The high-performance API framework for Go

You write your request handlers. Rivaas takes care of the rest.

See it in action

From go get to a fully observable, documented API.

What you get for free #

Replace 30 lines of setup with just 3.

Others

// Typical setup: wire each SDK separately
import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
    "go.opentelemetry.io/otel/sdk/resource"
    "go.opentelemetry.io/otel/sdk/trace"
    "github.com/prometheus/client_golang/prometheus"
    "log/slog"
    "os"
)
func setupObservability(ctx context.Context) {
    res, _ := resource.New(ctx,
        resource.WithAttributes(
            semconv.ServiceName("my-api"),
        ),
    )
    exp, _ := otlptracegrpc.New(ctx,
        otlptracegrpc.WithEndpoint("localhost:4317"),
    )
    tp := trace.NewTracerProvider(
        trace.WithBatcher(exp),
        trace.WithResource(res),
    )
    otel.SetTracerProvider(tp)
    reg := prometheus.NewRegistry()
    reg.MustRegister(collectors.NewGoCollector())
    logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
    slog.SetDefault(logger)
    // Then wrap every handler with middleware...
}

Rivaas

// Rivaas: one block, all three pillars
app.WithObservability(
    app.WithMetrics(),
    app.WithTracing(
        tracing.WithOTLP("localhost:4317")),
    app.WithLogging(
        logging.WithJSONHandler()),
)

Full OpenTelemetry stack — metrics, traces, and structured logs — configured in one block.

Proven Performance #

Fast routing with zero allocations.

Independent benchmarks comparing rivaas.dev/router against popular Go frameworks. All values are nanoseconds per operation (ns/op)—lower is better.

Why not Gin, Echo, or Fiber?

Gin, Echo, and Fiber are excellent HTTP routers — Rivaas's own router benchmarks alongside them. The difference is what you wire up after routing: OpenTelemetry, health probes, OpenAPI docs, structured error responses. That boilerplate usually takes a full sprint before you write any business logic.

Rivaas sets up that layer for you — but nothing is hidden. You can always see and change it. Every part is a standalone package with its own go.mod. Use rivaas.dev/app for the full stack, or drop in individual packages — rivaas.dev/router, rivaas.dev/tracing, rivaas.dev/binding — alongside whatever you already have.

Use what you need #

Use the full framework or individual packages. Same API, no lock-in.

// Use the full framework...
import "rivaas.dev/app"

// ...or just the packages you need
import "rivaas.dev/router"
import "rivaas.dev/binding"
import "rivaas.dev/validation"

// Every package has its own go.mod — no lock-in
// Same functional options everywhere

r, _ := router.New()
r.Use(cors.New(), compression.New(), recovery.New())

r.GET("/users/:id", getUser).WhereInt("id")
r.POST("/users", createUser)

r.Serve(":8080")

Wild Rhubarb of the Mountains

Named after a wild rhubarb plant that grows high in Iran's mountains, at 1,500–3,000 meters. It survives where little else can — yet has fed people for centuries. Like the plant, Rivaas is built to work hard and stay out of your way.

Resilient

Production-ready

Lightweight

Zero allocations

Self-sufficient

Integrated observability

Ready to build?

$ go get rivaas.dev/app