Keep an Ollama model loaded in memory
Ollama unloads your model after 5 minutes idle, so the next request pays the full load time again. Set keep_alive so it sticks, even after a reboot.
Why does Ollama unload the model after a few minutes?
Ollama keeps a model loaded in memory for five minutes after the last request, then frees it. The next request has to read the weights from disk and map them into RAM or VRAM again, so it stalls before the first token arrives. That is why a chat UI or a coding agent feels fast, goes quiet for a while, then feels slow again on the next message. Nothing is broken. The idle timer expired.
The timer is called keep_alive. It is per model, and it restarts every time a request finishes. A model that is currently answering a request is never unloaded, because the server only expires a model with no active request. As of August 2026 the default is five minutes, and it applies to every model this server loads.
There are two places to set keep_alive: on the individual request, or as the server default. A systemd drop-in is what makes the server default survive a restart. This guide assumes Ollama is already running as a service. If it is not, start with installing Ollama on a VPS and come back.
Which models are resident right now, and when do they expire?
ollama psNAME ID SIZE PROCESSOR CONTEXT UNTIL
qwen3:8b 500a1f067a9f 6.6 GB 100% GPU 4096 4 minutes from nowEmpty output means nothing is loaded, so the next request pays a full load. PROCESSOR tells you where the weights went. 100% GPU and 100% CPU are the clear cases. A split such as 25%/75% CPU/GPU means the model did not fit in VRAM, so part of it runs on the processor and generation is slower.
UNTIL is the countdown, and it prints a relative time such as 4 minutes from now. It prints Forever when the model was loaded with a negative keep_alive. It prints Stopping... during the short window while the server is unloading.
The column set has changed between releases, so read the header instead of counting fields in a script. For anything automated, ask the API:
curl -s http://localhost:11434/api/psEach entry carries expires_at, an absolute timestamp such as 2026-08-09T14:38:31.83753Z, and size_vram, the part of that model sitting in GPU memory. A size_vram of 0 means the model is running on the CPU.
What the reload actually costs
Do not guess at it. Ollama reports the load time in every response, as load_duration, in nanoseconds.
sudo apt install -y jq
ollama stop qwen3:8b
curl -s http://localhost:11434/api/generate -d '{"model": "qwen3:8b", "prompt": "hi", "stream": false}' | jq '{load_duration, total_duration}'
curl -s http://localhost:11434/api/generate -d '{"model": "qwen3:8b", "prompt": "hi", "stream": false}' | jq '{load_duration, total_duration}'The first call loads the model, so its load_duration is large. Divide by 1000000000 to read it as seconds. The second call runs while the model is resident and reports a much smaller number. The gap between those two figures is what every user pays once the timer has expired, and it is the whole reason to change keep_alive. For the generation speed either side of that pause, see how to measure tokens per second on your own box.
Keep an Ollama model loaded in memory on one request
Send keep_alive with the request. It applies to that model from the moment the request finishes.
curl -s http://localhost:11434/api/chat -d '{
"model": "qwen3:8b",
"messages": [{"role": "user", "content": "hello"}],
"keep_alive": "30m"
}'Four value forms are accepted:
- a duration string:
"30m","24h","90s" - a plain number, read as seconds:
3600 - a negative value,
-1or"-1m", meaning no idle timeout at all 0, meaning unload as soon as this request finishes
A value on the request overrides the server default, in both directions. That matters more than it sounds: a client sending its own keep_alive wins over anything you configured on the server.
You can also load a model without generating anything. Send only the model name. The server loads it and returns an empty response with "done": true.
curl -s http://localhost:11434/api/generate -d '{"model": "qwen3:8b", "keep_alive": "30m"}'That is the command to run after a reboot, or after pulling a new model, so the first real user request does not pay for the load. The CLI does the same job with a flag:
ollama run --keepalive 30m qwen3:8b "hello"Keep it loaded by default with OLLAMA_KEEP_ALIVE
The server reads OLLAMA_KEEP_ALIVE at startup and uses it for every model that does not carry its own value. It takes the same forms as the request field, so 30m, 3600 and -1 all work.
The catch is whose environment it has to be in. Running export OLLAMA_KEEP_ALIVE=30m in your SSH session does nothing, because the packaged install runs the server as a systemd service under its own user with its own environment. Your login shell and that service never meet. This is the most common reason the setting looks ignored.
Make it survive a restart with a systemd drop-in
sudo systemctl edit ollama.serviceThe editor opens with two comment markers. Type between them: systemd discards anything you write below the second marker.
[Service]
Environment="OLLAMA_KEEP_ALIVE=30m"Saving writes /etc/systemd/system/ollama.service.d/override.conf. That is a drop-in rather than an edit of the shipped unit, so an Ollama package upgrade that replaces ollama.service leaves your setting alone. If drop-ins and unit files are new to you, the systemd service and timer guide covers the mechanics.
sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=EnvironmentThe last command prints the environment the service will really run with. If OLLAMA_KEEP_ALIVE=30m is missing from that line, the drop-in did not take, and the cause is almost always a missing [Service] header or lines typed below the marker. The restart itself drops every loaded model, so the next request is a cold load. Warm it up with the preload call above.
What keeping a model resident costs you
The SIZE column in ollama ps is memory held for the whole idle window, not only during a request. An 8B model at 4-bit quantisation sits around 5 to 6 GB. Set keep_alive to -1 and you have decided that the model outranks everything else on the box, permanently. On a small VPS that is a direct trade against your database, your web app and your build jobs.
Watch the real numbers rather than trusting an estimate. Run this while a model is loaded, then again after ollama stop:
free -hThe available column is the memory the kernel could still hand to a new process. On an NVIDIA GPU box, nvidia-smi shows the same story in VRAM. If the box runs out, the kernel kills a process to recover:
sudo dmesg -T | grep -i "out of memory"A line naming ollama means the model server was the victim. A line naming your database means the model won and something you cared about lost. Both outcomes come from the same decision: a long keep-alive window on a box with no headroom.
Two costs here are easy to miss. A longer context length reserves a larger KV cache (key value cache, the per token attention state the model keeps while generating), and that cache is part of the resident size. OLLAMA_NUM_PARALLEL above 1 reserves that cache once per parallel slot. If you plan to serve several people from one model, size the memory for the slots, not for the weights alone.
A reasonable default: one model on a box with headroom can use -1. A shared box should use a window that covers the gaps between your requests, such as 30m, so the memory comes back when you stop working.
Unload a model immediately
ollama stop qwen3:8bIt returns with no output, and the model disappears from ollama ps. A name that is not loaded gives couldn't find model "qwen3:8b" to stop. The API form is a request with no prompt and keep_alive set to 0:
curl -s http://localhost:11434/api/chat -d '{"model": "qwen3:8b", "messages": [], "keep_alive": 0}'The reply carries "done_reason": "unload". Use this instead of restarting the service. systemctl restart ollama frees the memory too, but it drops every other loaded model and kills any request that was running.
Running more than one model on one server
OLLAMA_MAX_LOADED_MODELS caps how many models stay loaded at once, and as of August 2026 the default is three per GPU, or three on a CPU-only box. The cap counts models, while memory is the real limit, so a second large model can be refused room long before you reach three.
When a new model is requested and there is not enough memory for it, the scheduler unloads one of the resident models to make space. It prefers one with no active request, and it will evict a model whose timer has not expired, including a model loaded with -1. So a negative keep_alive means no idle timeout. It does not pin the weights against another model's request.
That decision is logged at debug level. Add a second Environment="OLLAMA_DEBUG=1" line to the same drop-in, restart, and watch:
sudo journalctl -u ollama -fA line about unloading a runner to make room, sitting next to the request that triggered it, tells you these two models do not fit together on this machine. The fix is fewer models on this box, or a long window for the one that must answer fast and 0 for the one you call rarely.
Guidance that outlives the next release
Ollama ships often and its defaults move, so check the build in front of you rather than memorising numbers:
ollama --version
ollama serve --helpollama serve --help lists the environment variables that build actually reads, OLLAMA_KEEP_ALIVE among them. Two rules have held across releases and are safe to build on. A value on the request beats the server default. And ollama ps is the truth about what is loaded, whatever a config file says it should be.
If an editor or an agent drives your server, check what that client sends before you blame the server. Pointing a coding agent at your own Ollama server covers where those request settings live.
FAQ
Why does Ollama unload my model after 5 minutes?
Five minutes is the default keep_alive, the idle timer Ollama starts when a request finishes. When it expires the server frees the weights, so the next request reloads them from disk, and that reload is the pause you feel. Raise it for one request by sending "keep_alive": "30m" in the JSON body, or for the whole server with the OLLAMA_KEEP_ALIVE environment variable.
How do I keep an Ollama model loaded in memory permanently?
Use a negative value: "keep_alive": -1 on the request, or OLLAMA_KEEP_ALIVE=-1 for the server. ollama ps then shows Forever in the UNTIL column. This removes the idle timer and nothing else. If another model is requested and memory is short, the scheduler still unloads this one to make room.
Why is OLLAMA_KEEP_ALIVE being ignored?
Check where you set it. Run systemctl show ollama --property=Environment, and if the variable is not in that output the server never saw it, because a variable exported in your shell does not reach a systemd service. Set it with sudo systemctl edit ollama.service, then run sudo systemctl daemon-reload and sudo systemctl restart ollama. The other cause is a client that sends its own keep_alive on the request, which overrides the server default.
How do I free the memory without restarting Ollama?
ollama stop qwen3:8b unloads that one model right away and leaves the server and every other loaded model running. Over the API, send a request with no prompt and "keep_alive": 0, and the reply comes back with "done_reason": "unload". Confirm with ollama ps, which should no longer list the model.