How the 2025 Multicloud Surge & New Inter
The cloud landscape is changing faster than ever. As 20...




A swap death spiral is a feedback loop, not a slow disk. The disk is doing exactly what the kernel asked it to do, at exactly the speed it was built for. What makes the event look like a hardware failure is that the workload and the reclaim path are chasing each other: every page the kernel pushes out to make room becomes, on its next access, a major fault that stalls a running task — and a stalled task holds memory longer. The system does not fail because a component underperformed. It fails because two correct mechanisms discovered each other.
This is why the standard diagnosis goes wrong so reliably. When a box that ran fine for months suddenly takes four hundred milliseconds to answer a health check, the first instinct is the disk — and the second is the provider. Both are usually wrong, and both are wrong in the same direction. The kernel's reclaim algorithm is not broken, and the volume underneath it is not lying about its latency. What has changed is that the working set no longer fits, and once that is true, the *rate* of paging matters far more than the *speed* of the device. A fast device in a spiral still spirals. It just does it with more cycles per second.
What follows is the loop described beat by beat, the four different instruments that answer four different questions about it, the refault arithmetic that explains why adding swap can make an outage longer instead of shorter, a table of five convincing misdiagnoses, the specific counters that separate a spiral from a genuinely slow disk, and a runbook ordered by cost.
The whole failure fits in six steps, and the important property is that each step is a reasonable response to the one before it.
Note what is absent from those six steps: any bad decision. The reclaim heuristics are the same ones that work correctly on a well-sized host. The application's access pattern is the same one that ran all last quarter. The only variable that changed is the margin between the working set and the RAM — and the loop is what happens when that margin is negative.
There is a second-order effect that makes the loop worse than the arithmetic suggests. A major fault does not merely cost its own latency; it takes a thread out of the runnable set. If the stalled thread held a lock, everything waiting on that lock stalls too, and those waiters are also holding memory. So a single page fault can convert into a service-wide stall while consuming no CPU at all. This is the reason CPU dashboards are almost useless during a spiral: a box in a swap loop can show 20 percent CPU, 40 percent CPU, or 95 percent CPU depending entirely on how many threads happened to be runnable in the last sampling interval.
Before the counters, the parameter — because the most common mental model of it is simply not what the kernel implements.
The folklore version goes like this: swappiness is a percentage, so a value of 60 means the kernel starts using swap once memory is 60 percent full. That model predicts a clean, predictable trigger point. No such trigger point exists. The kernel's own documentation describes the knob as the "rough relative IO cost of swapping and filesystem paging", with a range of 0 to 200 and a default of 60. At 100, the documentation states, the virtual memory subsystem "assumes equal IO cost and will thus apply memory pressure to the page cache and swap-backed pages equally." Lower values mean the kernel treats swap IO as more expensive than filesystem IO; higher values mean the reverse.
That is a ratio, not a tripwire. It enters the reclaim decision as a weight on how aggressively each of the two LRUs is scanned — anonymous pages (which must be written to swap) versus file-backed pages (which can simply be dropped if clean). The modern implementation in mm/vmscan.c works this out in a function that balances the cost of each list against the share of pages that are refaulting, and the comment above it is unusually explicit about the shape of the trade-off: the influence of the ratio is deliberately limited, so that "at least a third of the pressure is applied, before swappiness". Even a value of zero does not exempt anonymous memory indefinitely — the documentation notes that at 0 the kernel will not initiate swap until free and file-backed pages fall below the zone's high watermark. Zero delays the loop. It does not abolish it.
| swappiness | Anonymous-page weight (value / 200) | File-page weight (200 - value) / 200 | What it means in practice |
|---|---|---|---|
| 0 | 0.00 | 1.00 | Swap is a last resort, entered only below the high watermark. Cold anonymous pages accumulate and cannot be reclaimed until the zone is nearly dry. |
| 10 | 0.05 | 0.95 | Heavy bias to dropping page cache. Appropriate when the filesystem is slow and the service is cache-friendly. |
| 60 (default) | 0.30 | 0.70 | The general-purpose middle. Neither list is protected; both are scanned. |
| 100 | 0.50 | 0.50 | Documented as the point of equal IO cost between the two sources. |
| 133 | 0.67 | 0.33 | The documentation's worked example for in-memory or faster-than-filesystem swap: if swap random IO is twice as fast as filesystem IO, this is the value that expresses it. |
| 200 | 1.00 | 0.00 | Anonymous pages are preferred as reclaim victims over page cache. |
Two practical consequences follow. First, because the current implementation weighs reclaim by the share of pages that are refaulting, the algorithm is explicitly trying to learn which list is being hurt by being reclaimed. That is a good design and it is also the reason a spiral does not self-correct: once both lists are refaulting heavily, both costs look high, the balance becomes uninformative, and the kernel has no remaining signal to distinguish a genuinely cold page from a hot one. Second, values above 100 are not exotic. The documentation recommends them for in-memory swap — zram or zswap — and for hybrid setups where the swap device is faster than the filesystem. If you have ever seen a guide insist that swappiness is capped at 100, that guide is describing a much older kernel.
Most swap arguments are really arguments about which file someone looked at. There are four, they answer four different questions, and using one to answer another's question is where the confusion begins.
| Instrument | The question it answers | What it cannot tell you |
|---|---|---|
/proc/meminfo |
How much memory exists right now, and how much is committed | Whether any of it is moving. It is a snapshot of stock, not of flow. |
/proc/vmstat |
How much paging and faulting has happened since boot — cumulative event counters | Nothing about rate. A counter of 40 million is either a healthy decade or a bad afternoon. |
/proc/pressure/memory |
What share of time tasks are stalled on memory, over 10, 60 and 300 second windows | Which process, which page, which device. It quantifies harm, not cause. |
cgroup memory.* |
The same questions, but scoped to one service, with an explicit ceiling | Anything about processes outside that cgroup, including the ones competing with it. |
The first file is where the arithmetic of the margin lives. MemAvailable is the kernel's own estimate of how much memory can be given to a new application without swapping — and the fact that it is an estimate is stated in the documentation, which notes that it accounts for the need to keep some page cache for the system to function well. SwapTotal and SwapFree give the device's capacity and current occupancy. Committed_AS is the more interesting number: the documentation defines it as the sum of all memory allocated by processes "even if it has not been used by them as of yet", with the explicit example that a process which malloc()s 1 GB and touches 300 MB shows up as 1 GB. Committed memory is a promise. Resident memory is a fact. A host can be comfortable on the second and dangerously overextended on the first.
The second file is where the loop becomes visible, but only if you read it as a rate. /proc/vmstat is a flat list of cumulative event counters whose names come straight from the kernel's internal event enum: pswpin and pswpout count pages moved between memory and swap, pgmajfault counts faults that required a device read, and — the pair most people have never looked at — workingset_refault_anon and workingset_refault_file count pages that were evicted and then faulted back in. The name of the last pair is the giveaway about what they measure. They are not "reads". They are regrets.
The third file is the only one that speaks in units of harm. Pressure Stall Information, in the kernel since 4.20, exports the share of time in which tasks were stalled on a resource. The documentation's two lines carry the whole idea: the some line "indicates the share of time in which at least some tasks are stalled on a given resource", while the full line indicates the share of time in which all non-idle tasks are stalled simultaneously — and the documentation is direct about what that means: "a workload that spends extended time in this state is considered to be thrashing. This has severe impact on performance." That sentence is the definition of the thing this article is about, written by the people who implemented the counter. A full value that has been nonzero for minutes is not a warning sign. It is the loop, reported from inside.
The fourth instrument is the one that changes the fix. Everything above is host-wide; cgroup v2 gives per-service equivalents (memory.current, memory.high, memory.max, memory.pressure) plus the one thing host-wide counters can never provide: a ceiling that throttles a runaway service before the whole machine pays for it. Which is the subject of the runbook, later.
The kernel tracks how badly reclaim is doing, and the mechanism it uses is more precise than most operators expect. When a page is evicted, the kernel stores a small shadow entry in its place, recording the value of a per-node counter that accumulates evictions and activations. When a page faults back in and a shadow entry is waiting, the kernel subtracts the two readings. The difference has a name in the source: the refault distance.
The comment above the implementation explains what the number is for, and the derivation is worth following because it turns "is memory too small?" into an inequality. Two of its statements:
"The sum of evictions and activations between any two points in time indicate the minimum number of inactive pages accessed in between." And then: "When a page is finally evicted from memory, the number of inactive pages accessed while the page was in cache is at least the number of page slots on the inactive list."
From those, the source combines an in-cache distance with an out-of-cache distance to get the minimum access distance of the page, and states the test for whether the page could have stayed resident:
NR_inactive + (R - E) <= NR_inactive + NR_active
where (R - E) is the refault distance:
R = counter reading when the page faulted back in
E = counter reading when the page was evicted
For anonymous pages the source then extends the right-hand side to include the file lists, and simplifies to a statement that is remarkably readable: the refault distance can be seen as "a deficit in inactive list space". If the list had (R - E) more slots, the page would not have been evicted between its two accesses. And on a full system, the source notes, "the only thing eating into inactive list space is active pages."
This is the mechanism behind the counter-intuitive behaviour that makes swap spirals so hard to reason about, and it has three consequences that matter operationally.
The inequality is a test you can run in your head. Take the numbers from a real host during an incident: 800 inactive anonymous pages, 900 active anonymous pages, 1,200 inactive file pages, 2,000 active file pages, and a refault distance of 1,500. The test asks whether 800 + 1,500 <= 800 + 900 + 1,200 + 2,000 — that is, 2,300 <= 4,900, which is true. The page would have survived, and the kernel activates it optimistically on that basis. Raise the refault distance to 5,200 and the same test gives 6,000 <= 4,900, which is false: the page is evicted again, and it will be evicted again every time. That is the difference between a machine under pressure and a machine in a loop.
Adding swap moves the deficit rather than closing it. Swap capacity is not part of the inequality. It determines how many evicted pages still exist at all, not whether the pages being evicted were the right ones. A larger swap device lets the kernel evict more, which lets the deficit grow, which raises the refault distance, which makes the inequality fail more often. The honest statement is that more swap converts a fast, loud crash into a slow, quiet degradation — which is sometimes exactly what you want, and is never what "the machine will survive" means.
A spiral has no natural stopping point. When the deficit is large, the kernel activates refaulting pages optimistically, competing with the pages already active. If the assumption was right, the stale pages get pushed out and the working set is preserved; the source describes both outcomes side by side. If the assumption was wrong, "the existing workingset is thrashing in the space allocated to the page cache." Nothing in the loop tells the kernel which of the two it is looking at, because both look like refaults.
Every one of these observations is real. Every one of them is routinely attributed to the storage layer, and in four of the five cases the storage layer is a bystander.
| What you observe | The tempting conclusion | What it usually is |
|---|---|---|
iostat shows high device utilisation during the incident |
"The disk is saturated" | The device is busy because reclaim is feeding it. High utilisation with a low request size distribution is a symptom of paging, not of a slow device. See the notes on reading why iowait is a CPU time share rather than a device metric. |
| Latency climbs in steps and stays high for minutes, then recovers on its own | "The provider had a storage incident" | A refault deficit that briefly closed. A genuine device problem does not usually resolve without intervention once the load is unchanged. |
| RSS for the main process keeps growing across days | "There is a memory leak" | Possibly — but a leak inside a term of hundreds of kilobytes per hour is not what produces a sudden four-hundred-millisecond p99. Measure the leak separately from the incident; see how to read the three load average numbers without over-reading them. |
The box is slow but iostat and CPU look moderate |
"Nothing is wrong, the monitoring would have caught it" | Threads stalled on a refault are neither runnable nor blocked on IO in a way most dashboards attribute. This is what PSI exists to expose. |
| A neighbour on the same physical host gets blamed | "Noisy neighbour / oversubscribed hardware" | Shared-host contention is a real thing and is worth ruling in or out — but it produces a different signature. See below, because the test is cheap and it is not the same test. |
The noisy-neighbour case deserves its own sentence, because it is the one that is genuinely distinguishable and the one most often asserted without evidence. Contention for shared physical resources shows up as time the CPU spends ready to run but not scheduled — steal time — which is a different counter from anything in the swap path. If steal time is flat and pswpin/pswpout is climbing, the host's other tenants are not the story; the steal-time measurement is the one that actually settles the question. This distinction matters because the two conclusions lead to opposite purchases: one says move to a less contended host, the other says the working set needs more room.
Four numbers, read as a rate rather than as a total, distinguish a spiral from a slow device within about ten minutes. The method is deliberately boring.
step 1: ten minutes of flow, not stock.
vmstat -w 60 10
step 2: is the machine stalled, and on what? Watch full avg60 specifically.
cat /proc/pressure/memory
step 3: the two numbers that are regrets, not reads.
grep -E 'workingset_refault|pgmajfault|pswpin|pswpout|allocstall' /proc/vmstat
step 4: scoped to one service, if it runs in a cgroup.
cat /sys/fs/cgroup/service-name/memory.pressure
Read the output with these four rules.
Compare si and so across samples, not against zero. The vmstat columns are per-interval deltas, which is what makes them useful where the raw counters are not. A steady nonzero si/so is the loop's signature: reclaim is writing pages out and the workload is immediately asking for them back. A one-off burst that settles is a cold start. The distinction is trend, and it is visible in ten minutes.
Weight pgmajfault by its latency to get the fraction of a second it is costing you. This is the arithmetic that converts a counter into a user-visible number: major faults per second multiplied by the latency of a major fault gives stalled seconds per wall second. On a device with roughly 100 microseconds of random-read latency, 1,000 major faults per second costs about 0.10 seconds of stall per second — noticeable but sustainable. On a device with 10 milliseconds of latency, the same 1,000 faults per second costs a full second of stall per second, which is total loss of throughput. Same fault rate, same application, a hundredfold difference in outcome — and that hundredfold spread between solid-state random reads and a rotating disk's seek-plus-rotation is the reason the same workload can survive one host and die on another.
| Major faults per second | Device random-read latency | Stalled seconds per wall second | What the service feels like |
|---|---|---|---|
| 100 | 1.0 ms | 0.10 s | A measurable p99 regression; nobody pages |
| 500 | 0.5 ms | 0.25 s | Timeouts on slow endpoints |
| 1,000 | 0.1 ms | 0.10 s | The fast device absorbs it entirely |
| 1,000 | 1.0 ms | 1.00 s | No throughput at all; health checks fail |
| 5,000 | 0.2 ms | 1.00 s | Same failure, reached by fault rate instead of latency |
Watch workingset_refault as a proportion of total faults, not as a count. A standalone refault count grows forever on a healthy machine, because it has been counting since boot. The informative quantity is what share of fault activity is regret — pages that were in memory, were evicted, and had to come back. A share that is climbing is the clearest single indicator that reclaim is losing the argument, and it is the only counter in the set that is about the quality of the eviction decisions rather than their volume.
Read PSI's full avg60 as the harm meter, and ignore everything else when it is rising. The some line is unremarkable — tasks stall on memory briefly all the time. The full line means every non-idle task was stalled simultaneously, which is the kernel documentation's own definition of thrashing. A full avg60 that has been nonzero for minutes is the machine's answer to "is this a spiral", and it arrives without any need to correlate counters by hand.
A fifth signal belongs in the set because it explains why the loop started: allocstall, which counts how often a thread gave up on the free lists and entered direct reclaim itself. Direct reclaim on the allocating thread is where latency stops being background noise and becomes the caller's problem. The kernel documentation for the reclaim tuning parameters makes the same point from the other direction, noting that a high rate of threads entering direct reclaim or of kswapd going to sleep prematurely "can indicate that the number of free pages kswapd maintains for latency reasons is too small for the allocation bursts occurring in the system."
This is not an exotic failure mode specific to Linux virtual memory. It is the general behaviour of any system whose working set has overflowed the layer that was supposed to hold it — and once you see the shape, you find it in places with nothing in common except a hierarchy.
One layer down, inside the machine, the hierarchy is DRAM, then flash, then disk, and the cost of a step down is one to two orders of magnitude. That is the same asymmetry that governs network reach: the four independent ways a filesystem fills are a reminder that "out of space" is never one condition, and the same is true of memory. Each layer has its own reason for being full.
One layer up, the same shape appears in the network. Cloudflare's review of Internet disruptions in the third quarter of 2026, published 27 October 2026, recorded 49 disruptions in three months: 19 government-directed shutdowns, 14 power-related outages across 10 countries, and five natural disasters. The entry that belongs in this article is Honduras, where a power failure on 10 September at a single interconnection facility affected at least 11 major providers, lasted approximately three hours, and cut HTTP traffic across the country by 63 percent. Two providers were unaffected — and the report's explanation is the interesting part: their Honduran connectivity appears to rely more heavily on infrastructure outside the country. The failure was not distributed; it was concentrated at one point where many depended on it, and the networks that survived were the ones with an alternative path.
That is the same lesson as the refault inequality, stated in a different medium. A working set that fits inside RAM has an alternative path for every page: it never needs the device. A working set that does not fit has exactly one path, and it runs through the slower layer at the worst possible moment. The host-level version is quieter than a national outage, which is precisely why it goes undiagnosed for months.
There is a budget pressure closing in on this problem from the other side, and it pushes in exactly the wrong direction.
Memory has become the expensive part of the machine. TrendForce reported on 6 November 2026 that persistently high contract prices for mobile DRAM are pushing handset makers toward lower-cost reballed memory components, with penetration in that market expected to reach roughly 3 to 4 percent during 2026 and rise toward 7 to 9 percent in 2027 — and it noted that price increases are expected to gain further momentum in the first quarter of 2027. When the memory bill rises, the rational cost response is to buy less RAM and lean harder on the hierarchy beneath it. That response is correct as purchasing and dangerous as engineering, because it is the transfer of a capital cost into a latency cost that shows up three months later as an incident nobody can reproduce.
More swap is not free capacity. It is a longer loop. What actually removes the problem is enough resident memory for the working set, and that is a sizing decision made before the invoice rather than a tuning decision made during the outage — which is the case a fixed-resource instance with dedicated RAM and a known disk underneath it is built for. SurferCloud's ULightHost tiers are allocated on that basis, so the question the plan table answers is the one this section is about. The relevant question is not "how much swap", it is "does the working set fit", and an instance sized so that it does removes the deficit from the refault inequality instead of paying to relocate it.
Concretely: a workload with a 6 GB live working set on a host with 4 GB of RAM and 2 GB of swap does not fit. Every page is addressable, so nothing crashes immediately — and roughly 2 GB of the hot set is on the device at any moment, which is 2 GB of RAM's worth of latency paid on every pass. Adding another 2 GB of swap does not change that number. Moving to a host where the working set fits reduces it to zero. Where the choice is a low-cost instance family with pre-configured Linux or Windows images and a choice of regions, the configuration question is the same one: enough resident memory for what actually runs, so that the slow layer stays a fallback instead of becoming part of the steady state — the entry-level tiers are published with their memory and disk per plan, which is the comparison that matters here rather than the swap size.
Work down this list. The first three items are free or nearly free and resolve a large share of real incidents; the last items involve changing what you buy.
1. Confirm what you are looking at before changing anything. Ten minutes of vmstat -w 60 10 plus one reading of /proc/pressure/memory. Rising si/so with a nonzero full avg60 is a spiral. Rising device utilisation with a flat full is not, and tuning swap will not help it.
2. Bound the service instead of the host. Before touching a kernel parameter, put a ceiling on the thing that grows. In cgroup v2, memory.high throttles a service when it exceeds a soft limit, which pushes the pressure inside that service's own domain and makes the reclaim cost visible to its own metrics. memory.max is the hard ceiling that ends the argument. This is the single highest-leverage change on the list because it converts a host-wide outage into a contained slowdown, and because it makes the offending service's memory profile legible.
3. Reduce the working set if you can, rather than the pressure. The loop exists because the working set does not fit. Before buying memory, check whether the working set is genuinely hot: an unbounded in-process cache, an index held fully resident, a connection pool sized to the maximum rather than the mode. In one common class of web service the largest single reduction comes from bounding a cache that was implicitly unbounded, and the fix is a configuration line.
4. Reconsider swappiness only after you know the direction you want. If the workload is cache-friendly and the filesystem is fast, a lower value protects page cache. If the swap device is faster than the filesystem — in-memory compression, or a device that genuinely outperforms the storage — the documentation's model says a value above 100 is the correct expression of that, not a hack. What you should not do is set it to 1 and declare the machine fixed. The ratio changes which list is scanned first. It does not create room.
5. Increase swap deliberately, and know what you are buying. More swap buys survival time and lengthens the loop. That is a legitimate trade when the alternative is a process being killed — a periodic batch job that needs 8 GB for ten minutes once a day genuinely benefits. It is a bad trade when it is used to avoid acknowledging that a working set has outgrown its host, because the resulting incidents are slower, harder to attribute, and produce no crash log to point at.
6. Make the tier beneath the RAM predictable. Paging latency is the cost of every refault, so the layer underneath the memory is part of the memory budget whether or not anyone wrote that down. On a host where the slow layer is fast and low-variance, the loop is shallower and the thresholds you set can be looser. On a host where it is not, the same fault rate produces a different service. Measure it rather than assuming it; a single random-read latency measurement on the actual volume tells you which host you are on.
7. Instrument for the loop, not for the resource. Three series, and a rule for each. The first is the rate of pswpin plus pswpout; alert on a sustained trend rather than on a threshold. The second is full avg60 from /proc/pressure/memory; this is the harm meter and the only alarm on the list that is close to unambiguous. The third is pgmajfault as a rate, correlated with latency, because that product is the actual user-visible cost. If you keep only one, keep the second.
8. Re-check the sizing assumption quarterly. The loop does not appear because something broke. It appears because traffic grew, or an index grew, or a library added a cache, and the working set crossed the RAM line at some point between two releases with nothing in the diff to mark it. A working-set measurement once a quarter — peak Committed_AS against the instance's resident capacity — catches the crossing before the incidents start.
To be clear about the limits, because several of these are claimed regularly and none of them hold.
It does not make the slow layer fast. Raising swappiness, lowering it, or disabling swap changes which pages are chosen as victims and how quickly. It does not change what a page fault to the device costs. If the arithmetic in the table above says your fault rate times your latency already exceeds one stalled second per wall second, you are not in a tuning problem.
Disabling swap is not a fix, and in a different way it is worse. With swap disabled, the kernel cannot move anonymous pages out — so when memory is exhausted, the choice it retains is to kill a process. That converts the loop into an event that has the advantage of being loud. If your workload consists of processes that are safe to restart and you would rather have a crash than a degradation, that trade is defensible and you should make it deliberately. If the process is a database with a warm buffer pool, the event is a cold buffer pool, which is a longer outage than the loop would have been.
It does not eliminate the refault deficit. Nothing in the parameter set changes the inequality. The deficit is a statement about the relationship between the working set and the amount of memory holding it, and it can only be closed by changing one of those two numbers.
It is not the same problem as an out-of-memory kill. The two share a cause and differ in every observable respect. A kill is an event with a timestamp, a process name, and a line in the ring buffer. A spiral is a condition with none of those things — no crash, no error, no log entry, just a service that is slower than it was, for reasons that are not visible in any application-level metric. The second is harder to diagnose precisely because it does not announce itself.
Does swappiness equal the percentage of RAM that must be full before swapping starts? No. The kernel documentation describes it as the relative IO cost of swapping versus filesystem paging, in a range of 0 to 200 with a default of 60, where 100 means the two are treated as equally expensive. There is no threshold of the form the folklore describes. The nearest thing to a trigger point is the documented behaviour at 0, where swap is not initiated until free and file-backed pages fall below the zone's high watermark.
Should I set swappiness to 1 for a database server? Only for one specific reason: you want page cache preserved and you have decided that anonymous memory is not to be reclaimed until the machine is nearly dry. That is a real policy and it is appropriate for some workloads. It is not a general "make the database fast" setting, and it does not address a working set that does not fit.
My host has plenty of free memory but pages are still being swapped out. Why? Because the decision is made per reclaim target and per zone, not by a global percentage, and because the ratio between anonymous and file-backed scanning is weighted rather than absolute. It is also worth checking whether the instance's slab and filesystem caches are being counted differently than you expect. A "plenty free" reading on a snapshot does not mean the kernel saw headroom at the moment it chose the victim.
How do I tell a swap spiral from a genuinely slow volume? Three checks, in order. First, is full avg60 in /proc/pressure/memory rising — that means tasks are stalling, which a slow volume alone does not cause. Second, are pswpin and pswpout rising across samples in vmstat — that means recall is active. Third, is workingset_refault a rising share of fault activity — that means the eviction decisions are being regretted. All three together is a spiral. A slow volume with a fit working set produces none of them.
Is zram or zswap a way out? They change the cost of the layer beneath the RAM, which is genuinely useful, and the kernel documentation's own swappiness example for in-memory swap — a value above 100 where swap IO is faster than filesystem IO — exists precisely for that configuration. Neither creates capacity. Compression is a multiplier on the existing memory, and a compressed swap device will itself fill, at which point the same arithmetic resumes with an extra step in between.
Do containers change any of this? They change where the pressure lands and they make attribution easier, but the loop is the same. A cgroup that hits memory.max gets its own reclaim and its own potential kill, scoped to the container, while the node may still have memory in use by somebody else. The counter to read is the cgroup's memory.pressure, and the reason to set memory.high is that the throttle is visible in the service's own metrics rather than in the host's.
What is the single counter most likely to be missing from a dashboard? full avg60 from /proc/pressure/memory. It is one file read, it is the only signal in the set that is denominated in harm rather than in activity, and the kernel's own documentation uses the word "thrashing" to describe exactly the state it reports.
A swap death spiral is what happens when a working set quietly outgrows the memory holding it and the kernel responds correctly in every individual step. Nothing in the machine is malfunctioning. The reclaim path is doing what it was designed to do — moving the least valuable pages out of the way — and the workload is doing what it was designed to do, which is to touch the pages it needs. The failure is in the relationship between the two, and that relationship is decided once, in a sizing conversation, long before any of these counters move.
The operational lesson is to measure the margin rather than the symptom. Fault rate multiplied by fault latency, read as a rate over ten minutes, tells you whether you have a slow device or a loop, and the two answers lead to different purchases. TrendForce's November 2026 report on persistently high DRAM contract prices suggests the pressure to choose the wrong one will increase through 2027, because the cheaper answer will increasingly be the one that lengthens the loop rather than closing it. If you would like to compare plans on the variable that actually decides this — resident memory per tier, alongside the disk that reclaiming to it will cost you — the published plan table lists memory, disk and bandwidth per tier.
Full disclosure: we are the team at SurferCloud, a cloud provider operating 17 availability zones across 15 countries and regions. We wrote this because "the server got slow and then got better" is a report we receive regularly and almost never in those words — it arrives as a storage investigation. Corrections are welcome; the kernel documentation is a better authority than this article, and we would rather be corrected than quoted.
The cloud landscape is changing faster than ever. As 20...
In today's fast-paced digital landscape, businesses are...
Remote access is an essential feature for managing a Fe...