javascript-today

Fiber, Gin, Echo, Chi, and Hertz: How Gos Web Frameworks Stack Up Against net/http in 2026

Every couple of years someone declares that Go doesn’t need web frameworks anymore, and every couple of years the standard library gets just good enough to make that argument plausible without quite settling it. Go 1.22 shipped method-aware routing and path wildcards straight into net/http.ServeMux, which quietly closed the single biggest reason people reached for a router package in the first place. And yet Fiber, Gin, Echo, Chi, and newer entrants like Hertz are all still very much alive, still shipping releases in 2026, still showing up in production stacks at real scale.

The honest reason is that “routing” was never the whole job. Binding and validating request bodies, structuring middleware chains, grouping routes, standardizing error responses, and squeezing out the last few microseconds under extreme load are all still things the stdlib either doesn’t do or does in a way that gets repetitive fast. Here’s a practical rundown of where each framework actually earns its keep, and where plain net/http is still the right call.


The baseline: what net/http can do on its own now

Before comparing frameworks, it’s worth being precise about what you get for free. As of Go 1.22, http.ServeMux supports method-restricted patterns, path wildcards, and precedence rules that used to require a third-party router:

mux := http.NewServeMux()

mux.HandleFunc("GET /posts/{id}", getPost)
mux.HandleFunc("POST /posts", createPost)
mux.HandleFunc("GET /files/{path...}", serveFile)

func getPost(w http.ResponseWriter, r *http.Request) {
    id := r.PathValue("id")
    // ...
}

"GET /posts/{id}" only matches GET requests and returns a 405 automatically for anything else. {id} captures a single path segment, {path...} captures the rest, and more specific patterns (/posts/latest) win over wildcards (/posts/{id}) without any registration-order gymnastics. For a huge share of small services and internal tools, this is genuinely enough — no dependency, no version to track, no abstraction between you and the request.

What it still doesn’t give you: request binding and validation, grouped middleware with sane composition, structured JSON error responses, built-in rate limiting or CORS helpers, or the kind of ergonomic route grouping (api.Group("/v1")) that makes a 40-endpoint service easy to navigate. That gap is exactly where every framework below lives.


Fiber: the zero-allocation engine

Fiber doesn’t sit on top of net/http at all — it’s built on fasthttp, which aggressively reuses buffer pools and internal structs to keep heap allocations per request close to zero, even under sustained heavy load. The API is deliberately Express.js-shaped, which makes it one of the fastest frameworks to actually write in, especially for anyone coming from Node.

Where it shines:

  • Extremely low memory footprint per request, which matters at real scale — thousands of RPS on modest hardware — not on a hello-world benchmark
  • An API that reads like Express, so the learning curve for teams with Node backgrounds is close to zero
  • Still actively shipping — the v3 line is the current release track in 2026, with the project sitting around 39k+ GitHub stars

Honest caveats:

  • Because it bypasses net/http entirely, fasthttp’s RequestCtx is not an http.ResponseWriter/*http.Request pair. Standard Go middleware written against net/http.Handler doesn’t just drop in — Fiber ships an adapter package, but it’s a translation layer, not native compatibility
  • Some net/http-only libraries (certain OpenTelemetry instrumentation, some pprof and debugging tooling, anything expecting context.Context wired through the stdlib request) need extra glue or don’t have a Fiber-native equivalent at all
  • You’re now depending on fasthttp’s behavior, which deviates from the HTTP semantics net/http guarantees in a few edge cases (notably around header reuse and streaming) — worth reading before betting a large service on it

Reach for Fiber when raw throughput-per-dollar on the HTTP layer is a real constraint and you’re comfortable trading some ecosystem compatibility for it.


Gin and Echo: the high-speed workhorses

Gin and Echo solve a different problem than Fiber does. Both build directly on net/http — Gin still wraps http.ResponseWriter and *http.Request, and Echo interoperates with stdlib handlers via echo.WrapHandler — so you keep full compatibility with the rest of the Go ecosystem: standard middleware, net/http-based instrumentation, httptest, all of it. What they add on top is a highly-tuned radix-tree router (Gin’s is its own implementation, originally inspired by httprouter; Echo calls it an “optimized” radix-tree router that prioritizes routes) that resolves routes with effectively zero allocation, plus batteries: JSON binding and validation, route grouping, structured error handling, and a large middleware ecosystem.

Where they shine:

  • Full net/http compatibility means you’re never fighting the ecosystem — drop in any stdlib-compatible middleware or observability tool without an adapter
  • Route resolution in the single-digit-microsecond range, which is close enough to the fasthttp-based frameworks that the difference rarely matters outside of extreme-scale services
  • Gin is the closest thing Go has to a default choice for REST APIs and microservices — 88k+ GitHub stars, an enormous middleware catalog, and it’s what most teams already have institutional knowledge of
  • Echo v5 (current as of early 2026, with v4 still supported through the end of the year) leaned further into a cleaner API and better context handling, and is a common pick when teams want Gin’s ergonomics with a slightly more opinionated structure

Honest caveats:

  • Neither is meaningfully faster than a well-written net/http + Chi combination for anything short of extreme request volume — the win is developer ergonomics (binding, grouping, built-in helpers) more than raw speed
  • Both frameworks have their own context type (gin.Context, echo.Context) that wraps the request — it’s not a hard lock-in like fasthttp’s RequestCtx, but it’s still an abstraction you’re writing handlers against instead of plain net/http

Reach for Gin or Echo when you want a batteries-included REST framework that never makes you fight the standard library to get there.


Chi: 100% stdlib-compatible, zero-cost routing

Chi takes a narrower, more deliberate approach: it’s a router, not a framework. It’s 100% compatible with net/http’s Handler and HandlerFunc — no proprietary context type, no wrapper around the request or response. It uses a Patricia radix trie for routing, adds effectively zero allocation overhead over calling a stdlib handler directly, and the entire router implementation is under 1,000 lines of code with zero external dependencies.

Where it shines:

  • Because handlers are plain func(w http.ResponseWriter, r *http.Request), literally anything written for net/http — middleware, testing helpers, instrumentation — works without an adapter, forever
  • Clean, composable route grouping and middleware chaining without wrapping you in a framework’s opinions about binding, rendering, or error handling
  • Zero dependencies beyond the stdlib is a real supply-chain and long-term-maintenance advantage, especially for services meant to keep running with minimal upkeep for years

Honest caveats:

  • You don’t get Gin/Echo’s batteries — no built-in JSON binding/validation, no built-in structured error responses. You’re assembling those yourself or pulling in separate small packages
  • For teams that want an opinionated, complete framework experience out of the box, Chi’s minimalism can feel like more setup work up front

Reach for Chi when you want better ergonomics than raw ServeMux for a larger service, but refuse to give up plain net/http compatibility to get there.


Hertz: ByteDance’s extreme-scale framework

Hertz is the newest name on this list to most Go developers outside of large-scale infra teams, but it’s not new in production — it’s the framework ByteDance built and runs internally across its microservice fleet, open-sourced under the CloudWeGo umbrella. Instead of building on fasthttp or net/http, Hertz pairs a from-scratch networking engine called netpoll with fasthttp-style zero-allocation principles, and it can fall back to Go’s standard net package when netpoll’s epoll-based, non-blocking I/O model isn’t the right fit for a given deployment.

Where it shines:

  • Built specifically for millions of simultaneous RPC and HTTP connections with minimal GC pressure — this is the framework to look at when Gin-at-scale starts showing GC pauses under real production load
  • Ships code generation tooling (via its IDL-based workflow) aimed at large microservice fleets where consistency across dozens or hundreds of services matters more than any individual service’s flexibility
  • CloudWeGo’s own benchmarks show it ahead of fasthttp, Gin, and Echo in echo-request scenarios — worth treating as a relative signal rather than a promise, as with any vendor benchmark, but it’s a serious, actively maintained project rather than a toy

Honest caveats:

  • The ecosystem and English-language documentation are thinner than Gin’s or Echo’s — you’ll read more source and lean more on CloudWeGo’s own docs than Stack Overflow
  • Like Fiber, netpoll’s custom I/O model means you’re stepping outside net/http compatibility; the code-generation-heavy, IDL-driven workflow is also a bigger structural commitment than dropping in a router
  • It’s genuinely built for a scale most services never reach. Adopting Hertz for a service doing a few thousand RPS is bringing a scalpel-shaped-like-a-sledgehammer to a job that doesn’t need it

Reach for Hertz when you’re operating at genuine hyperscale-microservice traffic and Gin or Echo’s GC and allocation behavior has started showing up as a real bottleneck, not a theoretical one.


Quick reference

Framework Built on Router net/http compatible Best for
net/http (stdlib) ServeMux (Go 1.22+: methods, wildcards, precedence) Native Small services, internal tools, anything where zero dependencies and long-term stability matter more than convenience
Fiber fasthttp Custom, near-zero allocation No (adapter required) High-RPS services where memory-per-request is a hard constraint and Express-style ergonomics matter
Gin net/http Custom radix tree (httprouter-inspired) Native The default choice for REST APIs and microservices — batteries included, huge ecosystem
Echo net/http Optimized radix tree Native (via wrappers) Same use case as Gin, with a cleaner/more opinionated API in the v5 line
Chi net/http Patricia radix trie Native, zero abstraction Larger services that want real routing/grouping ergonomics without leaving plain net/http
Hertz netpoll (custom) Radix-tree, code-gen tooling No (adapter required) Hyperscale microservice fleets — millions of concurrent connections, GC-sensitive workloads

Which one to actually reach for

If the project is a handful of endpoints, an internal tool, or anything meant to be a single small binary with minimal upkeep — a local-first utility, a CLI companion server, something you want to still compile cleanly five years from now with no dependency rot — plain net/http on Go 1.22+ is genuinely enough now, and it wasn’t two years ago. That’s the real headline: the stdlib closed the gap for the simple case.

For a REST API or microservice of any real size, Gin remains the safe, well-worn default, with Echo a close and increasingly polished alternative if you prefer its API shape. If you want that same ergonomic improvement over ServeMux without ever leaving net/http’s compatibility guarantees — because you know you’ll need some stdlib-only middleware or tooling down the line — Chi is the better fit than either.

Fiber and Hertz both trade net/http compatibility for raw performance, but for different reasons and different scales: Fiber when per-request memory efficiency matters on infrastructure you’re paying for by the gigabyte, Hertz when you’re operating at a traffic scale where Gin’s GC behavior itself becomes the bottleneck. Neither is the right first choice for a typical service — both are the right choice once you’ve actually measured a problem they solve.

Sources: