CPU Credits and Burstable VPS Plans: Burst vs Sustained Load

Burstable VPS plans decouple the CPU you can consume for short periods from the CPU you pay for continuously. A plan advertised as “4 vCPU burstable” may guarantee only 20% of one core at steady state, with the rest available as credits that accumulate while idle and deplete under load. For a low-traffic API this is excellent economics. For a video transcoder it is a trap that manifests as mysterious slowdowns twelve hours after deployment.

This article explains how credit accounting works, how to measure it from inside the guest, and how to decide whether your workload profile fits. It focuses on measurable behavior rather than plan names, because the same accounting model appears under several different names. Instance families and their baseline ratios are listed on the main VPS hosting platform.

The Credit Accounting Model

Each vCPU has a baseline performance percentage. When the guest uses below baseline, credits accrue at a defined rate; when it uses above baseline, credits are consumed at the surplus rate. A vCPU at 20% baseline running at 100% for one minute consumes four minutes’ worth of credits. Total burst capacity is bounded by an account ceiling — often 24 hours of baseline per vCPU — which caps how long any single burst can last.

The practical consequence is a duty-cycle constraint. If your workload needs 100% CPU for 30 minutes out of every 8 hours on a single core, the average is about 6%, which fits comfortably within a 20% baseline. If it needs 100% for 7 hours out of 8, the average is 87%, and credits will exhaust and the guest will be throttled to 20% for the remainder. Compute your own duty cycle before choosing a plan; it is the only number that matters.

Reading Credit State From Inside the Guest

Most cloud platforms expose credit balance through an instance metadata endpoint or an agent, not through the kernel. On AWS, curl -s http://169.254.169.254/latest/meta-data/cpu-credits/ has historically returned balances for T-family instances; other providers expose equivalents through their own metadata service or console API. If your provider does not, infer the state from the CPU steal and throttling counters described below.

Inside the guest, the clearest kernel-level signal is CPU cgroup throttling. Read cat /sys/fs/cgroup/cpu.stat and watch nr_throttled and throttled_usec. On a burstable instance under sustained load, throttled_usec climbs steadily once credits run out, and /proc/pressure/cpu shows some avg10 rising while your own utilization is pinned at your quota rather than at 100% of the visible vCPUs. That combination — high pressure, utilization capped below total capacity — is the signature of throttling rather than contention.

Benchmarking Burst Behavior Deliberately

Measure the burst and the baseline separately. Start with a 60-second full-throttle run: sysbench cpu --threads=$(nproc) --time=60 run, which should show near-linear scaling if credits are full. Then run for 45 minutes and plot events per second in 60-second buckets. A healthy burstable instance shows a plateau, then a step down to a stable baseline level; the time to the step is your effective burst duration.

Run the long test after a period of idleness so credits start full, and again immediately after the first run so they start depleted. The difference between the two curves is the entire value proposition of the plan, quantified. Record cat /sys/fs/cgroup/cpu.stat before and after each run to confirm throttling occurred where the curve steps down, ruling out thermal or hypervisor explanations.

Workloads That Fit Burstable Plans

Burstable plans suit workloads with low mean utilization and short peaks: HTTP APIs with traffic concentrated in a few hours, scheduled batch jobs that run briefly, CI workers that are idle between builds, and staging environments. The common property is that the peak is short relative to the time available to replenish credits, and that degradation during throttling is acceptable because it happens during low-value periods.

A concrete test: model your workload as peak CPU-seconds per hour and compare it against the plan’s baseline capacity. A 2-vCPU plan at 20% baseline produces about 1440 CPU-seconds of continuous capacity per hour, with a burst ceiling far above that. If your hourly demand peaks below 1000 CPU-seconds, the plan fits with margin. If it exceeds the baseline for several consecutive hours, you are borrowing against credits you cannot repay.

Workloads That Should Not Use Credits

Sustained workloads are the wrong fit: databases under continuous load, media transcoding, compile farms, game servers with steady tick rates, and anything with a latency SLO. A database on a burstable plan behaves well during warm-up and degrades precisely when a long analytical query or a vacuum needs CPU, which is the worst possible correlation. Throttling does not fail requests cleanly; it stretches them, which turns into lock timeouts and retries that amplify the original load.

The diagnostic signature is p99 latency tracking the credit balance: stable during the morning, degrading through the afternoon, recovering after a quiet period. If throttled_usec correlates with your slow-request log, the plan is structurally wrong for the workload regardless of how much headroom the CPU graph appears to show.

Designing Around a Burst Ceiling

If you stay on a burstable plan, shape the workload to conserve credits. Pin batch jobs away from peak hours using systemd timers with RandomizedDelaySec and Nice=10, and cap them with CPUQuota=50% in the unit file so a single job cannot drain the balance. Move long-running work to a queue with rate limiting rather than firing it inline with requests.

Reduce CPU per request so the baseline goes further: enable opcache for PHP, use worker_processes sized to baseline rather than burst capacity, and cache aggressively at the edge. A 30% reduction in per-request CPU is equivalent to a 40% larger baseline, and it is usually cheaper than moving up a plan tier. Track requests-per-CPU-second as your primary efficiency metric rather than raw throughput.

Monitoring for Silent Throttling

Throttling is invisible on a naive CPU graph because utilization simply plateaus below capacity. Alert on rate(container_cpu_cfs_throttled_seconds_total[5m]) or the cgroup v2 equivalent rather than on utilization, and pair it with pressure stall information: node_pressure_cpu_waiting_seconds_total for some rising while utilization is flat is the definitive signal.

Also monitor the ratio of achieved throughput to offered load. If request rate is constant but response time grows steadily over hours, you have a capacity decay pattern that matches credit exhaustion, and no amount of application tuning will fix it. The managed versus unmanaged decision affects who watches these counters, but not what they mean.

When to Move to Sustained or Dedicated CPU

Move when any of three conditions holds: throttling occurs during your defined business hours, sustained load exceeds 60% of baseline for more than four hours per day, or a latency SLO applies to the workload. At that point a fixed-CPU or dedicated-core plan costs more per hour but delivers predictable scheduling, and the migration is usually cheaper than the engineering time spent tuning around credits.

Before migrating, re-baseline with the same 45-minute sustained test and confirm the new plan holds throughput flat for the full duration with throttled_usec staying at zero. A plan that removes core contention but keeps a cgroup CPU quota will show the same curve after a few hours, just with a different label.

Summary: Match Duty Cycle to Baseline

Burstable plans are a financing mechanism for idle time. They work when your duty cycle is well under the baseline ratio and your peaks are short and replenishable, and they fail when demand is sustained or latency-sensitive. Measure the burst curve and the throttle counters directly, size the workload to baseline rather than burst, and treat a rising throttled_usec during business hours as a migration signal rather than something to tune around.

Leave a Reply