How much RAM does an LLM really need on an iPhone?
A 2 GB model does not need 2 GB of RAM. Here is the arithmetic we actually enforce in Pocket AI, the incident that produced it, and the number your iPhone can really hold.
Every "run an LLM on your phone" guide tells you to check the file size. That number is the least useful one in the whole calculation.
A 2.0 GB model does not need 2.0 GB of RAM. It needs the weights, plus a KV cache, plus ggml's compute and graph buffers, plus the tokenizer and vocab, plus whatever the app itself is holding — and all of that has to fit inside a budget iOS sets for you, which is far smaller than the RAM figure on the spec sheet.
Get it wrong and iOS kills your app. Get it wrong with an entitlement, and you can restart the whole phone. We know, because we did.
The incident that produced the rule
Early on, nothing in Pocket AI stopped the engine loading weights bigger than the process was allowed to hold. iOS handled that the usual way: it jetsammed us. The app died, the user reopened it, and everyone moved on. Bad, but survivable.
Then we added com.apple.developer.kernel.increased-memory-limit.
That entitlement asks iOS to let one app grow past the normal per-process cap. It is the right entitlement for this workload — big models genuinely need it. But it changed the failure mode completely. The app was now allowed to grow far enough to starve the kernel instead of itself. Loading a 3.2 GB model on a 6 GB iPhone 14 Pro restarted the device.
The entitlement raises the ceiling. It does not create memory. Springboard, the daemons and the GPU still need their share of those same gigabytes, and a limit generous enough to starve the kernel is still a limit the kernel honours right up until the phone panics.
So the entitlement and a hard memory gate now ship together, and they have to stay together. Removing the gate without removing the entitlement re-arms the restart bug.
The arithmetic
Three numbers do all the work.
1. You may plan for 55% of physical RAM — at most.
iOS will tell you what your process may hold, via os_proc_available_memory(). With the increased-memory-limit entitlement that answer can be generous enough to be dangerous. So we take the smaller of what iOS permits and a hard bound of our own:
ceiling = min(processLimit, physicalRAM × 0.55)
2. Aim at 80% of that ceiling, not 100%.
iOS jetsams on approach, not on arrival. Memory pressure builds and the kernel starts killing before a process reaches its documented limit. Aiming at four fifths leaves the system the room it needs to stay alive.
3. Budget 600 MB of runtime overhead on top of the weights.
That covers the KV cache at our clamped context, ggml's compute and graph buffers, the tokenizer and vocab, and the app's own UI and image caches. It is deliberately generous. Underestimating it is what restarts the phone; overestimating it only makes us decline a model we might have squeezed in.
Put together, the largest weights a device will ever be allowed to hold:
maxWeights = (physicalRAM × 0.55 × 0.8) − 600 MB
What that means per iPhone
Apple does not publish RAM figures for iPhones, so the RAM column below is the widely-reported teardown number, not an Apple spec. Pocket AI does not guess: it reads ProcessInfo.processInfo.physicalMemory on your actual device and shows you the result.
| Device RAM | Planning ceiling | Largest model weights |
|---|---|---|
| 3 GB | 1.77 GB | 817 MB |
| 4 GB — iPhone 12 / 13 | 2.36 GB | 1.29 GB |
| 6 GB — iPhone 12–14 Pro, 14, 15 | 3.54 GB | 2.23 GB |
| 8 GB — iPhone 15 Pro, 16, 16e, 17 | 4.72 GB | 3.18 GB |
| 12 GB — iPhone 17 Pro, Air | 7.09 GB | 5.07 GB |
| 16 GB | 9.45 GB | 6.96 GB |
The practical consequences:
- A 4 GB iPhone 13 tops out around 1.3 GB of weights. That is a 1B model at Q4, and nothing larger.
- A 6 GB iPhone 14 Pro tops out at 2.23 GB. Llama 3.2 3B (2.0 GB) fits. Gemma 3 4B (2.5 GB) does not — and this is exactly the phone the restart happened on.
- You need 12 GB before a 4 GB-class download like Gemma 3n E4B is realistic.
Notice how little of the spec-sheet number survives. On an 8 GB phone you get 3.18 GB of weights — under 40% of the RAM printed in the reviews.
"Can it ever?" and "can it now?" are different questions
One subtlety worth copying if you are building this yourself. There are two readings, and conflating them produces a genuinely misleading error message.
os_proc_available_memory() reports remaining headroom, so it shrinks as your app allocates. Ask it twice and you get two answers. Adding the current footprint back turns it into a stable ceiling — the number that decides whether a device could ever run a model. That is what a download gate needs.
The live headroom is a different question: can it run right now, alongside everything else the phone is doing?
So the verdict has three states, not two:
- Fits. Load it.
- Too large for this device. Permanent. The fix is a smaller model, and the UI should say so — not "try again later", which sends the user into a retry loop that can never work.
- Not enough free memory right now. Temporary. Closing other apps really does help.
Getting that distinction right is the difference between a user picking a model that works and a user leaving a one-star review about an app that "never loads".
What we would do differently
Two things, honestly.
The 600 MB overhead figure is a constant, not a measurement. It should scale with the context length you actually configure — the KV cache is the dominant term, and it grows linearly with context. A 32k-context session and a 4k-context session do not cost the same, and we currently charge both the same generous flat rate.
And the 0.55 physical share is a single number applied to every device. There is decent reason to think a 12 GB phone can safely give up a larger fraction than a 4 GB phone, because the fixed cost of the rest of the system does not scale with RAM. We have not measured that carefully enough to move it yet.
Both make us conservative. Given the alternative is restarting someone's phone, that is the side to be wrong on.
The short version
- File size is not memory cost. Add ~600 MB.
- You get roughly 44% of physical RAM for weights, not 100%.
- The entitlement raises the ceiling; it does not create memory.
- Separate "could this device ever" from "can it right now", or your error messages will lie to people.