---
title: Pace rollouts with minReadySeconds
description: Make a new OMENative pod stay Ready for a warm-up window before it counts as Available, so a rollout waits before draining the old pods.
since: v1.3
---
A model server can pass its readiness probe and still fail while it warms up under its first requests. `lifecycle.minReadySeconds` gives each new pod a warm-up window. In a rollout with the default strategy, OME keeps the old pods serving until the new ones have stayed Ready for the whole window. It works like a Deployment's `minReadySeconds`, for components that run on [OMENative](../../concepts/omenative/overview.md).
You can set it on an [InferenceService](../../concepts/serving/inference-services.md), or as a default in a runtime or for the whole cluster.
- OME v1.3 or later, installed with the `ome-resources` chart as in [Install OME](../../getting-started/install.md), and `kubectl` access to the cluster. Until v1.3 is released, run [a build of `main`](../../getting-started/install.md#install-from-source).
- A namespace `llama-demo`.
- The ClusterBaseModel `llama-3-2-1b-instruct` in the `Ready` state, and the [ClusterServingRuntime](../../concepts/runtimes/serving-runtimes.md) `srt-llama-3-2-1b-instruct`. Both are in the [catalog of pre-configured models](../../getting-started/pre-configured-models.md). Check with `kubectl get clusterbasemodel llama-3-2-1b-instruct` and `kubectl get clusterservingruntime srt-llama-3-2-1b-instruct`.
- Room for one serving pod on an amd64 node, with an NVIDIA GPU, 10 CPUs and 30 GiB of memory. A rollout with the default strategy needs room for a second pod while it replaces the first.
## Ready versus available
Each replica of an OMENative component is an Instance: one pod, or a leader and its workers. A new pod is Ready, and receives requests, once its containers pass their readiness checks and OME puts it into rotation. It's Available once it has stayed Ready for `minReadySeconds`. The window delays what OME does next:
| When | What waits for the window |
| --- | --- |
| A `SurgeThenDrain` rollout, the default | Draining the old pods, which keep serving until then. |
| A `RecreatePod`, `InPlaceIfPossible` or `InPlaceOnly` rollout | The updated Instance's phase turning `Ready` on the new revision. |
| First deploy and scale-up | The new Instance's phase turning `Ready`. |
| An Instance migration | Draining the source Instance, which keeps serving until then. The window counts toward the migration's [deadline](../../concepts/omenative/migration-and-transient-scale.md#deadline). |
The InferenceService's `Ready` condition doesn't wait for the window. An Instance that's being replaced holds its place in the `maxSurge` or `maxUnavailable` budget for the whole window. So a rollout takes at least one window longer for each batch of Instances that move together. If a new pod stops being Ready during its window, the window starts over. [Readiness and availability](../../concepts/omenative/instances.md#readiness-and-availability) defines the states.
## Step 1: Set a window on an InferenceService
Create an InferenceService that runs in OMENative mode, with a 900-second window on its engine:
```yaml title="isvc.yaml"
apiVersion: ome.io/v1beta1
kind: InferenceService
metadata:
name: llama-chat
namespace: llama-demo
spec:
deploymentMode: OMENative
model:
name: llama-3-2-1b-instruct
runtime:
name: srt-llama-3-2-1b-instruct
engine:
minReplicas: 1
maxReplicas: 1
lifecycle:
minReadySeconds: 900
```
`spec.deploymentMode: OMENative` puts every component of the service on OMENative. In RawDeployment, MultiNode (deprecated) or any other mode, OME ignores `minReadySeconds`, and the webhook admits it without a warning. [How OME resolves the mode](../../concepts/architecture/deployment-modes.md#how-ome-resolves-the-mode) lists what else sets a component's mode.
Make the window longer than your readiness probe takes to catch a failure: about `failureThreshold` times the longer of `periodSeconds` and `timeoutSeconds`. Otherwise a pod can become Available before a failing probe marks it not Ready. The engine of `srt-llama-3-2-1b-instruct` probes every 60 seconds, waits up to 200 seconds for an answer and allows 3 failures. It catches a server that returns errors in about 3 minutes and one that hangs in about 10, so 900 seconds covers both.
Apply the file:
```bash
kubectl apply -f isvc.yaml
```
```output
inferenceservice.ome.io/llama-chat created
```
The first start pulls the SGLang image and loads the model, which can take several minutes.
## Step 2: Check the window in effect {#step-2-check-the-workload}
OME writes an InferenceReplica for each OMENative component, named `-`, here `llama-chat-engine`. Its `spec.minReadySeconds` is the window in effect, wherever it's set. Its status counts the Instances whose pods are all Ready, and those that are Available:
```bash
kubectl get inferencereplica llama-chat-engine -n llama-demo \
-o custom-columns=NAME:.metadata.name,MIN-READY:.spec.minReadySeconds,READY:.status.readyReplicas,AVAILABLE:.status.availableReplicas
```
During the window, the output looks like this:
```output
NAME MIN-READY READY AVAILABLE
llama-chat-engine 900 1
```
`` means 0. Once the pod has been Ready for 900 seconds, `AVAILABLE` shows `1`. The InferenceService reports the same counts in `status.components.engine.lifecycle`. Its spec shows only the value you set there.
## Set a default for many services
OME takes each component's window from the first of these that sets it, and uses 0 when none does:
| Set in | Field |
| --- | --- |
| The InferenceService | `spec.engine.lifecycle.minReadySeconds`, or the same under `decoder` or `router`. It wins even when it's `0`. |
| The service's ServingRuntime or ClusterServingRuntime | `spec.engineConfig.lifecycle.minReadySeconds`, or the same under `decoderConfig` or `routerConfig`. |
| The cluster | `ome.controller.minReadySeconds` in the `ome-resources` chart, unset by default. |
The value is a whole number of seconds, 0 or more.
### In a runtime
Set a 1200-second default on the engine of `srt-llama-3-2-1b-instruct`:
```bash
kubectl patch clusterservingruntime srt-llama-3-2-1b-instruct --type merge \
-p '{"spec":{"engineConfig":{"lifecycle":{"minReadySeconds":1200}}}}'
```
```output
clusterservingruntime.ome.io/srt-llama-3-2-1b-instruct patched
```
`llama-chat` sets its own value, so it keeps 900. Remove it, and the runtime's default takes over:
```bash
kubectl patch inferenceservice llama-chat -n llama-demo --type merge \
-p '{"spec":{"engine":{"lifecycle":{"minReadySeconds":null}}}}'
```
```output
inferenceservice.ome.io/llama-chat patched
```
```bash
kubectl get inferencereplica llama-chat-engine -n llama-demo -o jsonpath='{.spec.minReadySeconds}'
```
```output
1200
```
A service can pin its runtime with `spec.runtime.autoSync: false`. When you change the runtime, OME sets that service's `RuntimeDrifted` condition to True and leaves its serving workload as it is until you move the pin. See [Runtime revisions and pinning](../../concepts/runtimes/runtime-revisions.md#when-the-runtime-changes).
### For the whole cluster
Add the default to the values file that you installed `ome-resources` with:
```yaml title="values.yaml"
ome:
controller:
minReadySeconds: 60
```
Keep your other values in the file: `helm upgrade` resets every value that isn't in it to the chart's default. Upgrade with the chart version that you already run, so that OME stays in step with the `ome-crd` chart. `helm list -n ome` shows it in its `CHART` column:
```bash
helm upgrade --install ome oci://ghcr.io/moirai-internal/charts/ome-resources \
--namespace ome --version 1.3.0 -f values.yaml
```
Until v1.3 is released, upgrade from a checkout of `main` instead, as in [Install from source](../../getting-started/install.md#install-from-source).
Helm reports that the release has been upgraded. The upgrade restarts the controller, which then applies the new default. Check the `deploy` entry of the `inferenceservice-config` ConfigMap:
```bash
kubectl get configmap inferenceservice-config -n ome -o jsonpath='{.data.deploy}' | grep minReadySeconds
```
```output
"minReadySeconds": 60,
```
If you manage the ConfigMap yourself, add `"minReadySeconds": 60` to the JSON in its `deploy` entry. A later `helm upgrade` can overwrite the edit. [Change ConfigMap settings](../operate-ome/configure-the-controller.md#tune-the-config-cache) explains when an edit takes effect, and how to apply it at once.
## Troubleshooting
### The controller crash-loops or services stop updating
Nothing checks the cluster default when you set it. With a negative value, such as `-30`, new controller pods exit with `invalid deploy config, minReadySeconds must be >= 0, got -30`. A running controller logs the same error for every InferenceService and stops creating or updating serving workloads. Read the logs of every replica, and look for that error:
```bash
kubectl logs -n ome -l control-plane=ome-controller-manager --tail=-1
```
Set the value to 0 or more in your values file or the ConfigMap, then upgrade again or restart the controller.
### The value doesn't seem to apply
Check `spec.minReadySeconds` on the component's InferenceReplica, as in [Step 2](#step-2-check-the-workload), then find your case:
| What you see | Cause and fix |
| --- | --- |
| kubectl reports that the InferenceReplica isn't found | The component doesn't run on OMENative. Set `spec.deploymentMode: OMENative`, and remove any `ome.io/deploymentMode` annotation that names another mode, on the component or in the runtime. |
| The value isn't the runtime's | The InferenceService sets its own value, even `0`. Or it pins its runtime with `spec.runtime.autoSync: false`, and gets the change once you move the pin. |
| Pods didn't restart | Expected: the window isn't part of the pod template. OME uses a new value from then on, in rollouts in progress too. |
## Clean up
Delete the InferenceService:
```bash
kubectl delete inferenceservice llama-chat -n llama-demo
```
```output
inferenceservice.ome.io "llama-chat" deleted from llama-demo namespace
```
If you set the runtime default, remove it:
```bash
kubectl patch clusterservingruntime srt-llama-3-2-1b-instruct --type merge \
-p '{"spec":{"engineConfig":{"lifecycle":{"minReadySeconds":null}}}}'
```
```output
clusterservingruntime.ome.io/srt-llama-3-2-1b-instruct patched
```
If you set the cluster default, remove `minReadySeconds` from your values file, and run the `helm upgrade` command again with the same version.
## Next steps
- [OMENative update strategies](../../concepts/architecture/omenative-update-strategies.md): how SurgeThenDrain and the other strategies replace an Instance's pods, and how `partition`, `maxSurge` and `maxUnavailable` pace a rollout.
- [Rollout groups](../../concepts/rollouts-and-traffic/rollout-groups.md): roll the engine and the decoder out as one, by canary, blue-green or rolling update.
- [Pause and resume a rollout](pause-and-resume-a-rollout.md): hold a rollout in progress with the alpha `kubectl ome rollout pause` action, and continue it with `resume`.
- [LifecycleSpec](../../reference/api/ome.v1beta1.md#ome-io-v1beta1-LifecycleSpec) in the API reference: the other lifecycle fields of a component.