Skip to content
Snapshot of the v0.7 release. Fixes and additions since then are not in it. Current documentation →
Performance & Benchmarks

Performance & Benchmarks

goninja keeps a small benchmark suite to catch regressions in the request path. These are reproducible baselines for this repository, not claims that one framework is universally faster than another.

What is measured

Every benchmark seeds an in-memory SQLite database with 1,000 rows, starts a real goninjatest HTTP server, then measures complete HTTP GET requests. The measured work includes routing, generated handlers, GORM queries, conversion to generated response types, JSON encoding, and response-body draining. Seeding happens before the timer starts.

Task list

GET /tasks

List query and collection serialization.

Filtered book list

GET /books?published=true&…

Filter parsing, WHERE construction, count, list query, and serialization.

Book detail + preload

GET /books/{id}

Detail retrieval plus the automatic belongs-to preload.

This is not a production-deployment benchmark: there is no network hop, reverse proxy, PostgreSQL server, application middleware, or application-specific business logic. Do not compare these numbers directly with a benchmark that measures a different stack or workload.

Current tracked baseline

Tracked baseline

Ten samples per benchmark · representative medians

View raw samples

Task list

GET /tasks

75.5µs / op

Memory
19.6 KB
Allocs
415

Filtered book list

GET /books?…

189.0µs / op

Memory
37.3 KB
Allocs
840

Book detail + preload

GET /books/{id}

69.2µs / op

Memory
22.8 KB
Allocs
276

The raw file, rather than this table, is the source of truth. Hardware, Go version, database driver, operating-system load, and the benchmark workload all affect the result.

Run the suite

$ make bench

That runs each benchmark once with Go’s normal benchmark calibration. To refresh the committed ten-sample baseline deliberately:

$ make bench-baseline

Review and commit that file only when a change in the numbers is understood. It is not an automatic maintenance task.

Regression protection in CI

Pull requests that affect Go code, benchmark tooling, or their dependencies run make bench-check. CI takes ten fresh samples, compares them with the tracked baseline using benchstat, and fails only for a statistically significant regression above 25% in time, bytes allocated, or allocations. The comparison report is uploaded as a build artifact even when the check fails.

The threshold is intentionally wide because shared CI runners are noisy. A passing check means “no large measured regression under this workload,” not “performance is proven for every application.” Profile a real workload before making an optimization decision.