Health Checks
The health package provides health check functionality for microservices, including Kubernetes-style liveness and readiness probes.
Quick Start
import "go-micro.dev/v6/health"
func main() {
// Register health checks
health.Register("database", health.PingCheck(db.Ping))
health.Register("cache", health.TCPCheck("localhost:6379", time.Second))
// Add health endpoints
mux := http.NewServeMux()
health.RegisterHandlers(mux) // Registers /health, /health/live, /health/ready
http.ListenAndServe(":8080", mux)
}
Endpoints
| Endpoint | Purpose | Returns 200 when |
|---|---|---|
/health | Overall health status | All critical checks pass |
/health/live | Kubernetes liveness probe | Service is running |
/health/ready | Kubernetes readiness probe | All critical checks pass |
Response Format
{
"status": "up",
"checks": [
{
"name": "database",
"status": "up",
"duration": 1234567
},
{
"name": "cache",
"status": "up",
"duration": 567890
}
],
"info": {
"go_version": "go1.22.0",
"go_os": "linux",
"go_arch": "amd64",
"version": "1.0.0"
}
}
When unhealthy:
- HTTP status: 503 Service Unavailable
status:"down"- Failed checks include an
errorfield
Built-in Checks
PingCheck
For database connections with a Ping() method:
health.Register("postgres", health.PingCheck(db.Ping))
health.Register("mysql", health.PingContextCheck(db.PingContext))
TCPCheck
Verify TCP connectivity:
health.Register("redis", health.TCPCheck("localhost:6379", time.Second))
health.Register("kafka", health.TCPCheck("kafka:9092", 2*time.Second))
HTTPCheck
Verify an HTTP endpoint returns 200:
health.Register("api", health.HTTPCheck("http://api.internal/health", time.Second))
DNSCheck
Verify DNS resolution:
health.Register("dns", health.DNSCheck("api.example.com"))
CustomCheck
Any function returning an error:
health.Register("disk", health.CustomCheck(func() error {
var stat syscall.Statfs_t
if err := syscall.Statfs("/", &stat); err != nil {
return err
}
freeGB := stat.Bavail * uint64(stat.Bsize) / 1e9
if freeGB < 1 {
return fmt.Errorf("low disk space: %dGB free", freeGB)
}
return nil
}))
RegistryCheck
Verifies the service registry is still reachable. A go-micro service can keep running while it has silently lost its connection to the registry (etcd, Consul, …) — the process looks healthy, but other services can no longer discover it. RegistryCheck surfaces that state so a readiness probe can take the pod out of rotation.
svc := micro.NewService("orders")
health.Register("registry", health.RegistryCheck(svc.Options().Registry))
Registered checks are critical by default, so when the registry connection is lost, /health/ready returns 503 and Kubernetes stops routing to the pod:
readinessProbe:
httpGet:
path: /health/ready
port: 8080
periodSeconds: 5
The check lists services under the configured probe timeout, so an unreachable registry is reported as down rather than hanging the probe. It works with any registry implementation — the connectivity is exercised through the standard ListServices call.
Critical vs Non-Critical Checks
By default, all checks are critical. A critical check failure marks the service as not ready.
For non-critical checks (monitoring only):
health.RegisterCheck(health.Check{
Name: "external-api",
Check: health.HTTPCheck("https://api.external.com/status", 5*time.Second),
Critical: false, // Won't affect readiness
Timeout: 5 * time.Second,
})
Timeouts
Default timeout is 5 seconds. Override per-check:
health.RegisterCheck(health.Check{
Name: "slow-db",
Check: health.PingCheck(db.Ping),
Timeout: 10 * time.Second,
})
Adding Service Info
Include metadata in health responses:
health.SetInfo("version", "1.0.0")
health.SetInfo("commit", "abc123")
health.SetInfo("service", "users")
Kubernetes Configuration
apiVersion: v1
kind: Pod
spec:
containers:
- name: app
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
Integration with micro run
When using micro run with a micro.mu config that specifies ports, the runner waits for /health to return 200 before starting dependent services:
service database
path ./database
port 8081
service api
path ./api
port 8080
depends database
The api service won’t start until database’s /health endpoint is ready.
Programmatic Usage
// Check readiness in code
if health.IsReady(ctx) {
// Service is healthy
}
// Get full health status
resp := health.Run(ctx)
fmt.Printf("Status: %s\n", resp.Status)
for _, check := range resp.Checks {
fmt.Printf(" %s: %s (%v)\n", check.Name, check.Status, check.Duration)
}
Best Practices
- Keep checks fast - Health endpoints are called frequently
- Use timeouts - Don’t let slow dependencies block health checks
- Non-critical for optional deps - External APIs, caches that have fallbacks
- Critical for required deps - Databases, message queues
- Include version info - Helps debugging in production
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.