Healthchecks Reference
Status: canonical healthcheck contract companion for service.json.
This page describes the Service Lasso healthchecks contract used by service manifests. The general manifest reference remains service-json-reference.md; this page gives healthcheck-specific examples and implementation rules.
Canonical field
Use top-level healthchecks as an array.
"healthchecks": [
{
"id": "http-health",
"type": "http",
"url": "http://127.0.0.1:${HTTP_PORT}/health",
"expected_status": 200
}
]
The singular healthcheck field is not the target contract. During implementation it may be accepted only as a temporary internal migration bridge while checked-in manifests are converted. New manifests should use healthchecks only.
Evaluation model
Each item in healthchecks is evaluated as an independent readiness check.
Default semantics:
- every check is
requiredunless it explicitly sets"required": false - startup is ready only when all required checks pass
- optional checks are diagnostics only and must not block startup
- each check owns its own
retries,interval,start_period, andtimeout
No group-level all / any mode is part of the first contract. If alternatives are needed later, add grouping deliberately instead of overloading this first version.
Supported healthcheck types
Service Lasso healthchecks are declared with type.
Supported types:
processhttptcpudpfilevariable
process is the default health model when no stronger readiness check is needed. Use http, tcp, udp, file, or variable when startup should wait for a specific readiness signal.
Shared fields
Every healthcheck item has these shared fields:
{
"id": "readable-check-id",
"type": "http",
"required": true,
"retries": 30,
"interval": 1000,
"start_period": 0,
"timeout": 2000
}
Field meanings:
id: stable unique identifier for this check within the service manifest.type: healthcheck type.required: whether this check gates startup readiness. Defaults totrue.retries: number of readiness attempts before this check is considered failed.interval: milliseconds between attempts.start_period: milliseconds to wait before this check's first attempt.timeout: per-attempt timeout in milliseconds for checks that wait on network or process output.
When a service declares an explicit healthcheck item, Service Lasso should treat that item as a readiness check even when it omits retries or interval.
Intended defaults:
required = true
retries = 10
interval = 1000ms
start_period = 0ms
timeout = implementation-defined per check, usually 2000ms for network checks
HTTP healthcheck
Use http when the service exposes an HTTP readiness endpoint.
"healthchecks": [
{
"id": "http-health",
"type": "http",
"url": "http://127.0.0.1:${HTTP_PORT}/health",
"expected_status": 200,
"retries": 80,
"interval": 250
}
]
Rules:
urlis required.expected_statusdefaults to200when omitted.- Selectors such as
${HTTP_PORT}are resolved before the request. - Optional
cookiesmay be supplied as a string map for services whose readiness endpoint requires request state. Cookie values support the same selector resolution asurl.
Optional cookie form:
"healthchecks": [
{
"id": "http-cookie-health",
"type": "http",
"url": "http://127.0.0.1:${HTTP_PORT}/healthcheck",
"expected_status": 200,
"cookies": {
"healthcheck": "ready"
},
"retries": 180
}
]
TCP healthcheck
Use tcp when readiness is represented by a socket accepting connections.
Service Lasso should support three clean TCP forms.
Default single-port form
"healthchecks": [
{
"id": "tcp-ready",
"type": "tcp",
"retries": 30
}
]
This is allowed when the service has exactly one unambiguous resolved port. Service Lasso should connect to 127.0.0.1:<resolved-port>.
If a service declares multiple ports, it must use the explicit address form or the explicit host + port form.
Explicit address form
"healthchecks": [
{
"id": "tcp-http-port",
"type": "tcp",
"address": "127.0.0.1:${HTTP_PORT}",
"retries": 30
}
]
Explicit host and port form
"healthchecks": [
{
"id": "tcp-http-port",
"type": "tcp",
"host": "127.0.0.1",
"port": "${HTTP_PORT}",
"retries": 30
}
]
Rules:
addressis canonical when a single string is clearer.host+portis canonical when host and port should be edited independently.- Bare
type: "tcp"is canonical only for the unambiguous single-port case. - Do not add
tcphostortcpportaliases. Service Lasso manifests are new, so the schema should stay clean. - Selector resolution must work for derived port variables such as
${HTTP_PORT},${SERVICE_PORT}, and other declared port names.
UDP healthcheck
Use udp when the service exposes a UDP readiness protocol.
UDP is connectionless, so a UDP check must not pretend that a port can be verified the same way as TCP. Prefer explicit send and expect semantics.
"healthchecks": [
{
"id": "udp-ready",
"type": "udp",
"host": "127.0.0.1",
"port": "${UDP_PORT}",
"send": "ping",
"expect": "pong",
"retries": 80,
"interval": 250,
"timeout": 1000
}
]
Optional address form:
"healthchecks": [
{
"id": "udp-ready",
"type": "udp",
"address": "127.0.0.1:${UDP_PORT}",
"send": "ping",
"expect": "pong"
}
]
Rules:
senddefines the datagram payload to send.expectdefines the response payload required for a healthy result.- Selector resolution should apply to
address,host,port,send, andexpect. - Fire-and-forget UDP should be avoided for readiness because it does not prove the service received or handled the packet.
File healthcheck
Use file when readiness is represented by a file that the service creates.
"healthchecks": [
{
"id": "ready-file",
"type": "file",
"file": "${SERVICE_ROOT}/runtime/ready.txt",
"retries": 30,
"interval": 250
}
]
Relative paths are resolved against the service root:
"healthchecks": [
{
"id": "ready-file",
"type": "file",
"file": "runtime/ready.txt"
}
]
Rules:
- Selector resolution should apply before checking the filesystem path.
- Relative paths remain service-root relative.
- Health details should report the resolved path checked.
Variable healthcheck
Use variable when readiness is represented by a resolved variable.
"healthchecks": [
{
"id": "service-url-ready",
"type": "variable",
"variable": "SERVICE_URL",
"retries": 30
}
]
Selector form should also work:
"healthchecks": [
{
"id": "service-url-ready",
"type": "variable",
"variable": "${SERVICE_URL}",
"retries": 30
}
]
Rules:
- Bare names and
${VAR}selector form should both be accepted. - The healthcheck succeeds when the variable exists and resolves to a non-empty value.
- Variable health details should identify the variable key and scope without exposing sensitive values unnecessarily.
Runtime variables from process output
A service can declare outputvarregex to capture variables from stdout or stderr.
"outputvarregex": {
"FILEBEAT_ENABLED_INPUTS": ".*Loading and starting Inputs completed. Enabled inputs: (\\d+).*"
},
"healthchecks": [
{
"id": "filebeat-inputs-ready",
"type": "variable",
"variable": "FILEBEAT_ENABLED_INPUTS",
"retries": 180,
"interval": 1000
}
]
Rules:
- Each
outputvarregexkey is the variable name to set. - Each value is a regex string.
- The first capture group becomes the variable value.
- Captured values should be stored as runtime-scoped service variables.
- Variable healthchecks should be able to wait for these runtime-captured values.
- Captured runtime variables should appear in service variable/operator surfaces with source metadata such as
stdoutorstderr.
Multiple healthchecks examples
TCP plus HTTP
"healthchecks": [
{
"id": "tcp-port-open",
"type": "tcp",
"host": "127.0.0.1",
"port": "${HTTP_PORT}",
"retries": 30,
"interval": 250
},
{
"id": "http-ready",
"type": "http",
"url": "http://127.0.0.1:${HTTP_PORT}/health",
"expected_status": 200,
"retries": 80,
"interval": 250
}
]
Both checks are required because required defaults to true.
Required and optional checks
"healthchecks": [
{
"id": "http-ready",
"type": "http",
"url": "http://127.0.0.1:${HTTP_PORT}/health",
"required": true
},
{
"id": "diagnostic-ready-file",
"type": "file",
"file": "runtime/diagnostic-ready.txt",
"required": false
}
]
Startup is ready when http-ready passes. The optional file check is reported for diagnostics but does not block startup.
Result model
Health APIs and start traces should report aggregate health plus individual check results.
Per-check result shape:
interface ServiceHealthcheckResult {
id: string;
type: ServiceHealthcheck["type"];
required: boolean;
healthy: boolean;
attempts: number;
detail: string;
}
Aggregate shape:
interface ServiceHealthResult {
healthy: boolean;
detail: string;
checks: ServiceHealthcheckResult[];
}
The aggregate is healthy only when all required checks are healthy.
Implementation checklist
When changing healthcheck behaviour, update:
src/contracts/service.tssrc/runtime/health/types.tssrc/runtime/discovery/validateManifest.tssrc/runtime/health/evaluateHealth.tssrc/runtime/health/waitForReadiness.ts- the relevant checker under
src/runtime/health/ - service variable resolution in
src/runtime/operator/variables.tswhen variables are involved - service lifecycle/runtime state when new runtime values must persist
- API response contracts and dashboard/service detail surfaces for per-check results
- checked-in service manifests currently using singular
healthcheck - regression tests for startup readiness and direct health evaluation
Keep the schema clean. Prefer canonical Service Lasso field names over compatibility aliases unless there is a real existing manifest migration requirement.