Skip to main content

Overview

The healthcheck middleware provides liveness and readiness probe endpoints for container orchestration platforms like Kubernetes. It supports custom health checks for databases, caches, and other dependencies. Use it when you need:
  • Kubernetes liveness/readiness probes
  • Load balancer health checks
  • Dependency health monitoring

Installation

import "github.com/go-mizu/mizu/middlewares/healthcheck"

Quick Start

app := mizu.New()

// Register default endpoints
healthcheck.Register(app, healthcheck.Options{})

// Or add custom checks
healthcheck.Register(app, healthcheck.Options{
    Checks: []healthcheck.Check{
        healthcheck.DBCheck("postgres", db.Ping),
    },
})

Configuration

Options

OptionTypeDefaultDescription
LivenessPathstring"/healthz"Liveness endpoint path
ReadinessPathstring"/readyz"Readiness endpoint path
Checks[]Check[]Health checks to run

Check

FieldTypeDescription
NamestringCheck name for reporting
Checkfunc(context.Context) errorCheck function
Timeouttime.DurationCheck timeout

Examples

Basic Endpoints

healthcheck.Register(app, healthcheck.Options{})
// Creates:
// GET /healthz - liveness probe
// GET /readyz - readiness probe

With Database Check

healthcheck.Register(app, healthcheck.Options{
    Checks: []healthcheck.Check{
        {
            Name: "postgres",
            Check: func(ctx context.Context) error {
                return db.PingContext(ctx)
            },
            Timeout: 5 * time.Second,
        },
    },
})

Multiple Dependencies

healthcheck.Register(app, healthcheck.Options{
    Checks: []healthcheck.Check{
        healthcheck.DBCheck("postgres", db.Ping),
        {
            Name: "redis",
            Check: func(ctx context.Context) error {
                return redisClient.Ping(ctx).Err()
            },
            Timeout: 2 * time.Second,
        },
        {
            Name: "elasticsearch",
            Check: func(ctx context.Context) error {
                _, _, err := esClient.Ping()
                return err
            },
            Timeout: 3 * time.Second,
        },
    },
})

Custom Paths

healthcheck.Register(app, healthcheck.Options{
    LivenessPath:  "/health/live",
    ReadinessPath: "/health/ready",
})

Standalone Handlers

// Just liveness
app.Get("/healthz", healthcheck.Liveness())

// Just readiness with checks
app.Get("/readyz", healthcheck.Readiness(
    healthcheck.Check{Name: "db", Check: db.Ping},
))

Using DBCheck Helper

check := healthcheck.DBCheck("postgres", func(ctx context.Context) error {
    return db.PingContext(ctx)
})
// Creates check with 5s default timeout

API Reference

Functions

// Register adds health check routes to the app
func Register(app *mizu.App, opts Options)

// Liveness returns a simple liveness handler
func Liveness() mizu.Handler

// Readiness returns a readiness handler with checks
func Readiness(checks ...Check) mizu.Handler

// New creates a combined health handler
func New(opts Options) mizu.Handler

// DBCheck creates a database check with default timeout
func DBCheck(name string, pingFn func(context.Context) error) Check

Response Format

Liveness Response

ok

Readiness Response (Success)

{
    "status": "ok",
    "checks": {
        "postgres": "ok",
        "redis": "ok"
    }
}

Readiness Response (Failure)

{
    "status": "error",
    "checks": {
        "postgres": "ok",
        "redis": "connection failed"
    }
}

HTTP Status Codes

CodeMeaning
200Healthy
503Unhealthy (one or more checks failed)

Kubernetes Configuration

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /readyz
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5

Technical Details

Implementation Architecture

The healthcheck middleware is designed with the following technical characteristics:
  • Concurrent Check Execution: All health checks run in parallel using goroutines with a sync.WaitGroup to coordinate execution
  • Thread-Safe Results: A sync.Mutex protects the results map during concurrent check execution
  • Context-Based Timeouts: Each check runs with its own context.WithTimeout to prevent hanging checks
  • Default Timeout: If no timeout is specified, checks default to 5 seconds
  • Status Code Mapping: Returns HTTP 200 for healthy, HTTP 503 for unhealthy states

Core Components

  1. Check Struct: Defines a health check with name, check function, and timeout
  2. Status Struct: JSON response structure with overall status and individual check results
  3. Options Struct: Configuration for endpoint paths and checks list
  4. Liveness Handler: Simple text response (“ok”) with no dependency checks
  5. Readiness Handler: Executes all checks concurrently and aggregates results

Helper Functions

  • DBCheck: Creates a database health check with a 5-second default timeout
  • HTTPCheck: Creates an HTTP endpoint health check with a 10-second default timeout
  • New: Creates a combined handler that routes to liveness or readiness based on path
  • Register: Convenience function to register both endpoints on a router

Best Practices

  • Keep liveness checks simple (no external dependencies)
  • Include all critical dependencies in readiness checks
  • Set appropriate timeouts for each check
  • Use readiness to control traffic during startup/shutdown

Testing

Test Cases

Test CaseDescriptionExpected Behavior
TestLivenessBasic liveness endpoint testReturns HTTP 200 with “ok” text response
TestReadiness/no_checksReadiness with no checks configuredReturns HTTP 200 with “ok” text response
TestReadiness/all_healthyReadiness with all checks passingReturns HTTP 200 with JSON status “ok” and all checks marked “ok”
TestReadiness/one_unhealthyReadiness with one failing checkReturns HTTP 503 with JSON status “error” and error message in checks
TestReadiness_TimeoutCheck that exceeds timeoutReturns HTTP 503 due to context deadline exceeded
TestNew/livenessCombined handler with custom liveness pathRoutes to liveness handler and returns HTTP 200
TestNew/readinessCombined handler with custom readiness pathRoutes to readiness handler and returns HTTP 200 with checks
TestRegister/default_livenessRegister with default paths (/healthz)Liveness endpoint returns HTTP 200
TestRegister/default_readinessRegister with default paths (/readyz)Readiness endpoint returns HTTP 200 with checks
TestDBCheckDBCheck helper functionCreates check with name “postgres”, 5s timeout, and executes successfully