Health Quickstart
Expose /healthz and aggregate basic probes (script + HTTP) into a single JSON document for liveness / readiness checks. This is the migrated version of the previous Responses chapter entry, now expanded with concepts and operational notes.
Full source
File: pwsh/tutorial/examples/16.1-Health-Quickstart.ps1
<#
Health Quickstart Script
Migrated from 9.11-Health-Checks.ps1
Demonstrates basic health endpoint with script + HTTP probes.
#>
param(
[int]$Port = 5000,
[IPAddress]$IPAddress = [IPAddress]::Loopback
)
## 1. Logging (console sink for visibility)
New-KrLogger | Add-KrSinkConsole | Register-KrLogger -Name 'console' -SetAsDefault
## 2. Server
New-KrServer -Name 'Health Demo'
## 3. Listener (loopback port 5000)
Add-KrEndpoint -Port $Port -IPAddress $IPAddress
## 5. Enable configuration (locks in components)
Enable-KrConfiguration
## 6. Supporting route used by HTTP probe
Add-KrMapRoute -Verbs Get -Pattern '/ping' -ScriptBlock {
Write-KrJsonResponse @{ status = 'Healthy'; description = 'Self ping successful' }
}
## 7. Health endpoint (treat degraded as unhealthy for tighter SLAs)
Add-KrHealthEndpoint -Pattern '/healthz' -DefaultTags 'self' -TreatDegradedAsUnhealthy $true -ProbeTimeout '00:00:05'
## 8. Script probe (constant healthy)
Add-KrHealthProbe -Name 'Self' -Tags 'self' -ScriptBlock {
return New-KrProbeResult Healthy 'Main pipeline ready'
}
## 9. HTTP probe (calls /ping)
Add-KrHealthHttpProbe -Name 'Ping' -Url "http://127.0.0.1:$Port/ping" -Tags 'remote', 'self' -Timeout '00:00:02'
## 10. Start server
Start-KrServer -CloseLogsOnExit
Concepts
| Term | Meaning |
|---|---|
| Probe | A unit of health evaluation returning Status, Description, and optional Data |
| Status | Healthy, Degraded, or Unhealthy (optionally escalated if configured) |
| Endpoint | Aggregator that executes selected probes in parallel and shapes the response |
| Tags | Classification labels used to include/exclude probes per request |
| Timeout | Per-probe timeout (endpoint-level default) after which a probe is considered failed |
New-KrProbeResult | Helper cmdlet simplifying creation of ProbeResult objects |
Step-by-step
- (Logging) Configure console logger for visibility
- (Server) Create server & listener (loopback:5000)
- (Route) Map
/pingreturning a simple status object - (Endpoint) Register
/healthzwith: default tagself, shorter timeout, and escalate degraded to unhealthy - (Probe) Script probe
Self-> static readiness confirmation - (Probe) HTTP probe
Ping-> validates internal route - (Run) Start server; query endpoint
Response Shape
Typical aggregate (trimmed example):
{
"status": "Healthy",
"statusText": "healthy",
"generatedAt": "2025-09-26T10:15:04.1234567Z",
"summary": { "total": 2, "healthy": 2, "degraded": 0, "unhealthy": 0 },
"appliedTags": [ "self" ],
"probes": [
{
"name": "Self",
"tags": [ "self" ],
"status": "Healthy",
"statusText": "healthy",
"description": "Main pipeline ready",
"data": null,
"duration": "00:00:00.0001234",
"error": null
},
{
"name": "Ping",
"tags": [ "self" ],
"status": "Healthy",
"statusText": "healthy",
"description": null,
"data": null,
"duration": "00:00:00.0000150",
"error": null
}
]
}
Field overview:
status: Worst case across included probes (post escalation)statusText: Lowercase string form ofstatus(stable for consumers)generatedAt: UTC timestamp when aggregation finishedsummary: Count breakdown (total,healthy,degraded,unhealthy)appliedTags: Effective tag filter used for this requestprobes[]: Individual probe resultsname,tags,status,statusTextdescription: Optional detailsdata: Arbitrary key/value bag (when probe returns extra context)duration: Execution time (ISO 8601hh:mm:ss.fffffffTimeSpan format)error: Optional captured error text / exception summary
Execution Lifecycle
- Request arrives at
/healthz - Tag filter resolved (query:
tag/tags, fallback to endpoint defaults) - Probe list materialized & dispatched concurrently
- Each probe: run -> map result -> clamp to timeout (canceled => degraded/unhealthy per rules)
- Aggregate status computed (worst) then escalate if
-TreatDegradedAsUnhealthy - JSON serialized & returned (200 when healthy/degraded unless escalation triggers 503)
Options Summary
| Option | Script Param | Purpose |
|---|---|---|
-DefaultTags | Endpoint | Baseline tag set when caller omits tag(s) |
-ProbeTimeout | Endpoint | Per-probe timeout & cancellation window |
-TreatDegradedAsUnhealthy | Endpoint | Escalate degraded to unhealthy (for strict readiness) |
-ResponseContentType | Endpoint | Force JSON, YAML, XML, or auto negotiation for the aggregate payload |
-Tags | Probe | Assign classification labels |
-Timeout | Probe (e.g., HTTP/process) | Per-probe override (stronger than endpoint default) |
Filtering Examples
| Query | Effect |
|---|---|
?tag=self | Only self probes |
?tags=remote,api | remote OR api probes (union – duplicates removed) |
| none | Default endpoint tags (self) |
Multiple tag parameters are also merged: ?tag=self&tag=remote ⇒ same as ?tags=self,remote.
Failure & Escalation Scenarios
| Scenario | Raw Probe Status | Aggregate (TreatDegradedAsUnhealthy=$true) | HTTP Code |
|---|---|---|---|
| One degraded, others healthy | Degraded | Unhealthy | 503 |
| One unhealthy | Unhealthy | Unhealthy | 503 |
| All healthy | Healthy | Healthy | 200 |
| Timeout (internal) | Degraded (mapped) | Unhealthy | 503 |
Without escalation the degraded row would remain degraded with 200.
Note: An internal probe timeout (the per-probe timer expiring) maps to
Degradedfirst so transient slowness does not immediately fail readiness unless escalation is enabled. A caller / request cancellation (client disconnect or server shutdown token) is propagated and not converted to a probe status; the endpoint decides overall response.
Try it
Invoke-RestMethod http://127.0.0.1:5000/healthz | ConvertTo-Json -Depth 4
Invoke-RestMethod 'http://127.0.0.1:5000/healthz?tag=remote' | ConvertTo-Json -Depth 4
Custom output formats
Need a human-friendly YAML payload or legacy XML integration? Specify -ResponseContentType when registering the endpoint to override the default JSON response. Available formats:
- Json (default) - Standard JSON format for API consumption
- Yaml - Human-readable YAML format for debugging and configuration
- Xml - Legacy XML format for enterprise integration
- Auto - Content negotiation based on Accept header
The following sample demonstrates all response formats with multiple diverse probes including database connectivity simulation, cache performance monitoring, and disk space checking:
File: pwsh/tutorial/examples/16.7-Health-Response-Format.ps1
<#
Sample: Health Response Format
Purpose: Shows how to configure the health endpoint to return YAML, XML, or JSON responses.
File: 16.7-Health-Response-Format.ps1
Notes: Demonstrates ResponseContentType parameter options with multiple probes.
#>
param(
[int]$Port = 5000,
[IPAddress]$IPAddress = [IPAddress]::Loopback
)
## 1. Logging
New-KrLogger | Add-KrSinkConsole | Register-KrLogger -Name 'console' -SetAsDefault
## 2. Server
New-KrServer -Name 'Health Response Format Demo'
## 3. Listener (port 5000)
Add-KrEndpoint -Port $Port -IPAddress $IPAddress
#
## 5. Add some diverse probes for demonstration
Add-KrHealthProbe -Name 'Database' -Tags 'core', 'data' -ScriptBlock {
# Simulate database connectivity check
$connectionTime = Get-Random -Minimum 10 -Maximum 50
$data = @{ connectionTimeMs = $connectionTime; server = 'localhost:5432' }
New-KrProbeResult 'Healthy' "Connected in ${connectionTime}ms" -Data $data
}
Add-KrHealthProbe -Name 'Cache' -Tags 'core', 'perf' -ScriptBlock {
# Simulate cache health check
$hitRatio = [math]::Round((Get-Random -Minimum 85 -Maximum 98) / 100.0, 2)
$data = @{ hitRatio = $hitRatio; entries = 1247 }
$status = if ($hitRatio -lt 0.8) { 'Degraded' } else { 'Healthy' }
New-KrProbeResult $status "Hit ratio: $($hitRatio * 100)%" -Data $data
}
Add-KrHealthProbe -Name 'Disk Space' -Tags 'infra' -ScriptBlock {
# Simulate disk space check
$freePercent = Get-Random -Minimum 25 -Maximum 85
$status = if ($freePercent -lt 10) { 'Unhealthy' } elseif ($freePercent -lt 20) { 'Degraded' } else { 'Healthy' }
$data = @{ freePercent = $freePercent; totalGB = 500; freeGB = [math]::Round($freePercent * 5, 1) }
New-KrProbeResult $status "Free space: $freePercent%" -Data $data
}
## 6. Enable configuration
#Enable-KrConfiguration
## 7. Health endpoint with different response formats (uncomment one at a time to test)
# JSON (default)
Add-KrHealthEndpoint -Pattern '/healthz' -DefaultTags 'core' -ResponseContentType Auto
Enable-KrConfiguration
## 8. Start server
Start-KrServer
This example creates three endpoints:
/healthz- Returns YAML format using-ResponseContentType Yaml/health-json- Manual JSON endpoint usingWriteJsonResponse/health-xml- Manual XML endpoint usingWriteXmlResponse
The probes demonstrate different health scenarios with realistic data and status mapping:
- Database probe - Simulates connection timing with random latency
- Cache probe - Monitors hit ratio with degraded threshold at 80%
- Disk Space probe - Checks free space with unhealthy <10%, degraded <20%
Troubleshooting
| Symptom | Likely Cause | Resolution |
|---|---|---|
| Endpoint slow (>1s) | Too many long probes running in parallel | Shorten probe timeout; split into readiness vs diagnostics endpoint |
| Random degraded spikes | Intermittent dependency latency | Add retry inside probe or widen degraded threshold |
| 503 on deployment start | Strict escalation | Temporarily disable -TreatDegradedAsUnhealthy during warm-up |
| Missing probe in output | Tag filtering excluded it | Check query tags & default tags |
References
- Add-KrHealthEndpoint
- Add-KrScriptProbe
- Add-KrHttpProbe
- New-KrProbeResult
- New-KrServer
- Add-KrEndpoint
- Enable-KrConfiguration
- Start-KrServer
Previous / Next
Previous: None Next: Script Probe