[{"data":1,"prerenderedAt":2927},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fruntime\u002Fhealth-checks":314,"\u002Fdocs\u002Fruntime\u002Fhealth-checks-surround":2922},[4,38,86,149,176,219,257,273],{"title":5,"path":6,"stem":7,"children":8,"icon":37},"Getting Started","\u002Fdocs\u002Fgetting-started","1.docs\u002F1.getting-started\u002F1.index",[9,12,17,22,27,32],{"title":10,"path":6,"stem":7,"icon":11},"Getting started","i-lucide-flag",{"title":13,"path":14,"stem":15,"icon":16},"Modules overview","\u002Fdocs\u002Fgetting-started\u002Fmodules-overview","1.docs\u002F1.getting-started\u002F2.modules-overview","i-lucide-boxes",{"title":18,"path":19,"stem":20,"icon":21},"Installation","\u002Fdocs\u002Fgetting-started\u002Finstallation","1.docs\u002F1.getting-started\u002F3.installation","i-lucide-download",{"title":23,"path":24,"stem":25,"icon":26},"License configuration","\u002Fdocs\u002Fgetting-started\u002Flicense-configuration","1.docs\u002F1.getting-started\u002F4.license-configuration","i-lucide-key-round",{"title":28,"path":29,"stem":30,"icon":31},"Your first app","\u002Fdocs\u002Fgetting-started\u002Ffirst-app","1.docs\u002F1.getting-started\u002F5.first-app","i-lucide-square-play",{"title":33,"path":34,"stem":35,"icon":36},"Project setup","\u002Fdocs\u002Fgetting-started\u002Fproject-setup","1.docs\u002F1.getting-started\u002F6.project-setup","i-lucide-package",false,{"title":39,"path":40,"stem":41,"children":42,"icon":45},"Core Concepts","\u002Fdocs\u002Fconcepts","1.docs\u002F2.concepts\u002F1.index",[43,46,51,56,61,66,71,76,81],{"title":44,"path":40,"stem":41,"icon":45},"Core concepts","i-lucide-book-open",{"title":47,"path":48,"stem":49,"icon":50},"Architecture","\u002Fdocs\u002Fconcepts\u002Farchitecture","1.docs\u002F2.concepts\u002F2.architecture","i-lucide-layers",{"title":52,"path":53,"stem":54,"icon":55},"Exactly-once semantics","\u002Fdocs\u002Fconcepts\u002Fexactly-once","1.docs\u002F2.concepts\u002F3.exactly-once","i-lucide-shield-check",{"title":57,"path":58,"stem":59,"icon":60},"Lanes and parallelism","\u002Fdocs\u002Fconcepts\u002Flanes-and-parallelism","1.docs\u002F2.concepts\u002F4.lanes-and-parallelism","i-lucide-split",{"title":62,"path":63,"stem":64,"icon":65},"State and thread-safety","\u002Fdocs\u002Fconcepts\u002Fstate-and-thread-safety","1.docs\u002F2.concepts\u002F5.state-and-thread-safety","i-lucide-lock",{"title":67,"path":68,"stem":69,"icon":70},"Event time and watermarks","\u002Fdocs\u002Fconcepts\u002Fevent-time-and-watermarks","1.docs\u002F2.concepts\u002F6.event-time-and-watermarks","i-lucide-clock",{"title":72,"path":73,"stem":74,"icon":75},"The configuration model","\u002Fdocs\u002Fconcepts\u002Fconfiguration-model","1.docs\u002F2.concepts\u002F7.configuration-model","i-lucide-sliders-horizontal",{"title":77,"path":78,"stem":79,"icon":80},"The error-handling model","\u002Fdocs\u002Fconcepts\u002Ferror-handling-model","1.docs\u002F2.concepts\u002F8.error-handling-model","i-lucide-triangle-alert",{"title":82,"path":83,"stem":84,"icon":85},"How StoatFlow differs from Kafka Streams","\u002Fdocs\u002Fconcepts\u002Fhow-stoatflow-differs-from-ks","1.docs\u002F2.concepts\u002F9.how-stoatflow-differs-from-ks","i-lucide-arrow-left-right",{"title":87,"path":88,"stem":89,"children":90,"icon":93},"Building Topologies","\u002Fdocs\u002Fbuilding","1.docs\u002F3.building\u002F1.index",[91,94,99,104,109,114,119,124,129,134,139,144],{"title":92,"path":88,"stem":89,"icon":93},"Building topologies","i-lucide-blocks",{"title":95,"path":96,"stem":97,"icon":98},"Error handling and DLQ","\u002Fdocs\u002Fbuilding\u002Ferror-handling-dlq","1.docs\u002F3.building\u002F10.error-handling-dlq","i-lucide-circle-x",{"title":100,"path":101,"stem":102,"icon":103},"State stores","\u002Fdocs\u002Fbuilding\u002Fstate-stores","1.docs\u002F3.building\u002F11.state-stores","i-lucide-database",{"title":105,"path":106,"stem":107,"icon":108},"Testing topologies","\u002Fdocs\u002Fbuilding\u002Ftesting","1.docs\u002F3.building\u002F12.testing","i-lucide-flask-conical",{"title":110,"path":111,"stem":112,"icon":113},"Sources and sinks","\u002Fdocs\u002Fbuilding\u002Fstreams-builder","1.docs\u002F3.building\u002F2.streams-builder","i-lucide-import",{"title":115,"path":116,"stem":117,"icon":118},"KStream and KTable operations","\u002Fdocs\u002Fbuilding\u002Fkstream-ktable","1.docs\u002F3.building\u002F3.kstream-ktable","i-lucide-waypoints",{"title":120,"path":121,"stem":122,"icon":123},"Aggregations","\u002Fdocs\u002Fbuilding\u002Faggregations","1.docs\u002F3.building\u002F4.aggregations","i-lucide-sigma",{"title":125,"path":126,"stem":127,"icon":128},"Windowing","\u002Fdocs\u002Fbuilding\u002Fwindowing","1.docs\u002F3.building\u002F5.windowing","i-lucide-calendar-clock",{"title":130,"path":131,"stem":132,"icon":133},"Joins","\u002Fdocs\u002Fbuilding\u002Fjoins","1.docs\u002F3.building\u002F6.joins","i-lucide-git-merge",{"title":135,"path":136,"stem":137,"icon":138},"The Processor API","\u002Fdocs\u002Fbuilding\u002Fprocessor-api","1.docs\u002F3.building\u002F7.processor-api","i-lucide-cpu",{"title":140,"path":141,"stem":142,"icon":143},"Scheduled sources","\u002Fdocs\u002Fbuilding\u002Fscheduled-sources","1.docs\u002F3.building\u002F8.scheduled-sources","i-lucide-timer",{"title":145,"path":146,"stem":147,"icon":148},"Serdes and Avro","\u002Fdocs\u002Fbuilding\u002Fserdes","1.docs\u002F3.building\u002F9.serdes","i-lucide-binary",{"title":150,"path":151,"stem":152,"children":153,"icon":75},"Configuration","\u002Fdocs\u002Fconfiguration","1.docs\u002F4.configuration\u002F1.index",[154,156,161,166,171],{"title":155,"path":151,"stem":152,"icon":75},"How configuration works",{"title":157,"path":158,"stem":159,"icon":160},"Engine configuration (:core)","\u002Fdocs\u002Fconfiguration\u002Fcore-config","1.docs\u002F4.configuration\u002F2.core-config","i-lucide-settings-2",{"title":162,"path":163,"stem":164,"icon":165},"Runtime configuration (:runtime)","\u002Fdocs\u002Fconfiguration\u002Fruntime-config","1.docs\u002F4.configuration\u002F3.runtime-config","i-lucide-server-cog",{"title":167,"path":168,"stem":169,"icon":170},"Defaults, adaptivity, and presets","\u002Fdocs\u002Fconfiguration\u002Fdefaults-and-presets","1.docs\u002F4.configuration\u002F4.defaults-and-presets","i-lucide-gauge",{"title":172,"path":173,"stem":174,"icon":175},"Kafka client configuration","\u002Fdocs\u002Fconfiguration\u002Fkafka-client-config","1.docs\u002F4.configuration\u002F5.kafka-client-config","i-lucide-plug",{"title":177,"path":178,"stem":179,"children":180,"icon":183},"Running in Production","\u002Fdocs\u002Fruntime","1.docs\u002F5.runtime\u002F1.index",[181,184,189,194,199,204,209,214],{"title":182,"path":178,"stem":179,"icon":183},"The runtime","i-lucide-server",{"title":185,"path":186,"stem":187,"icon":188},"The REST API","\u002Fdocs\u002Fruntime\u002Frest-api","1.docs\u002F5.runtime\u002F2.rest-api","i-lucide-globe",{"title":190,"path":191,"stem":192,"icon":193},"Health checks","\u002Fdocs\u002Fruntime\u002Fhealth-checks","1.docs\u002F5.runtime\u002F3.health-checks","i-lucide-heart-pulse",{"title":195,"path":196,"stem":197,"icon":198},"Metrics","\u002Fdocs\u002Fruntime\u002Fmetrics","1.docs\u002F5.runtime\u002F4.metrics","i-lucide-activity",{"title":200,"path":201,"stem":202,"icon":203},"Pause and resume","\u002Fdocs\u002Fruntime\u002Fpause-unpause","1.docs\u002F5.runtime\u002F5.pause-unpause","i-lucide-pause",{"title":205,"path":206,"stem":207,"icon":208},"Plugins and lifecycle hooks","\u002Fdocs\u002Fruntime\u002Fplugins","1.docs\u002F5.runtime\u002F6.plugins","i-lucide-puzzle",{"title":210,"path":211,"stem":212,"icon":213},"Docker images","\u002Fdocs\u002Fruntime\u002Fdocker","1.docs\u002F5.runtime\u002F7.docker","i-lucide-container",{"title":215,"path":216,"stem":217,"icon":218},"GraalVM native image","\u002Fdocs\u002Fruntime\u002Fnative-image","1.docs\u002F5.runtime\u002F8.native-image","i-lucide-zap",{"title":220,"path":221,"stem":222,"children":223,"icon":226},"Deploying & Operating","\u002Fdocs\u002Foperating","1.docs\u002F6.operating\u002F1.index",[224,227,232,237,242,247,252],{"title":225,"path":221,"stem":222,"icon":226},"Deploying and operating","i-lucide-life-buoy",{"title":228,"path":229,"stem":230,"icon":231},"Running on Kubernetes","\u002Fdocs\u002Foperating\u002Fkubernetes","1.docs\u002F6.operating\u002F2.kubernetes","i-lucide-ship",{"title":233,"path":234,"stem":235,"icon":236},"High availability","\u002Fdocs\u002Foperating\u002Fhigh-availability","1.docs\u002F6.operating\u002F3.high-availability","i-lucide-copy",{"title":238,"path":239,"stem":240,"icon":241},"Liveness and readiness probes","\u002Fdocs\u002Foperating\u002Fprobes","1.docs\u002F6.operating\u002F4.probes","i-lucide-stethoscope",{"title":243,"path":244,"stem":245,"icon":246},"Observability","\u002Fdocs\u002Foperating\u002Fobservability","1.docs\u002F6.operating\u002F5.observability","i-lucide-telescope",{"title":248,"path":249,"stem":250,"icon":251},"Tuning under load","\u002Fdocs\u002Foperating\u002Ftuning","1.docs\u002F6.operating\u002F6.tuning","i-lucide-sliders",{"title":253,"path":254,"stem":255,"icon":256},"Production checklist","\u002Fdocs\u002Foperating\u002Fproduction-checklist","1.docs\u002F6.operating\u002F7.production-checklist","i-lucide-clipboard-check",{"title":258,"path":259,"stem":260,"children":261,"icon":85},"Migrating from Kafka Streams","\u002Fdocs\u002Fmigration","1.docs\u002F7.migration\u002F1.index",[262,263,268],{"title":258,"path":259,"stem":260,"icon":85},{"title":264,"path":265,"stem":266,"icon":267},"Migration without carrying state","\u002Fdocs\u002Fmigration\u002Fwithout-data-migration","1.docs\u002F7.migration\u002F2.without-data-migration","i-lucide-sparkles",{"title":269,"path":270,"stem":271,"icon":272},"Migration carrying state","\u002Fdocs\u002Fmigration\u002Fwith-data-migration","1.docs\u002F7.migration\u002F3.with-data-migration","i-lucide-database-backup",{"title":274,"path":275,"stem":276,"children":277,"icon":279},"Reference","\u002Fdocs\u002Freference","1.docs\u002F8.reference\u002F1.index",[278,280,285,290,295,300,305,309],{"title":274,"path":275,"stem":276,"icon":279},"i-lucide-list",{"title":281,"path":282,"stem":283,"icon":284},"Configuration reference","\u002Fdocs\u002Freference\u002Fconfiguration-reference","1.docs\u002F8.reference\u002F2.configuration-reference","i-lucide-table",{"title":286,"path":287,"stem":288,"icon":289},"REST API reference","\u002Fdocs\u002Freference\u002Frest-api-reference","1.docs\u002F8.reference\u002F3.rest-api-reference","i-lucide-network",{"title":291,"path":292,"stem":293,"icon":294},"Gradle plugin reference","\u002Fdocs\u002Freference\u002Fgradle-plugin-reference","1.docs\u002F8.reference\u002F4.gradle-plugin-reference","i-lucide-box",{"title":296,"path":297,"stem":298,"icon":299},"Maven reference","\u002Fdocs\u002Freference\u002Fmaven-reference","1.docs\u002F8.reference\u002F5.maven-reference","i-simple-icons-apachemaven",{"title":301,"path":302,"stem":303,"icon":304},"Kafka Streams compatibility matrix","\u002Fdocs\u002Freference\u002Fks-compatibility-matrix","1.docs\u002F8.reference\u002F6.ks-compatibility-matrix","i-lucide-table-2",{"title":306,"path":307,"stem":308,"icon":170},"Metrics reference","\u002Fdocs\u002Freference\u002Fmetrics-reference","1.docs\u002F8.reference\u002F7.metrics-reference",{"title":310,"path":311,"stem":312,"icon":313},"Glossary","\u002Fdocs\u002Freference\u002Fglossary","1.docs\u002F8.reference\u002F8.glossary","i-lucide-book-a",{"id":315,"title":190,"body":316,"description":2915,"extension":2916,"meta":2917,"navigation":2918,"pageType":2919,"path":191,"seo":2920,"stem":192,"__hash__":2921},"docs\u002F1.docs\u002F5.runtime\u002F3.health-checks.md",{"type":317,"value":318,"toc":2893},"minimark",[319,345,411,416,419,487,498,501,820,836,863,867,889,990,998,1001,1157,1166,1191,1197,1215,1229,1235,1256,1262,1265,1353,1371,1385,1400,1423,1429,1438,1463,1479,1483,1495,1509,1533,1643,1662,1666,1696,1700,1711,2316,2323,2482,2496,2499,2502,2617,2640,2644,2725,2841,2845,2889],[320,321,322,323,327,328,331,332,335,336,340,341,344],"p",{},"The ",[324,325,326],"code",{},":runtime"," module exposes two HTTP health endpoints — ",[324,329,330],{},"\u002Fhealth\u002Flive"," and ",[324,333,334],{},"\u002Fhealth\u002Fready"," — backed by a registry of health indicators. Each indicator answers two independent questions: ",[337,338,339],"em",{},"is the process alive?"," (liveness) and ",[337,342,343],{},"is the process ready to serve traffic?"," (readiness). This page covers the built-in indicators, exactly what flips each one, and how the probes behave while state is restoring.",[346,347,348],"tldr-panel",{},[349,350,351,364,378,388],"ul",{},[352,353,354,359,360,363],"li",{},[355,356,357],"strong",{},[324,358,330],{}," → keep the process running. Returns ",[324,361,362],{},"503"," only on a fatal condition where a restart is the right remedy.",[352,365,366,370,371,373,374,377],{},[355,367,368],{},[324,369,334],{}," → route traffic \u002F count as \"in service\". Returns ",[324,372,362],{}," during startup, ",[355,375,376],{},"restoration",", pause, and shutdown.",[352,379,380,383,384,387],{},[355,381,382],{},"Built-in indicators:"," app state, Kafka broker, Schema Registry (auto-enabled when configured), and license. The aggregate is UP only if ",[355,385,386],{},"every"," indicator is UP.",[352,389,390,393,394,397,398,331,400,397,403,405,406,410],{},[355,391,392],{},"k8s wiring:"," map ",[324,395,396],{},"livenessProbe"," → ",[324,399,330],{},[324,401,402],{},"readinessProbe",[324,404,334],{},". See ",[407,408,409],"a",{"href":239},"Probes",".",[412,413,415],"h2",{"id":414},"liveness-vs-readiness","Liveness vs readiness",[320,417,418],{},"The two probes serve different orchestrator decisions, so they have different failure semantics:",[420,421,422,443],"table",{},[423,424,425],"thead",{},[426,427,428,432,435,440],"tr",{},[429,430,431],"th",{},"Probe",[429,433,434],{},"Endpoint",[429,436,437,438],{},"Orchestrator action on ",[324,439,362],{},[429,441,442],{},"Use it to answer",[444,445,446,467],"tbody",{},[426,447,448,454,458,464],{},[449,450,451],"td",{},[355,452,453],{},"Liveness",[449,455,456],{},[324,457,330],{},[449,459,460,463],{},[355,461,462],{},"Restart"," the pod",[449,465,466],{},"\"Is this process wedged in a way only a restart fixes?\"",[426,468,469,474,478,484],{},[449,470,471],{},[355,472,473],{},"Readiness",[449,475,476],{},[324,477,334],{},[449,479,480,483],{},[355,481,482],{},"Stop routing traffic"," to the pod (no restart)",[449,485,486],{},"\"Can this process serve \u002F process right now?\"",[320,488,489,490,493,494,497],{},"The split matters because ",[355,491,492],{},"a restart does not fix every problem",". A pod that is still starting up, restoring its state stores, paused, or whose license has expired should ",[337,495,496],{},"not"," be restarted — restarting either wastes the work in progress or loops forever without resolving the issue. Those conditions flip readiness DOWN (stop sending it traffic) while keeping liveness UP (leave it running).",[320,499,500],{},"Both endpoints return the same JSON shape — an overall status plus one entry per indicator:",[502,503,508],"pre",{"className":504,"code":505,"language":506,"meta":507,"style":507},"language-json shiki shiki-themes vitesse-light","{\n  \"status\": \"UP\",\n  \"components\": [\n    { \"name\": \"stoatflow\", \"status\": \"UP\", \"details\": { \"state\": \"RUNNING\" } },\n    { \"name\": \"license\", \"status\": \"UP\", \"details\": { \"status\": \"VALID\", \"tier\": \"production\", \"daysRemaining\": 281 } },\n    { \"name\": \"kafka-broker\", \"status\": \"UP\", \"details\": { \"broker\": \"reachable\" } }\n  ]\n}\n","json","",[324,509,510,519,549,564,639,739,808,814],{"__ignoreMap":507},[511,512,515],"span",{"class":513,"line":514},"line",1,[511,516,518],{"class":517},"sYZai","{\n",[511,520,522,526,530,533,536,540,544,546],{"class":513,"line":521},2,[511,523,525],{"class":524},"s61at","  \"",[511,527,529],{"class":528},"su6XF","status",[511,531,532],{"class":524},"\"",[511,534,535],{"class":517},":",[511,537,539],{"class":538},"sSP4y"," \"",[511,541,543],{"class":542},"spphp","UP",[511,545,532],{"class":538},[511,547,548],{"class":517},",\n",[511,550,552,554,557,559,561],{"class":513,"line":551},3,[511,553,525],{"class":524},[511,555,556],{"class":528},"components",[511,558,532],{"class":524},[511,560,535],{"class":517},[511,562,563],{"class":517}," [\n",[511,565,567,570,572,575,577,579,581,584,586,589,591,593,595,597,599,601,603,605,607,610,612,614,617,619,622,624,626,628,631,633,636],{"class":513,"line":566},4,[511,568,569],{"class":517},"    {",[511,571,539],{"class":524},[511,573,574],{"class":528},"name",[511,576,532],{"class":524},[511,578,535],{"class":517},[511,580,539],{"class":538},[511,582,583],{"class":542},"stoatflow",[511,585,532],{"class":538},[511,587,588],{"class":517},",",[511,590,539],{"class":524},[511,592,529],{"class":528},[511,594,532],{"class":524},[511,596,535],{"class":517},[511,598,539],{"class":538},[511,600,543],{"class":542},[511,602,532],{"class":538},[511,604,588],{"class":517},[511,606,539],{"class":524},[511,608,609],{"class":528},"details",[511,611,532],{"class":524},[511,613,535],{"class":517},[511,615,616],{"class":517}," {",[511,618,539],{"class":524},[511,620,621],{"class":528},"state",[511,623,532],{"class":524},[511,625,535],{"class":517},[511,627,539],{"class":538},[511,629,630],{"class":542},"RUNNING",[511,632,532],{"class":538},[511,634,635],{"class":517}," }",[511,637,638],{"class":517}," },\n",[511,640,642,644,646,648,650,652,654,657,659,661,663,665,667,669,671,673,675,677,679,681,683,685,687,689,691,693,695,697,700,702,704,706,709,711,713,715,718,720,722,724,727,729,731,735,737],{"class":513,"line":641},5,[511,643,569],{"class":517},[511,645,539],{"class":524},[511,647,574],{"class":528},[511,649,532],{"class":524},[511,651,535],{"class":517},[511,653,539],{"class":538},[511,655,656],{"class":542},"license",[511,658,532],{"class":538},[511,660,588],{"class":517},[511,662,539],{"class":524},[511,664,529],{"class":528},[511,666,532],{"class":524},[511,668,535],{"class":517},[511,670,539],{"class":538},[511,672,543],{"class":542},[511,674,532],{"class":538},[511,676,588],{"class":517},[511,678,539],{"class":524},[511,680,609],{"class":528},[511,682,532],{"class":524},[511,684,535],{"class":517},[511,686,616],{"class":517},[511,688,539],{"class":524},[511,690,529],{"class":528},[511,692,532],{"class":524},[511,694,535],{"class":517},[511,696,539],{"class":538},[511,698,699],{"class":542},"VALID",[511,701,532],{"class":538},[511,703,588],{"class":517},[511,705,539],{"class":524},[511,707,708],{"class":528},"tier",[511,710,532],{"class":524},[511,712,535],{"class":517},[511,714,539],{"class":538},[511,716,717],{"class":542},"production",[511,719,532],{"class":538},[511,721,588],{"class":517},[511,723,539],{"class":524},[511,725,726],{"class":528},"daysRemaining",[511,728,532],{"class":524},[511,730,535],{"class":517},[511,732,734],{"class":733},"s-TwI"," 281",[511,736,635],{"class":517},[511,738,638],{"class":517},[511,740,742,744,746,748,750,752,754,757,759,761,763,765,767,769,771,773,775,777,779,781,783,785,787,789,792,794,796,798,801,803,805],{"class":513,"line":741},6,[511,743,569],{"class":517},[511,745,539],{"class":524},[511,747,574],{"class":528},[511,749,532],{"class":524},[511,751,535],{"class":517},[511,753,539],{"class":538},[511,755,756],{"class":542},"kafka-broker",[511,758,532],{"class":538},[511,760,588],{"class":517},[511,762,539],{"class":524},[511,764,529],{"class":528},[511,766,532],{"class":524},[511,768,535],{"class":517},[511,770,539],{"class":538},[511,772,543],{"class":542},[511,774,532],{"class":538},[511,776,588],{"class":517},[511,778,539],{"class":524},[511,780,609],{"class":528},[511,782,532],{"class":524},[511,784,535],{"class":517},[511,786,616],{"class":517},[511,788,539],{"class":524},[511,790,791],{"class":528},"broker",[511,793,532],{"class":524},[511,795,535],{"class":517},[511,797,539],{"class":538},[511,799,800],{"class":542},"reachable",[511,802,532],{"class":538},[511,804,635],{"class":517},[511,806,807],{"class":517}," }\n",[511,809,811],{"class":513,"line":810},7,[511,812,813],{"class":517},"  ]\n",[511,815,817],{"class":513,"line":816},8,[511,818,819],{"class":517},"}\n",[320,821,822,823,826,827,829,830,826,832,835],{},"HTTP status follows the overall status: ",[324,824,825],{},"200"," when ",[324,828,543],{},", ",[324,831,362],{},[324,833,834],{},"DOWN",". The format is compatible with Spring Boot Actuator, so existing dashboards and probe tooling that parse Actuator health work unchanged.",[837,838,841],"callout",{"color":839,"icon":840},"info","i-lucide-info",[320,842,843,844,846,847,852,853,855,856,858,859,862],{},"The aggregate is ",[324,845,543],{}," ",[355,848,849,850],{},"only if every registered indicator is ",[324,851,543],{},". One DOWN indicator flips the whole endpoint to ",[324,854,362],{},". The ",[324,857,556],{}," array always lists every indicator with its individual status, so you can see ",[337,860,861],{},"which"," one failed.",[412,864,866],{"id":865},"the-built-in-indicators","The built-in indicators",[320,868,869,872,873,876,877,880,881,884,885,888],{},[324,870,871],{},"StoatFlowRuntime"," registers four indicators automatically at startup (a fifth, ",[324,874,875],{},"ha",", when ",[407,878,879],{"href":234},"hot standby"," is enabled). Each is registered for ",[355,882,883],{},"both"," liveness and readiness, but most return ",[337,886,887],{},"different"," verdicts for the two checks — that is the whole point of the split.",[420,890,891,905],{},[423,892,893],{},[426,894,895,898,902],{},[429,896,897],{},"Indicator",[429,899,900],{},[324,901,574],{},[429,903,904],{},"What it checks",[444,906,907,928,944,960,972],{},[426,908,909,912,916],{},[449,910,911],{},"App state",[449,913,914],{},[324,915,583],{},[449,917,918,919,829,921,829,924,927],{},"The engine's lifecycle state (",[324,920,630],{},[324,922,923],{},"RESTORING",[324,925,926],{},"PAUSED",", …)",[426,929,930,933,937],{},[449,931,932],{},"Kafka broker",[449,934,935],{},[324,936,756],{},[449,938,939,940,943],{},"Broker connectivity via an ",[324,941,942],{},"AdminClient"," call",[426,945,946,949,954],{},[449,947,948],{},"Schema Registry",[449,950,951],{},[324,952,953],{},"schema-registry",[449,955,956,957],{},"HTTP reachability — ",[355,958,959],{},"only registered if a Schema Registry URL is configured",[426,961,962,965,969],{},[449,963,964],{},"License",[449,966,967],{},[324,968,656],{},[449,970,971],{},"Runtime license validity",[426,973,974,977,981],{},[449,975,976],{},"Hot standby",[449,978,979],{},[324,980,875],{},[449,982,983,984],{},"HA role and standby catch-up — ",[355,985,986,987],{},"only registered when ",[324,988,989],{},"ha.mode != off",[991,992,994,995,997],"h3",{"id":993},"app-state-stoatflow","App state (",[324,996,583],{},")",[320,999,1000],{},"The canonical indicator — it reads the engine's lifecycle state and maps it to liveness and readiness:",[420,1002,1003,1017],{},[423,1004,1005],{},[426,1006,1007,1010,1012,1014],{},[429,1008,1009],{},"Engine state",[429,1011,453],{},[429,1013,473],{},[429,1015,1016],{},"Why",[444,1018,1019,1033,1047,1061,1074,1088,1102,1115,1129,1143],{},[426,1020,1021,1026,1028,1030],{},[449,1022,1023],{},[324,1024,1025],{},"CREATED",[449,1027,834],{},[449,1029,834],{},[449,1031,1032],{},"Not started yet",[426,1034,1035,1040,1042,1044],{},[449,1036,1037],{},[324,1038,1039],{},"STARTING",[449,1041,543],{},[449,1043,834],{},[449,1045,1046],{},"Alive, not yet serving",[426,1048,1049,1054,1056,1058],{},[449,1050,1051],{},[324,1052,1053],{},"VALIDATING_STATE",[449,1055,543],{},[449,1057,834],{},[449,1059,1060],{},"Startup in progress",[426,1062,1063,1067,1069,1071],{},[449,1064,1065],{},[324,1066,923],{},[449,1068,543],{},[449,1070,834],{},[449,1072,1073],{},"Startup in progress — see below",[426,1075,1076,1080,1083,1085],{},[449,1077,1078],{},[324,1079,630],{},[449,1081,1082],{},"UP*",[449,1084,543],{},[449,1086,1087],{},"Ready to process",[426,1089,1090,1095,1097,1099],{},[449,1091,1092],{},[324,1093,1094],{},"DRAINING",[449,1096,543],{},[449,1098,834],{},[449,1100,1101],{},"Pausing, draining in-flight work",[426,1103,1104,1108,1110,1112],{},[449,1105,1106],{},[324,1107,926],{},[449,1109,543],{},[449,1111,834],{},[449,1113,1114],{},"Paused, not accepting new traffic",[426,1116,1117,1122,1124,1126],{},[449,1118,1119],{},[324,1120,1121],{},"STOPPING",[449,1123,543],{},[449,1125,834],{},[449,1127,1128],{},"Shutting down, no new traffic",[426,1130,1131,1136,1138,1140],{},[449,1132,1133],{},[324,1134,1135],{},"STOPPED",[449,1137,834],{},[449,1139,834],{},[449,1141,1142],{},"Terminated",[426,1144,1145,1150,1152,1154],{},[449,1146,1147],{},[324,1148,1149],{},"ERROR",[449,1151,834],{},[449,1153,834],{},[449,1155,1156],{},"Fatal error",[320,1158,1159,1160,1162,1163,1165],{},"Readiness is ",[324,1161,543],{}," in exactly one state — ",[324,1164,630],{},". Every transient lifecycle state (starting, restoring, draining, pausing, stopping) is readiness DOWN but liveness UP, so the orchestrator routes traffic away without killing a process that is doing legitimate work.",[320,1167,1168,1169,1171,1172,1175,1176,1179,1180,1183,1184,829,1187,1190],{},"*The asterisk on ",[324,1170,630],{}," liveness: if the engine's commit pipeline stalls past a configured threshold, liveness flips DOWN so the orchestrator can restart a wedged process. This is an independent safety net layered on top of the in-process supervision the engine already runs — the probe exists so Kubernetes has its own recovery path even if internal recovery is itself stuck. The threshold is the engine's ",[324,1173,1174],{},"commitStallThresholdMs"," field (default 45 000 ms; set ",[324,1177,1178],{},"0"," to disable the check), set in YAML via ",[324,1181,1182],{},"stoatflow.commit-stall.threshold-ms",". When it fires, the liveness response carries ",[324,1185,1186],{},"stall_age_ms",[324,1188,1189],{},"stall_threshold_ms",", and related detail fields so the cause is visible in the probe payload.",[991,1192,1194,1195,997],{"id":1193},"kafka-broker-kafka-broker","Kafka broker (",[324,1196,756],{},[320,1198,1199,1200,1202,1203,1206,1207,1210,1211,1214],{},"Verifies broker connectivity by listing topics through a dedicated ",[324,1201,942],{},". A StoatFlow app ",[355,1204,1205],{},"cannot make progress without its broker",", so this indicator returns the ",[337,1208,1209],{},"same"," verdict for both probes: unreachable broker → DOWN for liveness ",[337,1212,1213],{},"and"," readiness. Loss of broker connectivity is treated as fatal — a restart is a reasonable response.",[320,1216,1217,1218,1221,1222,1225,1226,410],{},"The check is bounded by a timeout (",[324,1219,1220],{},"runtime.health.kafka-broker.timeout-ms",", default 2 000 ms). On success the detail is ",[324,1223,1224],{},"{ \"broker\": \"reachable\" }","; on failure it is ",[324,1227,1228],{},"{ \"broker\": \"unreachable\", \"error\": \"…\" }",[991,1230,1232,1233,997],{"id":1231},"schema-registry-schema-registry","Schema Registry (",[324,1234,953],{},[320,1236,1237,1240,1241,1244,1245,1247,1248,1251,1252,1255],{},[355,1238,1239],{},"Self-enabling"," — this indicator is registered only when a Schema Registry URL is configured (",[324,1242,1243],{},"stoatflow.schema-registry-url","). If you don't use Schema Registry, it never appears in the ",[324,1246,556],{}," array. When present, it does an HTTP ",[324,1249,1250],{},"GET \u002Fsubjects"," against the registry; like the broker check it returns the same verdict for liveness and readiness (unreachable → DOWN for both). Its timeout is ",[324,1253,1254],{},"runtime.health.schema-registry.timeout-ms"," (default 5 000 ms).",[991,1257,1259,1260,997],{"id":1258},"license-license","License (",[324,1261,656],{},[320,1263,1264],{},"The license indicator is the clearest example of the liveness\u002Freadiness split:",[420,1266,1267,1278],{},[423,1268,1269],{},[426,1270,1271,1274,1276],{},[429,1272,1273],{},"License status",[429,1275,453],{},[429,1277,473],{},[444,1279,1280,1290,1301,1314,1327,1340],{},[426,1281,1282,1286,1288],{},[449,1283,1284],{},[324,1285,699],{},[449,1287,543],{},[449,1289,543],{},[426,1291,1292,1297,1299],{},[449,1293,1294],{},[324,1295,1296],{},"GRACE_PERIOD",[449,1298,543],{},[449,1300,543],{},[426,1302,1303,1308,1310],{},[449,1304,1305],{},[324,1306,1307],{},"EXPIRED",[449,1309,543],{},[449,1311,1312],{},[355,1313,834],{},[426,1315,1316,1321,1323],{},[449,1317,1318],{},[324,1319,1320],{},"REVOKED",[449,1322,543],{},[449,1324,1325],{},[355,1326,834],{},[426,1328,1329,1334,1336],{},[449,1330,1331],{},[324,1332,1333],{},"INVALID",[449,1335,543],{},[449,1337,1338],{},[355,1339,834],{},[426,1341,1342,1347,1349],{},[449,1343,1344],{},[324,1345,1346],{},"NO_KEY",[449,1348,543],{},[449,1350,1351],{},[355,1352,834],{},[320,1354,1355,1356,829,1358,829,1360,1362,1363,1365,1366,331,1368,1370],{},"Readiness goes DOWN the moment the license is no longer operational — ",[324,1357,1307],{},[324,1359,1320],{},[324,1361,1333],{},", or ",[324,1364,1346],{}," — so orchestrators stop routing traffic to a pod whose license has been pulled. ",[324,1367,699],{},[324,1369,1296],{}," are both treated as operational (the grace period exists precisely so a transient validation outage doesn't take you down).",[320,1372,1373,1374,1377,1378,331,1380,1382,1383,410],{},"Liveness stays ",[355,1375,1376],{},"UP regardless of license status",". Restarting a pod will not fix an expired or revoked license — it would just produce a restart loop that hides the real problem. The readiness payload carries the ",[324,1379,529],{},[324,1381,708],{},"; the operational (UP) readiness payload additionally carries ",[324,1384,726],{},[320,1386,1387,1388,1391,1392,1395,1396,1399],{},"Within the renewal-warning window, the ",[355,1389,1390],{},"liveness"," payload adds a ",[324,1393,1394],{},"licenseRenewalWarning"," detail (e.g. ",[324,1397,1398],{},"\"expires in 9 days\"",") so the nudge is visible on the liveness response too — even though liveness itself stays UP.",[837,1401,1403],{"color":839,"icon":1402},"i-lucide-shield",[320,1404,1405,1406,1408,1409,1412,1413,1416,1417,1419,1420,1422],{},"The license ",[355,1407,621],{}," also drives a readiness check at the cluster level and is mirrored on the dedicated ",[324,1410,1411],{},"\u002Flicense"," HTTP endpoint and license metrics. See the ",[407,1414,1415],{"href":186},"REST API"," for ",[324,1418,1411],{},", and ",[407,1421,195],{"href":196}," for the license gauges and counters.",[991,1424,1426,1427,997],{"id":1425},"hot-standby-ha","Hot standby (",[324,1428,875],{},[320,1430,1431,1432,1434,1435,1437],{},"Registered only when ",[407,1433,879],{"href":234}," is enabled (",[324,1436,989],{},"). It encodes the readiness contract that makes the rolling update order-independent:",[349,1439,1440,1458],{},[352,1441,1442,1444,1445,1447,1448,1450,1451,1453,1454,1457],{},[355,1443,473],{}," is UP when the pod is the active ",[355,1446,1213],{}," processing, or a standby ",[355,1449,1213],{}," caught up. A still-catching-up standby is ",[337,1452,496],{}," ready, so Kubernetes won't advance the roll until the restarted pod is a caught-up standby. With more than one standby it also enforces the redundancy floor — a caught-up standby is ready to roll only if rolling it leaves the active plus at least one other caught-up standby (",[324,1455,1456],{},"ha.desired-standbys",").",[352,1459,1460,1462],{},[355,1461,453],{}," stays UP while a standby is catching up (so it isn't killed mid-catch-up); it goes DOWN only when the pod is genuinely down or a restart is required (for example, after a source topic's partition count changes).",[320,1464,1465,1466,331,1469,1472,1473,405,1476,1478],{},"The payload carries ",[324,1467,1468],{},"role",[324,1470,1471],{},"ha_state"," details; readiness also reports ",[324,1474,1475],{},"replication_lag_records",[407,1477,233],{"href":234}," for the full operational picture.",[412,1480,1482],{"id":1481},"how-the-probes-behave-during-restoration","How the probes behave during restoration",[320,1484,1485,1486,1488,1489,1491,1492,1494],{},"State restoration is the case the readiness\u002Fliveness split is designed for. On startup — and again after a crash recovery — StoatFlow rebuilds its state stores from their changelog topics before it begins processing. While that runs, the engine is in ",[324,1487,923],{}," (preceded by ",[324,1490,1039],{}," \u002F ",[324,1493,1053],{},"):",[349,1496,1497,1503],{},[352,1498,1499,1502],{},[355,1500,1501],{},"Readiness is DOWN"," for the entire restoration. The app is alive but not yet processing, so the orchestrator must not count it as in service or route admin traffic to it as \"ready\".",[352,1504,1505,1508],{},[355,1506,1507],{},"Liveness is UP"," throughout. Restoration is expected, legitimate work — restarting mid-restore would throw away progress and start over, potentially never converging for a large state store.",[320,1510,1511,1512,1515,1516,1518,1519,1522,1523,1525,1526,1491,1529,1532],{},"This is why you map the ",[355,1513,1514],{},"readiness"," probe to load-balancer membership and the ",[355,1517,1390],{}," probe to restart decisions. A correctly-wired deployment lets a restoring pod take all the time it needs (within the readiness probe's ",[324,1520,1521],{},"failureThreshold × periodSeconds"," budget) without being killed. Size the readiness probe's startup tolerance to your largest expected restore — see ",[407,1524,409],{"href":239}," for the ",[324,1527,1528],{},"startupProbe",[324,1530,1531],{},"initialDelaySeconds"," guidance.",[502,1534,1538],{"className":1535,"code":1536,"language":1537,"meta":507,"style":507},"language-bash shiki shiki-themes vitesse-light","# During restoration: ready is 503, live is 200.\ncurl -s -o \u002Fdev\u002Fnull -w \"ready=%{http_code}\\n\" localhost:8080\u002Fhealth\u002Fready   # ready=503\ncurl -s -o \u002Fdev\u002Fnull -w \"live=%{http_code}\\n\"  localhost:8080\u002Fhealth\u002Flive    # live=200\n\n# The readiness body shows why:\ncurl -s localhost:8080\u002Fhealth\u002Fready | jq '.components[] | select(.name==\"stoatflow\")'\n# { \"name\": \"stoatflow\", \"status\": \"DOWN\", \"details\": { \"state\": \"RESTORING\" } }\n","bash",[324,1539,1540,1546,1578,1603,1609,1614,1638],{"__ignoreMap":507},[511,1541,1542],{"class":513,"line":514},[511,1543,1545],{"class":1544},"s8zF2","# During restoration: ready is 503, live is 200.\n",[511,1547,1548,1552,1556,1559,1562,1565,1567,1570,1572,1575],{"class":513,"line":521},[511,1549,1551],{"class":1550},"sySUi","curl",[511,1553,1555],{"class":1554},"sEi1f"," -s",[511,1557,1558],{"class":1554}," -o",[511,1560,1561],{"class":542}," \u002Fdev\u002Fnull",[511,1563,1564],{"class":1554}," -w",[511,1566,539],{"class":538},[511,1568,1569],{"class":542},"ready=%{http_code}\\n",[511,1571,532],{"class":538},[511,1573,1574],{"class":542}," localhost:8080\u002Fhealth\u002Fready",[511,1576,1577],{"class":1544},"   # ready=503\n",[511,1579,1580,1582,1584,1586,1588,1590,1592,1595,1597,1600],{"class":513,"line":551},[511,1581,1551],{"class":1550},[511,1583,1555],{"class":1554},[511,1585,1558],{"class":1554},[511,1587,1561],{"class":542},[511,1589,1564],{"class":1554},[511,1591,539],{"class":538},[511,1593,1594],{"class":542},"live=%{http_code}\\n",[511,1596,532],{"class":538},[511,1598,1599],{"class":542},"  localhost:8080\u002Fhealth\u002Flive",[511,1601,1602],{"class":1544},"    # live=200\n",[511,1604,1605],{"class":513,"line":566},[511,1606,1608],{"emptyLinePlaceholder":1607},true,"\n",[511,1610,1611],{"class":513,"line":641},[511,1612,1613],{"class":1544},"# The readiness body shows why:\n",[511,1615,1616,1618,1620,1622,1626,1629,1632,1635],{"class":513,"line":741},[511,1617,1551],{"class":1550},[511,1619,1555],{"class":1554},[511,1621,1574],{"class":542},[511,1623,1625],{"class":1624},"si04Y"," |",[511,1627,1628],{"class":1550}," jq",[511,1630,1631],{"class":538}," '",[511,1633,1634],{"class":542},".components[] | select(.name==\"stoatflow\")",[511,1636,1637],{"class":538},"'\n",[511,1639,1640],{"class":513,"line":810},[511,1641,1642],{"class":1544},"# { \"name\": \"stoatflow\", \"status\": \"DOWN\", \"details\": { \"state\": \"RESTORING\" } }\n",[320,1644,1645,1646,1649,1650,1491,1652,1654,1655,1658,1659,410],{},"The same pattern applies to ",[355,1647,1648],{},"pause\u002Funpause",": a paused engine (",[324,1651,926],{},[324,1653,1094],{},") is readiness DOWN, liveness UP — traffic is steered away but the process is left running so you can ",[324,1656,1657],{},"\u002Funpause"," it. See ",[407,1660,1661],{"href":201},"Pause and unpause",[412,1663,1665],{"id":1664},"the-indicator-registry","The indicator registry",[320,1667,1668,1669,1672,1673,1676,1677,1679,1680,1683,1684,1686,1687,1690,1691,1693,1694,410],{},"Indicators are held in a registry that keeps ",[355,1670,1671],{},"separate collections for liveness and readiness",". Registering an indicator with ",[324,1674,1675],{},"register(name, indicator)"," adds it to both; the registry also supports liveness-only and readiness-only registration. ",[324,1678,330],{}," evaluates every liveness indicator's ",[324,1681,1682],{},"livenessHealth()","; ",[324,1685,334],{}," evaluates every readiness indicator's ",[324,1688,1689],{},"health()",". The overall status is ",[324,1692,543],{}," only when all indicators in that collection report ",[324,1695,543],{},[991,1697,1699],{"id":1698},"adding-your-own-indicator","Adding your own indicator",[320,1701,1702,1703,1705,1706,1708,1709,1494],{},"A health indicator implements one interface — ",[324,1704,1689],{}," for readiness and an optional ",[324,1707,1682],{}," (defaults to the same verdict as ",[324,1710,1689],{},[1712,1713,1715,1966],"code-tabs",{"group":1714},"lang",[502,1716,1721],{"className":1717,"code":1718,"filename":1719,"language":1720,"meta":507,"style":507},"language-kotlin shiki shiki-themes vitesse-light","import io.stoatflow.runtime.health.Health\nimport io.stoatflow.runtime.health.HealthIndicator\n\nclass DownstreamApiHealthIndicator(\n    private val client: DownstreamClient,\n) : HealthIndicator {\n    \u002F\u002F Readiness: stop routing traffic if the dependency is down.\n    override fun health(): Health =\n        if (client.ping()) {\n            Health.up().withDetail(\"downstream\", \"reachable\").build()\n        } else {\n            Health.down().withDetail(\"downstream\", \"unreachable\").build()\n        }\n\n    \u002F\u002F Liveness: a downstream outage should NOT restart us — leave the default,\n    \u002F\u002F or override to return UP explicitly.\n    override fun livenessHealth(): Health =\n        Health.up().withDetail(\"downstream\", \"checked-on-readiness-only\").build()\n}\n","Kotlin","kotlin",[324,1722,1723,1732,1739,1743,1756,1772,1783,1788,1808,1823,1857,1868,1895,1901,1906,1912,1918,1934,1961],{"__ignoreMap":507},[511,1724,1725,1729],{"class":513,"line":514},[511,1726,1728],{"class":1727},"sbBg2","import",[511,1730,1731],{"class":1550}," io.stoatflow.runtime.health.Health\n",[511,1733,1734,1736],{"class":513,"line":521},[511,1735,1728],{"class":1727},[511,1737,1738],{"class":1550}," io.stoatflow.runtime.health.HealthIndicator\n",[511,1740,1741],{"class":513,"line":551},[511,1742,1608],{"emptyLinePlaceholder":1607},[511,1744,1745,1748,1752],{"class":513,"line":566},[511,1746,1747],{"class":1727},"class",[511,1749,1751],{"class":1750},"sUxyF"," DownstreamApiHealthIndicator",[511,1753,1755],{"class":1754},"suHK_","(\n",[511,1757,1758,1761,1764,1767,1770],{"class":513,"line":641},[511,1759,1760],{"class":1624},"    private",[511,1762,1763],{"class":1727}," val",[511,1765,1766],{"class":1754}," client: ",[511,1768,1769],{"class":1750},"DownstreamClient",[511,1771,548],{"class":1754},[511,1773,1774,1777,1780],{"class":513,"line":741},[511,1775,1776],{"class":1754},") : ",[511,1778,1779],{"class":1750},"HealthIndicator",[511,1781,1782],{"class":1754}," {\n",[511,1784,1785],{"class":513,"line":810},[511,1786,1787],{"class":1544},"    \u002F\u002F Readiness: stop routing traffic if the dependency is down.\n",[511,1789,1790,1793,1796,1799,1802,1805],{"class":513,"line":816},[511,1791,1792],{"class":1624},"    override",[511,1794,1795],{"class":1727}," fun",[511,1797,1798],{"class":1550}," health",[511,1800,1801],{"class":1754},"(): ",[511,1803,1804],{"class":1750},"Health",[511,1806,1807],{"class":517}," =\n",[511,1809,1811,1814,1817,1820],{"class":513,"line":1810},9,[511,1812,1813],{"class":1727},"        if",[511,1815,1816],{"class":1754}," (client.",[511,1818,1819],{"class":1550},"ping",[511,1821,1822],{"class":1754},"()) {\n",[511,1824,1826,1829,1832,1835,1838,1841,1844,1846,1849,1851,1854],{"class":513,"line":1825},10,[511,1827,1828],{"class":1754},"            Health.",[511,1830,1831],{"class":1550},"up",[511,1833,1834],{"class":1754},"().",[511,1836,1837],{"class":1550},"withDetail",[511,1839,1840],{"class":1754},"(",[511,1842,1843],{"class":542},"\"downstream\"",[511,1845,829],{"class":1754},[511,1847,1848],{"class":542},"\"reachable\"",[511,1850,1457],{"class":1754},[511,1852,1853],{"class":1550},"build",[511,1855,1856],{"class":1754},"()\n",[511,1858,1860,1863,1866],{"class":513,"line":1859},11,[511,1861,1862],{"class":1754},"        } ",[511,1864,1865],{"class":1727},"else",[511,1867,1782],{"class":1754},[511,1869,1871,1873,1876,1878,1880,1882,1884,1886,1889,1891,1893],{"class":513,"line":1870},12,[511,1872,1828],{"class":1754},[511,1874,1875],{"class":1550},"down",[511,1877,1834],{"class":1754},[511,1879,1837],{"class":1550},[511,1881,1840],{"class":1754},[511,1883,1843],{"class":542},[511,1885,829],{"class":1754},[511,1887,1888],{"class":542},"\"unreachable\"",[511,1890,1457],{"class":1754},[511,1892,1853],{"class":1550},[511,1894,1856],{"class":1754},[511,1896,1898],{"class":513,"line":1897},13,[511,1899,1900],{"class":1754},"        }\n",[511,1902,1904],{"class":513,"line":1903},14,[511,1905,1608],{"emptyLinePlaceholder":1607},[511,1907,1909],{"class":513,"line":1908},15,[511,1910,1911],{"class":1544},"    \u002F\u002F Liveness: a downstream outage should NOT restart us — leave the default,\n",[511,1913,1915],{"class":513,"line":1914},16,[511,1916,1917],{"class":1544},"    \u002F\u002F or override to return UP explicitly.\n",[511,1919,1921,1923,1925,1928,1930,1932],{"class":513,"line":1920},17,[511,1922,1792],{"class":1624},[511,1924,1795],{"class":1727},[511,1926,1927],{"class":1550}," livenessHealth",[511,1929,1801],{"class":1754},[511,1931,1804],{"class":1750},[511,1933,1807],{"class":517},[511,1935,1937,1940,1942,1944,1946,1948,1950,1952,1955,1957,1959],{"class":513,"line":1936},18,[511,1938,1939],{"class":1754},"        Health.",[511,1941,1831],{"class":1550},[511,1943,1834],{"class":1754},[511,1945,1837],{"class":1550},[511,1947,1840],{"class":1754},[511,1949,1843],{"class":542},[511,1951,829],{"class":1754},[511,1953,1954],{"class":542},"\"checked-on-readiness-only\"",[511,1956,1457],{"class":1754},[511,1958,1853],{"class":1550},[511,1960,1856],{"class":1754},[511,1962,1964],{"class":513,"line":1963},19,[511,1965,819],{"class":1754},[502,1967,1972],{"className":1968,"code":1969,"filename":1970,"language":1971,"meta":507,"style":507},"language-java shiki shiki-themes vitesse-light","import io.stoatflow.runtime.health.Health;\nimport io.stoatflow.runtime.health.HealthIndicator;\n\npublic class DownstreamApiHealthIndicator implements HealthIndicator {\n\n    private final DownstreamClient client;\n\n    public DownstreamApiHealthIndicator(DownstreamClient client) {\n        this.client = client;\n    }\n\n    \u002F\u002F Readiness: stop routing traffic if the dependency is down.\n    @Override\n    public Health health() {\n        return client.ping()\n            ? Health.up().withDetail(\"downstream\", \"reachable\").build()\n            : Health.down().withDetail(\"downstream\", \"unreachable\").build();\n    }\n\n    \u002F\u002F Liveness: a downstream outage should NOT restart us.\n    @Override\n    public Health livenessHealth() {\n        return Health.up().withDetail(\"downstream\", \"checked-on-readiness-only\").build();\n    }\n}\n","Java","java",[324,1973,1974,2002,2026,2030,2048,2052,2068,2072,2091,2107,2112,2116,2120,2128,2142,2155,2194,2233,2237,2241,2247,2254,2268,2306,2311],{"__ignoreMap":507},[511,1975,1976,1978,1981,1983,1985,1987,1990,1992,1995,1997,1999],{"class":513,"line":514},[511,1977,1728],{"class":1727},[511,1979,1980],{"class":1754}," io",[511,1982,410],{"class":517},[511,1984,583],{"class":1754},[511,1986,410],{"class":517},[511,1988,1989],{"class":1754},"runtime",[511,1991,410],{"class":517},[511,1993,1994],{"class":1754},"health",[511,1996,410],{"class":517},[511,1998,1804],{"class":1754},[511,2000,2001],{"class":517},";\n",[511,2003,2004,2006,2008,2010,2012,2014,2016,2018,2020,2022,2024],{"class":513,"line":521},[511,2005,1728],{"class":1727},[511,2007,1980],{"class":1754},[511,2009,410],{"class":517},[511,2011,583],{"class":1754},[511,2013,410],{"class":517},[511,2015,1989],{"class":1754},[511,2017,410],{"class":517},[511,2019,1994],{"class":1754},[511,2021,410],{"class":517},[511,2023,1779],{"class":1754},[511,2025,2001],{"class":517},[511,2027,2028],{"class":513,"line":551},[511,2029,1608],{"emptyLinePlaceholder":1607},[511,2031,2032,2035,2038,2040,2043,2046],{"class":513,"line":566},[511,2033,2034],{"class":1624},"public",[511,2036,2037],{"class":1624}," class",[511,2039,1751],{"class":1750},[511,2041,2042],{"class":1624}," implements",[511,2044,2045],{"class":1550}," HealthIndicator",[511,2047,1782],{"class":517},[511,2049,2050],{"class":513,"line":641},[511,2051,1608],{"emptyLinePlaceholder":1607},[511,2053,2054,2056,2059,2062,2066],{"class":513,"line":741},[511,2055,1760],{"class":1624},[511,2057,2058],{"class":1624}," final",[511,2060,2061],{"class":1754}," DownstreamClient",[511,2063,2065],{"class":2064},"svycV"," client",[511,2067,2001],{"class":517},[511,2069,2070],{"class":513,"line":810},[511,2071,1608],{"emptyLinePlaceholder":1607},[511,2073,2074,2077,2079,2081,2084,2087,2089],{"class":513,"line":816},[511,2075,2076],{"class":1624},"    public",[511,2078,1751],{"class":1550},[511,2080,1840],{"class":517},[511,2082,2083],{"class":1754},"DownstreamClient ",[511,2085,2086],{"class":2064},"client",[511,2088,997],{"class":517},[511,2090,1782],{"class":517},[511,2092,2093,2096,2098,2100,2103,2105],{"class":513,"line":1810},[511,2094,2095],{"class":1554},"        this",[511,2097,410],{"class":517},[511,2099,2086],{"class":2064},[511,2101,2102],{"class":517}," =",[511,2104,2065],{"class":1754},[511,2106,2001],{"class":517},[511,2108,2109],{"class":513,"line":1825},[511,2110,2111],{"class":517},"    }\n",[511,2113,2114],{"class":513,"line":1859},[511,2115,1608],{"emptyLinePlaceholder":1607},[511,2117,2118],{"class":513,"line":1870},[511,2119,1787],{"class":1544},[511,2121,2122,2125],{"class":513,"line":1897},[511,2123,2124],{"class":517},"    @",[511,2126,2127],{"class":1624},"Override\n",[511,2129,2130,2132,2135,2137,2140],{"class":513,"line":1903},[511,2131,2076],{"class":1624},[511,2133,2134],{"class":1754}," Health ",[511,2136,1994],{"class":1550},[511,2138,2139],{"class":517},"()",[511,2141,1782],{"class":517},[511,2143,2144,2147,2149,2151,2153],{"class":513,"line":1908},[511,2145,2146],{"class":1727},"        return",[511,2148,2065],{"class":2064},[511,2150,410],{"class":517},[511,2152,1819],{"class":1550},[511,2154,1856],{"class":517},[511,2156,2157,2160,2163,2165,2167,2169,2171,2173,2175,2178,2180,2182,2184,2186,2188,2190,2192],{"class":513,"line":1914},[511,2158,2159],{"class":1727},"            ?",[511,2161,2162],{"class":2064}," Health",[511,2164,410],{"class":517},[511,2166,1831],{"class":1550},[511,2168,1834],{"class":517},[511,2170,1837],{"class":1550},[511,2172,1840],{"class":517},[511,2174,532],{"class":538},[511,2176,2177],{"class":542},"downstream",[511,2179,532],{"class":538},[511,2181,588],{"class":517},[511,2183,539],{"class":538},[511,2185,800],{"class":542},[511,2187,532],{"class":538},[511,2189,1457],{"class":517},[511,2191,1853],{"class":1550},[511,2193,1856],{"class":517},[511,2195,2196,2199,2201,2203,2205,2207,2209,2211,2213,2215,2217,2219,2221,2224,2226,2228,2230],{"class":513,"line":1920},[511,2197,2198],{"class":1727},"            :",[511,2200,2162],{"class":2064},[511,2202,410],{"class":517},[511,2204,1875],{"class":1550},[511,2206,1834],{"class":517},[511,2208,1837],{"class":1550},[511,2210,1840],{"class":517},[511,2212,532],{"class":538},[511,2214,2177],{"class":542},[511,2216,532],{"class":538},[511,2218,588],{"class":517},[511,2220,539],{"class":538},[511,2222,2223],{"class":542},"unreachable",[511,2225,532],{"class":538},[511,2227,1457],{"class":517},[511,2229,1853],{"class":1550},[511,2231,2232],{"class":517},"();\n",[511,2234,2235],{"class":513,"line":1936},[511,2236,2111],{"class":517},[511,2238,2239],{"class":513,"line":1963},[511,2240,1608],{"emptyLinePlaceholder":1607},[511,2242,2244],{"class":513,"line":2243},20,[511,2245,2246],{"class":1544},"    \u002F\u002F Liveness: a downstream outage should NOT restart us.\n",[511,2248,2250,2252],{"class":513,"line":2249},21,[511,2251,2124],{"class":517},[511,2253,2127],{"class":1624},[511,2255,2257,2259,2261,2264,2266],{"class":513,"line":2256},22,[511,2258,2076],{"class":1624},[511,2260,2134],{"class":1754},[511,2262,2263],{"class":1550},"livenessHealth",[511,2265,2139],{"class":517},[511,2267,1782],{"class":517},[511,2269,2271,2273,2275,2277,2279,2281,2283,2285,2287,2289,2291,2293,2295,2298,2300,2302,2304],{"class":513,"line":2270},23,[511,2272,2146],{"class":1727},[511,2274,2162],{"class":2064},[511,2276,410],{"class":517},[511,2278,1831],{"class":1550},[511,2280,1834],{"class":517},[511,2282,1837],{"class":1550},[511,2284,1840],{"class":517},[511,2286,532],{"class":538},[511,2288,2177],{"class":542},[511,2290,532],{"class":538},[511,2292,588],{"class":517},[511,2294,539],{"class":538},[511,2296,2297],{"class":542},"checked-on-readiness-only",[511,2299,532],{"class":538},[511,2301,1457],{"class":517},[511,2303,1853],{"class":1550},[511,2305,2232],{"class":517},[511,2307,2309],{"class":513,"line":2308},24,[511,2310,2111],{"class":517},[511,2312,2314],{"class":513,"line":2313},25,[511,2315,819],{"class":517},[320,2317,2318,2319,2322],{},"Register it on the runtime builder with ",[324,2320,2321],{},"addHealthIndicator(name, indicator)",", which puts it in both the liveness and readiness collections alongside the built-ins:",[1712,2324,2325,2402],{"group":1714},[502,2326,2328],{"className":1717,"code":2327,"filename":1719,"language":1720,"meta":507,"style":507},"val runtime = StoatFlowRuntime.fromConfig(\n    topologyBuilder = { buildTopology(it) },\n    configure = {\n        addHealthIndicator(\"downstream-api\", DownstreamApiHealthIndicator(client))\n    },\n)\n",[324,2329,2330,2349,2365,2374,2392,2397],{"__ignoreMap":507},[511,2331,2332,2335,2338,2341,2344,2347],{"class":513,"line":514},[511,2333,2334],{"class":1727},"val",[511,2336,2337],{"class":1754}," runtime ",[511,2339,2340],{"class":517},"=",[511,2342,2343],{"class":1754}," StoatFlowRuntime.",[511,2345,2346],{"class":1550},"fromConfig",[511,2348,1755],{"class":1754},[511,2350,2351,2354,2356,2359,2362],{"class":513,"line":521},[511,2352,2353],{"class":1754},"    topologyBuilder ",[511,2355,2340],{"class":517},[511,2357,2358],{"class":1754}," { ",[511,2360,2361],{"class":1550},"buildTopology",[511,2363,2364],{"class":1754},"(it) },\n",[511,2366,2367,2370,2372],{"class":513,"line":551},[511,2368,2369],{"class":1754},"    configure ",[511,2371,2340],{"class":517},[511,2373,1782],{"class":1754},[511,2375,2376,2379,2381,2384,2386,2389],{"class":513,"line":566},[511,2377,2378],{"class":1550},"        addHealthIndicator",[511,2380,1840],{"class":1754},[511,2382,2383],{"class":542},"\"downstream-api\"",[511,2385,829],{"class":1754},[511,2387,2388],{"class":1550},"DownstreamApiHealthIndicator",[511,2390,2391],{"class":1754},"(client))\n",[511,2393,2394],{"class":513,"line":641},[511,2395,2396],{"class":1754},"    },\n",[511,2398,2399],{"class":513,"line":741},[511,2400,2401],{"class":1754},")\n",[502,2403,2405],{"className":1968,"code":2404,"filename":1970,"language":1971,"meta":507,"style":507},"var runtime = StoatFlowRuntime.fromConfig(\n    Main::buildTopology,\n    builder -> builder.addHealthIndicator(\"downstream-api\", new DownstreamApiHealthIndicator(client))\n);\n",[324,2406,2407,2426,2438,2477],{"__ignoreMap":507},[511,2408,2409,2412,2415,2417,2420,2422,2424],{"class":513,"line":514},[511,2410,2411],{"class":1624},"var",[511,2413,2414],{"class":2064}," runtime",[511,2416,2102],{"class":517},[511,2418,2419],{"class":2064}," StoatFlowRuntime",[511,2421,410],{"class":517},[511,2423,2346],{"class":1550},[511,2425,1755],{"class":517},[511,2427,2428,2431,2434,2436],{"class":513,"line":521},[511,2429,2430],{"class":1754},"    Main",[511,2432,2433],{"class":1727},"::",[511,2435,2361],{"class":1754},[511,2437,548],{"class":517},[511,2439,2440,2443,2446,2449,2451,2454,2456,2458,2461,2463,2465,2468,2470,2472,2474],{"class":513,"line":551},[511,2441,2442],{"class":1754},"    builder ",[511,2444,2445],{"class":517},"->",[511,2447,2448],{"class":2064}," builder",[511,2450,410],{"class":517},[511,2452,2453],{"class":1550},"addHealthIndicator",[511,2455,1840],{"class":517},[511,2457,532],{"class":538},[511,2459,2460],{"class":542},"downstream-api",[511,2462,532],{"class":538},[511,2464,588],{"class":517},[511,2466,2467],{"class":1727}," new",[511,2469,1751],{"class":1550},[511,2471,1840],{"class":517},[511,2473,2086],{"class":1754},[511,2475,2476],{"class":517},"))\n",[511,2478,2479],{"class":513,"line":566},[511,2480,2481],{"class":517},");\n",[837,2483,2484],{"color":839,"icon":175},[320,2485,2486,2489,2490,2493,2494,410],{},[407,2487,2488],{"href":206},"Plugins"," can register health indicators too — ",[324,2491,2492],{},"PluginContext.healthIndicatorRegistry()"," gives a plugin the same registry, including the liveness-only \u002F readiness-only registration methods for finer control than ",[324,2495,2453],{},[412,2497,150],{"id":2498},"configuration",[320,2500,2501],{},"The health checks themselves need no configuration to work — the four built-in indicators are wired automatically. The only tunables are the connectivity-check timeouts and the broader HTTP-server enablement:",[502,2503,2507],{"className":2504,"code":2505,"language":2506,"meta":507,"style":507},"language-yaml shiki shiki-themes vitesse-light","stoatflow:\n  # Schema Registry health auto-enables when this is set:\n  schema-registry-url: ${SCHEMA_REGISTRY_URL:-}\n\nruntime:\n  http:\n    enabled: true              # \u002Fhealth\u002Flive and \u002Fhealth\u002Fready live on the runtime HTTP server\n    port: ${HTTP_PORT:-8080}\n  health:\n    kafka-broker:\n      timeout-ms: 2000         # broker connectivity check timeout (default 2000)\n    schema-registry:\n      timeout-ms: 5000         # schema-registry check timeout (default 5000)\n","yaml",[324,2508,2509,2516,2521,2531,2535,2541,2548,2561,2571,2578,2585,2598,2605],{"__ignoreMap":507},[511,2510,2511,2513],{"class":513,"line":514},[511,2512,583],{"class":528},[511,2514,2515],{"class":517},":\n",[511,2517,2518],{"class":513,"line":521},[511,2519,2520],{"class":1544},"  # Schema Registry health auto-enables when this is set:\n",[511,2522,2523,2526,2528],{"class":513,"line":551},[511,2524,2525],{"class":528},"  schema-registry-url",[511,2527,535],{"class":517},[511,2529,2530],{"class":542}," ${SCHEMA_REGISTRY_URL:-}\n",[511,2532,2533],{"class":513,"line":566},[511,2534,1608],{"emptyLinePlaceholder":1607},[511,2536,2537,2539],{"class":513,"line":641},[511,2538,1989],{"class":528},[511,2540,2515],{"class":517},[511,2542,2543,2546],{"class":513,"line":741},[511,2544,2545],{"class":528},"  http",[511,2547,2515],{"class":517},[511,2549,2550,2553,2555,2558],{"class":513,"line":810},[511,2551,2552],{"class":528},"    enabled",[511,2554,535],{"class":517},[511,2556,2557],{"class":1727}," true",[511,2559,2560],{"class":1544},"              # \u002Fhealth\u002Flive and \u002Fhealth\u002Fready live on the runtime HTTP server\n",[511,2562,2563,2566,2568],{"class":513,"line":816},[511,2564,2565],{"class":528},"    port",[511,2567,535],{"class":517},[511,2569,2570],{"class":542}," ${HTTP_PORT:-8080}\n",[511,2572,2573,2576],{"class":513,"line":1810},[511,2574,2575],{"class":528},"  health",[511,2577,2515],{"class":517},[511,2579,2580,2583],{"class":513,"line":1825},[511,2581,2582],{"class":528},"    kafka-broker",[511,2584,2515],{"class":517},[511,2586,2587,2590,2592,2595],{"class":513,"line":1859},[511,2588,2589],{"class":528},"      timeout-ms",[511,2591,535],{"class":517},[511,2593,2594],{"class":733}," 2000",[511,2596,2597],{"class":1544},"         # broker connectivity check timeout (default 2000)\n",[511,2599,2600,2603],{"class":513,"line":1870},[511,2601,2602],{"class":528},"    schema-registry",[511,2604,2515],{"class":517},[511,2606,2607,2609,2611,2614],{"class":513,"line":1897},[511,2608,2589],{"class":528},[511,2610,535],{"class":517},[511,2612,2613],{"class":733}," 5000",[511,2615,2616],{"class":1544},"         # schema-registry check timeout (default 5000)\n",[837,2618,2620],{"color":2619,"icon":840},"warning",[320,2621,2622,2623,2626,2627,2629,2630,2632,2633,2636,2637,2639],{},"The commit-stall liveness check is governed by the ",[355,2624,2625],{},"engine"," setting ",[324,2628,1182],{}," (default 45 000 ms; set ",[324,2631,1178],{}," to disable the check), not a ",[324,2634,2635],{},"runtime.health.*"," key. It must be less than the barrier timeout. See the ",[407,2638,281],{"href":282}," for the full key list.",[412,2641,2643],{"id":2642},"quick-reference","Quick reference",[502,2645,2647],{"className":1535,"code":2646,"language":1537,"meta":507,"style":507},"# Liveness — should the orchestrator restart this pod?\ncurl -s localhost:8080\u002Fhealth\u002Flive  | jq .\n\n# Readiness — should the orchestrator route traffic to this pod?\ncurl -s localhost:8080\u002Fhealth\u002Fready | jq .\n\n# Just the HTTP status (what a probe actually checks):\ncurl -s -o \u002Fdev\u002Fnull -w \"%{http_code}\\n\" localhost:8080\u002Fhealth\u002Fready\n",[324,2648,2649,2654,2671,2675,2680,2694,2698,2703],{"__ignoreMap":507},[511,2650,2651],{"class":513,"line":514},[511,2652,2653],{"class":1544},"# Liveness — should the orchestrator restart this pod?\n",[511,2655,2656,2658,2660,2663,2666,2668],{"class":513,"line":521},[511,2657,1551],{"class":1550},[511,2659,1555],{"class":1554},[511,2661,2662],{"class":542}," localhost:8080\u002Fhealth\u002Flive",[511,2664,2665],{"class":1624},"  |",[511,2667,1628],{"class":1550},[511,2669,2670],{"class":542}," .\n",[511,2672,2673],{"class":513,"line":551},[511,2674,1608],{"emptyLinePlaceholder":1607},[511,2676,2677],{"class":513,"line":566},[511,2678,2679],{"class":1544},"# Readiness — should the orchestrator route traffic to this pod?\n",[511,2681,2682,2684,2686,2688,2690,2692],{"class":513,"line":641},[511,2683,1551],{"class":1550},[511,2685,1555],{"class":1554},[511,2687,1574],{"class":542},[511,2689,1625],{"class":1624},[511,2691,1628],{"class":1550},[511,2693,2670],{"class":542},[511,2695,2696],{"class":513,"line":741},[511,2697,1608],{"emptyLinePlaceholder":1607},[511,2699,2700],{"class":513,"line":810},[511,2701,2702],{"class":1544},"# Just the HTTP status (what a probe actually checks):\n",[511,2704,2705,2707,2709,2711,2713,2715,2717,2720,2722],{"class":513,"line":816},[511,2706,1551],{"class":1550},[511,2708,1555],{"class":1554},[511,2710,1558],{"class":1554},[511,2712,1561],{"class":542},[511,2714,1564],{"class":1554},[511,2716,539],{"class":538},[511,2718,2719],{"class":542},"%{http_code}\\n",[511,2721,532],{"class":538},[511,2723,2724],{"class":542}," localhost:8080\u002Fhealth\u002Fready\n",[420,2726,2727,2740],{},[423,2728,2729],{},[426,2730,2731,2734,2737],{},[429,2732,2733],{},"You see",[429,2735,2736],{},"Likely cause",[429,2738,2739],{},"Right action",[444,2741,2742,2761,2784,2804,2822],{},[426,2743,2744,2755,2758],{},[449,2745,2746,829,2749,2752,2753],{},[324,2747,2748],{},"ready=503",[324,2750,2751],{},"live=200",", state ",[324,2754,923],{},[449,2756,2757],{},"Rebuilding state stores on startup",[449,2759,2760],{},"Wait — this is normal; size your readiness\u002Fstartup budget for it",[426,2762,2763,2771,2777],{},[449,2764,2765,829,2767,2752,2769],{},[324,2766,2748],{},[324,2768,2751],{},[324,2770,926],{},[449,2772,2773,2774],{},"App was paused via ",[324,2775,2776],{},"\u002Fpause",[449,2778,2779,2781,2782,997],{},[324,2780,1657],{}," when ready (",[407,2783,1661],{"href":201},[426,2785,2786,2798,2801],{},[449,2787,2788,829,2790,2792,2793,2795,2796],{},[324,2789,2748],{},[324,2791,2751],{},", license ",[324,2794,1307],{},"\u002F",[324,2797,1320],{},[449,2799,2800],{},"License no longer operational",[449,2802,2803],{},"Renew the license — a restart won't help",[426,2805,2806,2816,2819],{},[449,2807,2808,829,2810,829,2813,2815],{},[324,2809,2748],{},[324,2811,2812],{},"live=503",[324,2814,756],{}," DOWN",[449,2817,2818],{},"Broker unreachable",[449,2820,2821],{},"Fix connectivity; restart is a valid response",[426,2823,2824,2835,2838],{},[449,2825,2826,829,2828,2752,2830,829,2832,2834],{},[324,2827,2748],{},[324,2829,2751],{},[324,2831,630],{},[324,2833,1186],{}," present",[449,2836,2837],{},"Commit pipeline stalled past threshold",[449,2839,2840],{},"Investigate; the orchestrator restart is the safety net",[412,2842,2844],{"id":2843},"next-steps","Next steps",[349,2846,2847,2861,2875,2882],{},[352,2848,2849,2853,2854,1491,2856,1491,2858,2860],{},[355,2850,2851],{},[407,2852,409],{"href":239}," — the Kubernetes ",[324,2855,396],{},[324,2857,402],{},[324,2859,1528],{}," wiring, with budgets sized for restoration.",[352,2862,2863,2867,2868,829,2871,1419,2873,410],{},[355,2864,2865],{},[407,2866,1415],{"href":186}," — the full endpoint catalogue, including ",[324,2869,2870],{},"\u002Fstate",[324,2872,1411],{},[324,2874,2776],{},[352,2876,2877,2881],{},[355,2878,2879],{},[407,2880,195],{"href":196}," — Prometheus gauges and counters, including engine state and license metrics.",[352,2883,2884,2888],{},[355,2885,2886],{},[407,2887,1661],{"href":201}," — how pausing interacts with readiness.",[2890,2891,2892],"style",{},"html pre.shiki code .s8zF2, html code.shiki .s8zF2{--shiki-default:#A0ADA0}html pre.shiki code .sySUi, html code.shiki .sySUi{--shiki-default:#59873A}html pre.shiki code .sEi1f, html code.shiki .sEi1f{--shiki-default:#A65E2B}html pre.shiki code .spphp, html code.shiki .spphp{--shiki-default:#B56959}html pre.shiki code .sSP4y, html code.shiki .sSP4y{--shiki-default:#B5695977}html pre.shiki code .si04Y, html code.shiki .si04Y{--shiki-default:#AB5959}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sbBg2, html code.shiki .sbBg2{--shiki-default:#1E754F}html pre.shiki code .sUxyF, html code.shiki .sUxyF{--shiki-default:#2E8F82}html pre.shiki code .suHK_, html code.shiki .suHK_{--shiki-default:#393A34}html pre.shiki code .sYZai, html code.shiki .sYZai{--shiki-default:#999999}html pre.shiki code .svycV, html code.shiki .svycV{--shiki-default:#B07D48}html pre.shiki code .su6XF, html code.shiki .su6XF{--shiki-default:#998418}html pre.shiki code .s-TwI, html code.shiki .s-TwI{--shiki-default:#2F798A}html pre.shiki code .s61at, html code.shiki .s61at{--shiki-default:#99841877}",{"title":507,"searchDepth":521,"depth":521,"links":2894},[2895,2896,2908,2909,2912,2913,2914],{"id":414,"depth":521,"text":415},{"id":865,"depth":521,"text":866,"children":2897},[2898,2900,2902,2904,2906],{"id":993,"depth":551,"text":2899},"App state (stoatflow)",{"id":1193,"depth":551,"text":2901},"Kafka broker (kafka-broker)",{"id":1231,"depth":551,"text":2903},"Schema Registry (schema-registry)",{"id":1258,"depth":551,"text":2905},"License (license)",{"id":1425,"depth":551,"text":2907},"Hot standby (ha)",{"id":1481,"depth":521,"text":1482},{"id":1664,"depth":521,"text":1665,"children":2910},[2911],{"id":1698,"depth":551,"text":1699},{"id":2498,"depth":521,"text":150},{"id":2642,"depth":521,"text":2643},{"id":2843,"depth":521,"text":2844},"Liveness and readiness probes on the StoatFlow runtime — the built-in indicators, what flips each, and how they behave during state restoration.","md",{},{"icon":193},"how-to",{"title":190,"description":2915},"aKsHdfgQA-rssGBQyrvARaRyLdXfloSV0EYsmAMQLGs",[2923,2925],{"title":185,"path":186,"stem":187,"description":2924,"icon":188,"children":-1},"A task-oriented tour of the runtime's built-in HTTP endpoints — metadata, topology, state and progress, health, control, license, metrics, and debug.",{"title":195,"path":196,"stem":197,"description":2926,"icon":198,"children":-1},"Scrape StoatFlow's Prometheus \u002Fmetrics endpoint — Micrometer integration, the key meters the engine emits, license metrics, and common tags.",1783713361318]