docs/comparison/gofr-vs-chi/page.md
{% answer %}
Chi is a small, idiomatic net/http-compatible router that composes beautifully with the standard library — a great fit when minimal dependencies and full control matter. GoFr has a wider scope: HTTP routing alongside gRPC, GraphQL, WebSockets, Pub/Sub, cron, migrations, OpenTelemetry tracing, Prometheus metrics, structured logging, datasource clients, and a service-to-service HTTP client with circuit breakers. Different goals, both open source — both have happy users.
{% /answer %}
func(http.ResponseWriter, *http.Request) everywhere; zero magic.net/http middleware, the standard library, and any third-party net/http-compatible library.Chi takes no position on how you structure your service or which libraries you bring for logging, tracing, datasources, or downstream calls — that's a strength when you want full control and a small dependency footprint. GoFr takes the opposite design choice: it standardizes a common combination of those layers (OpenTelemetry, Prometheus, structured logging, datasource clients with retries, message brokers, circuit breakers, health checks) so teams maintaining several services don't make the same composition choices repeatedly. Both approaches have their place.
Chi (with manual wiring):
import (
"database/sql"
"log/slog"
"github.com/go-chi/chi/v5"
"github.com/prometheus/client_golang/prometheus/promhttp"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel"
// ... otel exporter setup, prometheus registry setup, db driver, slog setup
)
// You write tracer init, metrics init, logger init, DB connection,
// then wrap your handler with otelhttp, register Prom on /metrics,
// and propagate a request-scoped logger.
GoFr:
package main
import "gofr.dev/pkg/gofr"
func main() {
app := gofr.New()
app.GET("/users/{id}", func(c *gofr.Context) (any, error) {
var name string
err := c.SQL.QueryRowContext(c, "SELECT name FROM users WHERE id=?", c.PathParam("id")).Scan(&name)
return map[string]string{"name": name}, err
})
app.Run()
}
Tracing, metrics, structured logging with trace IDs, and DB span correlation are emitted automatically.
{% faq %}
{% faq-item question="Can I use Chi-style net/http middleware in GoFr?" %}
Yes. GoFr's UseMiddleware accepts func(http.Handler) http.Handler — the standard net/http signature Chi uses.
{% /faq-item %}
{% faq-item question="Does GoFr support route patterns like Chi's?" %} GoFr supports path parameters, wildcards, and method-specific routing. The exact syntax differs slightly; see the routing reference. {% /faq-item %}
{% /faq %}