Sizing a unified-memory Mac for local models
Somebody buys the 64 GB MacBook Pro because the math on the spec sheet works out: a 60 GB quant, a few gigabytes of headroom, done deal. Then they open the browser tabs they always have open, let the IDE index the project in the background, and start a long chat session. Partway through a generation the machine starts swapping and the whole thing crawls to a stop. The model didn't get slower. The memory they thought they had was never actually free.
That's the trap unified memory sets for anyone sizing a Mac off the number on the box. There's no separate VRAM pool here, the GPU draws from the same memory as macOS itself, the window manager, Spotlight indexing in the background, your editor, your browser tabs, and whatever Docker containers you forgot were still running. The number printed on the spec sheet is a ceiling, not a budget, and a machine that looks generous on paper can behave like it's starving the moment you open more than one thing at a time.
Where the memory actually goes
Treat the total as a pool you draw down in order, long before you get anywhere near a model. macOS and its background daemons take a slice you don't control. Your IDE and browser and whatever else runs alongside inference take another slice, and that one you can control, mostly by closing things you don't need open. What's left after both of those is what you actually have for weights and KV cache, and that number, not the sticker on the machine, is what should decide your quant.
| Unified memory | What you're realistically sizing for |
|---|---|
| 24 GB | small quants, and only with the IDE and browser closed while they run |
| 36 GB | mid-size quants, if you stay disciplined about what else is open |
| 64 GB | larger quants, but only with real headroom management, not by default |
| 128 GB | bigger local models with room for an actual working session running alongside them |
None of that is a promise. A quick completion pass looks nothing like an overnight batch job, and a chat session that runs for hours accumulates KV cache in a way a five-turn test never will, so the same 64 GB machine can feel spacious for one workload and cramped for another.
Measure the machine doing your actual job
The only test worth trusting mirrors how you actually work: IDE open, browser open, the model loaded alongside them, not a freshly rebooted machine with nothing else running. Reserve memory for macOS and your tools first, then size the quant and KV cache in whatever remains, and keep the exact launch command next to the result so you can rerun it later without guessing what you did. One warm sample tells you almost nothing. Run a cold start too, since that's what a real session looks like the first time of the day. Run it long enough to expose thermal throttling or queueing under sustained load, and write down whether the output was actually usable, not just whether it appeared on screen.
Record only what could change your decision: time to first token, prompt-processing speed, generation speed, peak memory, and whether the task actually succeeded. A median tells you about the typical run. A slow percentile tells you about the pause that makes someone stop trusting the tool.
Loading is not the finish line
The most common mistake is treating a model that runs at all as a model that's sized correctly. Getting something to load says nothing about whether it performs well enough for the job, and a plausible-looking answer is worth checking, not trusting on sight. Check the actual runtime logs and the operating system's memory pressure, not the flag you passed at launch, because the flag tells you what you asked for and the logs tell you what actually happened. When two configurations give different results, change exactly one variable and be able to say why you expect the difference, or you're just collecting anecdotes with timestamps on them.
There's a maintenance cost too, and it's easy to underrate. A fragile five-percent win from some obscure flag combination evaporates the next time the model, the driver, or the runtime updates, and now you're debugging a regression instead of running inference. A short script, a handful of prompts that represent what you actually do, and a plain-text log of results is enough to retest after every upgrade. You don't need a dashboard for a laptop.
What headroom actually buys you
My rule is boring on purpose: size for the whole working session, not a clean-boot number you'll never see again once real work starts. Test the smallest plausible change first. Keep more headroom than feels necessary, because that spare capacity is what absorbs a longer prompt, a background app you forgot about, or the bigger model you'll want to try next month. Stop tuning once the setup meets your latency and quality bar. Chasing the last few points past that is how a weekend disappears.
I've written more on matching a machine's shape to the workload rather than backfilling the workload to the machine in hardware for local LLMs, and on the day-to-day mechanics of running MLX models on this same kind of hardware in mlx-lm as a daily driver; both assume the memory math from this piece.
If you're choosing between 24, 36, 64, and 128 GB right now, skip the chart. Open Activity Monitor, run your actual workflow with everything open the way it always is, and watch what's genuinely free before you ever load a model. That number is what you size the quant against, not the one on the box.