Skip to Content
GuideWorkload AutoscalerRecommendationPolicy

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 10m and Memory 10Mi. 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.

simulation

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

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.

percentile_explanation

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:

PercentileExplanationTypical Use Cases
P50Median; covers about half of usageDevelopment/testing environments; cost-sensitive; high utilization; occasional resource shortage acceptable
P70Slightly more conservative; covers most common loadsGeneral online services; moderate performance requirements; small degree of oversubscription acceptable
P90More robust; covers most situationsRecommended value for most production services; balances performance and cost
P95Close to worst-case; handles rare spikesCore services; systems with high stability requirements
P99Covers nearly all cases; may be oversizedCritical 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

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 TypePercentageAbsolute Value (Option 1)Absolute Value (Option 2)
CPU20%0.5200m
Memory10%0.25Gi500Mi

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.

buffer_effect

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

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 WindowCharacteristicsProsCons
6hVery short window; captures recent workload changesHighly responsive to traffic spikes and short-term patternsRecommendations change frequently, which may cause pods to be rescheduled more often
3dBalanced window; captures recent and mid-term trendsGood balance between stability and adaptability; suitable for most workloadsMay not fully capture long-term variations
7dLong window; covers a wide range of workload patternsMore stable recommendations; safer for critical workloadsLess 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, and DaemonSet workloads, the Workload Autoscaler still computes and stores recommendations while the first data window is being collected, but it keeps RecommendationReady=False until 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 latches status.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). RecommendationReady remains False until 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

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.

recommendation_pipeline

For Resource Limits, you can use either percentages or absolute values:

Resource TypePercentageAbsolute Value 1Absolute Value 2
CPU20%0.5100m
Memory10%1Gi500Mi

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 Min or Max is 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 settingMinMax
Xms — initial heap sizespec.jvm.minHeapXmsspec.jvm.maxHeapXms
Xmx — maximum heap sizespec.jvm.minHeapXmxspec.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.updateResources contains memory, or the field is omitted and defaults to CPU and Memory).
  • Runtime optimization is enabled (AutoscalingPolicy.spec.disableRuntimeOptimization is false or 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" with maxHeapXmx: "768Mi" is allowed and resolves to Xms and Xmx of 768Mi.
  • 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 - before helm upgrade, then wait for deployment/cloudpilot-workload-autoscaler to 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
Last updated on