Skip to main content
DevOps Insightsguides & answers

Linux · commonly confused

Free memory vs available memory

Short answer

free is memory nothing is using at all; available is the kernel's estimate of how much a new program could get without swapping, which counts the page cache it can give back. On a Linux server free can be small even when nothing is wrong, and available is the number to watch — and even available is not pressure. Pressure is the kernel having to work for memory: reclaiming, swapping in and out, tasks stalling.

Measured on this site's production server, a 2 GB EC2 instance, . The figures on this page were read from that machine, not taken from documentation.

First published

On this page · 10 sections

In simple terms

Linux keeps recently read files in RAM, in the page cache, because memory holding nothing is memory wasted. So after a while much of the RAM can hold cache. The kernel takes that memory back when a program needs it, and free does not count it as used.

free counts only memory holding nothing at all. It shrinks as files are read into the page cache, so it can be small on a perfectly healthy server, and it says almost nothing about whether that server is short of memory.

available is the useful number: the kernel's estimate of what a new program could get without swapping — roughly the free memory plus the cache it could give back. When that gets low, the server really is running short.

Neither number shows pain directly. Little available memory can be fine, and swap in use can be fine. Trouble is the kernel having to work for memory: reclaiming, swapping in and out, tasks waiting.

Words used on this page

MemFree
Memory holding nothing at all. free shows it in its free column.
MemAvailable
The kernel's estimate of how much memory a new program could get without swapping. free shows it in its available column.
page cache
Copies of file data kept in RAM after a read or write, so the next read does not have to go to disk.
buff/cache
free's column for Buffers, Cached and SReclaimable added together. Part of it, such as tmpfs and shared memory, cannot simply be dropped.
reclaim
The kernel freeing pages for reuse, by dropping cache it can re-read or writing pages out to swap. When it happens in the middle of an allocation, the program waits.
swap in, swap out
Moving pages from disk back into RAM, and from RAM out to disk. vmstat shows them per second as si and so.
SwapCached
Pages that were swapped out, have been read back in, and still keep their copy in swap.
pressure stall information
PSI: the share of recent time in which tasks waited for memory, in /proc/pressure/memory, as averages over 10, 60 and 300 seconds.
anon and file
Two lines in a cgroup's memory.stat: anon is program memory with no file behind it, file is cached file data, including tmpfs and shared memory.
OOM killer
The kernel's last resort when memory cannot be reclaimed: it ends a process to free memory.

What actually happens

free(1) reads /proc/meminfo. Its free column is MemFree, unused memory. buff/cache is Buffers plus the page cache plus reclaimable slab. available is MemAvailable, which the manual describes as an estimate of how much memory is available for starting new applications, without swapping, taking the page cache into account and allowing that not all reclaimable slab can actually be reclaimed. MemAvailable exists since Linux 3.14.

Measured on this site's own production server, a 2 GB EC2 instance, on 8 Oct 2026: free 94 MB, buff/cache 1,481 MB, available 1,363 MB, 54 MB of swap in use, no swapping in progress, and memory pressure averages of zero. By the free column it was nearly out of memory. By every measure that matters it was healthy.

The same server during a Next.js image build showed the other side: available fell as low as 269 MB, swap in use passed 1.1 GB, and pages moved in and out of swap at tens of megabytes a second. That is memory pressure, and it shows as activity — the si and so columns of vmstat, pswpin/s and pswpout/s in sar -W — not as a small free figure.

Pressure stall information makes it explicit. /proc/pressure/memory reports the share of time in which at least some tasks (the some line) or all non-idle tasks (full) were stalled on memory, as averages over 10, 60 and 300 seconds. The amount of page cache does not appear there; time spent reclaiming memory, or reading back pages from swap or from files that were evicted while still in use, does.

Reading memory on a Linux server

free -m                                   # read "available", not "free"
grep -E 'MemFree|MemAvailable|^Cached|SReclaimable' /proc/meminfo

# Is memory actually under pressure? Look at activity, not levels.
vmstat 5                                  # si/so: swapped in/out per second
cat /proc/pressure/memory                 # share of time tasks stalled on memory
sar -W 5 3                                # pswpin/s, pswpout/s (sysstat)

# A service's "memory" can be mostly cache it read.
grep -E '^(anon|file) ' /sys/fs/cgroup/system.slice/docker.service/memory.stat

Do not "fix" low free memory with echo 3 > /proc/sys/vm/drop_caches. The kernel documentation says those caches are reclaimed automatically when memory is needed, that dropping them can cost significant I/O and CPU to rebuild, and that it is not recommended outside testing or debugging.

Try it yourself

Before you start

  • A shell on the Linux machine you want to check. Everything here reads Linux's /proc and /sys files, which macOS and Windows do not have.
  • The tools: free and vmstat come from the procps package, sar from sysstat. If sar is missing, vmstat 5 shows the same swap-in and swap-out activity in its si and so columns.
  • Linux 3.14 or later for MemAvailable, and a kernel with pressure stall information enabled for /proc/pressure/memory. When PSI is switched off, the whole /proc/pressure directory is missing.
  • No root access. /proc/meminfo and /proc/pressure/memory are readable by every user. Root is only needed to write kernel settings such as drop_caches, which this page advises against.
  • For a single service's figures, cgroup v2 (stat -fc %T /sys/fs/cgroup/ prints cgroup2fs) and the service's cgroup path, which cat /proc/<pid>/cgroup shows on its 0:: line.

Reading /proc/meminfo the way free does

Not reproduced: this was written on macOS, which has neither free nor /proc. The output is the example /proc/meminfo printed in the Linux kernel documentation (The /proc Filesystem, meminfo section), cut down to the lines this grep selects. Each line is verbatim. The documentation does not say what machine the sample came from, and this machine has no swap configured.

Command

grep -E '^(MemTotal|MemFree|MemAvailable|Buffers|Cached|Shmem|SReclaimable|SwapTotal|SwapFree):' /proc/meminfo

Output · as shown in Linux kernel — The /proc Filesystem (meminfo)

MemTotal:       32858820 kB
MemFree:        21001236 kB
MemAvailable:   27214312 kB
Buffers:          581092 kB
Cached:          5587612 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Shmem:              9976 kB
SReclaimable:     517708 kB

How to read it

  • free reads these same fields. Its free column is MemFree: 21001236 kB, about 20 GiB of the 31.3 GiB in MemTotal. Free is large on this machine. It would be much smaller on one whose page cache had grown, and that alone would say nothing about a shortage.
  • Its buff/cache column is Buffers + Cached + SReclaimable: 581092 + 5587612 + 517708 = 6686412 kB, about 6.4 GiB. Note that Cached includes Shmem, here 9976 kB of tmpfs and shared memory, which the kernel cannot simply drop.
  • Its available column is MemAvailable, 27214312 kB. That is 473336 kB less than free plus buff/cache, because the kernel's estimate keeps back the page cache the system needs to run and slab it cannot reclaim. In procps 4.0.4, free's used column is total minus available: 5644508 kB here.
  • SwapTotal and SwapFree are both 0: there is no swap. vmstat's si and so would stay at zero however short of memory this machine got, so on a server like this, pressure shows in /proc/pressure/memory and not in swap activity.

The mistake this causes

Alerting on, or acting on, the free column — or on swap simply being in use.

Why people do it free counts only memory holding nothing; the page cache is designed to fill the rest and is given back on demand. Swap in use is history: pages moved out at some point. Some may have been read back in since and still keep a copy in swap, which /proc/meminfo counts as SwapCached. Neither one measures a shortage.

What you see Alerts that fire on healthy servers, scheduled cache drops that send cached reads back to disk, instances upsized to fix a number that was never the problem — while real pressure, which shows as swap activity and stalls, goes unwatched.

If it goes wrong

cat: /proc/pressure/memory: No such file or directory
Pressure stall information is off. The kernel creates /proc/pressure only when PSI is enabled. Kernels built with PSI but disabled by default turn it on with the psi=1 boot parameter. Until then, use vmstat's si and so columns.
The grep on /sys/fs/cgroup/system.slice/docker.service/memory.stat reports No such file or directory
Check that the machine uses cgroup v2: stat -fc %T /sys/fs/cgroup/ should print cgroup2fs. Then find the real path from the service's main process: the 0:: line of cat /proc/<pid>/cgroup is its directory under /sys/fs/cgroup.
free -m inside a container does not match the container's memory limit
Expected. Kubernetes' documentation notes that free -m does not work in a container. Read the container's cgroup instead: memory.current for usage, memory.max for its limit, and memory.stat for the anon and file split.
Kubernetes reports low memory.available or evicts pods while free on the node shows plenty available
They are different calculations. The kubelet computes memory.available from the cgroupfs as capacity minus the working set, and only excludes inactive file cache. Active file cache counts against it, while MemAvailable treats more cache as reclaimable. Compare against the kubelet's own calculation, which its documentation links to as a script.
sar: command not found
sar is in the sysstat package. Install it, or use vmstat 5, whose si and so columns show the same swap-in and swap-out activity.

How it shows up in production

A check on a small server fires: free memory 94 MB of 2 GB.

Someone logs in, sees 54 MB of swap in use as well, and concludes the box is out of memory.

available says 1,363 MB, vmstat shows no swapping, /proc/pressure/memory averages zero. The memory is cache, and the swap was written days earlier during a build and never needed back. systemd even reports docker.service at 499 MB — of which 451 MB is reclaimable file cache.

The real problem on that same server appeared only during deploys: available collapsing to a few hundred MB while swap churned. The fix went into the build, not the cache, and the alert moved from free to available and swap activity.

How to tell which one you are hitting

Is available low, or only free?
Low free on its own is normal once the page cache has grown. Low available is what needs attention.
Is swap moving, or just occupied?
Occupied with si/so near zero is history. Sustained swap-in and swap-out is pressure.
Are tasks stalling on memory?
Watch the avg10/avg60/avg300 values in /proc/pressure/memory over time; values above zero mean work waited for memory.
Is a service's memory figure mostly cache?
Compare anon and file in its cgroup's memory.stat. file is mostly page cache the kernel can reclaim, but it includes shmem (tmpfs and shared memory), which can only go to swap; subtract it to get the reclaimable part.

Security considerations

  • Swap holds whatever was in memory, including secrets. The mlock(2) manual warns that passwords or keys could be paged onto swap "where they might be accessible to the enemy" after the program has erased them and exited. Programs that hold keys should lock those pages with mlock. The manual adds that suspend saves RAM to disk regardless of memory locks.
  • When available really runs out and reclaim fails, the kernel's OOM killer ends a process. It chooses by memory use, not by importance, so the victim can be your database. Watch available and pressure rather than free, so you hear about it before then. For processes that must survive, lower their /proc/<pid>/oom_score_adj; -1000 exempts a process entirely, which means something else is killed instead.
  • Inside a container, free does not show the container's limit: Kubernetes' documentation says free -m does not work there. A program that sizes its caches from /proc/meminfo can grow past its cgroup's memory.max, and the kernel then invokes the OOM killer inside that cgroup.
  • Cache drops leave a trail. Writing to drop_caches needs root, and the kernel logs each use, as in the documentation's example cat (1234): drop_caches: 3, naming the process. If disk reads spike on a schedule, look for that line before suspecting the workload.
  • Monitoring these signals needs no root. /proc/meminfo and /proc/pressure/memory are readable by everyone, and unprivileged users can create PSI triggers as long as the window is a multiple of 2 seconds. Run the agent as an ordinary user rather than giving it root.

In an interview

How this gets asked in an interview

Usually phrased as free -m shows 90 MB free on a 2 GB server. Is it running out of memory?

What a strong answer contains Not from that number. free counts unused memory, and Linux fills the rest with page cache it reclaims on demand. Look at available — MemAvailable, the kernel's estimate of what a new process can get without swapping. Then look for pressure as activity: swap-in and swap-out in vmstat or sar -W, and stall time in /proc/pressure/memory. A small free figure and swap in use can both be harmless history.

The follow-up "Why not just drop the caches?" Because the kernel already gives them back when memory is needed, and dropping them throws away data that then has to be read from disk again — the kernel documentation recommends against it outside testing.

Sources

The behaviour this page describes, as documented by the projects themselves.

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere

Something wrong or out of date? Report it