RecommendationPolicy
Recommendation Policy is used to configure the recommendation strategy of the Workload Autoscaler.
It allows you to define the range of recommendation values, enabling more flexible resource management.
This document explains the meaning and valid range of each field in the Recommendation Policy.
Note: For all containers, if the recommended values are below the minimums, the system automatically raises them to: CPU
10mand Memory10Mi. This ensures that resource requests never fall below safe operational thresholds.
The Simulation section previews resource recommendations against actual usage as you edit the supported CPU and Memory settings. Simulation does not evaluate JVM-specific settings, including heap bounds; use the workload’s actual recommendations and runtime metrics to verify their effect after rollout.

Strategy Type*
StrategyType defines the type of recommendation strategy. Currently, we only provide the Percentile strategy type.
Additional strategy types will be available in the future.
Percentile

When StrategyType is set to Percentile, this configuration is required. You need to specify a Percentile value for
both CPU and Memory. The range of Percentile is from P50 to P100.
The Percentile is a statistical metric that indicates the percentage of data points in a dataset that fall below or equal to a given value.
We recommend choosing an appropriate Percentile value based on the characteristics and requirements of your workload.
Below are some commonly used Percentile values and their typical use cases:
| Percentile | Explanation | Typical Use Cases |
|---|---|---|
| P50 | Median; covers about half of usage | Development/testing environments; cost-sensitive; high utilization; occasional resource shortage acceptable |
| P70 | Slightly more conservative; covers most common loads | General online services; moderate performance requirements; small degree of oversubscription acceptable |
| P90 | More robust; covers most situations | Recommended value for most production services; balances performance and cost |
| P95 | Close to worst-case; handles rare spikes | Core services; systems with high stability requirements |
| P99 | Covers nearly all cases; may be oversized | Critical services such as finance, payments, or trading where stability is paramount |
Note: In general, we recommend setting the Memory Percentile to at least P90 or higher, while the CPU Percentile can be configured more flexibly.
Buffer

Buffer is used to add a margin on top of the recommended value to handle burst traffic or sudden resource demands.
You can configure Buffer separately for CPU and Memory.
Buffer values can be specified as either a percentage or an absolute value:
| Resource Type | Percentage | Absolute Value (Option 1) | Absolute Value (Option 2) |
|---|---|---|---|
| CPU | 20% | 0.5 | 200m |
| Memory | 10% | 0.25Gi | 500Mi |
When the buffer is a percentage, it is directly multiplied by each container’s recommendation to obtain the final value. When the buffer is an absolute value, it is allocated to each container based on its proportion of the total pod recommendation.
Note: For Java workloads, the memory buffer configuration does not affect JVM-level recommendations. It only affects the final container-level memory recommendation.
History Window*

History Window defines the time window of historical data used to calculate the recommended values.
It specifies the duration of resource usage data that will be considered during recommendation calculations.
You can configure separate history windows for CPU and Memory to accommodate different resource usage patterns.
In most cases, we recommend setting the history window to 1–3 days.
-
A shorter window may fail to capture long-term workload trends.
-
A longer window may make recommendations less flexible.
For critical workloads, you can set it to 7 days to ensure recommendations account for a wider range of usage scenarios.
| History Window | Characteristics | Pros | Cons |
|---|---|---|---|
| 6h | Very short window; captures recent workload changes | Highly responsive to traffic spikes and short-term patterns | Recommendations change frequently, which may cause pods to be rescheduled more often |
| 3d | Balanced window; captures recent and mid-term trends | Good balance between stability and adaptability; suitable for most workloads | May not fully capture long-term variations |
| 7d | Long window; covers a wide range of workload patterns | More stable recommendations; safer for critical workloads | Less flexible, may respond slowly to sudden changes |
Note: When the source data (Prometheus Pod usage metrics) is insufficient, the Workload Autoscaler will compute using whatever data is available, which may result in recommendations that are lower or higher than expected.
Initial onboarding gate (default enabled): For newly managed
Deployment,StatefulSet, andDaemonSetworkloads, the Workload Autoscaler still computes and stores recommendations while the first data window is being collected, but it keepsRecommendationReady=Falseuntil the configured CPU and Memory windows are satisfied. The first pass is accumulated from workload-level history rather than a single Pod lifetime, so ordinary Pod churn during rollouts does not restart progress. For Java workloads, the same first-pass gate also waits for the required JVM windows. After the first successful pass, the APC latchesstatus.initialOptimizationDataWindowSatisfiedAt, and later rollouts or short-lived metric gaps do not reopen this gate.
Dedicated startup policy: When an AutoscalingPolicy enables ResourceStartupBoost with a separate RecommendationPolicy, the startup policy evaluates the same full workload history with generic CPU and Memory queries. It has an independent evaluation schedule, policy hash, and initial-data latch (
status.startupInitialOptimizationDataWindowSatisfiedAt).RecommendationReadyremainsFalseuntil both steady and startup pipelines are ready; the startup calculation does not fall back to the steady policy when it is missing or stale.
Resource Limits

You can set both Min and Max limits for CPU and Memory. This ensures that the recommended values will not fall below or exceed the range you define.
The order of application is: Raw Recommendation → Buffer → Min Limit → Max Limit → KeepLimit Clamp, meaning the final recommended value (including the Buffer) will not exceed the Max limit.
For Resource Limits, you can use either percentages or absolute values:
| Resource Type | Percentage | Absolute Value 1 | Absolute Value 2 |
|---|---|---|---|
| CPU | 20% | 0.5 | 100m |
| Memory | 10% | 1Gi | 500Mi |
In most cases, we recommend using percentages so the system can adjust based on your original Request configuration.
For example, if you set CPU to 30% ~ 200%, the final recommended value will never be lower than 30% of the original Request,
nor higher than 200% of the original Request.
We strongly recommend that you configure Min limits for both CPU and Memory resources to prevent recommended values from being too low in certain cases, which could cause Pods to fail to run properly.
Multi-container Resource Limits distribution
For workloads with multiple containers, absolute value Resource Limits are distributed across containers:
- If all containers have original Requests configured for that resource, the limit is distributed by each container’s share of the total original Requests.
- Otherwise, the limit is distributed by each container’s share of the total recommendation.
Note: A percentage
MinorMaxis applied only when the specific container has an original Request for the corresponding resource. If it does not, that percentage bound is skipped only for that container-resource pair; bounds for other resources and containers, as well as absolute-value bounds, continue to apply.
Evaluation Period*
Evaluation Period defines the time window used to evaluate recommendations. This is specified as a duration, and you can configure it in minutes or seconds.
In most cases, we recommend setting it between 30s and 5m.
JVM
JVM is used to configure JVM-specific recommendation behavior for Java workloads. For supported application startup settings and rollout behavior, see Java Workload Optimization.
Recent Non-Heap Window
Recent Non-Heap Window defines the short window used for JVM non-heap protection.
CloudPilot AI uses the larger result between the History Window and this recent window to guard against both historical and recent non-heap memory growth.
If not configured, the system uses the built-in default of 2 hours.
Min HeapXms Ratio Of Memory
Min HeapXms Ratio Of Memory defines the minimum ratio of HeapXms to the total JVM memory recommendation.
The valid range is 0 to less than 1.
For example, 0.2 means HeapXms must be at least 20% of the memory recommendation.
If not configured, the system uses the built-in default of 0.25 (25%).
When this ratio is not met, the system increases both HeapXms and the total memory recommendation proportionally to satisfy the constraint. This is part of the existing calculation, before the optional JVM Heap Bounds are applied; final heap ceilings can take precedence over this ratio.
JVM Heap Bounds
In the RecommendationPolicy’s JVM section, configure Min and Max together on the Xms row and the Xmx row:
| Heap setting | Min | Max |
|---|---|---|
| Xms — initial heap size | spec.jvm.minHeapXms | spec.jvm.maxHeapXms |
| Xmx — maximum heap size | spec.jvm.minHeapXmx | spec.jvm.maxHeapXmx |
Each field is optional and accepts an absolute Kubernetes memory quantity, such as 512Mi or 1Gi, not a percentage. In the Console, enter a positive value and select Mi or Gi. Leave a field empty, or clear it and save, to remove that bound. Leaving all four fields unset preserves the existing recommendation calculation; it does not disable JVM optimization.
Example RecommendationPolicy configuration:
spec:
jvm:
minHeapXms: "512Mi"
maxHeapXms: "1Gi"
minHeapXmx: "768Mi"
maxHeapXmx: "2Gi"For each row, Min must not exceed Max. When using the additional bounds, the range must contain a positive whole-Mi value: minimums round up and maximums round down, so a maximum must be at least 1Mi. Prefer whole-Mi or whole-Gi values to avoid surprising rounding.
When bounds apply
Heap bounds apply only when all of the following conditions are met:
- The container is identified as a Java container.
- Memory is selected in Update Resources (
AutoscalingPolicy.spec.updateResourcescontainsmemory, or the field is omitted and defaults to CPU and Memory). - Runtime optimization is enabled (
AutoscalingPolicy.spec.disableRuntimeOptimizationisfalseor omitted).
They do not apply to CPU-only policies, non-Java or unidentified containers, or policies with Disable Runtime Optimization enabled. In a mixed-runtime Pod, only eligible Java containers receive heap bounds.
How bounds affect recommendations
The existing heap-used, GC, Heap Buffer, and ratio calculations are unchanged. minHeapXms retains its existing behavior: raising this floor can raise Xmx and the container Memory recommendation. The additional bounds are applied after that calculation, rather than introducing a new sizing formula.
- Xms and Xmx are constrained independently. Applying an Xms maximum does not recalculate Xmx from the capped Xms, and applying an Xmx minimum does not automatically raise Xms.
- Final Xmx takes precedence: Xms cannot exceed the final Xmx, even if this lowers Xms below
minHeapXms. For example,minHeapXms: "1Gi"withmaxHeapXmx: "768Mi"is allowed and resolves to Xms and Xmx of768Mi. - A change to Xmx adjusts the JVM-aware Memory baseline by the same amount, preserving its non-heap allowance. Container buffers, OOM floors, and resource policies are applied afterward, so the final Memory change can differ. A heap maximum is not a cap on total container Memory.
These are recommendation bounds, not an immediate change to a running JVM. Heap changes require a newly created Pod; in InPlace mode, the configured JVM Heap Drift fallback governs recreation.
Conflicts with container Memory settings
The resolved heap and required non-heap allowance must still fit the container Memory recommendation after Request Max, Limit Policy, and Startup Boost constraints. If these settings make the required Memory unreachable, the workload’s recommendation fails (RecommendationReady=False), and the last successful recommendations are kept. Check the condition message and adjust the conflicting bound or container Memory setting.
Operational impact: Higher heap bounds can require more container Memory and cluster capacity; tighter maximums can reduce JVM headroom and increase GC or OOM risk. Check workload behavior and available capacity before rollout.
Selfhost upgrade note: Helm does not update CRDs that already exist. The Selfhost installers apply the Workload Autoscaler CRDs before the Helm upgrade automatically; for a manual Selfhost Helm upgrade, run
helm show crds cloudpilot-selfhost/workload-autoscaler --version <workload-autoscaler-chart-version> | kubectl apply -f -beforehelm upgrade, then wait fordeployment/cloudpilot-workload-autoscalerto finish rolling out. The CRD schema validates quantity syntax, while the RecommendationPolicy validation webhook enforces the heap-bound value constraints. Apply these fields only after the CRDs, webhook, and controller are ready; applying them during a CRD-first window with an older webhook can bypass those value checks.
Heap Buffer
Heap Buffer is used to add extra headroom on top of the computed HeapXms to derive HeapXmx.
It supports either a percentage such as 25% or an absolute value such as 300Mi.
The added heap delta is also added to the memory recommendation to maintain consistency between the JVM Heap and the container memory.
The optional heap bounds are applied afterward, so the final gap between Xms and Xmx can differ from Heap Buffer.
Heap Used Percentile
Heap Used Percentile controls which percentile of JVM heap-used samples is used as the baseline for JVM heap sizing.
If not configured, the system uses P20. The valid range is P20–P100.
A lower value reacts more aggressively to sustained low heap usage and can reduce memory faster. A higher value is more conservative and keeps more headroom for workloads with irregular heap usage or periodic allocation spikes.
This field affects the baseline heap-used query used in JVM-aware recommendations. It is combined with GC-pressure and heap-wave analysis; it does not replace the regular Memory percentile configured in the Percentile section.
Example:
spec:
jvm:
heapUsedPercentile: 50