Home / Guides / Troubleshooting / Apple

Your Mac is swapping to disk instead of running the model

macOS

Written by Jakub Rusinowski · Last updated September 1, 2026

AI educator & workshop leader on local LLM deployment

The error

Activity Monitor → Memory
  Memory Pressure:  ▇▇▇▇▇▇▇▇  (red)
  Swap Used:        14.62 GB
  Memory Used:      31.88 GB of 32.00 GB

Which one is it?

If you seeThe cause isGo to
Memory Pressure is red and Swap Used is climbing into the gigabytesThe working set exceeds physical memory and macOS is paging to SSDFix 2: cut the model or the context
Everything freezes and the beachball appears the moment the model loadsA single large allocation pushed the whole system into swap at onceFix 1: confirm it in Activity Monitor, then Fix 2
It runs fine for a while and degrades as the conversation growsThe KV cache grows with context and is eating the remaining headroomFix 3: cap the context length
Pressure is yellow and generation is merely slow, not frozenYou are close to the limit but not over itFix 4: close the browser and reclaim a few gigabytes
Memory is fine and the loader still reports a low working-set sizeThe Metal working-set ceiling, not memory pressureThis is a different page — see the wired-limit guide

When you see it

On an Apple Silicon Mac there is no separate VRAM to run out of, so there is no out-of-memory error to read. The model loads, macOS accepts the allocation, and then the machine becomes unusable — cursor stuttering, beachball, everything slow, generation at a fraction of a token per second.

What's actually going on

Apple Silicon shares one pool of memory between CPU and GPU, which is what makes it good at this — no copying weights across a bus — and also what removes the safety net. On a discrete GPU an oversized model fails with an out-of-memory error. Here, macOS does what it always does when memory is short: it swaps, writing least-recently-used pages to SSD. For most applications that is graceful. For inference it is catastrophic, because the working set is the model weights and they are all touched on every single token, so the machine spends its time paging gigabytes back and forth. A model that fits your total memory on paper does not fit in practice, because macOS itself, your browser, and the inference app's own overhead are drawing on the same pool.

How to fix it

1. Confirm it in Activity Monitor before changing anything

Open Activity Monitor → Memory. Two figures matter, and neither is "Memory Used". Memory Pressure is the graph at the bottom: green is healthy, yellow is tight, red means macOS is actively paging. Swap Used should be near zero on a machine with headroom; gigabytes of swap while a model is loaded is the diagnosis. vm_stat gives the same picture in a terminal, and the pageout counts are the ones to watch.

zsh
# zsh — swap in use, and how much has been paged out
sysctl vm.swapusage
vm_stat | grep -E 'Pageouts|Swapins|Swapouts'

# Watch memory pressure live while a model generates
memory_pressure -l 1
Did it work? You have confirmed the diagnosis when vm.swapusage shows used swap growing while the model runs, and returning to roughly flat once it unloads.
sysctl vm.swapusage

2. Size the model against roughly 70–75% of your memory, not 100% Most common fix

The practical rule is that about 70–75% of total unified memory is available to a model, with the rest going to macOS, the window server, and whatever else you have open. That is also the fraction our own calculator uses, so the numbers here and on the analyzer agree. Below, what actually fits at Q4_K_M with an 8K context, computed from the same engine that drives the site — the figures include the KV cache and runtime overhead, not just the weights. 8 GB (~6 GB usable): a 3B (3.7 GB) comfortably, a 4B (4.4 GB) at a squeeze. An 8B at Q4 needs 6.7 GB and will swap. 16 GB (~12 GB usable): an 8B (6.7–7.0 GB) comfortably; a 14B (11.1 GB) fits with little to spare. 24 GB (~18 GB usable): a 14B comfortably; a 24B (16.4 GB) fits. 36 GB (~27 GB usable): a 32B (22.8 GB) or a 27B (25.4 GB), the latter tight. 48 GB (~36 GB usable): a 32B with real headroom, or a 30B MoE. 64 GB (~48 GB usable): a 70B (45.7 GB) fits, with almost nothing spare. 128 GB (~96 GB usable): a 70B comfortably, with room for a long context.

zsh
# zsh — your actual total, in GB
sysctl -n hw.memsize | awk '{printf "%.0f GB total, ~%.1f GB usable for a model\n", $1/1073741824, $1/1073741824*0.75}'
Did it work? After dropping a size or a quant level, Memory Pressure stays green and Swap Used stops growing through a full generation.
sysctl vm.swapusage && ollama ps
Check what fits your hardware — check the exact memory a model needs against your Mac
Open the VRAM checker →

3. Cap the context length — it is the same arithmetic

The KV cache grows linearly with context and it comes out of the same pool as the weights. A model that loads comfortably at 4K can push a 16 GB Mac into swap at 32K, which is exactly the pattern behind "it was fine and then got slow as we talked". Ollama's default is 4096 tokens; raising it is a memory decision, not a convenience one. Set it deliberately and measure.

zsh
# zsh — cap it for one run and watch what changes
OLLAMA_CONTEXT_LENGTH=4096 ollama run qwen3:8b

# Persist it for the Ollama app
launchctl setenv OLLAMA_CONTEXT_LENGTH 8192
# then quit and reopen the Ollama app
Did it work? With the shorter context, swap stops growing during a long conversation that previously degraded.
sysctl vm.swapusage

4. Close the browser — genuinely the second-biggest consumer

This sounds like filler advice and it is not: on most Macs the browser is the largest memory consumer after the model. A Chrome or Safari window with thirty tabs, a video call, and a couple of Electron apps routinely account for 6–10 GB, which on a 16 GB machine is the entire difference between fitting and swapping. Sort Activity Monitor by memory and look at the top of the list before concluding the model is too big.

zsh
# zsh — top ten memory consumers right now
ps -A -o rss=,comm= | sort -rn | head -10 | awk '{printf "%.1f GB  %s\n", $1/1048576, $2}'
Did it work? Free memory rises by a gigabyte or more and Memory Pressure moves back toward green before you load the model.
memory_pressure -l 1 | tail -3

5. Drop a quantisation level before dropping a model

If a model is close but not quite fitting, the cheaper move is a lower quant rather than a smaller model. Q4_K_M is the sweet spot for local use and the quality gap from Q6 or Q8 is small enough that most people cannot identify it in chat, coding, or summarisation. Going below Q4 is where degradation becomes obvious. On a Mac the choice is more consequential than on a discrete GPU, because the penalty for overshooting is swap rather than a clean refusal.

zsh
# zsh — a Q4_K_M tag rather than the default
ollama pull qwen3:8b-q4_K_M
ollama run qwen3:8b-q4_K_M
ollama ps

6. Only then look at the Metal working-set ceiling

There is a separate limit on how much of unified memory Metal will hand the GPU, and raising it is sometimes appropriate — but it is the last thing to try, not the first. It does not create memory; it changes the split, and raising it on a machine that is already swapping makes things worse rather than better. Do it only once Memory Pressure is green at your chosen model size and the loader is still reporting a working-set ceiling below what you have spare.

zsh
# zsh — what does Metal currently think it can use?
# Look for this line in llama.cpp / Ollama loader output:
#   ggml_metal_init: recommendedMaxWorkingSetSize = ...
journalctl 2>/dev/null || log show --last 5m --predicate 'process CONTAINS "ollama"' | grep -i recommendedMax

If none of this worked

If memory pressure is green and the loader still refuses to allocate, the Metal working-set ceiling is the constraint rather than memory itself. If the GPU is not being used at all — swap or no swap — that is a different failure with its own page.

Include this when you report it

Related

A model that fits most setups:
View model & requirements →

Frequently asked questions

Why does my Mac freeze instead of showing an out-of-memory error?

Because unified memory has no separate VRAM to exhaust. macOS accepts the allocation and swaps least-recently-used pages to SSD. Since inference touches every weight on every token, the machine spends its time paging, which presents as a freeze rather than an error.

How much of my Mac's memory can a model actually use?

About 70–75% in practice, with the rest going to macOS, the window server and your other applications. Our calculator uses 75% for exactly this reason, so a 16 GB Mac has roughly 12 GB of headroom for a model plus its KV cache.

Does an 8 GB Mac run local models at all?

Yes, at 3B and below. A 3B at Q4 needs about 3.7 GB with an 8K context, which fits the roughly 6 GB you have available. An 8B at Q4 needs about 6.7 GB and will push an 8 GB machine into swap.

Why does it slow down as the conversation gets longer?

The KV cache grows with context and draws on the same memory pool as the weights. A model comfortable at 4K tokens can push a machine into swap by 32K. Capping the context length fixes it, and it is the same arithmetic as choosing the model size.

Will raising the Metal wired limit fix this?

No, and it can make it worse. That setting changes how unified memory is split between GPU and system, not how much exists. On a machine already swapping, giving the GPU more takes it from macOS. Get memory pressure green first, then consider it.