Skip to main content
Healthcheck middleware provides liveness, readiness, and startup probe endpoints for Fiber applications, following Kubernetes health check conventions.

Installation

go get -u github.com/gofiber/fiber/v3
go get -u github.com/gofiber/fiber/v3/middleware/healthcheck

Signatures

func New(config ...Config) fiber.Handler

Constants

const (
    LivenessEndpoint  = "/livez"    // Liveness probe endpoint
    ReadinessEndpoint = "/readyz"   // Readiness probe endpoint
    StartupEndpoint   = "/startupz" // Startup probe endpoint
)

Usage

Basic Usage

package main

import (
    "github.com/gofiber/fiber/v3"
    "github.com/gofiber/fiber/v3/middleware/healthcheck"
)

func main() {
    app := fiber.New()

    // Use default health checks (always return true)
    app.Get(healthcheck.LivenessEndpoint, healthcheck.New())
    app.Get(healthcheck.ReadinessEndpoint, healthcheck.New())
    app.Get(healthcheck.StartupEndpoint, healthcheck.New())

    app.Listen(":3000")
}

Custom Probes

var (
    dbReady    = false
    cacheReady = false
    started    = false
)

// Liveness: Is the application running?
app.Get(healthcheck.LivenessEndpoint, healthcheck.New())

// Readiness: Can the application handle requests?
app.Get(healthcheck.ReadinessEndpoint, healthcheck.New(healthcheck.Config{
    Probe: func(c fiber.Ctx) bool {
        return dbReady && cacheReady
    },
}))

// Startup: Has the application finished starting up?
app.Get(healthcheck.StartupEndpoint, healthcheck.New(healthcheck.Config{
    Probe: func(c fiber.Ctx) bool {
        return started
    },
}))

Custom Endpoints

// Use custom endpoint names
app.Get("/health", healthcheck.New())
app.Get("/ready", healthcheck.New(healthcheck.Config{
    Probe: func(c fiber.Ctx) bool {
        return checkDependencies()
    },
}))

All Methods Support

// Respond to all HTTP methods
app.All("/healthz", healthcheck.New())

Configuration

Next
func(fiber.Ctx) bool
default:"nil"
Function to skip this middleware when it returns true. Note: If this returns true and no other handlers are defined for the route, Fiber returns 404 Not Found.
Probe
func(fiber.Ctx) bool
default:"func(c fiber.Ctx) bool { return true }"
Function executed to determine health state. Returning true indicates the application is healthy (200 OK), false indicates unhealthy (503 Service Unavailable).

Default Configuration

func defaultProbe(_ fiber.Ctx) bool { return true }

var ConfigDefault = Config{
    Next:  nil,
    Probe: defaultProbe,
}

Best Practices

Probe Types

  • Liveness: Checks if the application is running. If this fails, the container should be restarted.
  • Readiness: Checks if the application is ready to accept traffic. If this fails, traffic should be stopped.
  • Startup: Checks if the application has finished starting. Protects slow-starting containers from premature termination.

Kubernetes Configuration

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  containers:
  - name: app
    image: my-app:latest
    livenessProbe:
      httpGet:
        path: /livez
        port: 3000
      initialDelaySeconds: 3
      periodSeconds: 10
    readinessProbe:
      httpGet:
        path: /readyz
        port: 3000
      initialDelaySeconds: 5
      periodSeconds: 5
    startupProbe:
      httpGet:
        path: /startupz
        port: 3000
      failureThreshold: 30
      periodSeconds: 10

Common Patterns

Database Health Check

func checkDatabase(db *sql.DB) bool {
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()
    return db.PingContext(ctx) == nil
}

app.Get(healthcheck.ReadinessEndpoint, healthcheck.New(healthcheck.Config{
    Probe: func(c fiber.Ctx) bool {
        return checkDatabase(db)
    },
}))

Multiple Service Dependencies

type HealthChecker struct {
    db    *sql.DB
    cache *redis.Client
}

func (h *HealthChecker) IsReady() bool {
    // Check all dependencies
    dbOK := h.db.Ping() == nil
    cacheOK := h.cache.Ping(context.Background()).Err() == nil
    return dbOK && cacheOK
}

checker := &HealthChecker{db: db, cache: cache}

app.Get(healthcheck.ReadinessEndpoint, healthcheck.New(healthcheck.Config{
    Probe: func(c fiber.Ctx) bool {
        return checker.IsReady()
    },
}))

Startup Probe with Initialization

var startupComplete atomic.Bool

func main() {
    app := fiber.New()

    // Startup probe
    app.Get(healthcheck.StartupEndpoint, healthcheck.New(healthcheck.Config{
        Probe: func(c fiber.Ctx) bool {
            return startupComplete.Load()
        },
    }))

    // Run initialization in background
    go func() {
        initializeDatabase()
        warmupCache()
        startupComplete.Store(true)
    }()

    app.Listen(":3000")
}

Graceful Shutdown

var shutdownInitiated atomic.Bool

app.Get(healthcheck.ReadinessEndpoint, healthcheck.New(healthcheck.Config{
    Probe: func(c fiber.Ctx) bool {
        // Stop receiving traffic during shutdown
        return !shutdownInitiated.Load()
    },
}))

// Graceful shutdown handler
go func() {
    <-sigChan
    shutdownInitiated.Store(true)
    time.Sleep(5 * time.Second) // Allow load balancer to drain
    app.Shutdown()
}()

Response Codes

  • 200 OK: Probe returned true (healthy)
  • 503 Service Unavailable: Probe returned false (unhealthy)
  • 404 Not Found: Next function returned true and no other handlers are defined

Build docs developers (and LLMs) love