Choose between right-sizing, an isolated swap pilot and more RAM using workload behaviour, SLOs and a financial break-even test.

Your CI runners keep hitting memory limits, browser workers leave CPU idle, and another RAM upgrade looks expensive. October’s Kubernetes benchmarks make SSD-backed swap worth investigating, but their largest density gain belongs to a particular sandbox workload—not your entire platform. The production question is whether cheaper completed work survives the latency, storage and operational costs. Start with three possible decisions: right-size requests, pilot swap in an isolated pool, or keep RAM-only nodes. Then make the winning option earn its place through a repeatable acceptance test.
Which workloads should get a swap pilot?
Fix requests before asking swap to increase density
How many London nodes must disappear to save money?
Build an isolated pool without mixing provider settings
Prove useful throughput before approving more pods
Make rollback a capacity plan rather than a panic command
Not cluster-wide, and not before measuring the workload. If you’re asking “should I enable swap on Kubernetes?”, start with one isolated workload, not a fleet-wide setting.
Use our Cold pages, SLO headroom, Cash framework. All three gates must pass before a Kubernetes LimitedSwap pilot earns production capacity:
| Workload | Engineering recommendation |
|---|---|
| CI compilation and linking | Pilot repeatable builds with cold pages; keep hot, memory-intensive linking in RAM. |
| Idle browser sessions | Pilot if anonymous pages stay cold; measure resume latency. |
| Continuously active browser automation | Prefer RAM-only when the active working set dominates. |
| Sandboxed Python execution | Pilot repeatable batch jobs; separate memory-streaming jobs. |
| Customer-facing APIs | Prefer RAM-only where tight tail-latency objectives dominate. |
| Databases | Default to RAM-only; protect latency-sensitive working sets. |
| Control-plane services | Keep RAM-only; do not make cluster recovery depend on paging. |
These are engineering recommendations, not universal workload guarantees. An idle browser and a continuously busy browser are different capacity problems.
The Kubernetes post dated 5 October 2026 reports Kata Chrome concurrency increasing from 40 to 50 pods. It reports gVisor Chrome rising from 80 to 160, and gVisor Python from 80 to 240. That 3× result describes Python, not all Kubernetes workloads.
The same post supplies the practical warning: reducing the kernel-build memory limit to 200 MB increased execution time by over 40%. That is a useful boundary for Kubernetes swap performance, not evidence of equivalent billing reductions.
If any gate fails, choose right-sizing or RAM-only capacity. Start with Cloudline’s CLI guide to Kubernetes pod sizing when requests are the first problem to fix.
Swap has to earn its place in one workload, not win an argument for the whole cluster.
Share this quote

kubectl top pods -A --containers
kubectl describe node "$NODE"
kubectl get pods -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,QOS:.status.qosClass,NODE:.spec.nodeName'
Start here, but do not mistake a current utilisation snapshot for a sizing history. Capture startup peaks and complete job cycles, including browser launches and concurrent CI builds. A runner idling at 500Mi can still need 4Gi during compilation.
kubectl top is not an exact RSS measurement.The scheduler places workloads using resource requests; it does not account for swap availability or consumption. Enabling swap does not increase allocatable physical memory. Over-requested pods may therefore remain Pending, even with unused swap space.
Correct inflated requests using observed demand and headroom. Cutting requests merely to force placement creates a different risk: more workloads competing for the same RAM during correlated peaks. That is overcommit, not Kubernetes memory optimisation.
Upstream Kubernetes LimitedSwap eligibility and allocation applies to Burstable pods, with exclusions including containers whose memory requests equal limits. Its proportional per-container swap allowance is:
(containerMemoryRequest / nodeTotalMemory) × totalPodsSwapAvailable
Lower requests can therefore also reduce a container’s swap allowance. Do not apply this formula uncritically to GKE node memory swap: Google documents allocation in terms of limits.
Cgroup v2 is a prerequisite; use Cloudline’s cgroup v2 go/no-go guide rather than treating migration as part of this pilot.
Draw two lanes behind the same cluster scheduler: a RAM-only service pool and an opt-in worker pool with encrypted SSD-backed swap. Monitoring observes both lanes. Explicit workload placement, using node affinity and taints with tolerations, keeps ordinary services out of the swap pool.

For 25 October 2026, model London (europe-west2) using illustrative budget inputs, not live supplier tariffs. Use 730 hours, USD, no VAT and no currency conversion. Savings require removable nodes, not a percentage extrapolated from peak pod density.
Assume existing 8-vCPU/32-GiB nodes cost $0.35/hour; swap-compatible equivalents cost $0.50/hour. Larger-memory 8-vCPU/64-GiB nodes cost $0.68/hour. Add $40/month per surviving swap node for SSD capacity.
| Pool | Monthly arithmetic | Total |
|---|---|---|
| 10 existing RAM-only nodes | 10 × $0.35 × 730 | $2,555 |
| 7 compatible swap nodes | 7 × (($0.50 × 730) + $40) | $2,835 |
| 6 compatible swap nodes | 6 × $405 | $2,430 |
| 5 or 6 larger-memory RAM-only nodes | 5 or 6 × ($0.68 × 730) | $2,482 / $2,978.40 |
At least four nodes must disappear merely to cross break-even. Neither swap nor larger-memory candidate counts predict performance. Node removal must remain feasible across zones and during a node failure.
If existing machines are already compatible at $365/month, the calculation changes. Ten cost $3,650; nine swap nodes at $405 cost $3,645. That saves just $5 before additional operating costs.
The SSD allowance is a budget assumption. Google’s disk pricing documentation confirms provisioned SSD capacity is charged, including unused capacity. Local SSD pricing varies by region, machine series and disk type.
Measure total pool cost divided by unique jobs completed successfully within the agreed deadline. At an assumed 100,000 qualifying completions, $2,555 and $2,430 become $0.02555 and $0.02430 per completed job. Include retries in resource consumption, not as extra successful jobs.
Compare identical workloads, resilience headroom, boot disks, discounts, autoscaling floors and operational effort. Kubernetes swap performance matters only if useful completions survive those constraints. Extend this model to actual billing data using Cloudline’s cost-visibility breakdown.
A denser node saves nothing until you can safely stop paying for another node.
Share this quote

Keep the pilot isolated: label its nodes workload-pool=swap-workers and taint them swap=enabled:NoSchedule. Apply upstream settings through node-image and bootstrap management, never undocumented hand edits to managed nodes.
Kubernetes LimitedSwap requires cgroup v2, a compatible runtime and already-provisioned encrypted swap. Follow the upstream encrypted-swap provisioning tutorial. This kubelet fragment neither creates storage nor provisions encryption:
failSwapOn: false
memorySwap:
swapBehavior: LimitedSwap
Check the node, deploy the configuration, then restart kubelet:
sudo swapon --show
stat -fc %T /sys/fs/cgroup
sudo systemctl restart kubelet
Expect cgroup2fs. Inspect the effective configuration through configz, rather than trusting the file:
kubectl get --raw "/api/v1/nodes/$NODE/proxy/configz" \
| jq '.kubeletconfig | {failSwapOn, memorySwap}'
Use an existing compatible Standard cluster running at least 1.34.1-gke.1341000. For GKE node memory swap, save this as system-config.yaml, leaving encryption enabled by default:
linuxConfig:
swapConfig:
enabled: true
ephemeralLocalSsdProfile:
swapSizePercent: 30
gcloud container node-pools create swap-workers \
--cluster="$CLUSTER" \
--location=europe-west2 \
--machine-type=n2-standard-8 \
--ephemeral-storage-local-ssd=count=1 \
--num-nodes=1 \
--node-locations=europe-west2-a \
--node-labels=workload-pool=swap-workers \
--node-taints=swap=enabled:NoSchedule \
--system-config-from-file=system-config.yaml
This pilot shares one Local SSD with ephemeral storage; it is not a dedicated-device design. For dedicated swap, replace the profile entirely with this alternative; never combine both profiles:
linuxConfig:
swapConfig:
enabled: true
dedicatedLocalSsdProfile:
diskCount: 1
Check the pool and repeat configz inspection against one of its nodes:
gcloud container node-pools describe swap-workers \
--cluster="$CLUSTER" --location=europe-west2
NODE=$(kubectl get nodes -l workload-pool=swap-workers \
-o jsonpath='{.items[0].metadata.name}')
kubectl get --raw "/api/v1/nodes/$NODE/proxy/configz" \
| jq '.kubeletconfig | {failSwapOn, memorySwap}'
Use this pod-spec fragment for a Burstable worker. Illustrative sizing: 512Mi requested, 2Gi limit, not a density recommendation.
spec:
nodeSelector: {workload-pool: swap-workers}
tolerations:
- key: swap
operator: Equal
value: enabled
effect: NoSchedule
containers:
- name: worker
image: python:3.13-slim
command: ["sleep", "infinity"]
resources:
requests:
memory: 512Mi
limits:
memory: 2Gi
A toleration permits placement; the selector confines it. Terraform should own the eventual pool configuration: import an existing pool into managed infrastructure safely.
Amazon EKS managed node groups run EC2 nodes, but this GKE system-config file is not an EKS interface.

Test Kubernetes swap performance with three reproducible arms:
Initially, hold application image digest, runtime isolation, CPU allocation, workload corpus and node count constant. Repeat identical workloads across all three. Then test the smaller pool required by your cost model; same-node improvements do not prove savings.
Run concurrency steps, idle-and-reactivate cycles, synchronised cold starts, sustained load and one-node-loss recovery. Measure end-to-end job completion, not just pod readiness or HTTP submission latency.
for c in 10 20 40; do
k6 run --env CONCURRENCY="$c" --out json="results-$c.json" load.js || break
done
The accompanying load.js sets concurrency from CONCURRENCY, submits real jobs, polls completion and records a custom job_duration_ms Trend. Include failure checks for unsuccessful, incorrect or timed-out jobs. Its options include:
export const options = {
vus: Number(__ENV.CONCURRENCY),
duration: '30m',
thresholds: {
job_duration_ms: ['p(95)<60000', 'p(99)<90000'],
checks: ['rate>0.99'],
},
};
Substitute your actual SLOs for these example thresholds. Failed k6 thresholds produce a non-zero exit code, stopping the sweep.
The SIGs Agent Sandbox c4-standard-8 runc sweep reported 120 healthy swap-backed pods with p99 ChromeReady of 58 seconds. At 200 healthy pods, p99 reached 268 seconds. More surviving pods can still breach readiness objectives. Keep this sweep separate from the blog’s different runtime and machine comparisons.
Alongside load tests, collect node evidence:
vmstat 1
cat /proc/pressure/memory
iostat -xz 1
kubectl describe node "$NODE"
kubectl get events -A --sort-by=.lastTimestamp
Run continuous samplers in separate terminals. Correlate swap-in/out, disk latency, CPU saturation, OOMKilled events, evictions and MemoryPressure with job-duration spikes. Non-zero swap occupancy alone is not failure. On GKE, capture node and container swap-used metrics too.
Approve more pods only when SLO compliance, stable throughput, recovery and lower cost per qualifying completion hold together. These are the acceptance gates for Cloudline’s monitoring and reliability implementation, not pod-count targets.

A Kubernetes swap production pilot needs an exit route with enough RAM to carry the workload. Spare SSD space is not rollback capacity. Budget for temporary overlap between pilot and fallback nodes.
For Kubernetes LimitedSwap, the sequence matters more than the command. Draining first can push swap-sized workers onto ordinary nodes and turn a contained experiment into wider memory pressure.
kubectl cordon "$NODE"
Restore RAM-only placement and the original safe requests and limits in the deployment or job-controller source of truth. Apply those changes before recreating work; swap-sized workers must not spill onto ordinary nodes.kubectl drain "$NODE" --ignore-daemonsets --timeout=15m
Respect termination grace periods and PodDisruptionBudgets. If draining times out, investigate rather than bypassing eviction safeguards. Drain does not guarantee application-level job preservation. An emptyDir-related refusal requires a deliberate decision to preserve, checkpoint or discard that data—not an automatic destructive flag.swapoff -a under pressure: first remove workloads and establish RAM headroom. Re-run baseline completion and SLO checks, then remove unused SSD capacity.Acceptance and rollback checklist: these are this article’s operating policy, not upstream Kubernetes defaults.
For help sizing a reversible pilot, commission a Kubernetes capacity-and-reliability review.
Enable swap only when cold memory, SLO headroom and the financial model agree. Right-size first, keep customer-facing services isolated, and require the smaller pool to prove useful throughput under pressure and during recovery. If those tests fail, buying RAM can be the cheaper production decision. Cloudline Consulting can help you commission a Kubernetes capacity-and-reliability review covering workload sizing, node economics, observability and a rollback plan—so the next infrastructure purchase follows evidence rather than a density headline.