extensions/smallrye-health/deployment/src/main/resources/META-INF/quarkus-skill.md
Implement HealthCheck, mark the implementation as a CDI bean, and annotate with @Liveness, @Readiness, or @Startup:
@Liveness
@ApplicationScoped
public class MyLivenessCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.up("my-liveness");
}
}
@Liveness — is the application running? (Kubernetes restarts on failure)@Readiness — can the application handle requests? (Kubernetes stops routing traffic on failure)@Startup — has the application finished initializing? (Kubernetes kills on failure during startup, after success it switches to liveness)All annotations are in org.eclipse.microprofile.health.*. Watch for the clash with io.quarkus.runtime.Startup — use the full import for the health annotation.
Use the fluent builder for responses with custom data:
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("Database Connection")
.up()
.withData("connection", "established")
.withData("pool-size", 10)
.build();
}
Shortcuts: HealthCheckResponse.up("name") and HealthCheckResponse.down("name") for simple cases.
Use @Observes StartupEvent to track when initialization completes:
@Startup
@ApplicationScoped
public class InitHealthCheck implements HealthCheck {
private volatile boolean ready = false;
void onStart(@Observes StartupEvent event) {
// perform initialization
ready = true;
}
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("init")
.status(ready)
.build();
}
}
For non-blocking checks, implement AsyncHealthCheck (SmallRye-specific):
@Readiness
@ApplicationScoped
public class ReactiveCheck implements AsyncHealthCheck {
@Override
public Uni<HealthCheckResponse> call() {
return Uni.createFrom().item(HealthCheckResponse.up("reactive-check"));
}
}
Import: io.smallrye.health.api.AsyncHealthCheck.
Group checks into custom categories with @HealthGroup (SmallRye-specific):
@HealthGroup("external")
@ApplicationScoped
public class ExternalApiCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.up("external-api");
}
}
Access grouped checks at /q/health/group/external. Access all health group checks at /q/healht/group. Import: io.smallrye.health.api.HealthGroup. A check can belong to both a group and a standard category (e.g., @Readiness @HealthGroup("external")) and also to multiple health groups (e.g., @HealthGroup("group1") @HealthGroup("group2)).
@Startup import clash. org.eclipse.microprofile.health.Startup vs io.quarkus.runtime.Startup — use the health one for health checks.@ApplicationScoped (or another scope) alongside the health annotation./q/. Liveness at /q/health/live, readiness at /q/health/ready, startup at /q/health/started, combined at /q/health.Test health endpoints with REST-assured against the JSON response:
@QuarkusTest
class HealthCheckTest {
@Test
void testLiveness() {
given()
.when().get("/q/health/live")
.then()
.statusCode(200)
.body("status", is("UP"))
.body("checks.find { it.name == 'my-liveness' }.status", is("UP"));
}
@Test
void testReadinessWithData() {
given()
.when().get("/q/health/ready")
.then()
.statusCode(200)
.body("checks.find { it.name == 'Database Connection' }.data.connection",
is("established"));
}
}
Health response JSON structure:
{"status": "UP", "checks": [{"name": "...", "status": "UP", "data": {...}}]}
When any check is DOWN, the HTTP status changes to 503 and "status" becomes "DOWN".