healthcheck

healthcheck runs dependency probes concurrently and aggregates them into a single HTTP health endpoint.

Part of nurago, a collection of independent Go packages for backend services.

import "github.com/tecnickcom/nurago/pkg/healthcheck"

Package healthcheck runs dependency probes concurrently and aggregates them into a single HTTP health endpoint.

It standardizes health probing around three pieces:

  • [HealthChecker]: check contract (HealthCheck(context.Context) error), with HealthCheckFunc to adapt a plain function
  • [HealthCheck]: ID + checker registration unit
  • [Handler]: HTTP aggregator that runs checks concurrently and writes a combined result

The default handler response is JSON and maps each check ID to either “OK” or the check error message.

The client packages in this library expose a HealthCheck method that satisfies HealthChecker directly, so they register without an adapter: redis, valkey, sqs, s3, sqlconn, ipify and slack.

Aggregation Semantics

  • checks execute in parallel
  • overall HTTP status is 200 when all checks pass
  • overall HTTP status is 503 when any check fails
  • response payload always includes per-check results
  • a checker panic is recovered, logged, and reported as a failed check
  • with WithTimeout, checks that overrun are reported as failed

Check IDs should be unique and non-empty: results are keyed by ID, so duplicate or empty IDs collapse into a single entry (a warning is logged at construction).

Result-writing behavior is customizable via WithResultWriter to integrate custom envelopes (for example JSendX) while keeping the execution model unchanged.

HTTP Probe Helper

CheckHTTPStatus is a helper for external HTTP dependencies. It supports context timeout control and request customization via WithConfigureRequest.

For an implementation example, see examples/service/internal/cli/bind.go.

When To Use

  • A readiness endpoint must report the status of several dependencies individually.
  • You want each probe bounded by a timeout so one hung dependency does not hang the endpoint.
  • Your clients already expose a HealthCheck(ctx) error method.

Example

checks := []healthcheck.HealthCheck{
	healthcheck.New("database", &database{}),
	healthcheck.New("cache", healthcheck.HealthCheckFunc(func(_ context.Context) error {
		return nil
	})),
}

// Each check runs in its own goroutine, bounded by the handler timeout.
handler := healthcheck.NewHandler(checks, healthcheck.WithTimeout(time.Second))

rec := httptest.NewRecorder()
handler.ServeHTTP(rec, httptest.NewRequestWithContext(
	context.TODO(), http.MethodGet, "/healthz", nil,
))

body, _ := io.ReadAll(rec.Body)

fmt.Println(rec.Code)
fmt.Println(string(body))

// Output:
// 200
// {"cache":"OK","database":"OK"}

Full source is in example_healthcheck_test.go. More runnable examples are on pkg.go.dev.

Dependencies

Importing this package pulls 1 external module:

  • github.com/julienschmidt/httprouter