The Instance Reportcompute desk — instances & pricing

instances / Containers

Cut Container Costs with Spot Instances and Kubernetes

Spec filed 2026-10-15

1 Overview

Running containerized workloads on interruptible compute is one of the most reliable ways to reduce the largest line item in a Kubernetes bill: the worker nodes themselves. The core idea is simple. Instead of paying a premium for capacity that is guaranteed to stay available, you bid on spare capacity that can be reclaimed when demand rises elsewhere. In exchange for accepting that risk, the effective hourly rate for those nodes can fall dramatically, often to a fraction of the standard price. For teams whose applications can tolerate a node disappearing and their pods being rescheduled, this is close to free money.

The catch is that the discount is not a discount on your architecture. It is a discount on a specific operational contract: you accept that any given node may vanish with little warning, and you design your workloads so that this is survivable. Kubernetes already provides most of the primitives you need, including eviction, rescheduling, disruption budgets, and graceful termination. The work is in wiring those primitives together deliberately rather than assuming the cluster will absorb the shock on its own.

This article describes the general pattern, not any particular vendor or product. The same logic applies whether you run a managed control plane or your own, and whether your interruptible capacity comes from a marketplace, a preemptible pool, or a spare-capacity tier. The economics and the failure modes are broadly similar, and so are the engineering practices that make the pattern safe.

2 Why this workload pattern matters

Compute cost in a container platform is dominated by the number and size of worker nodes you keep running. Control planes, ingress, and storage add overhead, but the steady hum of CPU and memory reserved for pods is what drives the bill. If a meaningful share of your pods are stateless, horizontally scalable, and tolerant of restarts, then a meaningful share of your node capacity does not need to be premium. Moving that share onto interruptible capacity changes the cost curve without changing the application.

The pattern matters because the alternative is usually worse. Teams that cannot tolerate interruption end up over-provisioning guaranteed capacity to absorb peaks, then paying for that capacity around the clock even when demand is low. Teams that can tolerate interruption gain a second lever beyond right-sizing and autoscaling. They can keep a small, stable baseline of guaranteed nodes for critical components and burst the rest onto cheap, reclaimable capacity. That hybrid shape is what makes the economics work: the baseline protects availability, and the interruptible pool absorbs variability.

There is also a scheduling benefit. Interruptible nodes tend to be plentiful in regions and zones where spare capacity exists, which means you can often get more total capacity than you could otherwise justify at full price. For batch jobs, CI runners, data processing, and stateless web tiers, that extra headroom translates directly into throughput per dollar. The pattern is not universally applicable, but where it fits, it fits well.

3 The architecture in plain terms

The architecture starts with a node pool that is explicitly marked as interruptible. In Kubernetes terms, you typically taint those nodes so that only pods which tolerate the taint will land there. That taint is the contract: it says these nodes may disappear, and only workloads that accept that risk should be scheduled onto them. You then attach tolerations to the workloads you want to run cheaply, and leave critical system components, stateful databases, and anything with strict latency guarantees on a separate, stable pool.

Within the interruptible pool, you want the scheduler to spread pods rather than pack them tightly onto a few nodes. Spreading reduces the blast radius when a node is reclaimed, because fewer replicas disappear at once. You also want disruption budgets that prevent voluntary evictions from taking down too many replicas of a service simultaneously. These budgets do not stop involuntary reclamation, but they do keep rolling updates and node drains from compounding the damage.

Finally, you want graceful shutdown to be real, not theoretical. Containers should handle termination signals, stop accepting new work, finish in-flight requests within a bounded time, and exit cleanly. Readiness probes should remove a pod from service before it dies, and connection draining should give clients time to move elsewhere. When these pieces are in place, a reclaimed node becomes an ordinary rescheduling event rather than an incident. The cluster heals itself, and the only visible effect is a brief dip in capacity that the remaining replicas absorb.

4 Scaling and cost trade-offs

The cost trade-off is straightforward in direction and messy in magnitude. Interruptible capacity is cheaper per unit of compute, but it is also less predictable, so you need more headroom and more replicas to achieve the same reliability. If you run exactly enough replicas to handle peak load on stable nodes, you cannot simply move them to interruptible nodes and expect the same result. You need slack, because some fraction of your capacity may be unavailable at any moment. The question is whether the discount outweighs the cost of that slack.

In practice, the answer depends on how elastic your workload is and how quickly it can recover. A stateless service that can scale horizontally and start new replicas in seconds can tolerate a lot of churn. A stateful service with slow startup, long-lived connections, or in-memory state cannot. The right split is usually a stable baseline sized for your minimum viable load, plus an interruptible pool sized for the variable portion. Autoscaling then adjusts the interruptible pool up and down, while the baseline stays fixed.

There is also a hidden cost in complexity. Managing two pools, tuning taints and tolerations, and debugging scheduling failures takes engineering time. That time is real, and it should be weighed against the savings. For small clusters the overhead may not be worth it. For large clusters running many stateless replicas, the savings can be substantial enough to justify a dedicated effort. The trade-off is not just dollars per hour; it is dollars per hour against the operational burden of running a more dynamic fleet.

5 Failure modes and what to watch

The dominant failure mode is abrupt node termination. When capacity is reclaimed, the node is removed and its pods are evicted, often with a short notice period. If those pods were the only replicas of a service, or if they held state that was not externalized, the result is an outage or data loss. The mitigation is redundancy: never run a single replica of anything important on interruptible capacity, and never store durable state only on the node. Treat every pod on those nodes as disposable.

A second failure mode is cascading rescheduling. If many nodes are reclaimed at once, the scheduler may struggle to place all the evicted pods, especially if the stable pool is already full. Pods can end up pending, and services can degrade while capacity is restored. Disruption budgets, pod anti-affinity, and a healthy stable baseline all reduce this risk. So does monitoring pending pods and node churn, because a slow drift toward unschedulable workloads is easy to miss until it becomes an outage.

A third failure mode is subtle: slow or incorrect shutdown. If a container ignores termination signals, it may be killed mid-request, producing errors that look like random flakiness. If readiness probes are too slow, traffic may continue routing to a dying pod. If clients do not retry, brief interruptions become user-visible failures. These issues are not unique to interruptible capacity, but they are exposed more often because nodes disappear more often. Watching error rates, retry counts, and pod restart frequency around reclamation events is the fastest way to catch them.

6 Operating it in practice

Operating this pattern well is mostly about discipline and observability. Start by classifying workloads. Anything stateless, horizontally scalable, and tolerant of restarts is a candidate for interruptible capacity. Anything stateful, latency-sensitive, or hard to restart stays on stable nodes. Encode that classification in your manifests using taints, tolerations, and node selectors, so the decision is explicit and reviewable rather than accidental. Then verify it with scheduling tests, not just by reading the configuration.

Next, invest in fast startup and clean shutdown. Smaller images, fewer dependencies, and parallel initialization all shorten the window during which a replacement pod is not yet serving. Graceful termination handlers, sensible termination grace periods, and readiness gates that reflect true availability make reclamation uneventful. These improvements pay off even on stable nodes, so they are not wasted effort if you later change your capacity mix.

Finally, monitor the things that matter: node churn, pod evictions, pending pods, restart rates, and the latency and error rates of services running on interruptible capacity. Set alerts that fire on sustained churn or on services that lose too many replicas at once. Review the split between stable and interruptible capacity periodically, because the right ratio changes as your traffic patterns and reliability requirements evolve. The pattern is not set-and-forget; it is a living balance between cost and resilience.

7 Frequently asked questions

Is interruptible capacity safe for production? It can be, for the right workloads. The key is redundancy and disposability. If a service can lose a node without losing availability, and no durable state lives only on that node, then interruptible capacity is a reasonable production choice. If a service cannot tolerate that, keep it on stable nodes. The pattern is about matching capacity type to workload characteristics, not about a blanket rule.

How much cheaper is it really? The discount varies by market, region, and time, and it can change as spare capacity fluctuates. Treat any specific number as a rough relative comparison rather than a guarantee. The savings are usually large enough to matter at scale, but they come with the cost of extra headroom and engineering effort, so the net benefit depends on your workload and your team.

Do I need special tooling? Kubernetes already provides the primitives: taints, tolerations, disruption budgets, probes, and graceful termination. You may want autoscalers that understand multiple node pools and monitoring that tracks churn and evictions. The tooling matters less than the design. If your workloads are redundant, stateless, and quick to restart, the platform will handle reclamation gracefully. If they are not, no amount of tooling will make the pattern safe.

What about stateful workloads? Some stateful systems can run on interruptible capacity if they replicate across nodes and tolerate losing a replica, but this requires careful design and testing. For most teams, the simpler and safer choice is to keep stateful components on stable capacity and move only the stateless tiers onto interruptible nodes. That split captures most of the savings with far less risk.

+ Adjacent specs