This episode dissects Echo's architecture from the inside: how echo.Echo becomes a net/http handler, how the radix tree router matches paths, the execution order of the middleware chain, and the role of echo.Context that wraps request and response in every handler.

Before writing code, you need to understand what happens behind the scenes. Echo is often called a "web framework", but it's really a thin layer that orchestrates how standard HTTP requests are processed. Understanding this architecture will make debugging much easier throughout the series.
Episode 2 dissects Echo's architecture from the inside: how an echo.Echo instance becomes a net/http handler, how the radix tree router matches paths, how the middleware chain is executed at root, group, and route levels, and the role of echo.Context that wraps request and response.
The flow of a request in Echo is simple but precise:
net/http server receives the request and calls the Echo handler.echo.Context.In Echo v5, the handler signature is func(echo.Context) error. Note that in v5 echo.Context is always a pointer *echo.Context, an important change from v4 that we'll discuss in episode 20.
func handler(c echo.Context) error {
return c.String(200, "selamat datang di Echo")
}The handler receives a context, does something, then returns an error. The function handler(c echo.Context) error is the basic contract of every Echo application — there are no hidden panics, all failures flow as errors.
The core of Echo's performance is the router. The router uses a radix tree — a compressed trie — where each node represents a path segment. Matching is done per character in a single pass, not by iterating over a list of routes.
Each node stores the supported HTTP methods, the handler, and middleware metadata. When a route is registered, Echo inserts it into the tree according to the path pattern. That's why e.GET("/users/:id") and e.GET("/users/:id/posts") don't collide — they're different nodes on the same branch.
e := echo.New()
e.GET("/users/:id", getUser)
e.GET("/users/:id/posts", getPosts)When a request to /users/42 comes in, the router traverses the tree, finds the :id node, and fills in the parameter value 42. The handler retrieves this value via c.Param("id").
One of Echo's strengths: automatic route priority. If you register /users/new and /users/:id, the static new route takes precedence when a request comes in for /users/new — no special registration order needed. This differs from some other frameworks that depend on declaration order.
Echo middleware is arranged like layers of an onion. Execution starts from the outermost middleware, descends through c.Next(), reaches the handler, then climbs back up. Where you attach middleware determines its position in the chain:
e.Pre: middleware before routing, runs first.e.Use: middleware at the root level, applies to all routes.group.Use: middleware specific to a group.e := echo.New()
e.Pre(middleware.RemoveTrailingSlash())
e.Use(middleware.Logger())
api := e.Group("/api", middleware.CORS())
api.GET("/health", healthHandler)In the code above, RemoveTrailingSlash runs before routing, Logger for all requests, and CORS only for routes inside the /api group. This is a pattern you'll use over and over.
echo.Context is the object you'll touch most often. It wraps the request (c.Request()), the response (c.Response()), route parameters, query, and data stored inside it.
In Echo v5, the context is a pointer *echo.Context, which makes it lighter to pass around and store. The context provides a set of methods that will accompany you throughout the series:
name := c.Param("name")
q := c.QueryParam("q")
body := new(User)
if err := c.Bind(body); err != nil {
return err
}
return c.JSON(200, body)Methods like c.Param, c.QueryParam, c.Bind, and c.JSON are the most widely used parts of the API surface — their details will be broken down one by one in episodes 4, 5, and 7.
Echo's architecture can be summarized in the following components:
func(echo.Context) error function containing the application logic.All of these components can be replaced or customized. The binder, validator, and renderer are pluggable — you'll take advantage of this starting in episode 5.
cd belajar-echo
go mod tidyRun go mod tidy to clean up dependencies before writing code in the next episode.
Episode 2 lifted the veil on Echo's architecture: echo.Echo is a net/http handler, the radix tree router matches paths in a single pass with automatic priority, middleware is arranged in layers at pre, root, group, and route levels, and echo.Context is the main bridge between request, response, and handler.
Key takeaways:
echo.Echo is wrapped into a standard net/http handler.e.Pre, e.Use, group.Use, and route middleware have different scopes.echo.Context is a pointer *echo.Context.In the next episode we'll build setup & hello world — your first Echo project with echo.New(), the RequestLogger middleware based on slog and Recover, your first handler that returns text and JSON, and running the server on port 8080. Preparation is done, time to write real code!