Health checks, declared not improvised
A tiny DSL for service readiness/liveness checks — run concurrently, aggregated correctly, serialized anywhere.
Open source · MIT license · Rust · TypeScript · Kotlin
val health = healthChecks {
check("database", critical = true) {
if (db.ping()) up() else down("primary unreachable")
}
check("cache") { up("hitRate" to "0.93") }
check("disk", timeout = 2.seconds) {
val free = freePercent()
when {
free < 5 -> down("disk almost full: $free%")
free < 15 -> degraded("disk low: $free%")
else -> up("freePercent" to free.toString())
}
}
}
val report = health.run() // all checks run concurrently
report.status // UP | DEGRADED | DOWN
report.toJson()health-dsl turns your ad-hoc /health endpoint into a declaration: declare checks, run them concurrently with per-check timeouts, aggregate a correct overall status (critical-down vs degraded), and serialize to JSON. Native in Rust, TypeScript, and Kotlin.
Most services grow an ad-hoc /health endpoint: a pile of try/catch blocks, inconsistent timeouts, one slow dependency that hangs the whole probe, and no clear distinction between "we are down" and "we are degraded but still serving." health-dsl makes that a declaration.
You declare checks; they run concurrently with per-check timeouts, so report.durationMs is roughly your slowest check, not the sum. Aggregation is correct by design: a critical dependency that is DOWN makes the system DOWN, while a non-critical failure (or any degraded check) caps the system at DEGRADED but still healthy — you stop conflating "page someone" with "we are fine." No check can break the report: exceptions, panics, and timeouts fold into a DOWN outcome. Then serialize anywhere with a dependency-free JSON renderer or a map/struct form for Jackson, kotlinx.serialization, serde, or a Spring Actuator HealthIndicator.
Built to get out of your way
Correct aggregation
Status is ordered UP < DEGRADED < DOWN — aggregation is "take the worst," with a non-critical DOWN capped at DEGRADED. A critical dependency going down pages you; a degraded cache does not.
Concurrent, with timeouts
Checks run concurrently (tokio / Promise.all / coroutines) with per-check timeouts. A hung dependency becomes a DOWN outcome after its timeout instead of hanging the whole probe. durationMs reflects your slowest check.
Serialize anywhere
A dependency-free JSON renderer plus a map/struct form for Jackson, kotlinx.serialization, serde, or a Spring Actuator HealthIndicator. One stable JSON shape across all three languages.
Add it in one line
Same library, three ecosystems. Pick yours.
cargo add health-dsl --git https://github.com/slothlabsorg/health-dslnpm i @slothlabs/health-dslrepositories {
maven("https://jitpack.io")
}
dependencies {
implementation("com.github.slothlabsorg:health-dsl:v0.1.0")
}npm packages publish under the @slothlabs scope · JitPack builds from the git tag v0.1.0
One small example
A tiny DSL for service readiness/liveness checks — run concurrently, aggregated correctly, serialized anywhere.
val health = healthChecks {
check("database", critical = true) {
if (db.ping()) up() else down("primary unreachable")
}
check("cache") { up("hitRate" to "0.93") }
check("disk", timeout = 2.seconds) {
val free = freePercent()
when {
free < 5 -> down("disk almost full: $free%")
free < 15 -> degraded("disk low: $free%")
else -> up("freePercent" to free.toString())
}
}
}
val report = health.run() // all checks run concurrently
report.status // UP | DEGRADED | DOWN
report.toJson()Try health-dsl in your stack
Free and open source. Rust, TypeScript, or Kotlin — same semantics everywhere.