Skip to content
Health & Readiness Probes

Health & Readiness Probes

The SDK exposes liveness and readiness probes on every service it starts. A database-ping readiness check is registered automatically by the scaffold. You can add domain-specific checks by implementing one interface and passing instances to server.Config.

Use this page when you need to verify that probes are wired correctly, add a custom dependency check, or configure your Kubernetes pod spec to use these endpoints.

Endpoints

SurfaceEndpointBehaviour
HTTP (gateway)GET /healthzLiveness. Returns 200 as long as the process is serving. No dependency checks — a dependency failure does not kill a live pod.
HTTP (gateway)GET /readyzReadiness. Returns 200 when all registered readiness checks pass; returns 503 with a JSON body listing failures when any check fails.
gRPCgrpc.health.v1.Health/CheckReflects the same readiness state: SERVING when ready, NOT_SERVING when any check fails.

Both HTTP endpoints are unauthenticated — they are not subject to the authz interceptor — so the kubelet can reach them without credentials. The gRPC health service methods are declared Public in the authz rule set automatically by server.New.

When HTTPAddr is empty (gRPC-only mode), only the gRPC health service is exposed.

Readiness check interface

The readiness check interface lives in github.com/infobloxopen/devedge-sdk/health:

type Check interface {
    Name() string                    // stable key; appears in /readyz JSON on failure
    Check(ctx context.Context) error // nil = ready; non-nil = not ready
}

server.Config accepts a ReadinessChecks []health.Check field. An empty slice means the service is always considered ready (the same behaviour as the liveness probe). Each check runs with a 2-second per-check timeout so a hung dependency cannot stall the probe indefinitely.

Built-in database check

The SDK provides one built-in check that pings a *database/sql.DB (or anything with a PingContext method):

import (
    sdkhealth "github.com/infobloxopen/devedge-sdk/health"
    "github.com/infobloxopen/devedge-sdk/server"
)

sqlDB, _ := gormDB.DB()   // or sql.Open(...)
s, err := server.New(server.Config{
    // ...
    ReadinessChecks: []sdkhealth.Check{
        sdkhealth.NewDBCheck("db", sqlDB),
    },
})

NewDBCheck accepts any Pinger (interface { PingContext(context.Context) error }), satisfied by *sql.DB from both GORM (db.DB()) and ent (sql.Open). No ORM type enters server.Config.

The scaffolded main.go / main.ent.go registers this check by default — the scaffold wires it for you, with no extra wiring required.

Custom readiness checks

Implement health.Check for any dependency:

type cacheCheck struct{ c *redis.Client }

func (c *cacheCheck) Name() string { return "cache" }
func (c *cacheCheck) Check(ctx context.Context) error {
    return c.c.Ping(ctx).Err()
}

Then register it alongside the DB check:

ReadinessChecks: []sdkhealth.Check{
    sdkhealth.NewDBCheck("db", sqlDB),
    &cacheCheck{c: redisClient},
},

A failure body from /readyz looks like:

{"status":"unready","checks":{"cache":"dial tcp ...: connection refused"}}

Kubernetes probe configuration

Point your Kubernetes probe spec at the HTTP endpoints:

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

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

Or use the gRPC health check (requires Kubernetes 1.24 or later with gRPC probe support):

livenessProbe:
  grpc:
    port: 9090
readinessProbe:
  grpc:
    port: 9090

The Helm chart generated by F035 (#95) wires these probes automatically.

Dependency notes

grpc/health and grpc/health/grpc_health_v1 are sub-packages of google.golang.org/grpc, which is already in the module graph. No new transitive dependency is added. The health package itself depends only on context and time from the standard library — no ORM, no SDK.