Files
httpserver/docs/adr/ADR-001-chi-over-echo.md
Rene Nochebuena 1ec0780f72 docs(httpserver): correct tier from 4 to 3
httpserver depends on launcher (Tier 2), placing it at Tier 3.
With launcher corrected from Tier 5 to Tier 2, httpserver's tier
drops accordingly.
2026-03-19 13:39:19 +00:00

2.0 KiB

ADR-001: chi over Echo

Status: Accepted Date: 2026-03-18

Context

httpserver needs an HTTP router. The two leading candidates were:

  • chi (github.com/go-chi/chi/v5) — a lightweight, idiomatic router whose root type implements http.Handler and whose middleware signature is func(http.Handler) http.Handler
  • Echo — a full web framework with its own Context type, its own middleware signature (echo.MiddlewareFunc), and handler signature (echo.HandlerFunc)

The project constraint is that all transport-layer modules must compose cleanly with the rest of the micro-lib stack, which is built entirely on stdlib net/http types. httpmw middleware, httputil handler adapters, and all application handlers use http.Handler and http.ResponseWriter/*http.Request directly.

Decision

Use chi. Every chi middleware is func(http.Handler) http.Handler, every chi handler is http.Handler, and chi.Router itself satisfies http.Handler. This means:

  • Any middleware written for the stdlib works with chi without wrapping.
  • Any http.Handler can be registered directly without conversion.
  • httputil.Handle and httputil.HandleNoBody adapters slot in without adapter code.
  • The server itself can be tested with httptest.NewRecorder against the router directly, without starting a process.

Echo would require wrapping every stdlib handler and middleware at the boundary, creating a permanent impedance mismatch between httpserver and the rest of the stack.

Consequences

  • All route handlers and middleware in this project must use stdlib net/http types. No Echo-style context is available.
  • chi's URL parameter API (chi.URLParam(r, "id")) is used for path parameters rather than a framework-specific context method.
  • The chi dependency is a direct, visible import in httpserver.go and in any application that calls srv.Route(...) with a func(chi.Router) callback. This is accepted as the deliberate, explicit contract of the embedded router design (see ADR-002).