Learning Fiber - Hooks and Event-Driven in v3
Series/Learn Fiber/Episode 15
Episode 15 of 23

Learning Fiber - Hooks and Event-Driven in v3

This episode covers hooks and the event-driven pattern in Fiber v3: the OnListen and OnShutdown lifecycle hooks, hooks when routes and groups are registered, custom events via On and Emit, and using hooks for instrumentation and observability.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

In episode 6 you saw the OnListen and OnShutdown hooks. Episode 15 expands this topic into an event-driven pattern: Fiber v3 registers hooks not only for the server lifecycle, but also for events inside the application — such as when a route is registered — plus custom events you can define yourself.

The event-driven pattern separates "what happens" from "who responds". This is very useful for logging, metrics, audit, and integrations — monitoring code no longer gets mixed into every handler.

Lifecycle Hooks

Running Actions at Important Moments

Lifecycle hooks give you entry points at the start and end of the server's life. They can be registered directly or chained:

Lifecycle hooks
app.Hooks().OnListen(func(addr fiber.ListenOnListenData) error {
    log.Printf("listening on %s", addr.Addr)
    return nil
})
 
app.Hooks().OnShutdown(func() {
    closeDB()
    cancelBackgroundJobs()
})

OnListen is called when the server is ready to accept connections; OnShutdown when graceful shutdown begins. The full family: OnListen, OnShutdown, OnPreShutdown, OnPostShutdown, OnMount, OnUnmount, and OnFork. Closing resources in hooks is cleaner than putting them in main.

Hooks for Routes

Detecting Route and Group Registration

Fiber v3 fires hooks every time a route, name, or group is registered. This opens the door to automatic tooling:

Hooks saat route didaftarkan
app.Hooks().OnRoute(func(r fiber.Route) error {
    log.Printf("route terdaftar: %s %s", r.Method, r.Path)
    return nil
})
 
app.Hooks().OnGroup(func(g *fiber.Group) error {
    log.Printf("group dibuat: prefix=%s", g.Prefix)
    return nil
})

OnRoute is called every time a new route is registered, carrying a fiber.Route object with method and path. OnGroup is called when a group is created. With these hooks, an endpoint list can be generated automatically for documentation without writing it by hand.

Custom Events

Emitting and Listening to Your Own Events

Besides built-in hooks, Fiber v3 supports custom events through On and Emit:

Custom events
app.Hooks().On("user:created", func(data any) {
    metrics.Inc("user_created")
    notify("user", data)
})
 
app.Post("/users", func(c fiber.Ctx) error {
    var user User
    if err := c.Bind().JSON(&user); err != nil {
        return err
    }
    createUser(user)
    app.Hooks().Emit("user:created", user)
    return c.Status(fiber.StatusCreated).JSON(user)
})

app.Hooks().On("user:created", fn) registers a listener; app.Hooks().Emit("user:created", user) sends an event complete with data. Handlers just call Emit — they don't need to know who's listening. Adding new features (email, webhook, audit) only requires adding a listener, without touching the handler.

Event Naming Convention

Custom events will grow over time. Set a naming pattern early so they're easy to track:

Pola penamaan event
app.Hooks().On("order:placed", handleOrderPlaced)
app.Hooks().On("order:payment-failed", handlePaymentFailed)
app.Hooks().On("order:fulfilled", handleOrderFulfilled)

The domain:action pattern — order:placed, payment-failed, fulfilled — makes events easy to find and map. Naming consistency matters when you have dozens of events and listeners spread across many files.

Instrumentation with Hooks

Example: Metrics and Audit

The combination of built-in hooks and custom events forms an observability layer without polluting business code:

Instrumentasi via hooks
app.Hooks().OnListen(func(d fiber.ListenOnListenData) error {
    metrics.Gauge("uptime", 0)
    return nil
})
 
app.Hooks().OnRoute(func(r fiber.Route) error {
    auditLog("route_registered", map[string]string{
        "method": r.Method, "path": r.Path,
    })
    return nil
})

A single registration point records every route for audit; a single OnListen listener initializes metrics. The result: logs and metrics that are consistent, centralized, and easy to remove when no longer needed.

Testing

Melihat hooks bekerja
curl -X POST -H "Content-Type: application/json" \
  --data '{"name":"Budi"}' http://localhost:3000/users

While the server runs, look at the terminal: the OnListen and OnRoute hooks print logs at startup. When the POST request above is processed, the user:created event triggers the metrics and notification listeners — all recorded without extra code in the main handler.

Closing

Key takeaways:

  • Lifecycle hooks: OnListen, OnShutdown, OnPreShutdown, OnPostShutdown, OnMount, OnUnmount, OnFork.
  • OnRoute and OnGroup fire events when routes/groups are registered — useful for tooling.
  • Custom events use app.Hooks().On(name, fn) and app.Hooks().Emit(name, data).
  • Handlers just Emit; listeners handle the side effects.
  • The domain:action naming pattern keeps events organized.
  • Hooks are the foundation of instrumentation: centralized metrics, audit, and logs.

In the next episode, episode 16, we discuss JWT and security — the jwt middleware in Fiber, token validation, secret storage, and API authentication security practices.