Ask a Linux server “how much memory is free?” and the honest answer is “it’s complicated.” Modern Linux deliberately uses almost all your RAM—for caches, buffers, and reclaimable structures—because unused memory is wasted memory.
That’s why the number people fixate on, free, is almost never the number that matters.
The source of truth is /proc/meminfo: a plain-text file the kernel updates continuously with dozens of memory counters. Learn to read it and you can tell, at a glance, whether a machine is genuinely low on memory, drowning in cache, leaking, or about to invoke the OOM killer.
This article walks through the fields that actually matter, what they mean, and how to reason about them.
Table of Contents
Reading the file
cat /proc/meminfo
You’ll get output like this (trimmed):
MemTotal: 16384000 kB
MemFree: 512340 kB
MemAvailable: 9871232 kB
Buffers: 204800 kB
Cached: 7331840 kB
SwapCached: 0 kB
Active: 6012416 kB
Inactive: 4821504 kB
Dirty: 12288 kB
Writeback: 0 kB
AnonPages: 4102144 kB
Mapped: 921600 kB
Slab: 1048576 kB
SReclaimable: 786432 kB
SUnreclaim: 262144 kB
SwapTotal: 4194304 kB
SwapFree: 4194304 kB
Everything is in kilobytes (despite the kB label, these are 1024-byte units). The counters are instantaneous—reread the file to see them change.
The three numbers you check first
MemTotal
Total usable RAM the kernel manages (slightly less than physical RAM—some is reserved for the kernel image and hardware). Your denominator for percentages.
MemFree
RAM that is completely unused right now. On a healthy, busy server this is often small—and that’s fine. A low MemFree alone is not a problem. Do not alert on it.
MemAvailable — the one that matters
This is the field to watch. MemAvailable is the kernel’s estimate of how much memory is available for starting new applications without swapping, accounting for the fact that most cache and reclaimable slab can be freed on demand.
Rule of thumb: judge memory pressure by
MemAvailable, notMemFree. IfMemAvailableis healthy, the box has room even ifMemFreelooks tiny.See also: Mastering the Linux Command Line — Your Complete Free Training Guide
A quick “real” usage percentage:
awk '/MemTotal/{t=$2} /MemAvailable/{a=$2} END{printf "Used: %.1f%%\n", (t-a)/t*100}' /proc/meminfo
Cache and buffers: the “used” memory that isn’t
Cached
The page cache—file contents the kernel keeps in RAM so repeat reads don’t hit disk. This is usually the largest consumer on a file/database server, and it’s good. It’s reclaimable: the kernel drops it instantly when apps need memory.
Buffers
Raw block-device / filesystem metadata buffers. Smaller than Cached and also reclaimable.
Why free -h shows “available” separately
The classic free command derives its columns from these fields:
free -h
total used free shared buff/cache available
Mem: 15Gi 4.1Gi 500Mi 120Mi 11Gi 9.4Gi
- used ≈
MemTotal − MemFree − Buffers − Cached − reclaimable slab - buff/cache =
Buffers + Cached + SReclaimable - available =
MemAvailable
The takeaway: “used” excludes cache on modern free, so a big buff/cache with healthy available is a well-utilized machine, not a starved one.
Anonymous memory: what your apps actually hold
AnonPages
Memory that is not backed by a file—process heaps, stacks, malloc’d data. Unlike page cache, anonymous memory can only be reclaimed by swapping it out. Rising AnonPages with flat cache usually means your applications are genuinely consuming more memory (or leaking).
Mapped
File-backed pages currently mapped into process address spaces (shared libraries, mmap’d files). Part of both process footprint and the page cache picture.
Active vs Inactive
The kernel tracks pages on active and inactive LRU lists:
Active— recently used; less likely to be reclaimed.Inactive— not used recently; the first candidates for reclaim.
You’ll also see Active(anon)/Inactive(anon) and Active(file)/Inactive(file) splits. A large Inactive(file) is reclaimable cache—more headroom than it looks.
Dirty pages and writeback
Dirty
Page-cache data that has been modified but not yet written to disk. Normal in small amounts. A persistently large Dirty can cause latency spikes when the kernel finally flushes it.
Writeback
Pages currently being written to disk. If Writeback is consistently high, your storage may be a bottleneck—the kernel is struggling to flush fast enough.
These are governed by vm.dirty_ratio and vm.dirty_background_ratio; tune them only if you understand your write pattern.
Slab: the kernel’s own memory
The slab allocator holds kernel data structures (inodes, dentries, network buffers). Three fields describe it:
Slab— total slab memory.SReclaimable— slab that can be freed under pressure (e.g. cached directory entries). Counts toward “available.”SUnreclaim— slab that cannot be reclaimed. If this grows without bound, suspect a kernel-side leak or a driver holding too many objects.
A steadily climbing SUnreclaim is one of the few /proc/meminfo signals that points at the kernel rather than user space.
Swap: the pressure valve
SwapTotal: 4194304 kB
SwapFree: 4194304 kB
SwapCached: 0 kB
SwapTotal/SwapFree— swap capacity and what’s unused.SwapCached— pages that are both in RAM and swap (so they needn’t be re-written if swapped again).
The interesting question isn’t the size but the rate: is the system actively swapping? /proc/meminfo shows the state; use vmstat 1 and watch the si/so (swap-in/swap-out) columns to see the activity. Sustained nonzero si/so under load means real memory pressure and likely latency pain.
Putting it together: is this box healthy?
A quick decision guide from /proc/meminfo alone:
| Symptom | Likely meaning |
|---|---|
MemFree low, MemAvailable high | Healthy—cache is doing its job |
MemAvailable low, big Cached | Cache can be reclaimed; watch, don’t panic |
MemAvailable low, small Cached, high AnonPages | Real pressure—apps hold the RAM |
AnonPages climbing steadily over time | Possible application memory leak |
SUnreclaim climbing steadily | Possible kernel/driver leak |
Active swap (si/so in vmstat) | The system is out of easy options |
Handy one-liners:
# Real usage % (based on MemAvailable)
awk '/MemTotal/{t=$2}/MemAvailable/{a=$2}END{printf "%.1f%% used\n",(t-a)/t*100}' /proc/meminfo
# Watch the fields that matter, live
watch -n1 "grep -E 'MemFree|MemAvailable|Cached|AnonPages|Dirty|SwapFree' /proc/meminfo"
# Reclaimable vs not
grep -E 'SReclaimable|SUnreclaim' /proc/meminfo
Common misreadings to avoid
- “Free memory is almost zero—we’re out of RAM!” Almost always false. Check
MemAvailable. Low free + high available = a well-used server. - Alerting on
MemFree. Alert onMemAvailable(or a derived usage %) and on swap activity instead. - Treating
buff/cacheas lost memory. It’s reclaimable and beneficial; dropping it (echo 3 > /proc/sys/vm/drop_caches) usually just slows you down. - Ignoring
SUnreclaimgrowth. It’s the clearest hint that a leak is in the kernel, not your app.
Bottom line
/proc/meminfo is the ground truth for Linux memory, but only if you read the right fields:
MemAvailabletells you real headroom—use it, notMemFree.Cached/Buffers/SReclaimableare reclaimable and usually a sign of good utilization.AnonPagesis what your apps truly hold; watch it for leaks.SUnreclaimpoints at the kernel when it grows unbounded.- Swap activity (via
vmstat) confirms whether pressure is real.
Master those, and “how much memory is free?” stops being a trick question.



