{"id":1093,"date":"2026-08-31T09:30:00","date_gmt":"2026-08-30T23:30:00","guid":{"rendered":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/"},"modified":"2026-11-03T20:27:52","modified_gmt":"2026-11-03T09:27:52","slug":"local-ai-server-freezes-unified-memory","status":"publish","type":"post","link":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/","title":{"rendered":"Why Does a Local AI Server Freeze? Sizing Memory for LLMs (Part 3 of 11)"},"content":{"rendered":"\n<p class=\"has-pale-cyan-blue-background-color has-background wp-block-paragraph\">In its first month of testing, our lab AI server froze five times with no kernel error and no warning. This is what caused it, the memory budget we settled on, and the steps to size one for your own server.<\/p>\n\n\n\n<div class=\"wp-block-group has-background\" style=\"background-color:#f4f6f8;padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<p class=\"wp-block-paragraph\"><strong>Where this fits \u00b7 Running Local AI in Production \u00b7 Part 3 of 11<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\" style=\"font-size:17px\">You are reading Part 3 of 11 in a series where we built a private AI server in our lab and ran realistic test workloads on it for seven weeks. Each part stands on its own. The previous part covered one LLM gateway as the only way to reach a model: keys, budgets and tracing; this one covers five hard freezes and the memory budget that ended them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" style=\"font-size:16px\"><a href=\"https:\/\/catharsis.net.au\/blog\/llm-gateway-one-door-for-every-model\/\" target=\"_blank\" rel=\"noreferrer noopener\">\u2190 Part 2: How Do You Control Access to Local AI Models? Use a Gateway<\/a> &nbsp;\u00b7&nbsp; <a href=\"https:\/\/catharsis.net.au\/blog\/running-local-ai-in-production-series-guide\/\" target=\"_blank\" rel=\"noreferrer noopener\">Series guide<\/a> &nbsp;\u00b7&nbsp; <a href=\"https:\/\/catharsis.net.au\/blog\/local-llm-context-budget\/\" target=\"_blank\" rel=\"noreferrer noopener\">Part 4: What Happens When a Prompt Is Too Big for a Local LLM? \u2192<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\" style=\"font-size:16px\">Just want it working? Follow the <a href=\"https:\/\/catharsis.net.au\/blog\/local-ai-litellm-setup-guide\/\" target=\"_blank\" rel=\"noreferrer noopener\">step-by-step setup guide<\/a>: local AI with Ollama and LiteLLM, from a bare server to a secure gateway.<\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>See all 11 parts of the series<\/summary>\n\n<ol class=\"wp-block-list\">\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/why-run-ai-on-your-own-hardware\/\" target=\"_blank\" rel=\"noreferrer noopener\">Local AI or Cloud AI? Why We Built a Private AI Server<\/a>: why we built the lab on our own hardware, what ran on it and what that choice cost<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/llm-gateway-one-door-for-every-model\/\" target=\"_blank\" rel=\"noreferrer noopener\">How Do You Control Access to Local AI Models? Use a Gateway<\/a>: one LLM gateway as the only way to reach a model: keys, budgets and tracing<\/li>\n\n\n<li><strong>Why Does a Local AI Server Freeze? Sizing Memory for LLMs<\/strong> (you are here): five hard freezes and the memory budget that ended them<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/local-llm-context-budget\/\" target=\"_blank\" rel=\"noreferrer noopener\">What Happens When a Prompt Is Too Big for a Local LLM?<\/a>: fitting every prompt to a local model&#8217;s context window<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/smart-routing-single-gpu-local-llm\/\" target=\"_blank\" rel=\"noreferrer noopener\">How Do You Run Several AI Models on One GPU Without Slowdowns?<\/a>: routing requests across models on a single GPU without constant model swaps<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/gitops-for-a-gpu-ai-server\/\" target=\"_blank\" rel=\"noreferrer noopener\">How Do You Keep an AI Server Stable? GitOps for Local AI<\/a>: running the server from a Git repository: deploys, drift, pinning and safe AI agents<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/observability-for-local-ai\/\" target=\"_blank\" rel=\"noreferrer noopener\">What Is Your Local AI Server Actually Doing? Observability Basics<\/a>: making the server observable: traces, dashboards, usage and heat<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/multi-agent-stock-analysis-local-llm\/\" target=\"_blank\" rel=\"noreferrer noopener\">Can Local AI Agents Analyse Stocks? How We Tested and Scored Them<\/a>: a multi-agent stock-analysis experiment and how we scored the agents<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/\" target=\"_blank\" rel=\"noreferrer noopener\">Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost<\/a>: a Telegram AI agent on local models, and why its fixed prompt became the budget<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/local-ai-business-workflows\/\" target=\"_blank\" rel=\"noreferrer noopener\">Can AI Automate Business Workflows Without Sending Data Out?<\/a>: document, email and knowledge-base workflows that keep data on the server<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/private-ai-lab-lessons-and-whats-next\/\" target=\"_blank\" rel=\"noreferrer noopener\">Is Private AI Worth It? Lessons From Seven Weeks in Our Lab<\/a>: the lessons from seven weeks, the honest limits and what comes next<\/li>\n\n<\/ol>\n\n<\/details>\n\n<\/div><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" style=\"font-size:16px\"><em>This series documents a private AI server we built and stress-tested in our lab. Workloads and data are synthetic or generalised; the problems, measurements and fixes are real.<\/em><\/p>\n\n\n\n<div class=\"wp-block-group has-background\" style=\"background-color:#f4f6f8;padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<h3 class=\"wp-block-heading\">TL;DR<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>A local AI server on shared memory freezes when the memory reserved for context outgrows what the machine has, not because of the model weights alone. In our lab, four parallel slots at a 64k context took one model to about 33 GB, roughly 19 GB of weights plus roughly 14 GB of KV cache.<\/li>\n\n\n<li>The symptom was brutal. In about a month of testing the server hard-froze five times with no error in any log, every workload stopped, and only a power-cycle brought it back.<\/li>\n\n\n<li>We contained one model we could never fix, pinned our software, added a watchdog and an outside heartbeat, and wrote a memory budget from measurements. With one slot and a 32k context, that model now measures 20.3 GB.<\/li>\n\n\n<li>The lesson: on a shared-memory machine, size the reservation, and measure every number instead of calculating it.<\/li>\n\n<\/ul>\n\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group has-background\" style=\"background-color:#f4f6f8;padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Jargon buster: 15 terms used in this post, explained in plain English<\/summary>\n\n<ul class=\"wp-block-list\">\n\n<li><strong>Context window<\/strong>: The maximum number of tokens a model can consider at once, covering both the prompt and its answer.<\/li>\n\n\n<li><strong>KV cache<\/strong>: Working memory a model keeps while it reads a prompt. It grows with the length of the context, so long contexts need a lot of memory.<\/li>\n\n\n<li><strong>Unified memory<\/strong>: A design where the CPU and GPU share one pool of memory instead of the GPU having its own. Flexible, but both compete for the same space.<\/li>\n\n\n<li><strong>Slot (parallel requests)<\/strong>: One request a model server can work on at the same time. More slots serve more people at once but reserve more memory.<\/li>\n\n\n<li><strong>Model swap<\/strong>: Unloading one model from memory and loading another. It takes seconds to minutes, so frequent swapping makes everything slow.<\/li>\n\n\n<li><strong>Ollama<\/strong>: Free, open-source software that downloads and runs AI models on your own machine and answers requests over a local API.<\/li>\n\n\n<li><strong>LLM gateway<\/strong>: A single service every AI request must pass through, so access, budgets and logging are controlled in one place.<\/li>\n\n\n<li><strong>Docker \/ container<\/strong>: A way of packaging an application with everything it needs so it runs the same anywhere; each packaged application runs in its own container.<\/li>\n\n\n<li><strong>Docker Compose<\/strong>: A tool that defines and starts a set of related containers from one configuration file.<\/li>\n\n\n<li><strong>Pinning<\/strong>: Locking software to an exact version so it can&#8217;t change unexpectedly during an update.<\/li>\n\n\n<li><strong>Loopback<\/strong>: A network address that only the server itself can reach, so a service listening there isn&#8217;t exposed to the network.<\/li>\n\n\n<li><strong>Sandbox<\/strong>: An isolated environment that limits what a program can see or change, so a misbehaving program can&#8217;t affect the rest of the system.<\/li>\n\n\n<li><strong>Watchdog<\/strong>: A timer that restarts a machine if the system stops checking in, used to recover from freezes automatically.<\/li>\n\n\n<li><strong>Heartbeat<\/strong>: A regular &#8216;I&#8217;m alive&#8217; signal sent to an outside monitor; if it stops, the monitor raises an alarm.<\/li>\n\n\n<li><strong>systemd<\/strong>: The service manager on most Linux systems: it starts, stops and supervises background services.<\/li>\n\n<\/ul>\n\n<\/details>\n\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group has-background\" style=\"background-color:#f4f6f8;padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<h3 class=\"wp-block-heading\">In this post<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><a href=\"#the-problem-why-did-the-server-keep-freezing\">The problem: why did the server keep freezing?<\/a><\/li>\n\n\n<li><a href=\"#what-we-were-aiming-for\">What we were aiming for<\/a><\/li>\n\n\n<li><a href=\"#how-we-approached-it\">How we approached it<\/a><\/li>\n\n\n<li><a href=\"#what-we-built\">What we built<\/a><\/li>\n\n\n<li><a href=\"#challenges-we-hit\">Challenges we hit<\/a><\/li>\n\n\n<li><a href=\"#the-result\">The result<\/a><\/li>\n\n\n<li><a href=\"#do-it-yourself-size-a-memory-budget-for-ollama\">Do it yourself: size a memory budget for Ollama<\/a><\/li>\n\n\n<li><a href=\"#key-takeaways\">Key takeaways<\/a><\/li>\n\n<\/ul>\n\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-problem-why-did-the-server-keep-freezing\">The problem: why did the server keep freezing?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The lab server is an NVIDIA DGX Spark, a compact desktop AI system built on the GB10 Grace Blackwell Superchip with 128 GB of <strong>unified memory<\/strong>, one pool shared by the CPU and GPU, roughly 120 GB of it usable. That lets a desk-sized machine hold a 30-billion-parameter model, and makes everything run short at once when the models take too much. Over seven weeks it carried test workflows, a Telegram agent, the LLM gateway our test clients used (<a href=\"https:\/\/catharsis.net.au\/blog\/llm-gateway-one-door-for-every-model\/\" target=\"_blank\" rel=\"noreferrer noopener\">Part 2<\/a>) and a multi-agent stock-analysis service on public market data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In its first month the server froze five times. Each time ping, SSH and the gateway all went down together. After a restart, the previous boot&#8217;s journal just stopped mid-operation, with no kernel panic, no NVIDIA driver Xid error and no out-of-memory kill. Holding the power button was the only way back.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For a business this is the worst kind of failure. One machine runs everything, so one freeze stops every workflow at once, and with no error message there is nothing to fix.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-we-were-aiming-for\">What we were aiming for<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>No more freezes caused by how memory was set up, with a written budget everyone could check.<\/li>\n\n\n<li>Any freeze that did happen should recover by itself and be noticed straight away, even if the server couldn&#8217;t report it.<\/li>\n\n\n<li>A model we suspected but couldn&#8217;t diagnose should be testable without putting everything else at risk.<\/li>\n\n\n<li>Every number in the budget should come from a measurement, not a guess.<\/li>\n\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"how-we-approached-it\">How we approached it<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The options pulled in different directions. We could give every model a bigger context so prompts stopped being cut off, or cap it so memory stayed predictable. We could keep several parallel slots so callers rarely waited, or use one slot and accept a queue. We could try to root-cause the suspect model, or contain it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We chose predictability every time. Contexts are capped, each model gets one slot, and the suspect model runs in its own sandbox. We accepted that some callers would wait and that long jobs would have to fit a smaller window. Because nothing on the server could log its own death, we also decided that detection had to live somewhere else.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-we-built\">What we built<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The challenges below explain how we found each cause; this is the setup we ended with.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Pinned software and one way in<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ollama, the server that runs the models, is pinned to an exact version, and changes go through the repository and a deploy script (Part 6), never a web UI. Ollama listens only on the server itself (loopback). Every client goes through the gateway, which requires authentication. Keep-alive went from 30 seconds to 5 minutes, so models swap in and out less often.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A sandbox for the risky model<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A second, loopback-only Ollama instance runs the suspect model alone, with conservative settings: flash attention off, an unquantised f16 <strong>KV cache<\/strong> (the working memory a model keeps for every token of its context), one slot, a 16k context and a 2-minute keep-alive. Its container has a 48 GB memory limit, but on unified memory that only limits the process&#8217;s system memory, so the one-slot, 16k setting is the real guard for GPU allocations. Only gateway keys that name the model can call it, at up to 20 requests a minute. A 20-minute phased soak test, from a cold load through long prompts, tool calls and concurrent requests to an idle unload, finished with 53 requests, no errors, no GPU alarms and no kernel messages.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A watchdog and an outside heartbeat<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A hardware watchdog (systemd&#8217;s <code>RuntimeWatchdogSec=60s<\/code>) has the init process keep resetting a hardware timer. If the kernel hangs, the board reboots itself after 60 seconds, so with boot time and an automatic GPU-access restore a freeze becomes a three to four minute outage. Because a watchdog can miss a stall, a separate device also checks the server and raises an alert when it stops answering.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A written memory budget<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Capacity is a chain of numbers, so changing one means recalculating the rest.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\">\n<thead>\n<tr>\n<th>Setting<\/th>\n<th>Value<\/th>\n<th>Why<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Model tag <code>num_ctx<\/code><\/td>\n<td>32,768 (16,384 for one small model and the sandbox)<\/td>\n<td>The original tags carried 65,536, which we had set, and froze the server. The <code>-32k<\/code> tags share the same weight files.<\/td>\n<\/tr>\n<tr>\n<td><code>OLLAMA_NUM_PARALLEL<\/code><\/td>\n<td>1<\/td>\n<td>Four slots at 64k took one model to about 33 GB.<\/td>\n<\/tr>\n<tr>\n<td>Per-request capacity<\/td>\n<td>32,768 tokens, prompt and answer<\/td>\n<td>Each slot reserves the full <code>num_ctx<\/code>, so total KV is <code>num_ctx \u00d7 slots<\/code><\/td>\n<\/tr>\n<tr>\n<td>Gateway limit<\/td>\n<td>26,000<\/td>\n<td>Leaves at least 6,768 tokens for the reply (<a href=\"https:\/\/catharsis.net.au\/blog\/local-llm-context-budget\/\" target=\"_blank\" rel=\"noreferrer noopener\">Part 4<\/a>)<\/td>\n<\/tr>\n<tr>\n<td>Models kept loaded<\/td>\n<td>Two only, measured at 37.8 GB (qwen3-coder 20.3 + gemma4 17.5)<\/td>\n<td>Everything else is &quot;cold&quot;: callable by name, never chosen automatically<\/td>\n<\/tr>\n<tr>\n<td>Always free<\/td>\n<td>At least 40 GB<\/td>\n<td>OCR (about 7 GB on demand), containers (about 15 GB) and prompt processing<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Detection that gets read<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The per-minute sampler now warns on low free memory, high GPU memory, growing swap or a prompt near the largest reserved context. Severe levels send a Telegram alert, as does any prompt bigger than the gateway would ever admit, a second line of defence in case something bypasses the gateway. The dashboard shows memory pressure and each model&#8217;s reserved context.<\/p>\n\n\n\n<div class=\"wp-block-group has-pale-cyan-blue-background-color has-background\" style=\"padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px;margin-top:32px;margin-bottom:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<p class=\"wp-block-paragraph\"><strong>Thinking about private AI for your organisation?<\/strong> We design, build and secure on-premises AI platforms for Australian organisations, with the guardrails this series describes built in from the start.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/catharsis.net.au\/local-ai\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=local-ai-series&amp;utm_content=part-03-mid\" target=\"_blank\" rel=\"noreferrer noopener\">Explore Private AI<\/a><\/div>\n\n<\/div>\n\n<\/div><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"challenges-we-hit\">Challenges we hit<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">A silent upgrade and a model that hung while loading<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The Ollama container had been recreated from a container-management web UI with &quot;recreate with pull&quot; on the <code>:latest<\/code> tag, which quietly upgraded Ollama and pruned &quot;unused&quot; images, including the one OCR needed. Three days later came the first freeze. Five days before that, because the Telegram agent&#8217;s prompts were being cut off silently at 16k, we had raised the two main models&#8217; context to 65,536 tokens in each model&#8217;s own settings file, the Modelfile.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The sampler&#8217;s last lines before freezes one, two and three matched. <code>nemotron-3-nano:30b<\/code> had loaded within the previous 60 seconds, twice as a swap from another model, with more than 80 GB available and swap near zero. That model loaded about 30 times in the period and hung 3 times, apparently at random, always while loading. It is a hybrid Mamba and mixture-of-experts model with 31.6 B parameters, 3 B active per token, taking 24 GB at Q4_K_M <strong>quantisation<\/strong> (weights stored at about 4 bits each), and it was running with an 8-bit cache, flash attention and four slots. Hybrid state-space models use code paths plain transformers never touch. The server died before it could log anything, so we never found the root cause. That is why it got the sandbox.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A crash loop and a side door<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The fourth freeze came the next morning, with nemotron not loaded. The tracing service, Langfuse, had restarted 72 times that boot, the last time 2 seconds before the freeze, because a half-finished deployment crashed whenever the gateway sent it traces. Removing the trace callbacks stopped the loop. Three minutes after that reboot, a test client&#8217;s IDE plugin loaded nemotron again by calling Ollama directly, past the gateway. We renamed the model&#8217;s tags so the old names no longer resolved, and that is why Ollama now listens on loopback only.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The freeze we fully explained<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Five days after the sandbox went in, the server froze in the early hours, and the newly added watchdog didn&#8217;t recover it. An overnight stock analysis was running, and its debate transcript grows with every call, so the prompts climbed from 50k to 52k, 54k, 57k, 59k, 61k, 63k and finally 65,007 tokens. The model serving it, <code>qwen3-coder<\/code>, still had <code>num_ctx 65536<\/code> in its Modelfile. <code>num_ctx<\/code> is Ollama&#8217;s context window, the most tokens one request can hold, and the per-model value overrode the server-wide <code>OLLAMA_CONTEXT_LENGTH=16384<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With <code>OLLAMA_NUM_PARALLEL=4<\/code>, Ollama gives every slot the full <code>num_ctx<\/code> and reserves KV cache for all of them. Four slots at 64k took the model to about 33 GB, roughly 19 GB of weights plus roughly 14 GB of KV cache, though only one client was using one slot. <code>OLLAMA_MAX_LOADED_MODELS=2<\/code> let a second model stay loaded beside it. The last readings showed 46.7 GB on the GPU, 65.5 GB of RAM in use and 3.2 GB of swap. The next 65k prompt started processing, and 28 seconds later the server stopped.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>KV reserved \u2248 slots \u00d7 context length \u00d7 bytes of cache per token\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For qwen3-coder (48 layers, 4 KV heads of 128 dimensions) an 8-bit cache costs roughly 50 KB per token. Four slots of 65,536 tokens is 262,144 tokens, or about 14 GB, before prompt processing allocates temporary memory on top.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nothing caught it. The sampler&#8217;s log went unread and hung with the host. The gateway passed prompts of any size, because by default LiteLLM treats <code>max_input_tokens<\/code> as model metadata and enforces it only if you turn on its pre-call checks. Why the watchdog stayed quiet we never proved: it only reboots when the init process stops resetting the timer, so something was evidently still doing that while everything else starved. That is why the heartbeat lives on a separate device.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A reload that takes the GPU away<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">After the second freeze the GPU was unusable until a second reboot. On this server <code>systemctl daemon-reload<\/code> (and <code>daemon-reexec<\/code>, <code>edit<\/code>, <code>enable<\/code> or <code>disable<\/code>) rebuilds the container cgroups and drops their permission to use the GPU. Ollama starts a new runner for every model load, so the model lands on the CPU and <code>nvidia-smi<\/code> inside the container fails with <code>Failed to initialize NVML<\/code>. It is a known issue in the NVIDIA Container Toolkit, documented with workarounds such as its CDI mode (the Container Device Interface). We now prefer cron to systemd timers, run a restore script every minute that restarts only broken GPU containers, reload systemd only when a unit file changed, and verify the end state after deploys.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Power-offs that were most likely heat<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Two days after the fifth freeze, and again the next day, the server turned <strong>off<\/strong>, with about 100 GB of memory free. The one-minute readings beforehand were 88.0 \u00b0C and 87.7 \u00b0C, below the critical trip point, but an average hides the peak. Measured after the restart, one ordinary stock analysis took the chip from 48 \u00b0C to 95 \u00b0C in four minutes. Better ventilation brought idle from about 50 \u00b0C to about 37 \u00b0C, and a recorder now writes a <code>HOT<\/code> line to disk at 85 \u00b0C or above, sampling every 2 seconds.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Calculated numbers that were wrong<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In one week, several calculated budgets failed. An embedding model configured for 4,096 tokens was trained on 2,048, and Ollama silently dropped the rest. Doubling the context cost 3.22 GB on <code>qwen3:14b<\/code> but 0.80 GB on <code>gemma3:12b<\/code>, and the textbook KV formula was about 19% optimistic, the direction that freezes a server.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-result\">The result<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">One model&#8217;s footprint went from about 33 GB at four 64k slots to 22.3 GB at an interim two slots, and 20.3 GB at one slot and 32k. The resident pair measures 37.8 GB, leaving at least 40 GB free. That step of about 2 GB per 32k slot matches the arithmetic. A week of measurement (1,342 requests, 52 overlaps, never more than 4 at once) showed the extra slots were rarely used anyway.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The costs are real. A second caller now waits in Ollama&#8217;s queue, a median of 18 seconds and 58 at the 90th percentile. Long jobs have to summarise or retrieve less to fit 32k, and only two models stay loaded. The nemotron freezes were never root-caused, and the 40 GB floor is a policy rather than a proven predictor, since three recorded freezes happened with more than 80 GB available.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"do-it-yourself-size-a-memory-budget-for-ollama\">Do it yourself: size a memory budget for Ollama<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">What you need: a Linux server with a GPU or unified memory, Docker with Compose, and, if you use NVIDIA GPUs, the NVIDIA Container Toolkit. Allow about two hours.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li>\n<p><strong>Pin Ollama, give it the GPU and keep it private.<\/strong> Refer to the image by digest and publish the port on loopback only. The <code>devices<\/code> block below is the NVIDIA form; other vendors differ.<\/p>\n<pre><code class=\"language-yaml\">services:\n  ollama:\n    image: ollama\/ollama@sha256:&lt;digest&gt;\n    restart: unless-stopped\n    ports:\n      - &quot;127.0.0.1:11434:11434&quot;\n    volumes:\n      - ollama:\/root\/.ollama\n    deploy:\n      resources:\n        reservations:\n          devices:\n            - driver: nvidia\n              count: all\n              capabilities: [gpu]\nvolumes:\n  ollama:\n<\/code><\/pre>\n<p>Check: <code>docker compose config --images<\/code> prints <code>ollama\/ollama@sha256:\u2026<\/code>, <code>docker compose exec ollama nvidia-smi -L<\/code> lists the GPU, and <code>curl -m 5 http:\/\/&lt;server&gt;:11434<\/code> from another machine is refused.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Set slots, context and keep-alive explicitly<\/strong> under the same service.<\/p>\n<pre><code class=\"language-yaml\">    environment:\n      OLLAMA_NUM_PARALLEL: &quot;1&quot;\n      OLLAMA_CONTEXT_LENGTH: &quot;32768&quot;\n      OLLAMA_MAX_LOADED_MODELS: &quot;2&quot;\n      OLLAMA_KEEP_ALIVE: &quot;5m&quot;\n<\/code><\/pre>\n<p>Check: <code>docker compose exec ollama env | grep OLLAMA<\/code> lists all four.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Find hidden overrides.<\/strong> Run <code>docker compose exec ollama ollama show &lt;model&gt; --modelfile | grep num_ctx<\/code> for every model. Any value there beats <code>OLLAMA_CONTEXT_LENGTH<\/code>, and a client can still override both per request with <code>options.num_ctx<\/code>. Check: every model either has no <code>num_ctx<\/code> line or shows the value you intend.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Build tags with the context fixed in them.<\/strong> Inside the container, write a two-line Modelfile, <code>FROM &lt;model&gt;<\/code> and <code>PARAMETER num_ctx 32768<\/code>, then run <code>ollama create &lt;model&gt;-32k -f Modelfile<\/code>. Check: <code>ollama show &lt;model&gt;-32k --parameters<\/code> shows <code>num_ctx 32768<\/code>.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Measure the real footprint.<\/strong> Send each model one short request, then run <code>curl -s localhost:11434\/api\/ps<\/code>. Check: note <code>size_vram<\/code> and <code>context_length<\/code> for every loaded model (older Ollama versions omit <code>context_length<\/code>; then read it from <code>ollama ps<\/code>). These are your budget, not the arithmetic.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Measure the KV cost.<\/strong> Load a 16k and a 32k tag of the same model in turn and compare <code>size_vram<\/code>. The difference is the cost of 16k more context per slot. If the formula disagrees, trust the measurement and add a margin.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Write the budget down.<\/strong> Resident models plus a fixed free floor must fit in memory. Check: with both models loaded and a long prompt processing, <code>free -g<\/code> stays above the floor.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Sandbox a risky model.<\/strong> Run a second Ollama service with its own model volume, <code>ports: [&quot;127.0.0.1:11435:11434&quot;]<\/code> and these settings. KV cache type is global per server, which is why it needs its own instance.<\/p>\n<pre><code class=\"language-yaml\">    environment:\n      OLLAMA_FLASH_ATTENTION: &quot;0&quot;\n      OLLAMA_KV_CACHE_TYPE: &quot;f16&quot;\n      OLLAMA_NUM_PARALLEL: &quot;1&quot;\n      OLLAMA_CONTEXT_LENGTH: &quot;16384&quot;\n      OLLAMA_KEEP_ALIVE: &quot;2m&quot;\n<\/code><\/pre>\n<p>Point only the gateway at it. Check: <code>\/api\/ps<\/code> on the main instance never lists that model.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Add a watchdog and an outside heartbeat.<\/strong> First run <code>sudo wdctl<\/code> to confirm the board has a hardware watchdog. If it does, create a drop-in so package upgrades don&#8217;t overwrite it, and apply it with a planned reboot rather than a re-exec, given the GPU issue above.<\/p>\n<pre><code class=\"language-bash\">sudo mkdir -p \/etc\/systemd\/system.conf.d\nprintf '[Manager]\\nRuntimeWatchdogSec=60s\\n' | sudo tee \/etc\/systemd\/system.conf.d\/watchdog.conf\n<\/code><\/pre>\n<p>On a separate device, schedule a check every minute that alerts after a few missed answers. Check: after the reboot <code>sudo wdctl<\/code> shows a 60-second timeout, and unplugging the server&#8217;s network raises the alert.<\/p>\n<\/li>\n\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"key-takeaways\">Key takeaways<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>On unified memory, reserved memory is what freezes the machine. Watch slots, context length and cache precision together.<\/li>\n\n\n<li>A model&#8217;s own settings file can override your server-wide limit, so build tags with the context fixed in them.<\/li>\n\n\n<li>Pin your images and never let a UI pull <code>:latest<\/code>.<\/li>\n\n\n<li>Contain what you can&#8217;t root-cause, and monitor from outside the box.<\/li>\n\n\n<li>Average temperatures hide peaks, and calculated budgets hide surprises. Measure before you trust a number.<\/li>\n\n<\/ul>\n\n\n\n<div class=\"wp-block-group has-light-green-cyan-background-color has-background\" style=\"padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px;margin-top:40px;margin-bottom:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<h2 class=\"wp-block-heading\">Planning private AI?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Catharsis Cyber Security is a Sydney cyber security company. We design, build and secure private AI platforms like the one in this lab, and help you decide where local or cloud AI fits.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/catharsis.net.au\/contact-us\/?type=contact&amp;service=local-ai&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=local-ai-series&amp;utm_content=part-03-contact\" target=\"_blank\" rel=\"noreferrer noopener\">Talk to us about AI<\/a><\/div>\n\n\n<div class=\"wp-block-button is-style-outline is-style-outline--1\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/catharsis.net.au\/secure-ai\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=local-ai-series&amp;utm_content=part-03-end\" target=\"_blank\" rel=\"noreferrer noopener\">Explore Secure AI<\/a><\/div>\n\n<\/div>\n\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group has-background\" style=\"background-color:#f4f6f8;padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<p class=\"wp-block-paragraph\"><strong>Keep reading the series<\/strong><\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n\n<div class=\"wp-block-button is-style-outline is-style-outline--2\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/catharsis.net.au\/blog\/llm-gateway-one-door-for-every-model\/\" target=\"_blank\" rel=\"noreferrer noopener\">\u2190 Part 2<\/a><\/div>\n\n\n<div class=\"wp-block-button is-style-outline is-style-outline--3\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/catharsis.net.au\/blog\/running-local-ai-in-production-series-guide\/\" target=\"_blank\" rel=\"noreferrer noopener\">Series guide<\/a><\/div>\n\n\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/catharsis.net.au\/blog\/local-llm-context-budget\/\" target=\"_blank\" rel=\"noreferrer noopener\">Next: Part 4 \u2192<\/a><\/div>\n\n<\/div>\n\n<\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>In its first month of testing, our lab AI server froze five times with no kernel error and no warning. This is what caused it, the memory budget we settled on, and the steps to size one for your own server.<\/p>\n","protected":false},"author":2,"featured_media":1092,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[69],"tags":[83,91,90,75,80,92,89,93,79],"class_list":["post-1093","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","tag-ai-lab","tag-context-window","tag-kv-cache","tag-local-llm","tag-ollama","tag-post-mortem","tag-private-ai-server","tag-reliability","tag-unified-memory"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Why Does a Local AI Server Freeze? Sizing Memory for LLMs (Part 3 of 11) - Catharsis | Blog<\/title>\n<meta name=\"description\" content=\"Why does a local AI server freeze? Five lab freezes traced to reserved KV cache, not model weights, and how to size a memory budget for LLMs.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Why Does a Local AI Server Freeze? Sizing Memory for LLMs (Part 3 of 11) - Catharsis | Blog\" \/>\n<meta property=\"og:description\" content=\"Why does a local AI server freeze? Five lab freezes traced to reserved KV cache, not model weights, and how to size a memory budget for LLMs.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/\" \/>\n<meta property=\"og:site_name\" content=\"Catharsis | Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-30T23:30:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-11-03T09:27:52+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2026\/11\/local-ai-series-part-03.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1280\" \/>\n\t<meta property=\"og:image:height\" content=\"720\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Sajal Jain\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Sajal Jain\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"18 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/\"},\"author\":{\"name\":\"Sajal Jain\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#\\\/schema\\\/person\\\/f0826efb92a7aaf8d46b24715990e099\"},\"headline\":\"Why Does a Local AI Server Freeze? Sizing Memory for LLMs (Part 3 of 11)\",\"datePublished\":\"2026-08-30T23:30:00+00:00\",\"dateModified\":\"2026-11-03T09:27:52+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/\"},\"wordCount\":3362,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/local-ai-series-part-03.jpg\",\"keywords\":[\"AI lab\",\"context window\",\"KV cache\",\"local LLM\",\"Ollama\",\"post-mortem\",\"private AI server\",\"reliability\",\"unified memory\"],\"articleSection\":[\"Artificial Intelligence\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/\",\"name\":\"Why Does a Local AI Server Freeze? Sizing Memory for LLMs (Part 3 of 11) - Catharsis | Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/local-ai-series-part-03.jpg\",\"datePublished\":\"2026-08-30T23:30:00+00:00\",\"dateModified\":\"2026-11-03T09:27:52+00:00\",\"description\":\"Why does a local AI server freeze? Five lab freezes traced to reserved KV cache, not model weights, and how to size a memory budget for LLMs.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/#primaryimage\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/local-ai-series-part-03.jpg\",\"contentUrl\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/local-ai-series-part-03.jpg\",\"width\":1280,\"height\":720,\"caption\":\"Memory modules on a circuit board\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/local-ai-server-freezes-unified-memory\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Why Does a Local AI Server Freeze? Sizing Memory for LLMs (Part 3 of 11)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/\",\"name\":\"Catharsis | Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#organization\",\"name\":\"Catharsis | Blog\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/01\\\/catharsis_au.jpg\",\"contentUrl\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/01\\\/catharsis_au.jpg\",\"width\":215,\"height\":60,\"caption\":\"Catharsis | Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#\\\/schema\\\/person\\\/f0826efb92a7aaf8d46b24715990e099\",\"name\":\"Sajal Jain\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/01\\\/Sajal-copy-96x96.jpg\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/01\\\/Sajal-copy-96x96.jpg\",\"contentUrl\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/01\\\/Sajal-copy-96x96.jpg\",\"caption\":\"Sajal Jain\"},\"description\":\"Cyber Security Enthusiast | OSCP | CEH | CHFI | CNSS | Master of IT Security &amp; Master of IT Management\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/author\\\/sajal-jain\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Why Does a Local AI Server Freeze? Sizing Memory for LLMs (Part 3 of 11) - Catharsis | Blog","description":"Why does a local AI server freeze? Five lab freezes traced to reserved KV cache, not model weights, and how to size a memory budget for LLMs.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/","og_locale":"en_US","og_type":"article","og_title":"Why Does a Local AI Server Freeze? Sizing Memory for LLMs (Part 3 of 11) - Catharsis | Blog","og_description":"Why does a local AI server freeze? Five lab freezes traced to reserved KV cache, not model weights, and how to size a memory budget for LLMs.","og_url":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/","og_site_name":"Catharsis | Blog","article_published_time":"2026-08-30T23:30:00+00:00","article_modified_time":"2026-11-03T09:27:52+00:00","og_image":[{"width":1280,"height":720,"url":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2026\/11\/local-ai-series-part-03.jpg","type":"image\/jpeg"}],"author":"Sajal Jain","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Sajal Jain","Est. reading time":"18 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/#article","isPartOf":{"@id":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/"},"author":{"name":"Sajal Jain","@id":"https:\/\/catharsis.net.au\/blog\/#\/schema\/person\/f0826efb92a7aaf8d46b24715990e099"},"headline":"Why Does a Local AI Server Freeze? Sizing Memory for LLMs (Part 3 of 11)","datePublished":"2026-08-30T23:30:00+00:00","dateModified":"2026-11-03T09:27:52+00:00","mainEntityOfPage":{"@id":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/"},"wordCount":3362,"commentCount":0,"publisher":{"@id":"https:\/\/catharsis.net.au\/blog\/#organization"},"image":{"@id":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/#primaryimage"},"thumbnailUrl":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2026\/11\/local-ai-series-part-03.jpg","keywords":["AI lab","context window","KV cache","local LLM","Ollama","post-mortem","private AI server","reliability","unified memory"],"articleSection":["Artificial Intelligence"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/","url":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/","name":"Why Does a Local AI Server Freeze? Sizing Memory for LLMs (Part 3 of 11) - Catharsis | Blog","isPartOf":{"@id":"https:\/\/catharsis.net.au\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/#primaryimage"},"image":{"@id":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/#primaryimage"},"thumbnailUrl":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2026\/11\/local-ai-series-part-03.jpg","datePublished":"2026-08-30T23:30:00+00:00","dateModified":"2026-11-03T09:27:52+00:00","description":"Why does a local AI server freeze? Five lab freezes traced to reserved KV cache, not model weights, and how to size a memory budget for LLMs.","breadcrumb":{"@id":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/#primaryimage","url":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2026\/11\/local-ai-series-part-03.jpg","contentUrl":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2026\/11\/local-ai-series-part-03.jpg","width":1280,"height":720,"caption":"Memory modules on a circuit board"},{"@type":"BreadcrumbList","@id":"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/catharsis.net.au\/blog\/"},{"@type":"ListItem","position":2,"name":"Why Does a Local AI Server Freeze? Sizing Memory for LLMs (Part 3 of 11)"}]},{"@type":"WebSite","@id":"https:\/\/catharsis.net.au\/blog\/#website","url":"https:\/\/catharsis.net.au\/blog\/","name":"Catharsis | Blog","description":"","publisher":{"@id":"https:\/\/catharsis.net.au\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/catharsis.net.au\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/catharsis.net.au\/blog\/#organization","name":"Catharsis | Blog","url":"https:\/\/catharsis.net.au\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/catharsis.net.au\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2019\/01\/catharsis_au.jpg","contentUrl":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2019\/01\/catharsis_au.jpg","width":215,"height":60,"caption":"Catharsis | Blog"},"image":{"@id":"https:\/\/catharsis.net.au\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/catharsis.net.au\/blog\/#\/schema\/person\/f0826efb92a7aaf8d46b24715990e099","name":"Sajal Jain","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2019\/01\/Sajal-copy-96x96.jpg","url":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2019\/01\/Sajal-copy-96x96.jpg","contentUrl":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2019\/01\/Sajal-copy-96x96.jpg","caption":"Sajal Jain"},"description":"Cyber Security Enthusiast | OSCP | CEH | CHFI | CNSS | Master of IT Security &amp; Master of IT Management","url":"https:\/\/catharsis.net.au\/blog\/author\/sajal-jain\/"}]}},"_links":{"self":[{"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/posts\/1093","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/comments?post=1093"}],"version-history":[{"count":5,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/posts\/1093\/revisions"}],"predecessor-version":[{"id":1217,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/posts\/1093\/revisions\/1217"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/media\/1092"}],"wp:attachment":[{"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/media?parent=1093"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/categories?post=1093"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/tags?post=1093"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}