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
| Surface | Endpoint | Behaviour |
|---|---|---|
| HTTP (gateway) | GET /healthz | Liveness. Returns 200 as long as the process is serving. No dependency checks — a dependency failure does not kill a live pod. |
| HTTP (gateway) | GET /readyz | Readiness. Returns 200 when all registered readiness checks pass; returns 503 with a JSON body listing failures when any check fails. |
| gRPC | grpc.health.v1.Health/Check | Reflects 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.
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: 10Or use the gRPC health check (requires Kubernetes 1.24 or later with gRPC probe support):
livenessProbe:
grpc:
port: 9090
readinessProbe:
grpc:
port: 9090The 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.