Skip to main content

Command Palette

Search for a command to run...

Introducing the ICC Planner Plan Ahead, Scale with Confidence

Updated
12 min readView as Markdown
Introducing the ICC Planner
Plan Ahead, Scale with Confidence

Production traffic usually isn’t random or completely steady. For instance, an app might be quiet at night, see steady use during the day, and then get busier in the evening. On Fridays, that evening spike can be even bigger.

Traditional autoscalers don’t remember these patterns. When the next spike happens, they wait for a metric to cross a threshold and react as if it’s the first time.

Platformatic ICC uses a different method for real-time scaling. Its live scaler watches Node.js signals, predicts where the load will be when a new pod is ready, and scales up before demand rises. We covered this short-horizon algorithm in Ahead of Time Scaling.

The new ICC Planner takes this idea further, looking ahead from just seconds to several weeks. It learns your app’s recurring capacity patterns, predicts pod demand for each time of day, and turns these patterns into suggestions you can review and accept. You can also add one-time or recurring events yourself. Either way, the Planner sets a pod floor before the expected load hits. The live scaler still reacts if actual demand goes above the plan.

With this, ICC now has two ways to look ahead:

  • The real-time scaler asks, “How many pods will this app need by the time a new pod is ready?”

  • The Planner asks, “What capacity does this app usually need at this time on this type of day?”

One handles the next few seconds. The other prepares for demand that is visible on the calendar.


Why short-term prediction is not enough

A real-time scaler works well when load ramps up. It notices the increase as it happens and starts provisioning capacity before the current pods reach their limit. But detecting demand quickly does not make new capacity appear instantly. Kubernetes still has to schedule the pods, start the application, wait for readiness, and begin routing traffic to them. During that interval, the existing pods continue to carry the load.

For example, an application might need 3 pods overnight and 10 during the day. In the evening, demand rises to about 20 pods, and on Friday evenings, it goes even higher. The real-time scaler reacts as the increase happens, but the first new pods still need time to get ready.

Without a plan, operators must either accept exposure during each ramp or keep the application’s minimum near its evening peak all day. A handwritten schedule is possible, but somebody must identify the pattern, work out the right capacity for every hour, and keep the rules current as usage changes.

The Planner offers a more reliable solution. It finds the daytime level, the evening ramp, and the extra Friday demand from the history ICC already has, then shows the evidence for each suggestion. Operators can keep the normal minimum at 3 pods and only accept higher floors for the times that need them. After each window, the floor is removed, and the real-time scaler goes back to following current demand.


Learning capacity instead of guessing from traffic

The Planner does not guess application capacity from request counts. Ten requests could be ten cache hits or ten heavy server-side renders, and those have very different effects on a Node.js process.

Instead, it learns from the output of ICC’s real-time scaler. As the scaler processes Event Loop Utilization (ELU) and heap signals, it figures out the capacity target: how many pods the app needs to handle the workload safely. The Planner uses this value to make floor suggestions.

ICC organizes these capacity targets by time of day and compares the same windows across days. This helps the Planner spot the quiet overnight period, the steady daytime level, the rising evening pattern, and the extra Friday demand.


A calendar designed for operational review

A long list of numbers would make the forecast hard to read. Instead, the Planner shows up to 60 days of upcoming capacity in a calendar heatmap: weeks run across, hours run down, and each cell shows its pod count.

The colours are based on the app’s own history. ICC uses five bands around its normal capacity, so a high-load period stands out whether the app usually runs 3 pods or 100. The legend shows the actual pod ranges for each colour.

The cell treatment tells you where each value came from:

  • Solid cell: is the actual number of pods that ran in a historical window

  • Translucent cell with a dashed border: is a forecast

  • Purple cell: is a scheduled floor produced by an accepted suggestion or a custom event

The Show Previous Forecasted toggle splits historical cells diagonally to show the actual value next to the forecast made before that window. This lets you see forecast quality right in the operating view. A model that keeps missing a peak cannot hide behind a newly updated history.

The view opens around the current week, with recent history on the left and the forecast on the right. It loads a wide range in both directions, so operators can scroll from the evidence to the plan without switching charts or figuring out dates.


Two types of suggestions: baseline and patterns

Operators do not need to understand the model behind the forecast. The Planner gives two types of plain-language suggestions, each answering the same questions: how many pods should be ready, and when?

Baseline suggestions

A baseline is the capacity an app usually needs during a certain time window, no matter the day. It shows up as an everyday suggestion like:

Every day · 5–6 PM — set to 13 pods

Accepting this creates a recurring floor of 13 pods during that hour. The baseline is helpful when the app’s normal capacity changes during the day. Instead of keeping the same minimum all day, an operator can accept the right everyday floor only where history shows it is needed.

Pattern suggestions

A pattern is a recurring exception to the baseline. For example, in the seeded workload, Friday evenings often need 8 more pods than the same hours on other days.

Pattern suggestions show the full pod floor the operator would accept, not just an adjustment to add to the baseline. For example:

Every Friday · 5–6 PM — set to 21 pods
Every Friday · 8–9 PM — set to 30 pods

The Planner shows the full floor for each window. The operator sees 21 or 30 pods, not just a +8 adjustment to combine with another suggestion.


Reviewing a suggestion

Each card includes the action, how often it repeats, and a confidence indicator showing how often the capacity need appears in the app’s history. The floor also stays within the app’s hard minimum and maximum limits, so the UI never promises a value the scaler cannot enforce.

When you select a card, it highlights its recent and future times in the calendar and dims unrelated cells. This is the key review step in the Planner: one click links the recommendation to the historical evidence and shows every future window it would affect.

The detailed review goes even further. Expanding Show Context (Past Data) breaks down recent occurrences into the capacity that was already needed, the part explained by the selected suggestion, and any extra from another suggestion. For example, if the baseline is 10 pods, and a recurring Wednesday pattern adds 5 more,g the suggested floor is 15 pods. On two dates, another pattern added 3 more pods, bringing the total to 18, but the action from the selected suggestion stays the same.

Timezone handling is clear. The rule stays anchored to the cluster calendar, but an operator in another time zone also sees the matching time on their own clock, including a next-day or previous-day marker if the offset crosses midnight. The schedule does not change meaning based on who is viewing it.


Suggestions stay under operator control.

The Planner does not automatically turn every forecast into a scaling rule. Suggestions appear in their own sidebar, and each one must be accepted directly.

Accepting a suggestion creates a lasting recurring floor. The card briefly confirms the action, then moves from Suggestions to Scheduled, and the matching future cells turn purple. Deleting the scheduled action removes that floor and shows the current learned suggestion again if the pattern still exists.

An accepted suggestion is a snapshot of the decision the operator approved. Nightly model updates keep refreshing the candidate behind it, but they do not change the active value without review. This prevents a new fluctuation from changing production capacity without approval.

The same principle applies when accepted suggestions overlap. ICC resolves them by specificity:

  1. The most specific matching rule wins, even when its value is lower.

  2. If two matching rules overlap without either being more specific, the higher floor wins.

  3. If no accepted suggestion matches, there is no suggestion-derived floor for that window.

For example, if the everyday 5–6 PM floor of 13 pods and the Friday 5–6 PM floor of 21 pods are both accepted, the Friday-specific floor wins on Fridays. The everyday floor continues to apply on the other six days. Removing the Friday rule automatically falls back to the everyday floor.

Hard pod limits always take priority. The Planner’s scheduled floors are soft limits within that window; they can prepare capacity, but cannot override the deployment’s safety settings.


Add known events to the plan.

History is not the only useful source of information. An operator might know that next Friday’s promotion will push the app beyond its usual evening peak, even if that event has never shown up in the data. The Schedule Events button lets you add that knowledge directly to the plan.

The form asks for a title, date, time range, timezone, and minimum pod count. An event can run once, repeat daily, weekly, or monthly, or use a custom recurrence with selected weekdays and an optional end date. After saving, the event appears under Scheduled and its affected cells turn purple, just like a floor from a suggestion. You can delete it from the same sidebar when it is no longer needed.

A custom event takes priority over accepted baseline and pattern suggestions wherever their windows overlap. This lets an explicit operational decision temporarily replace the learned plan without deleting it. When the custom event ends, the accepted suggestions take effect again.

You can do the same thing through the public API, so you can add events from a deployment workflow, campaign calendar, or another internal tool.

curl -X POST "$ICC_URL/scaler/user-schedules" \
 -H "authorization: Bearer $APPLICATION_TOKEN" \
 -H "content-type: application/json" \
 -d '{
   "name": "Friday evening promotion",
   "startsAt": "2026-08-07T17:00:00.000Z",
   "durationMinutes": 240,
   "timezone": "UTC",
   "minPods": 35
 }'

This request creates a one-time event. Adding an iCalendar recurrence rule (RRULE), such as

"rrule": "FREQ=WEEKLY", makes it recurring. The returned id can be used to remove it later:

curl -X DELETE "$ICC_URL/scaler/user-schedules/$USER_SCHEDULE_ID" \
 -H "authorization: Bearer $DEPLOY_TOKEN"

The plan and the live scaler work together

At the start of a scheduled window, ICC sets the scheduled floor in the app’s scaling limits and brings the deployment up to that count. It does not wait for incoming traffic or a new metrics batch. This way, the pods can already be running when the first request or job arrives, which is especially useful for sudden events.

The floor is not a fixed replica count. If the Friday plan sets a floor of 21 pods and a sudden surge needs 25, the live scaler can still scale up to 25. The plan just says, “do not go below 21 during this window.” When the window ends, the floor is cleared, and normal scale-down logic brings the app back to its current demand.

This split in responsibility is intentional:

  • The Planner handles learned recurring demand and explicitly scheduled events before they begin.

  • The live scaler handles deviations, ramps, and events without a plan as their signals arrive.

  • Hard limits define the outer safety window for both.

The result is not a choice between scheduled scaling and dynamic scaling. ICC brings them together into one control loop.


What the Planner changes

Ahead-of-time scaling used to mean looking far enough ahead to cover pod startup time. The Planner expands that horizon without losing the signal-aware behaviour that made the real-time scaler useful.

For operators, it turns historical capacity into something you can review and act on. You can see the pattern, check the evidence, compare old forecasts with actual results, and decide which recurring floors should be part of the production plan.

For applications, it closes the gap that short-term trends cannot cover: the first seconds of recurring or known demand. Capacity can be ready for the daytime level, each step in an evening ramp, the extra Friday peak, or a one-time event added by an operator.

For infrastructure cost, it replaces permanent safety buffers with smaller windows based on real need. You keep the capacity needed for a known peak without paying for it all week.

The live scaler still handles real-time changes. The Planner gives it a head start when history or the operator knows what is coming next.

Platformatic ICC is available at icc.platformatic.dev.