This episode covers Fiber v3 performance tips and best practices: limit middleware, use fasthttp pooling and prefork, render templates with github.com/gofiber/template, and serve public asset files and folders with app.Static.

Fiber is built on fasthttp and is very fast — but performance still depends on how we use it. Episode 12 covers performance tips and best practices: limiting middleware, leveraging fasthttp pooling, rendering templates, and serving public assets correctly.
Performance is a cumulative result. A little waste in every middleware will be felt under high traffic. This topic also completes the part of web applications we haven't touched yet: HTML pages from the server.
Every middleware adds per-request cost. Only install middleware you actually need, and attach it to groups rather than globally:
app := fiber.New()
app.Use(logger.New())
app.Use(recover.New())
api := app.Group("/api", authMiddleware())
admin := app.Group("/admin", authMiddleware(), rateLimiter())logger and recover genuinely need to be global. But authMiddleware is enough for the /api group, and rateLimiter only for /admin. Too much middleware at the global level slows down every route for no reason.
Fiber uses fasthttp, which reuses connections and buffers. Avoid storing *fiber.Ctx pointers outside the handler scope:
func badHandler(c fiber.Ctx) error {
globalCtx = &c // jangan simpan ctx: di-reuse antar request
return nil
}
func goodHandler(c fiber.Ctx) error {
result := c.Params("id") // salin data yang dibutuhkan
storeResult(result)
return nil
}The fasthttp context is recycled after the request finishes. Storing a Ctx pointer in a global variable or goroutine will read request data that has already expired. Always copy the values you need before the handler finishes.
Prefork runs several workers, one per CPU core. This multiplies throughput on multicore machines:
app := fiber.New(fiber.Config{
Prefork: true,
})With Prefork: true, Fiber creates one worker process per core and shares the port. Great for production; for development it's better to turn it off because hot-reload works more simply with a single process.
Fiber doesn't put a template engine in its core. Use the github.com/gofiber/template package, which provides many engines — HTML, Pug, Mustache, and others:
import "github.com/gofiber/template/html/v2"
engine := html.New("./views", ".html")
app := fiber.New(fiber.Config{
Views: engine,
})html.New("./views", ".html") loads all .html files from the views folder. For another engine, just change the import, for example template/pug/v2 or template/mustache/v2 — the fiber.Views interface stays the same.
With Views installed, handlers can render full HTML pages complete with data:
app.Get("/", func(c fiber.Ctx) error {
return c.Render("index", fiber.Map{
"Title": "Halaman Utama",
"User": map[string]any{"Name": "Budi"},
}, "layouts/main")
})c.Render("index", data, "layouts/main") renders the index template with data, then wraps it in the layouts/main layout. The result is a complete HTML page from the server — the main pattern for applications that aren't pure APIs.
app.Static serves files from a folder, and app.StaticIndex sets a folder's index file:
app.Static("/", "./public")
app.StaticIndex("/", "./public/index.html")app.Static("/", "./public") maps / to the public folder. If ./public/index.html exists, the / route responds with that page directly — no extra handler needed. For a single file, use app.Static("/favicon.ico", "./public/favicon.ico").
curl http://localhost:3000/
curl http://localhost:3000/public/logo.pngThe first request renders the index template with its layout; the second fetches a file from the public folder. Check the logs to confirm the logger middleware records both.
Key takeaways:
*fiber.Ctx pointers outside the handler scope because fasthttp reuses the ctx.Prefork: true uses all cores for higher throughput.github.com/gofiber/template provides HTML, Pug, Mustache, and other engines.c.Render(name, data, layout) renders complete server-side pages.app.Static and app.StaticIndex serve public asset folders and files.In the next episode, episode 13, we discuss server events (SSE) — streaming events to the browser with EventSource, hooking events, and event listeners in Fiber v3.