All toolsJob NodePool Optimization · illustrative values

Run batch jobs. Use fewer nodes.

Many batch jobs can wait a little. Give running jobs time to finish, reuse their freed capacity, and keep the next small batch on a smaller set of nodes.

See the examples

Less allocated capacity, with a waiting trade-off.

WHY BATCH NODES STAY UNDERUSED

Jobs finish. The node cost can linger.

Three common patterns leave more nodes allocated than the remaining work needs.

Long jobs leave scattered gaps
Short jobs finish first. One long job can keep a mostly empty node occupied, so that node cannot be reclaimed as empty.
Node
L··
Node
L··
Node
L··

Free slots are scattered across busy nodes.

Short bursts create too many nodes
A large wave of short jobs can trigger a large scale-out. If some waiting is acceptable, fewer nodes can serve those jobs in several waves.
Node
SS
Node
SS
Node
SS

The work can end soon after new nodes start.

A small trickle keeps the fleet busy
After a burst, a few new jobs may land across different nodes. Those nodes keep receiving work and struggle to become empty.
Node
S·
Node
S·
Node
S·

Small arrivals can prolong a large fleet.

S · Short jobL · Long job· Free slot

TWO CONTROLS, WORKING TOGETHER

Let jobs wait. Let extra nodes empty.

Provisioning delay: reuse before growing
A Pending job does not have to trigger an immediate new node. Allow eligible jobs to wait while running jobs finish; their free slots can serve the next jobs. Grow gradually when demand still needs capacity.
A short-job burst arrives
Traditional NodePool
Node
S1S2
Node
S3S4
Node
S5S6

Six jobs run on three nodes

No waiting jobs
Job NodePool
Node
S1S2

Two run; four wait

4 waitingS3S4S5S6

The active minimum can be filled immediately. Available slots can always be used without waiting for the delay. Fewer early allocations can also reduce the number of nodes that later long jobs keep occupied.

Minimum active nodes: focus later arrivals
Choose a smaller Active set for new jobs to prefer. Extra nodes finish their existing work and receive less new work, giving them a chance to become empty and be reclaimed.
A burst uses extra nodes
Traditional NodePool
Node
SS
Node
SS
Node
SS

Extra capacity handles the burst

Job NodePool
Active
SS
Node
SS
Node
SS

Extra capacity handles the burst

This soft preference starts after 10 minutes of pool stability. Full Active nodes can use surplus capacity. Running jobs stay in place; normal consolidation governs empty-node deletion.

These sketches explain the idea, without a real-time scale. Placement and consolidation vary. The examples below show the resource savings alongside the extra waiting time.

ILLUSTRATIVE WORKLOAD SIMULATOR

See the resource advantage. See the waiting trade-off.

Run the same work with traditional scale-out and Job NodePool optimization. Follow three ways to reduce allocated capacity: reuse during a burst, reduce fragmented tails, and naturally drain surplus nodes.

Short tasks arrive progressively into an empty pool. Reusing completed-task slots while growth initializes can avoid immediate fan-out, at the cost of more waiting.

Your batch profile
Illustrative values
64
30s
30s
1

0 existing nodes · 4 slots each

The pool is empty at t=0. 64 short tasks arrive progressively from 1s across 30s. Each takes 10s, compared with 30s to initialize a node.

Ready nodes share a least-occupied placement rule with rotating ties. Empty nodes use the same idle tail in both strategies. No idle node is reserved by the active minimum.

Totals for the complete workload below; node views follow the selected time.

LESS ALLOCATED NODE-TIME

64.3%

1120 → 400 node-seconds · Peak nodes: 16 → 4

OCCUPIED-SLOT UTILIZATION

40%

Traditional: 14.3%

FINAL TASK COMPLETION

121s

Traditional: 59s

Timeline t + 0s

0 / 64 incoming tasks have arrived · Next arrival: 1s

At 0s, both pools are empty and no tasks have arrived. The first arrivals are at 1s; nodes are created only after demand arrives.

S · Short 10s· Idle / starting
Traditional NodePool
0 allocated
Allocate for the whole pending burst; spread tasks across ready nodes.

No nodes allocated.

0 busy slots0 waiting0 complete0 idle slots on busy nodes
Job NodePool
0 allocated
Reuse completed-task slots while one growth node initializes. Reassess the queue before adding another.

No nodes allocated.

0 busy slots0 waiting0 complete0 idle slots on busy nodes
Allocated nodes over the same window
Traditional Job optimized
Node counts over 152 seconds. Immediate peak 16; optimized peak 4. The area under each line is allocated node-time.08160s76s152s

Area under the line = allocated node-seconds. Startup and the modeled idle tail both count.

Optimizer timeline
0 marked claims initializing

    Move the timeline to follow reuse, eligibility, and node initialization.

    Same completed work. A shared measurement window.

    Both strategies finish 64 incoming tasks and 0 already-running tasks: 640 useful task-slot-seconds over the same 152s window. Utilization = useful task-slot-seconds ÷ (allocated node-seconds × 4 slots per node). Startup, idle slots, and empty-node idle tails all count.

    Short tasks finish before the next growth node initializes, allowing repeated reuse. Longer tasks or faster startup can require more nodes. Serial growth limits in-flight claims, not nodes per fixed time interval.

    Each synthetic task uses one identical slot. Waiting age begins at arrival in this model. These are illustrative occupied-slot results, not measured CPU utilization or a savings promise. Real packing, startup, consolidation settings, and disruption budgets determine your result.

    Average task wait: 26s traditional / 62s Job · Peak nodes: 16 traditional / 4 Job

    Keep the next small batch on the active set.

    After the pool has been stable for 10 minutes, the Agent prefers a smaller active set and soft-drains surplus nodes. Existing jobs finish; new work prefers active nodes; empty nodes become eligible for normal consolidation.

    01

    Concentrate new work
    Prefer the configured active set after stabilization.

    02

    Let existing work finish
    Surplus nodes drain naturally without restarting Jobs.

    03

    Release empty nodes
    Normal consolidation settings and budgets govern deletion.

    The Agent uses PreferNoSchedule, a soft preference. It does not evict running jobs or reserve idle capacity. Protect active tasks with karpenter.sh/do-not-disrupt: "true" and use a dedicated batch pool.

    Apply the gate to the right jobs.

    The delay and serial growth require all three conditions. Pool-level active-set preferences are a separate Agent behavior.

    Provisioning eligibility
    1. Run to completion

      restartPolicy: Never or OnFailure.

    2. One explicit target pool

      A unique karpenter.sh/nodepool node selector or unambiguous required node affinity.

    3. A positive provisioning delay

      The target NodePool opts in with a valid duration.

    Always-restarting Pods, ambiguous or unbound Pods, disabled-delay pools, deleting-node replacements, and disruption simulations bypass this provisioning gate. Exempt claims can count toward the minimum without consuming the Job growth budget.

    CloudPilot AI NodePool wrapper
    This setting sits alongside nodePoolSpec; it is not a native Karpenter NodePoolSpec field.
    jobNodePoolOptimization:
      minActiveNodes: 1
      provisioningDelay: 30s
    
    # Bind a run-to-completion Pod to the pool
    restartPolicy: Never
    nodeSelector:
      karpenter.sh/nodepool: batch-workers
    Read the full setup and operating guide

    More useful node-time. An acceptable completion time.

    Compare equivalent work over the same window: allocated node-time, actual CPU and memory utilization, Pending latency, completed jobs, and final completion time. Short bursts offer the strongest reuse opportunity; sustained queues still need capacity.

    Configure Job NodePool optimization

    CloudPilot AI / Interactive tools