Skip to content
Trilha
Chapters

Reference

Performance and comparison

How much Trilha costs over the standard library, how to measure it yourself, and how it compares with other approaches.

Methodology#

The only number worth publishing is the cost of the framework over the standard library, which is the real alternative in Go. The benchmarks live in bench/ (a separate module, so Trilha stays dependency-free) and measure, in process (httptest, no network), the same work done two ways: with Trilha and with plain net/http + html/template.

git clone https://github.com/emersonjoe/trilha && cd trilha
make bench            # runs; make bench-results rewrites bench/RESULTS.md

Scenarios: page with layout and 20 items (h × html/template), JSON response, static file (Public × http.FileServer), 200 routes with a parameter (ServeMux on both sides) and a chain of 5 middlewares.

Reference results#

Apple M2, Go 1.25, 2026-09-05 (median of 3 runs; bench/RESULTS.md has the full output). Values per request.

ScenarioStdlibTrilhaDifference
Page (20 items, layout)29.4 µs · 270 allocs19.4 µs · 482 allocsh is ~34 % faster than html/template here, with more allocations
JSON (20 items)4.2 µs7.6 µs+3.4 µs
Static (1.4 KB)1.4 µs4.3 µs+2.9 µs
200 routes + parameter0.72 µs4.0 µs+3.3 µs
5 middlewares0.64 µs4.1 µs+3.4 µs

Honest reading: Trilha has a fixed cost of ~3 µs and ~40 allocations per request, regardless of the route. It pays for: request id (random), CSP nonce, security headers, Ctx with a value map, body limit, timing and structured logging of every request (slog, which formats the line even when discarded). In a real server a database query costs 100 µs to a few ms, and the network more; the difference disappears. If that ever matters to you, the path is reducing allocations in Ctx and making logging optional per route — and the benchmark is there to prove the gain.

Observability#

ScenarioWithout metricsWith metricsDifference
Trivial route (c.Text)4.1 µs · 50 allocs4.1 µs · 50 allocswithin noise; zero allocations
/_trilha/health/live probe0.9 µs · 18 allocsbypasses the router and the middleware chain

Instrumentation only exists when Observability.Metrics is configured; off, it is a pointer comparison. On, the series key is built in a stack buffer and looked up as map[string(bytes)], a form the compiler resolves without allocating — which is why the allocation count does not change.

The edit → see cycle of trilha dev is ~1.2 s in the blog example (Go recompilation) and ~30 ms for changes only in public/ (make reload measures on your machine).

Comparison of approach#

No third-party numbers: versions change, configurations differ and each project optimizes for different things. What can be compared safely is the approach. Always check each project's documentation; names cited are trademarks of their respective owners and there is no affiliation.

Trilhaplain net/httpGo routers (chi, echo, gin, fiber)templ + htmxNext.js
Routesby folders in app/ (page.go, route.go)registered by handregistered by handregistered by hand (with the router you choose)by folders in app/
Nested layoutslayout.go per foldermanualmanualcomponentslayout.tsx
HTMLtyped h DSL (escaped by default) or html/templatehtml/templatehtml/template or libstempl (compiled)JSX/React
Client interactivityHTML + ui.js (200 lines) or htmx; no hydrationyour choiceyour choicehtmxReact (hydration, RSC)
Runtime dependenciesnonenonethe router (+ deps)templ (+ generator)Node, React, Next
Devtrilha dev: ~1 s reload, compile error on the pagemanual go runair/manualtempl generate --watch + reloadnext dev (HMR)
Productionone static binary with public/ embeddedbinarybinarybinaryNode or edge; build
Static exporttrilha exportmanualmanualmanualoutput: 'export'
Default securityCSP with nonce, HSTS, CSRF, rate limit, signed cookies, timeoutsnothing (you configure)variesnothing (you configure)basic headers; CSRF in Server Actions
AIai (OpenAI-compatible), ai/mcpVercel AI SDK (package)

When not to use Trilha: apps that need a highly interactive client UI (editors, real-time dashboards with complex state) are better served by React/Next or by an SPA; and projects that already have a Go router and mature templates gain little by switching. Trilha shines in server-rendered business apps, content sites and APIs with a dashboard, where a dependency-free binary and strong conventions weigh more than fine-grained interactivity.

Cost per feature for an agent#

The numbers above are what the framework costs per request. There is a second cost, paid by whoever writes the app with an AI tool: the tokens an agent spends discovering what the project already has, getting a signature wrong, running five checks one at a time. That is what bench/agent measures.

make bench-agent copies examples/blog or examples/sso into a module of its own, runs a coding agent (claude -p, with no MCP servers, plugins or user memory: only what is inside the project counts) on four fixed tasks, and decides pass or fail with a hidden test:

ScenarioTask
commentsPOST/GET /api/posts/{id}/comments with Bind, validation, 404
contact-forma /contato page inside the root layout with a ui form
cognitoswitch the login provider of the SSO example from Keycloak to Cognito
paginationfive posts per page at /blog, with ?page=N and prev/next

Each scenario runs three times; bench/agent/RESULTS.md shows the median of tokens in (fresh and read from cache), tokens out, turns, denied tool calls, time and cost, and how many runs passed. The comparison is always Trilha before against Trilha after — same task, same agent, same model — never against another framework. make bench-agent-dry builds the fixtures and proves the hidden tests fail without an agent, spending nothing; the CI never runs the agent.