[{"data":1,"prerenderedAt":1370},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Foperating\u002Fprobes":314,"\u002Fdocs\u002Foperating\u002Fprobes-surround":1365},[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":238,"body":316,"description":1358,"extension":1359,"meta":1360,"navigation":1361,"pageType":1362,"path":239,"seo":1363,"stem":240,"__hash__":1364},"docs\u002F1.docs\u002F6.operating\u002F4.probes.md",{"type":317,"value":318,"toc":1345},"minimark",[319,332,380,387,392,408,467,489,493,499,585,591,612,616,632,635,650,663,668,674,691,709,713,803,807,813,1078,1111,1115,1159,1178,1182,1185,1284,1293,1297,1341],[320,321,322,323,327,328,331],"p",{},"StoatFlow exposes two HTTP health endpoints designed to drive Kubernetes liveness and readiness probes: ",[324,325,326],"code",{},"\u002Fhealth\u002Flive"," decides whether the pod should be kept alive, ",[324,329,330],{},"\u002Fhealth\u002Fready"," decides whether it should receive traffic and count toward a rollout. This page shows how to wire them, what each one gates on, and how to set the probe periods.",[333,334,335],"tldr-panel",{},[336,337,338,357,365],"ul",{},[339,340,341,345,346,348,349,352,353,356],"li",{},[342,343,344],"strong",{},"Readiness"," (",[324,347,330],{},") is UP only while the engine is ",[324,350,351],{},"RUNNING"," — it returns 503 during startup, state restoration, pause, and shutdown, plus when the broker is unreachable or the license is non-operational. Wire it to ",[324,354,355],{},"readinessProbe"," so rollouts and load balancers wait.",[339,358,359,345,362,364],{},[342,360,361],{},"Liveness",[324,363,326],{},") stays UP through normal transient states so the orchestrator doesn't restart a healthy-but-busy pod — but returns 503 if the commit pipeline has frozen, so Kubernetes restarts the wedged process.",[339,366,367,368,371,372,375,376,379],{},"Both endpoints return HTTP ",[342,369,370],{},"200 = UP",", ",[342,373,374],{},"503 = DOWN",", with a JSON body listing each component. Default port is ",[342,377,378],{},"8080",".",[320,381,382,383,386],{},"For the response shape and the full component breakdown, see ",[384,385,190],"a",{"href":191},". This page is about wiring and tuning the probes.",[388,389,391],"h2",{"id":390},"the-two-endpoints","The two endpoints",[320,393,394,395,398,399,403,404,407],{},"Both endpoints aggregate every registered health indicator. The overall status is ",[342,396,397],{},"UP (HTTP 200)"," only when ",[400,401,402],"em",{},"every"," component is UP; if any component is DOWN, the endpoint returns ",[342,405,406],{},"DOWN (HTTP 503)",". The JSON body always lists the per-component status so you can see which one tripped.",[409,410,411,430],"table",{},[412,413,414],"thead",{},[415,416,417,421,424,427],"tr",{},[418,419,420],"th",{},"Endpoint",[418,422,423],{},"Probe",[418,425,426],{},"UP means",[418,428,429],{},"DOWN means",[431,432,433,450],"tbody",{},[415,434,435,440,444,447],{},[436,437,438],"td",{},[324,439,330],{},[436,441,442],{},[324,443,355],{},[436,445,446],{},"Ready to process and serve traffic",[436,448,449],{},"Don't route traffic \u002F don't advance rollout yet",[415,451,452,456,461,464],{},[436,453,454],{},[324,455,326],{},[436,457,458],{},[324,459,460],{},"livenessProbe",[436,462,463],{},"Process is healthy, leave it running",[436,465,466],{},"Process is wedged, restart it",[320,468,469,470,473,474,371,477,480,481,484,485,488],{},"The built-in indicators are ",[324,471,472],{},"stoatflow"," (engine state), ",[324,475,476],{},"license",[324,478,479],{},"kafka-broker",", and — when a Schema Registry URL is configured — ",[324,482,483],{},"schema-registry",". Each contributes to both probes, but several of them deliberately report ",[342,486,487],{},"different"," liveness vs. readiness status (table below).",[388,490,492],{"id":491},"what-readiness-gates","What readiness gates",[320,494,495,496,498],{},"Readiness answers \"should this pod receive traffic and count as available?\" StoatFlow returns ",[324,497,330],{}," = DOWN (503) until the application is genuinely able to process records:",[336,500,501,522,531,559,565],{},[339,502,503,506,507,510,511,510,514,517,518,521],{},[342,504,505],{},"State restoration."," On cold start or restart the engine rebuilds state stores from their changelog topics before processing begins. Readiness stays DOWN for the whole ",[324,508,509],{},"STARTING"," \u002F ",[324,512,513],{},"VALIDATING_STATE",[324,515,516],{},"RESTORING"," window. During a rolling update this is what keeps Kubernetes from cutting traffic over to a pod that hasn't caught up yet. See ",[384,519,520],{"href":48},"Architecture — lifecycle"," for the cold-start sequence.",[339,523,524,527,528,530],{},[342,525,526],{},"Broker availability."," The ",[324,529,479],{}," indicator checks broker connectivity. If the broker is unreachable, readiness goes DOWN — the pod can't make progress, so it shouldn't be considered ready.",[339,532,533,527,536,538,539,371,542,371,545,548,549,552,553,556,557,379],{},[342,534,535],{},"License.",[324,537,476],{}," indicator returns readiness DOWN when the runtime license is ",[324,540,541],{},"EXPIRED",[324,543,544],{},"REVOKED",[324,546,547],{},"INVALID",", or absent — the orchestrator stops routing to a pod whose license has been pulled. (",[324,550,551],{},"VALID"," and ",[324,554,555],{},"GRACE_PERIOD"," are treated as operational.) See ",[384,558,23],{"href":24},[339,560,561,564],{},[342,562,563],{},"Schema Registry"," (only when configured). If a Schema Registry URL is set and the registry is unreachable, readiness goes DOWN.",[339,566,567,570,571,510,574,577,578,581,582,379],{},[342,568,569],{},"Pause and shutdown."," While paused (",[324,572,573],{},"DRAINING",[324,575,576],{},"PAUSED",") or shutting down (",[324,579,580],{},"STOPPING","), readiness is DOWN so load balancers drain the pod cleanly. See ",[384,583,584],{"href":201},"Pause \u002F unpause",[320,586,587,588,590],{},"Readiness returns UP only when the engine is in the ",[324,589,351],{}," state and every other component is healthy.",[592,593,595],"callout",{"color":594,"icon":236},"info",[320,596,597,603,604,607,608,611],{},[342,598,599,600],{},"Under ",[384,601,602],{"href":234},"hot standby"," readiness carries an extra condition: the active reports ready while processing, and a standby reports ready ",[342,605,606],{},"only once it has caught up",". That's what makes the rolling update across the cluster order-independent — Kubernetes won't advance the roll until the restarted pod is a caught-up standby. A still-catching-up standby keeps its ",[400,609,610],{},"liveness"," UP so it isn't killed mid-catch-up. With more than one standby, readiness also holds the redundancy floor so a roll never drops below the active plus a warm spare.",[388,613,615],{"id":614},"what-liveness-gates","What liveness gates",[320,617,618,619,371,621,371,623,371,625,371,627,371,629,631],{},"Liveness answers a narrower question: \"is this process broken in a way that only a restart can fix?\" It deliberately stays UP through the normal transient states — ",[324,620,509],{},[324,622,513],{},[324,624,516],{},[324,626,573],{},[324,628,576],{},[324,630,580],{}," — so the orchestrator doesn't kill a pod that's simply busy restoring state or draining for a clean shutdown.",[320,633,634],{},"Liveness returns DOWN in two situations:",[636,637,638,644],"ol",{},[339,639,640,643],{},[342,641,642],{},"Hard dependency failure"," — the broker (or a configured Schema Registry) is unreachable. These can't be made healthy by anything the pod is doing, so a restart is the right response.",[339,645,646,649],{},[342,647,648],{},"A frozen commit pipeline"," (see below).",[320,651,652,653,655,656,659,660,662],{},"Note one deliberate asymmetry: the ",[342,654,476],{}," indicator never fails liveness. An expired or revoked license fails ",[400,657,658],{},"readiness"," (traffic stops) but keeps ",[400,661,610],{}," UP — restarting the pod won't fix a license problem, and a restart loop would only hide it.",[664,665,667],"h3",{"id":666},"stall-aware-liveness","Stall-aware liveness",[320,669,670,671,673],{},"The commit barrier is the heart of exactly-once processing: a transaction periodically commits state, output, and offsets together (see ",[384,672,52],{"href":53},"). If that pipeline were ever to freeze — a commit that starts but never finishes — the pod would sit there alive but making no progress, the worst kind of failure for an orchestrator to miss.",[320,675,676,677,679,680,345,683,686,687,690],{},"StoatFlow guards against this. The runtime tracks how long it has been since the last successful commit while commit work is pending. If that age exceeds a configured threshold, ",[324,678,326],{}," flips to DOWN — Kubernetes restarts the pod, and the restarted process resumes from the last successful barrier with no duplicates downstream. The threshold is ",[324,681,682],{},"stoatflow.commit-stall.threshold-ms",[342,684,685],{},"default 45000 ms","; set to ",[324,688,689],{},"0"," to disable the check, which re-introduces the silent-freeze failure mode and is discouraged).",[592,692,694],{"color":594,"icon":693},"i-lucide-info",[320,695,696,697,700,701,704,705,708],{},"This stall check is an independent recovery path. The runtime also detects and aborts a frozen commit internally, but the liveness probe gives Kubernetes its own way to recover even if the in-process recovery is itself wedged. Both read the same ",[324,698,699],{},"threshold-ms",". When liveness trips on a stall, the JSON body includes a ",[324,702,703],{},"stall_age_ms"," detail and the ",[324,706,707],{},"\u002Fdebug\u002Fbarriers"," endpoint shows the stuck barrier.",[388,710,712],{"id":711},"liveness-vs-readiness-per-component","Liveness vs. readiness, per component",[409,714,715,733],{},[412,716,717],{},[415,718,719,722,728],{},[418,720,721],{},"Component",[418,723,724,725,727],{},"Liveness (",[324,726,326],{},")",[418,729,730,731,727],{},"Readiness (",[324,732,330],{},[431,734,735,761,780,791],{},[415,736,737,742,756],{},[436,738,739,741],{},[324,740,472],{}," engine",[436,743,744,745,371,747,371,749,371,751,371,753,755],{},"UP during transient states (",[324,746,509],{},[324,748,516],{},[324,750,573],{},[324,752,576],{},[324,754,580],{},"); DOWN if the commit pipeline has stalled past the threshold",[436,757,758,759],{},"UP only in ",[324,760,351],{},[415,762,763,767,770],{},[436,764,765],{},[324,766,476],{},[436,768,769],{},"UP regardless of license status",[436,771,772,773,510,775,510,777,779],{},"DOWN on ",[324,774,541],{},[324,776,544],{},[324,778,547],{}," \u002F absent key",[415,781,782,786,789],{},[436,783,784],{},[324,785,479],{},[436,787,788],{},"DOWN if broker unreachable",[436,790,788],{},[415,792,793,798,801],{},[436,794,795,797],{},[324,796,483],{}," (if configured)",[436,799,800],{},"DOWN if registry unreachable",[436,802,800],{},[388,804,806],{"id":805},"kubernetes-probe-configuration","Kubernetes probe configuration",[320,808,809,810,812],{},"Point both probes at the HTTP server's port (default ",[324,811,378],{},"). A typical container spec:",[814,815,820],"pre",{"className":816,"code":817,"language":818,"meta":819,"style":819},"language-yaml shiki shiki-themes vitesse-light","# Deployment \u002F Pod container spec\nports:\n  - name: http\n    containerPort: 8080\n\nreadinessProbe:\n  httpGet:\n    path: \u002Fhealth\u002Fready\n    port: http\n  periodSeconds: 5\n  timeoutSeconds: 3\n  failureThreshold: 3        # 3 × 5s = ~15s of consecutive failures before \"not ready\"\n\nlivenessProbe:\n  httpGet:\n    path: \u002Fhealth\u002Flive\n    port: http\n  periodSeconds: 10\n  timeoutSeconds: 3\n  failureThreshold: 3        # ~30s of consecutive failures before restart\n\nstartupProbe:\n  httpGet:\n    path: \u002Fhealth\u002Fready\n    port: http\n  periodSeconds: 10\n  failureThreshold: 60       # allow up to ~10 minutes for state restoration\n","yaml","",[324,821,822,831,842,858,870,877,884,892,903,913,924,935,949,954,961,968,978,987,997,1006,1018,1023,1031,1038,1047,1056,1065],{"__ignoreMap":819},[823,824,827],"span",{"class":825,"line":826},"line",1,[823,828,830],{"class":829},"s8zF2","# Deployment \u002F Pod container spec\n",[823,832,834,838],{"class":825,"line":833},2,[823,835,837],{"class":836},"su6XF","ports",[823,839,841],{"class":840},"sYZai",":\n",[823,843,845,848,851,854],{"class":825,"line":844},3,[823,846,847],{"class":840},"  -",[823,849,850],{"class":836}," name",[823,852,853],{"class":840},":",[823,855,857],{"class":856},"spphp"," http\n",[823,859,861,864,866],{"class":825,"line":860},4,[823,862,863],{"class":836},"    containerPort",[823,865,853],{"class":840},[823,867,869],{"class":868},"s-TwI"," 8080\n",[823,871,873],{"class":825,"line":872},5,[823,874,876],{"emptyLinePlaceholder":875},true,"\n",[823,878,880,882],{"class":825,"line":879},6,[823,881,355],{"class":836},[823,883,841],{"class":840},[823,885,887,890],{"class":825,"line":886},7,[823,888,889],{"class":836},"  httpGet",[823,891,841],{"class":840},[823,893,895,898,900],{"class":825,"line":894},8,[823,896,897],{"class":836},"    path",[823,899,853],{"class":840},[823,901,902],{"class":856}," \u002Fhealth\u002Fready\n",[823,904,906,909,911],{"class":825,"line":905},9,[823,907,908],{"class":836},"    port",[823,910,853],{"class":840},[823,912,857],{"class":856},[823,914,916,919,921],{"class":825,"line":915},10,[823,917,918],{"class":836},"  periodSeconds",[823,920,853],{"class":840},[823,922,923],{"class":868}," 5\n",[823,925,927,930,932],{"class":825,"line":926},11,[823,928,929],{"class":836},"  timeoutSeconds",[823,931,853],{"class":840},[823,933,934],{"class":868}," 3\n",[823,936,938,941,943,946],{"class":825,"line":937},12,[823,939,940],{"class":836},"  failureThreshold",[823,942,853],{"class":840},[823,944,945],{"class":868}," 3",[823,947,948],{"class":829},"        # 3 × 5s = ~15s of consecutive failures before \"not ready\"\n",[823,950,952],{"class":825,"line":951},13,[823,953,876],{"emptyLinePlaceholder":875},[823,955,957,959],{"class":825,"line":956},14,[823,958,460],{"class":836},[823,960,841],{"class":840},[823,962,964,966],{"class":825,"line":963},15,[823,965,889],{"class":836},[823,967,841],{"class":840},[823,969,971,973,975],{"class":825,"line":970},16,[823,972,897],{"class":836},[823,974,853],{"class":840},[823,976,977],{"class":856}," \u002Fhealth\u002Flive\n",[823,979,981,983,985],{"class":825,"line":980},17,[823,982,908],{"class":836},[823,984,853],{"class":840},[823,986,857],{"class":856},[823,988,990,992,994],{"class":825,"line":989},18,[823,991,918],{"class":836},[823,993,853],{"class":840},[823,995,996],{"class":868}," 10\n",[823,998,1000,1002,1004],{"class":825,"line":999},19,[823,1001,929],{"class":836},[823,1003,853],{"class":840},[823,1005,934],{"class":868},[823,1007,1009,1011,1013,1015],{"class":825,"line":1008},20,[823,1010,940],{"class":836},[823,1012,853],{"class":840},[823,1014,945],{"class":868},[823,1016,1017],{"class":829},"        # ~30s of consecutive failures before restart\n",[823,1019,1021],{"class":825,"line":1020},21,[823,1022,876],{"emptyLinePlaceholder":875},[823,1024,1026,1029],{"class":825,"line":1025},22,[823,1027,1028],{"class":836},"startupProbe",[823,1030,841],{"class":840},[823,1032,1034,1036],{"class":825,"line":1033},23,[823,1035,889],{"class":836},[823,1037,841],{"class":840},[823,1039,1041,1043,1045],{"class":825,"line":1040},24,[823,1042,897],{"class":836},[823,1044,853],{"class":840},[823,1046,902],{"class":856},[823,1048,1050,1052,1054],{"class":825,"line":1049},25,[823,1051,908],{"class":836},[823,1053,853],{"class":840},[823,1055,857],{"class":856},[823,1057,1059,1061,1063],{"class":825,"line":1058},26,[823,1060,918],{"class":836},[823,1062,853],{"class":840},[823,1064,996],{"class":868},[823,1066,1068,1070,1072,1075],{"class":825,"line":1067},27,[823,1069,940],{"class":836},[823,1071,853],{"class":840},[823,1073,1074],{"class":868}," 60",[823,1076,1077],{"class":829},"       # allow up to ~10 minutes for state restoration\n",[592,1079,1081],{"color":1080,"icon":70},"warning",[320,1082,1083,1089,1090,1093,1094,1096,1097,1100,1101,1104,1105,1107,1108,1110],{},[342,1084,1085,1086,1088],{},"Use a ",[324,1087,1028],{}," for any topology with non-trivial state."," Cold-start restoration time scales with state size and can exceed a default liveness ",[324,1091,1092],{},"initialDelaySeconds",". The ",[324,1095,1028],{}," holds the liveness probe off until restoration completes — ",[324,1098,1099],{},"failureThreshold × periodSeconds"," is your total restoration budget. Raise ",[324,1102,1103],{},"failureThreshold"," for large state rather than inflating ",[324,1106,1092],{},". While the startup probe is running, readiness is already DOWN (the engine isn't ",[324,1109,351],{}," yet), so no traffic arrives.",[664,1112,1114],{"id":1113},"tuning-the-periods","Tuning the periods",[336,1116,1117,1127,1145],{},[339,1118,1119,1122,1123,1126],{},[342,1120,1121],{},"Readiness period"," controls how quickly traffic is cut from a pod that goes unhealthy and restored when it recovers. A short ",[324,1124,1125],{},"periodSeconds"," (e.g. 5s) reacts fast at the cost of slightly more probe load; the probe is cheap (an in-process status aggregation), so erring short is fine.",[339,1128,1129,1134,1135,1138,1139,345,1142,1144],{},[342,1130,1131,1132],{},"Liveness period and ",[324,1133,1103],{}," govern how long a wedged pod survives before restart: roughly ",[324,1136,1137],{},"periodSeconds × failureThreshold",". Keep this comfortably ",[342,1140,1141],{},"longer than the stall threshold",[324,1143,682],{},", default 45s) so a genuine stall is what trips the restart, not a single slow probe — for example a 10s period × 3 failures (~30s) layered on top of the stall threshold means a real freeze is reported by the endpoint well before the probe budget would have expired on its own.",[339,1146,1147,1152,1153,1155,1156,1158],{},[342,1148,1149],{},[324,1150,1151],{},"timeoutSeconds"," should leave headroom over the broker health-check timeout, since the readiness aggregation includes the ",[324,1154,479],{}," connectivity check. The default broker check timeout is short, but set ",[324,1157,1151],{}," to at least 2-3s.",[592,1160,1162],{"color":594,"icon":1161},"i-lucide-shield",[320,1163,1164,1166,1167,1170,1171,1174,1175,379],{},[324,1165,682],{}," must be ",[342,1168,1169],{},"less than"," the commit transaction timeout (",[324,1172,1173],{},"stoatflow.commit-barrier.timeout-ms",") — validated at startup. This ordering ensures the in-process recovery has its chance to abort a stuck commit before the stall check escalates to a pod restart. See ",[384,1176,1177],{"href":158},"Core configuration",[388,1179,1181],{"id":1180},"verifying-locally","Verifying locally",[320,1183,1184],{},"With the app running, the endpoints answer over HTTP. A ready pod returns 200:",[814,1186,1190],{"className":1187,"code":1188,"language":1189,"meta":819,"style":819},"language-bash shiki shiki-themes vitesse-light","# Returns 200 + {\"status\":\"UP\",...} when RUNNING; 503 during restoration\u002Fpause\u002Fshutdown\ncurl -s -o \u002Fdev\u002Fnull -w '%{http_code}\\n' localhost:8080\u002Fhealth\u002Fready\n\n# Returns 200 unless the process is wedged (commit stall) or a hard dependency is down\ncurl -s -o \u002Fdev\u002Fnull -w '%{http_code}\\n' localhost:8080\u002Fhealth\u002Flive\n\n# Inspect the component breakdown\ncurl -s localhost:8080\u002Fhealth\u002Fready | jq\n","bash",[324,1191,1192,1197,1229,1233,1238,1259,1263,1268],{"__ignoreMap":819},[823,1193,1194],{"class":825,"line":826},[823,1195,1196],{"class":829},"# Returns 200 + {\"status\":\"UP\",...} when RUNNING; 503 during restoration\u002Fpause\u002Fshutdown\n",[823,1198,1199,1203,1207,1210,1213,1216,1220,1223,1226],{"class":825,"line":833},[823,1200,1202],{"class":1201},"sySUi","curl",[823,1204,1206],{"class":1205},"sEi1f"," -s",[823,1208,1209],{"class":1205}," -o",[823,1211,1212],{"class":856}," \u002Fdev\u002Fnull",[823,1214,1215],{"class":1205}," -w",[823,1217,1219],{"class":1218},"sSP4y"," '",[823,1221,1222],{"class":856},"%{http_code}\\n",[823,1224,1225],{"class":1218},"'",[823,1227,1228],{"class":856}," localhost:8080\u002Fhealth\u002Fready\n",[823,1230,1231],{"class":825,"line":844},[823,1232,876],{"emptyLinePlaceholder":875},[823,1234,1235],{"class":825,"line":860},[823,1236,1237],{"class":829},"# Returns 200 unless the process is wedged (commit stall) or a hard dependency is down\n",[823,1239,1240,1242,1244,1246,1248,1250,1252,1254,1256],{"class":825,"line":872},[823,1241,1202],{"class":1201},[823,1243,1206],{"class":1205},[823,1245,1209],{"class":1205},[823,1247,1212],{"class":856},[823,1249,1215],{"class":1205},[823,1251,1219],{"class":1218},[823,1253,1222],{"class":856},[823,1255,1225],{"class":1218},[823,1257,1258],{"class":856}," localhost:8080\u002Fhealth\u002Flive\n",[823,1260,1261],{"class":825,"line":879},[823,1262,876],{"emptyLinePlaceholder":875},[823,1264,1265],{"class":825,"line":886},[823,1266,1267],{"class":829},"# Inspect the component breakdown\n",[823,1269,1270,1272,1274,1277,1281],{"class":825,"line":894},[823,1271,1202],{"class":1201},[823,1273,1206],{"class":1205},[823,1275,1276],{"class":856}," localhost:8080\u002Fhealth\u002Fready",[823,1278,1280],{"class":1279},"si04Y"," |",[823,1282,1283],{"class":1201}," jq\n",[320,1285,1286,1287,1289,1290,1292],{},"During state restoration ",[324,1288,330],{}," returns 503 with a body identifying the in-progress restorations; once the engine reaches ",[324,1291,351],{}," it flips to 200.",[388,1294,1296],{"id":1295},"see-also","See also",[336,1298,1299,1304,1309,1315,1324,1329],{},[339,1300,1301,1303],{},[384,1302,190],{"href":191}," — response format, all indicators, registering custom ones",[339,1305,1306,1308],{},[384,1307,233],{"href":234}," — how readiness gates the hot-standby rolling update",[339,1310,1311,1314],{},[384,1312,1313],{"href":229},"Kubernetes"," — deploying StoatFlow on Kubernetes",[339,1316,1317,1319,1320,1323],{},[384,1318,243],{"href":244}," — metrics and the ",[324,1321,1322],{},"\u002Fdebug\u002F*"," endpoints",[339,1325,1326,1328],{},[384,1327,584],{"href":201}," — how pause affects readiness",[339,1330,1331,1333,1334,552,1337,1340],{},[384,1332,1177],{"href":158}," — ",[324,1335,1336],{},"commit-stall",[324,1338,1339],{},"commit-barrier"," settings",[1342,1343,1344],"style",{},"html pre.shiki code .s8zF2, html code.shiki .s8zF2{--shiki-default:#A0ADA0}html pre.shiki code .su6XF, html code.shiki .su6XF{--shiki-default:#998418}html pre.shiki code .sYZai, html code.shiki .sYZai{--shiki-default:#999999}html pre.shiki code .spphp, html code.shiki .spphp{--shiki-default:#B56959}html pre.shiki code .s-TwI, html code.shiki .s-TwI{--shiki-default:#2F798A}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 .sySUi, html code.shiki .sySUi{--shiki-default:#59873A}html pre.shiki code .sEi1f, html code.shiki .sEi1f{--shiki-default:#A65E2B}html pre.shiki code .sSP4y, html code.shiki .sSP4y{--shiki-default:#B5695977}html pre.shiki code .si04Y, html code.shiki .si04Y{--shiki-default:#AB5959}",{"title":819,"searchDepth":833,"depth":833,"links":1346},[1347,1348,1349,1352,1353,1356,1357],{"id":390,"depth":833,"text":391},{"id":491,"depth":833,"text":492},{"id":614,"depth":833,"text":615,"children":1350},[1351],{"id":666,"depth":844,"text":667},{"id":711,"depth":833,"text":712},{"id":805,"depth":833,"text":806,"children":1354},[1355],{"id":1113,"depth":844,"text":1114},{"id":1180,"depth":833,"text":1181},{"id":1295,"depth":833,"text":1296},"Wire StoatFlow's \u002Fhealth\u002Flive and \u002Fhealth\u002Fready endpoints to Kubernetes probes — what readiness gates, why a frozen commit pipeline fails liveness, and how to tune probe periods.","md",{},{"icon":241},"how-to",{"title":238,"description":1358},"I_W1BBpqtnkozfovo5tLfP1OzVRK2GKzJo_8sgI7rOE",[1366,1368],{"title":233,"path":234,"stem":235,"description":1367,"icon":236,"children":-1},"Two HA tiers for StoatFlow — fast restart by default, or an opt-in hot-standby cluster (one active plus one or more warm standbys) with near-instant, lag-aware failover — how to choose, configure, deploy, and operate each.",{"title":243,"path":244,"stem":245,"description":1369,"icon":246,"children":-1},"Operating-time visibility for a single-instance app — scrape \u002Fmetrics into Prometheus and Grafana, the meters worth alerting on, correlating logs to lanes and barriers via opt-in MDC, and the \u002Fdebug\u002Fthreads and \u002Fdebug\u002Fbarriers endpoints for diagnosing a frozen or slow pipeline.",1783713362849]