Updated Jun 23, 2026

Where to Go Next

Stop for a second and look at what you can actually do now. You can spin up an Echo server, route requests with path and query parameters, group routes, bind and validate JSON into structs with c.Bind, shape responses with c.JSON and the right status codes, write and chain middleware, build full CRUD for a resource, and let Echo's central HTTPErrorHandler turn returned errors into clean HTTP responses — then test the whole thing with httptest and ship it with graceful shutdown. That's a real REST API, not a toy.

And here's the quieter win. Echo is a thin, error-clean layer over net/http. An instance (echo.New()) holds your routes and middleware, an echo.Context carries each request, and your handlers func(c echo.Context) error return their failures for one central handler to render. Nothing was hidden behind magic — which means when something breaks at 2am, you can reason about it.

So this last phase isn't more handlers. It's the map: where Echo sits among the other Go web frameworks, the layer you'll almost certainly add next, and one concrete thing to go build.

Echo vs the field

You now know enough to choose a framework on purpose rather than by reputation. The good news in Go: these frameworks are far more alike than the JavaScript world's are. They all sit on (or near) net/http, they all do routing, params, and middleware. The differences are about feel, not whole different universes.

flowchart TD
  Start[Need a Go web service?] --> Std{Stdlib purity?}
  Std -- Yes, minimal --> Chi[chi or net/http]
  Std -- No, want batteries --> Style{Handler style?}
  Style -- Return an error --> Echo[Echo]
  Style -- Write to a context --> Gin[Gin]

A line on each:

  • Echo — error-returning handlers (func(c echo.Context) error), a generous set of built-in middleware, and a central HTTPErrorHandler that renders failures in one place. If you like writing handlers that hand their errors up rather than writing the response by hand, this is your framework. (You're here.)
  • Gin — the most popular Go web framework, with the biggest ecosystem and the most Stack Overflow answers. The main stylistic difference: handlers take a *gin.Context and write to it instead of returning an error. See Gin From Zero.
  • chi — minimal and proudly so. It's a router that stays pure net/http — handlers are plain http.HandlerFunc, middleware is standard func(http.Handler) http.Handler. Nothing to unlearn, nothing locked in. See chi From Zero.
  • The standard library alone — for many services, net/http plus modern Go's routing is genuinely enough. Knowing what Echo saves you starts with knowing what you'd write by hand. See Web Services With Only net/http.

💡 How to pick: Echo and Gin are very close — same speed class, same batteries-included spirit. The real choice between them is taste: do you prefer handlers that return an error (Echo) or ones that write to a context (Gin), and which built-in middleware you want out of the box. Reach for chi or net/http instead when you want stdlib purity and zero lock-in.

📝 None of these is "the best." They're aimed at slightly different tastes. The senior instinct isn't memorizing a winner — it's asking "best for this job and this team?" and answering honestly. You have the pieces for that now.

The layer you'll add next: a real database

Every API in this guide stored books in memory. That's perfect for learning and useless in production — restart the server and the data's gone. The very next thing almost every real Echo service grows is a database.

Here's the reassuring part: your handlers barely change. Remember how Phase 6 kept the HTTP logic separate from where the data lived? That paid off. The handler still binds JSON, validates, calls a store, and returns a response (or an error, the Echo way). All that swaps underneath is the store — from a map to a database-backed one.

GORM From Zero is the natural next read. GORM is Go's most popular ORM: you define your Book struct, point it at SQLite (or Postgres later), and your create/read/ update/delete calls become real persistence. The shape of your Phase 6 handlers stays intact — you're replacing the bottom layer, not rewriting the top.

What to build

Reading more won't make this stick. Building one real thing will. So here's the assignment, and it's deliberately concrete.

Take the books API you grew across this guide and carry it all the way home:

  • Swap the in-memory store for GORM + SQLite so books survive a restart. The handlers stay; the store changes. (GORM From Zero walks the persistence part.)
  • Add JWT auth with Echo's built-in middleware.JWT so each request proves who it is, and books belong to a user. This is exactly the middleware pattern from Phase 5, applied to a real job.
  • Add request logging (and, when you're ready, basic metrics) so you can see what your service is doing in production — Echo ships a Logger middleware to start from.
  • Generate API docs with OpenAPI/Swagger so other people — and future you — can read the contract.
  • Tidy up config so secrets and ports come from the environment, not hardcoded values.
  • Deploy it somewhere you can hit from your phone, with the graceful shutdown from Phase 7 wired up.

If the books API feels too familiar, build something small and new end to end instead — a notes API or a bookmarks API. Same muscles: routes, binding, a store, middleware, tests, deploy. The point is finishing one project completely, which teaches more than three more tutorials would.

The honest close

Echo was never magic. Strip the helpers away and it's a handful of things you now understand completely: an instance that holds your routes, a context that carries each request, a middleware chain that wraps it all, and handlers that return errors for a central handler to render — all sitting on the same net/http you could write by hand if you had to.

That's why you can read the machine now. You can build a real service on top of Echo, and — more importantly — reason about it when it misbehaves. Go finish the books API, give it a database, lock it behind JWT, deploy it, and show someone. You're ready.

Recap

  1. You can ship a real Echo API — routed, bound and validated, middleware-wrapped, tested, and deployed — and you understand why, because Echo hid nothing behind magic.
  2. Echo and Gin are close cousins — same speed class and batteries; pick by handler style (Echo returns errors, Gin writes to a context) and which built-in middleware you want.
  3. Reach for chi or net/http when you want stdlib purity and zero lock-in instead of batteries.
  4. A database is the next layer — most Echo services add one, and with the Phase 6 separation in place your handlers barely change; you swap the in-memory store for GORM.
  5. Build and finish one thing — carry the books API to GORM + SQLite, JWT auth, request logging, OpenAPI docs, real config, and a deploy. Or build a small notes / bookmarks API end to end.

Quick check

Three decisions to take with you as you leave this guide:

[
  {
    "q": "You like writing handlers that return an error for one central handler to render, and you want generous built-in middleware. Which framework fits best?",
    "choices": [
      "chi, because it's minimal",
      "Echo, with its error-returning handlers and central HTTPErrorHandler",
      "net/http alone, always",
      "Gin, because it writes to a context"
    ],
    "answer": 1,
    "explain": "Echo's whole personality is handlers that return an error (func(c echo.Context) error) for a central HTTPErrorHandler, plus a generous set of built-in middleware. Gin writes to a context instead; chi and net/http favor stdlib purity over batteries."
  },
  {
    "q": "How should you honestly choose between Echo and Gin?",
    "choices": [
      "Gin is always faster, so pick Gin",
      "They're very close — pick by handler style (return an error vs write to a context) and which built-in middleware you want",
      "Echo is built on fasthttp, so it can't use net/http middleware",
      "Echo is for beginners and Gin is for experts"
    ],
    "answer": 1,
    "explain": "Echo and Gin are in the same speed and batteries class. The real difference is taste: error-returning handlers (Echo) versus writing to a context (Gin), and which built-in middleware each gives you. Both sit on net/http."
  },
  {
    "q": "You're adding a real database to your books API from Phase 6. What mostly changes?",
    "choices": [
      "Every handler must be rewritten from scratch",
      "Only the store layer swaps from an in-memory map to a GORM-backed one; the handlers stay roughly the same",
      "You must abandon Echo and switch to chi",
      "Nothing — Echo stores data in a database automatically"
    ],
    "answer": 1,
    "explain": "Because the HTTP logic was kept separate from where data lives, the handlers still bind, validate, call a store, and return a response or error. You swap the store from a map to GORM + a database — the bottom layer changes, the top stays."
  }
]

← Phase 7: Testing & Production · Guide overview

Check your understanding

1. You like writing handlers that return an error for one central handler to render, and you want generous built-in middleware. Which framework fits best?

2. How should you honestly choose between Echo and Gin?

3. You're adding a real database to your books API from Phase 6. What mostly changes?

Was this page helpful?