Nothing causes more confusion for people new to Linux than opening free and seeing almost no “free” memory available, even on a system that’s barely doing anything. I remember genuinely panicking about this early in my career before understanding how Linux actually manages memory. free is simple to run but easy to misread — so let’s go through it properly, column by column.
What is the free Command?
free displays a summary of total, used, and available system memory, including both physical RAM and swap space. It reads its data from /proc/meminfo, the kernel’s live memory statistics interface, and presents it in a condensed, human-friendly table.
Basic Syntax
free [OPTIONS]
A Real Example
free -h
Actual output from a test system:
total used free shared buff/cache available
Mem: 3.9Gi 197Mi 3.8Gi 4.2Mi 46Mi 3.7Gi
Swap: 0B 0B 0B
Understanding Every Column
This is the part that actually matters:
- total — total installed physical RAM (or configured swap size)
- used — memory currently in active use by running processes and the kernel itself, calculated as
total - free - buff/cache(roughly; modernfreeaccounts for reclaimable slab memory too) - free — memory that is completely unused and immediately available with zero overhead
- shared — memory used by
tmpfsand shared memory segments (/dev/shm, inter-process shared memory) - buff/cache — memory used for disk buffers and the page cache. This is memory the kernel is using to cache recently read/written files for speed, but it is reclaimable — the kernel will drop it instantly if an application needs that memory instead
- available — the single most useful number on this whole screen: an estimate of how much memory is actually available for starting new applications, accounting for reclaimable cache, without triggering swapping
The Number Everyone Misreads
Look at that free column again: 3.8Gi free. Someone new to Linux might read this and assume the system is barely using any memory at all — but the real story is in used (197Mi) and available (3.7Gi). The buff/cache column here is only 46Mi in this example because it’s a freshly booted test system with almost nothing cached yet; on a real production server that’s been running for weeks, buff/cache frequently grows to consume nearly all otherwise-unused RAM, and that is completely normal, healthy behavior — not a memory problem.
The rule I always tell people: never judge memory pressure from the free column. Always look at available instead. Linux is deliberately designed to use “unused” RAM for caching, on the principle that unused memory is wasted memory — and it will release that cache instantly the moment an application actually needs it.
Common Parameters
| Option | Description |
|---|---|
-h | Human-readable output (auto-scaled units: Ki, Mi, Gi) |
-b | Show output in bytes |
-k | Show output in kibibytes (default) |
-m | Show output in mebibytes |
-g | Show output in gibibytes |
-w | “Wide” mode — splits the buff/cache column into separate buffers and cache columns |
-s <seconds> | Continuously refresh output every N seconds, like a simplified top for memory only |
-c <count> | Combined with -s, limits the number of refresh iterations |
-t | Add a totals row summing memory and swap together |
-l | Show detailed low and high memory statistics (mostly relevant on older 32-bit systems) |
Practical Examples
Human-readable, one-shot check (my most common invocation)
free -h
Continuously monitor memory every 2 seconds
free -h -s 2
I use this when actively watching memory behavior during a load test or while reproducing a suspected leak — it’s a lightweight alternative to keeping a full top session open.
Watch memory for a fixed number of iterations, useful in scripts
free -h -s 5 -c 6
Refreshes every 5 seconds, stops after 6 total readings (30 seconds total).
Wide format, separating buffers from cache
free -w -h
Output format:
total used free shared buffers cache available
Mem: 3.9Gi 197Mi 3.8Gi 4.2Mi 12Mi 34Mi 3.7Gi
Swap: 0B 0B 0B
- buffers — raw block device I/O buffers
- cache — page cache for file contents
This distinction rarely matters day-to-day, but it’s occasionally useful when specifically diagnosing block-device-level I/O caching behavior versus file-level caching.
Show a combined memory + swap totals row
free -h -t
How free Works Internally
free is a thin, fast reader of /proc/meminfo, a virtual file the kernel keeps continuously updated with live memory statistics. You can view the raw source data yourself:
cat /proc/meminfo | head -10
This file contains dozens of fields (MemTotal, MemFree, MemAvailable, Buffers, Cached, SwapTotal, SwapFree, Slab, SReclaimable, and many more), and free essentially aggregates and formats a curated subset of them into the compact table you see.
The available column specifically is computed using a kernel-provided estimate (MemAvailable in /proc/meminfo, introduced in Linux 3.14) that accounts for reclaimable page cache and slab memory, giving a genuinely more accurate picture of “how much memory could I actually use right now” than a naive free + cached calculation would.
Real-World Use Cases
Pre-deployment capacity check:
free -h
Before deploying a memory-hungry service, I always check available to confirm there’s realistically enough headroom, rather than trusting total alone.
Diagnosing swap thrashing:
free -h
vmstat 1 5
If Swap: used is climbing and vmstat‘s si/so (swap in/out) columns show constant activity, that’s a strong signal the system is under real memory pressure and actively swapping — a serious performance problem, unlike high buff/cache which is harmless.
Confirming a memory leak’s system-wide impact over time:
free -h -s 10 -c 60 | tee memory-log.txt
Logs memory usage every 10 seconds for 10 minutes, which I then review to see if available memory is steadily trending downward — a real leak signature, as opposed to normal cache growth which plateaus.
Quick swap configuration check:
free -h
swapon --show
Combining these tells me both how much swap exists and how it’s currently being used.
Troubleshooting Common Issues
“free” column looks alarmingly low, but the system feels fine — This is almost always just healthy page cache usage. Check available instead of free.
“available” is low and the system is genuinely sluggish — This is real memory pressure. Check for a runaway process with ps aux --sort=-%mem | head, and investigate whether it’s an actual leak or just a legitimately memory-hungry workload that needs more RAM or better tuning.
Swap shows 0 total — Some systems (particularly containers, and increasingly some cloud server images) are configured with no swap at all, often intentionally for performance-predictability reasons. This isn’t a free problem — it reflects the actual system configuration, verifiable with swapon --show or checking /etc/fstab.
Output units look wrong compared to what you expected — Remember -h uses binary units (Ki/Mi/Gi = 1024-based), which is standard for free, whereas some other tools report decimal (K/M/G = 1000-based) units. This can cause small apparent discrepancies when cross-checking against other utilities.
Performance Optimization Considerations
- Don’t chase “low free memory” as a problem to fix — it’s frequently a sign of a healthy, well-utilized system, not a resource shortage.
- Focus tuning efforts on
availablememory trends over time and actual swap activity (si/soinvmstat), which are the metrics that genuinely correlate with real performance problems. - For memory-sensitive workloads (databases, JVM-based apps), tune the application’s own memory limits based on
availablememory headroom, leaving comfortable room for the kernel’s page cache to continue doing its job.
Security Implications
free‘s output itself carries minimal direct security risk — it’s simply system-wide aggregate memory statistics, without process-specific detail. That said, unusual memory patterns (a sudden, sustained drop in available with no obvious application explanation) can sometimes be an early indirect signal of a compromised process consuming resources (like a cryptominer), which is worth folding into broader monitoring and alerting rather than treating free in isolation.
free vs. Related Commands
| Command | Difference |
|---|---|
vmstat | Shows memory alongside CPU, I/O, and swap activity over time, better for spotting trends and swap thrashing |
top / htop | Show memory summary plus per-process memory breakdown together in one live view |
/proc/meminfo | The raw kernel data source free itself reads from, with many more granular fields |
smem | Reports more accurate per-process memory usage accounting for shared memory (PSS), avoiding the double-counting issue with plain RSS |
numastat | Memory statistics broken down by NUMA node, relevant on multi-socket servers |
Compatibility Across Distributions
free is part of procps/procps-ng and is present on virtually every Linux distribution by default — Ubuntu, Debian, RHEL, CentOS, Fedora, Arch, openSUSE. Output format and available flags are consistent across all of them, since they all read from the same standardized /proc/meminfo kernel interface. The one notable difference is the available column itself, which requires a kernel version of at least 3.14 (released in 2014) — on genuinely ancient kernels, this column may be absent or computed less accurately by free itself as a fallback estimate.
free Inside Containers — A Common Gotcha
This is one of the most important practical caveats about free, and it catches a lot of people off guard: inside a Docker or other cgroup-constrained container, free frequently reports the host’s total memory, not the container’s actual memory limit. If you’ve set a container memory limit of 512MB via docker run --memory=512m, running free -h inside that container may still show the full host memory (say, 64GB), because free is reading /proc/meminfo, which in many configurations reflects the underlying host’s kernel view rather than the container’s cgroup-imposed limit.
To see the actual enforced limit and current usage from within a cgroup-constrained environment, check the cgroup interface directly instead:
# cgroup v2
cat /sys/fs/cgroup/memory.max
cat /sys/fs/cgroup/memory.current
# cgroup v1 (older systems)
cat /sys/fs/cgroup/memory/memory.limit_in_bytes
cat /sys/fs/cgroup/memory/memory.usage_in_bytes
I’ve seen real incidents where a containerized application appeared to have plenty of “free” memory according to free -h, right up until it hit its actual cgroup limit and got OOM-killed without warning — because nobody was looking at the number that actually mattered. If you’re debugging memory issues inside a container, always check the cgroup limits directly rather than trusting free‘s output at face value.
Understanding the OOM Killer’s Relationship to free’s Numbers
When a system runs critically low on available memory, the Linux kernel’s Out-Of-Memory (OOM) killer steps in and forcibly terminates a process to reclaim memory, based on a scoring system (visible per-process in /proc/[pid]/oom_score). This is a last-resort mechanism, and by the time it activates, free‘s available column would already be showing a very low number for some time beforehand. I always treat available dropping toward zero as an early warning sign, well before actual OOM kills start happening — proactive monitoring based on trends in available memory is far better than reactively investigating after the OOM killer has already taken down a process.
dmesg | grep -i "killed process"
journalctl -k | grep -i "out of memory"
These commands show a history of any OOM kill events, which I always cross-reference against free/memory monitoring history when investigating an application that mysteriously restarted or crashed.
Comparing free’s Numbers Against /proc/meminfo Directly
For genuinely deep debugging, it’s sometimes worth bypassing free entirely and reading the raw kernel data:
cat /proc/meminfo
This exposes far more granular fields than free surfaces by default — things like Dirty (memory waiting to be written back to disk), Writeback (memory actively being written back), AnonPages (memory used by processes not backed by a file), Mapped (files mapped into process memory via mmap), and SReclaimable/SUnreclaim (reclaimable vs. non-reclaimable kernel slab memory). I rarely need this level of detail day-to-day, but when chasing a genuinely subtle memory issue — like slab memory growth from a kernel-level driver bug — this raw data is where the real answers live.
Summary
free looks like the simplest command in this whole series, but it’s also the one most commonly misread. The core lesson I always pass on: ignore the raw free column, and pay attention to available instead — Linux using “spare” RAM for disk cache is a feature, not a problem, and understanding that distinction is the difference between panicking over a healthy system and correctly identifying real memory pressure when it actually happens.
References
- Linux man-pages project,
free(1): https://man7.org/linux/man-pages/man1/free.1.html - The Linux Kernel
/proc/meminfodocumentation: https://www.kernel.org/doc/html/latest/filesystems/proc.html#meminfo - GNU/Linux
procps-ngproject: https://gitlab.com/procps-ng/procps - Linux Kernel documentation on memory management: https://www.kernel.org/doc/html/latest/admin-guide/mm/index.html
