<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Erik Bagdaer</title>
    <description>The latest articles on DEV Community by Erik Bagdaer (@macyou).</description>
    <link>https://dev.to/macyou</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4119466%2Fe08cfbda-cbd9-4620-8bf6-10d6af41c32c.png</url>
      <title>DEV Community: Erik Bagdaer</title>
      <link>https://dev.to/macyou</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/macyou"/>
    <language>en</language>
    <item>
      <title>Our watchdog restarted a healthy agent 24 times a day for months, and its own log said everything was fine</title>
      <dc:creator>Erik Bagdaer</dc:creator>
      <pubDate>Thu, 24 Sep 2026 10:47:48 +0000</pubDate>
      <link>https://dev.to/macyou/our-watchdog-restarted-a-healthy-agent-24-times-a-day-for-months-and-its-own-log-said-everything-2c2h</link>
      <guid>https://dev.to/macyou/our-watchdog-restarted-a-healthy-agent-24-times-a-day-for-months-and-its-own-log-said-everything-2c2h</guid>
      <description>&lt;p&gt;Disclosure first: I work on macyou.co, which rents Apple Silicon machines, so I have a stake in where people run things. Everything below is from our own install and from a harness anyone can run without a paid key, both open.&lt;/p&gt;

&lt;p&gt;We have an agent that has run unattended since May: a gateway, a model behind it, a vector memory, about seventy scheduled jobs. Ask me whether it works and I would have said yes without hesitating.&lt;/p&gt;

&lt;p&gt;Then I measured it, and found it restarts every hour, on the hour, and has been doing that for months.&lt;/p&gt;

&lt;h3&gt;
  
  
  The number, and why the first version of this number was wrong
&lt;/h3&gt;

&lt;p&gt;I started where everyone starts, with the log. The watchdog writes a line whenever it decides something, and counting those lines gave 2,688 kickstarts over 126 days, about 21 a day. I nearly published that as "the watchdog saved the agent 2,688 times".&lt;/p&gt;

&lt;p&gt;It would have been wrong twice.&lt;/p&gt;

&lt;p&gt;Wrong once because log lines are not restarts. A sampler that recorded the gateway's process age every hour for three and a half days puts the real figure at exactly 24 restarts a day, while the log was writing 96 kickstart lines a day over the same window. Four lines per restart, which nobody would guess from reading the log.&lt;/p&gt;

&lt;p&gt;Wrong twice, and this is the part worth your time, because the restarts are not rescues. Here are the intervals between restarts, reconstructed from process age:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3603.2 s mean, 0.65 s standard deviation, range 3602 to 3606, over 79 consecutive gaps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is not a process falling over. A crashing process does not crash on a metronome with sub second jitter. Something restarts it every hour by construction, and it took measuring the process to see it, because the log describes its own decisions in a vocabulary that sounds like rescue.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the watchdog actually checks
&lt;/h3&gt;

&lt;p&gt;Reading its source settles it. The check is: has a line tagged &lt;code&gt;[telegram]&lt;/code&gt; appeared in the log in the last thirty minutes? If not, and the Telegram API is reachable, the gateway is declared hung and kickstarted. There is even a comment above the threshold warning that idle long polling produces no log lines, so the value must be generous.&lt;/p&gt;

&lt;p&gt;It is not generous enough. In quiet hours nothing arrives for thirty minutes, the check cannot tell a hung poller from a quiet one, and a healthy process gets killed. Of the last two hundred decisions in the log, two hundred were "Bot API reachable, gateway telegram stale, kickstart".&lt;/p&gt;

&lt;p&gt;So the real lesson is not that agents are fragile. It is that a health check which measures traffic will restart you precisely when nothing is happening, and it will look like diligence in the log while it does it.&lt;/p&gt;

&lt;p&gt;The fix is a heartbeat the work writes, not one the traffic writes. Have the agent touch a file when it finishes a unit of work, have the watchdog restart on that file going stale, and idleness stops being indistinguishable from death. Our kit does it that way now, which is easy to say after four months of doing it the other way.&lt;/p&gt;

&lt;h3&gt;
  
  
  While I was in there: what the frameworks do when things go wrong
&lt;/h3&gt;

&lt;p&gt;Same harness, different question. One task for each framework: call a tool until a counter reaches three, then stop. Same mock endpoint, same step limit of twelve. The endpoint can be told to return 500, return 429, or reply with something that is not JSON. The tool can be told to fail every time. No paid keys, so all of it is reproducible for nothing.&lt;/p&gt;

&lt;p&gt;Versions on 2026-09-20: langgraph 1.2.11, openai-agents 0.22.3, crewai 1.15.22.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;th&gt;LangGraph&lt;/th&gt;
&lt;th&gt;OpenAI Agents SDK&lt;/th&gt;
&lt;th&gt;CrewAI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nothing wrong&lt;/td&gt;
&lt;td&gt;done in 4 model calls&lt;/td&gt;
&lt;td&gt;done in 4&lt;/td&gt;
&lt;td&gt;done in 4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool fails every time&lt;/td&gt;
&lt;td&gt;stops at once, 1 call spent&lt;/td&gt;
&lt;td&gt;runs to the cap, 12 calls&lt;/td&gt;
&lt;td&gt;13 calls, then a validation error&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Endpoint returns 500 three times&lt;/td&gt;
&lt;td&gt;raises, process exits&lt;/td&gt;
&lt;td&gt;raises, process exits&lt;/td&gt;
&lt;td&gt;retries and finishes, 7 calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Endpoint returns 429 three times&lt;/td&gt;
&lt;td&gt;raises, process exits&lt;/td&gt;
&lt;td&gt;raises, process exits&lt;/td&gt;
&lt;td&gt;retries and finishes, 7 calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reply is not valid JSON&lt;/td&gt;
&lt;td&gt;raises&lt;/td&gt;
&lt;td&gt;raises&lt;/td&gt;
&lt;td&gt;recovers and finishes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt tokens for identical work&lt;/td&gt;
&lt;td&gt;428&lt;/td&gt;
&lt;td&gt;472&lt;/td&gt;
&lt;td&gt;802&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State survives the process dying&lt;/td&gt;
&lt;td&gt;yes, sqlite checkpointer, one line&lt;/td&gt;
&lt;td&gt;yes, SQLiteSession, one line&lt;/td&gt;
&lt;td&gt;partly, memory is optional and needs an embedder&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Toughness inverts, which is the useful part. Against a flaky endpoint CrewAI is the survivor, because litellm retries underneath it, while the other two let the exception out and your unattended process exits. Against a tool that keeps failing it reverses: LangGraph stops after one model call, the Agents SDK spends its entire step budget discovering the tool is still broken, twelve calls per cycle for as long as the backend is down.&lt;/p&gt;

&lt;p&gt;Neither is wrong. But combine that table with the story above and you can see the shape of the thing: a supervisor that restarts too eagerly, plus a framework that retries too eagerly, is a machine for spending money at four in the morning while every log says healthy.&lt;/p&gt;

&lt;p&gt;One aside for private deployments: the Agents SDK ships traces to a hosted endpoint by default. In my runs it surfaced as a 401.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to take from this
&lt;/h3&gt;

&lt;p&gt;Measure the process, not its opinion of itself. Every number in the first draft of this post came from a log written by the component being judged, and every one of them was wrong in a direction that flattered the setup.&lt;/p&gt;

&lt;p&gt;Write the heartbeat from the work. If your liveness signal is traffic, your agent will be restarted hardest at night, when nothing is wrong.&lt;/p&gt;

&lt;p&gt;Count what a restart costs before deciding it is harmless. Ours takes seconds and nobody noticed for four months, which is exactly why nobody looked.&lt;/p&gt;

&lt;p&gt;The lab, a watchdog that keys on progress, a proxy that caps the daily spend and writes a ledger, and launchd and systemd templates are here, MIT, four tests, no keys needed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/bagdaer1/agent-uptime-kit" rel="noopener noreferrer"&gt;https://github.com/bagdaer1/agent-uptime-kit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;python lab/drive.py&lt;/code&gt; and you get the table above with your own versions. If your framework behaves differently, that is the interesting case and I would like the numbers.&lt;/p&gt;

&lt;h3&gt;
  
  
  The part where I am not neutral
&lt;/h3&gt;

&lt;p&gt;Where an agent lives matters more than what it is written in. A laptop sleeps and stops mid task. A serverless function dies at its timeout with no state. A Linux VPS is the right answer for most agents and it is what I would tell a friend to rent. A dedicated Mac earns its keep in three cases: the agent needs a local model in unified memory, it has to drive macOS or build for Apple platforms, or the token bill has passed the rent.&lt;/p&gt;

&lt;p&gt;We rent the third thing. The full numbers, including what a four month old install looks like on disk, are at &lt;a href="https://macyou.co/agents" rel="noopener noreferrer"&gt;https://macyou.co/agents&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>devops</category>
      <category>python</category>
    </item>
    <item>
      <title>Best Hardware for Local LLMs in 2026: Mac vs NVIDIA vs AMD, One Formula for Every Row</title>
      <dc:creator>Erik Bagdaer</dc:creator>
      <pubDate>Thu, 17 Sep 2026 15:39:06 +0000</pubDate>
      <link>https://dev.to/macyou/best-hardware-for-local-llms-in-2026-mac-vs-nvidia-vs-amd-one-formula-for-every-row-3jop</link>
      <guid>https://dev.to/macyou/best-hardware-for-local-llms-in-2026-mac-vs-nvidia-vs-amd-one-formula-for-every-row-3jop</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://macyou.co/compare/local-llm-hardware" rel="noopener noreferrer"&gt;macyou.co&lt;/a&gt;, where the tables update as specs change. Disclosure up front: I run Macyou, we rent dedicated Apple Silicon Macs. That is exactly why every number below is computed the same way for NVIDIA, AMD and Apple, and why the section on where a Mac is the wrong purchase is the longest one.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The honest short version, and it is not the one you would expect from a company that rents Macs: &lt;strong&gt;if your model fits in 32 GB, buy an NVIDIA card.&lt;/strong&gt; An RTX 5090 moves 1,792 GB/s against 546 for an M4 Max. Above 32 GB the question changes completely, because speed stops mattering when the model will not load at all, and that is where unified memory earns its price.&lt;/p&gt;

&lt;h2&gt;
  
  
  The market has split into three shapes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fast and small.&lt;/strong&gt; Discrete GPUs put GDDR7 behind a wide bus and reach 936 to 1,792 GB/s. Consumer cards stop at 24 or 32 GB, so they hold roughly 32B at Q4. Two cards double the capacity on paper but split the model across a bus, which is a different and worse thing than one pool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Big and slow.&lt;/strong&gt; The 128 GB unified memory boxes, the NVIDIA DGX Spark (GB10) and the AMD Strix Halo systems, use LPDDR5x. They hold a 123B model at 273 and 256 GB/s respectively, between a quarter and a seventh of a modern GPU.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Big and fast, at a price.&lt;/strong&gt; Apple's Ultra tier is the only consumer hardware that is both. The M5 Ultra addresses 512 GB at 1,200 GB/s. NVIDIA's answer in that quadrant is the RTX PRO 6000 at 96 GB and 1,597 GB/s, a workstation part with a workstation price.&lt;/p&gt;

&lt;h2&gt;
  
  
  The comparison that surprises people
&lt;/h2&gt;

&lt;p&gt;The DGX Spark costs $3,999 and has 273 GB/s of memory bandwidth. The M4 Pro, a two year old mid tier chip in a Mac mini, has 273 GB/s. Same number. The M4 Max has 546 GB/s at the same 128 GB, twice the Spark, and the M5 Ultra is 4.4 times it. If you are buying a 128 GB box for generation speed, make that comparison first. If you are buying it for CUDA, prompt processing or fine tuning, none of this applies and the Spark is a reasonable purchase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Everything, at Q4_K_M
&lt;/h2&gt;

&lt;p&gt;Tokens per second for generation, computed identically for every row from memory bandwidth and model size. "no" means the model does not fit. Memory is the largest configuration available.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hardware&lt;/th&gt;
&lt;th&gt;Memory&lt;/th&gt;
&lt;th&gt;Bandwidth&lt;/th&gt;
&lt;th&gt;8B&lt;/th&gt;
&lt;th&gt;32B&lt;/th&gt;
&lt;th&gt;70B&lt;/th&gt;
&lt;th&gt;123B&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RTX 3090&lt;/td&gt;
&lt;td&gt;24 GB&lt;/td&gt;
&lt;td&gt;936 GB/s&lt;/td&gt;
&lt;td&gt;105&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;~$1,300 used&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 4090&lt;/td&gt;
&lt;td&gt;24 GB&lt;/td&gt;
&lt;td&gt;1,008 GB/s&lt;/td&gt;
&lt;td&gt;109&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 5090&lt;/td&gt;
&lt;td&gt;32 GB&lt;/td&gt;
&lt;td&gt;1,792 GB/s&lt;/td&gt;
&lt;td&gt;146&lt;/td&gt;
&lt;td&gt;62&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX PRO 6000 Blackwell&lt;/td&gt;
&lt;td&gt;96 GB&lt;/td&gt;
&lt;td&gt;1,597 GB/s&lt;/td&gt;
&lt;td&gt;139&lt;/td&gt;
&lt;td&gt;57&lt;/td&gt;
&lt;td&gt;30.1&lt;/td&gt;
&lt;td&gt;18.2&lt;/td&gt;
&lt;td&gt;varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DGX Spark (GB10)&lt;/td&gt;
&lt;td&gt;128 GB&lt;/td&gt;
&lt;td&gt;273 GB/s&lt;/td&gt;
&lt;td&gt;42.9&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;5.7&lt;/td&gt;
&lt;td&gt;3.3&lt;/td&gt;
&lt;td&gt;~$3,999&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AMD Strix Halo (Ryzen AI Max+ 395)&lt;/td&gt;
&lt;td&gt;128 GB&lt;/td&gt;
&lt;td&gt;256 GB/s&lt;/td&gt;
&lt;td&gt;40.7&lt;/td&gt;
&lt;td&gt;11.3&lt;/td&gt;
&lt;td&gt;5.4&lt;/td&gt;
&lt;td&gt;3.1&lt;/td&gt;
&lt;td&gt;~$2,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apple M5 Ultra&lt;/td&gt;
&lt;td&gt;512 GB&lt;/td&gt;
&lt;td&gt;1,200 GB/s&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;td&gt;45.5&lt;/td&gt;
&lt;td&gt;23.3&lt;/td&gt;
&lt;td&gt;13.9&lt;/td&gt;
&lt;td&gt;varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apple M5 Max&lt;/td&gt;
&lt;td&gt;128 GB&lt;/td&gt;
&lt;td&gt;614 GB/s&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;25.5&lt;/td&gt;
&lt;td&gt;12.5&lt;/td&gt;
&lt;td&gt;7.3&lt;/td&gt;
&lt;td&gt;varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apple M5 Pro&lt;/td&gt;
&lt;td&gt;64 GB&lt;/td&gt;
&lt;td&gt;307 GB/s&lt;/td&gt;
&lt;td&gt;47.3&lt;/td&gt;
&lt;td&gt;13.4&lt;/td&gt;
&lt;td&gt;6.4&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apple M6&lt;/td&gt;
&lt;td&gt;32 GB&lt;/td&gt;
&lt;td&gt;153 GB/s&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;6.9&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apple M4 Max (40-core GPU)&lt;/td&gt;
&lt;td&gt;128 GB&lt;/td&gt;
&lt;td&gt;546 GB/s&lt;/td&gt;
&lt;td&gt;74&lt;/td&gt;
&lt;td&gt;22.9&lt;/td&gt;
&lt;td&gt;11.2&lt;/td&gt;
&lt;td&gt;6.5&lt;/td&gt;
&lt;td&gt;varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apple M4 Pro&lt;/td&gt;
&lt;td&gt;64 GB&lt;/td&gt;
&lt;td&gt;273 GB/s&lt;/td&gt;
&lt;td&gt;42.9&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;5.7&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apple M3 Ultra&lt;/td&gt;
&lt;td&gt;512 GB&lt;/td&gt;
&lt;td&gt;819 GB/s&lt;/td&gt;
&lt;td&gt;97&lt;/td&gt;
&lt;td&gt;32.9&lt;/td&gt;
&lt;td&gt;16.4&lt;/td&gt;
&lt;td&gt;9.7&lt;/td&gt;
&lt;td&gt;varies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Where a Mac is the wrong purchase
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anything that fits in 24 or 32 GB.&lt;/strong&gt; A used RTX 3090 at around $1,300 runs an 8B model at 105 tokens/sec. The base M4 does 21. The 3090 runs out of memory before 32B, but a 5090 holds it and still runs it at 62 tokens/sec, against 12 on an M4 Pro.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fine tuning.&lt;/strong&gt; MLX is good and improving, but the ecosystem assumes CUDA. You will hit repositories that will not run without porting, and the time spent porting is usually worth more than the hardware difference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Long prompts with short answers.&lt;/strong&gt; Prompt processing is compute bound, not bandwidth bound, and NVIDIA hardware is substantially better at it. The Spark processes prompts two to three times faster than a Strix Halo box despite nearly identical generation speed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Serving many users at once.&lt;/strong&gt; These figures are single stream. Batched serving is where GPU compute and stacks like vLLM pull away, and none of the unified memory machines, Apple included, are the right tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where a Mac is the right purchase
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Models between 32 and 128 GB, where you still want speed.&lt;/strong&gt; This is the gap the GPUs leave. A 70B at Q4 will not load on a 5090; on a 128 GB box it runs at about 5.7 tokens/sec; on an M4 Max it runs at 11.2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The very large models, at all.&lt;/strong&gt; Above 128 GB the field empties out. Apple's Ultra tier at 256 and 512 GB is most of what is left short of datacenter hardware.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Machines that have to be quiet, small and always on.&lt;/strong&gt; A Mac mini idles at a few watts and is silent. A 5090 draws hundreds of watts under load and needs a case and a power supply built around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the newest Apple chips land
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Chip&lt;/th&gt;
&lt;th&gt;Bandwidth&lt;/th&gt;
&lt;th&gt;Max memory&lt;/th&gt;
&lt;th&gt;Versus the DGX Spark&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;M5 Ultra&lt;/td&gt;
&lt;td&gt;1,200 GB/s&lt;/td&gt;
&lt;td&gt;512 GB&lt;/td&gt;
&lt;td&gt;4.4x bandwidth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M5 Max&lt;/td&gt;
&lt;td&gt;614 GB/s&lt;/td&gt;
&lt;td&gt;128 GB&lt;/td&gt;
&lt;td&gt;2.25x bandwidth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M5 Pro&lt;/td&gt;
&lt;td&gt;307 GB/s&lt;/td&gt;
&lt;td&gt;64 GB&lt;/td&gt;
&lt;td&gt;1.12x bandwidth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M6&lt;/td&gt;
&lt;td&gt;153 GB/s&lt;/td&gt;
&lt;td&gt;32 GB&lt;/td&gt;
&lt;td&gt;0.56x bandwidth&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read the M6 row before drawing the wrong conclusion from the others. Apple's entry desktop chip sits at 153 GB/s, below both 128 GB boxes, so the boxes are not simply slower than Macs. The crossover is the M5 Pro, the first chip in a Mac mini to edge past them, by twelve percent. What separates the classes is the top, not the entry point: Apple keeps scaling to 614 and 1,200 GB/s while the boxes stop at 273. Their argument was never speed. It is 128 GB for around $2,000, and against that specific number Apple has nothing to offer.&lt;/p&gt;

&lt;h2&gt;
  
  
  How these numbers were produced, and what is wrong with them
&lt;/h2&gt;

&lt;p&gt;Every speed above comes from one formula applied to every row: seconds per token equals weight size divided by (bandwidth times 0.915), plus 3.9 ms of fixed overhead. The two constants were fitted by least squares to six models measured on a base M4 and reproduce all six within 4%. The &lt;a href="https://macyou.co/mac-llm-calculator" rel="noopener noreferrer"&gt;calculator&lt;/a&gt; runs it for any model and chip.&lt;/p&gt;

&lt;p&gt;The obvious objection, stated before someone else does: the overhead constant was measured on Apple hardware running Ollama. Applying it to CUDA and ROCm assumes a comparable per token cost, which I have not verified. It is not a rounding error: without it the formula claims a 5090 does over 300 tokens/sec on an 8B model, which nobody observes; with it, 146, which matches what people report. If you have measured numbers on a 5090 or a Spark, I would like to check the model against them. The &lt;a href="https://news.ycombinator.com/item?id=49739917" rel="noopener noreferrer"&gt;HN thread&lt;/a&gt; is the place.&lt;/p&gt;

&lt;p&gt;Everything else is a published specification with a source link on the original page. Street prices move constantly; treat the price column as an order of magnitude.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>ai</category>
      <category>hardware</category>
      <category>apple</category>
    </item>
    <item>
      <title>Run Local LLMs on a Mac in 2026: Which Chip Runs Which Model, and Why Bandwidth Beats Cores</title>
      <dc:creator>Erik Bagdaer</dc:creator>
      <pubDate>Thu, 10 Sep 2026 14:03:09 +0000</pubDate>
      <link>https://dev.to/macyou/run-local-llms-on-a-mac-in-2026-which-chip-runs-which-model-and-why-bandwidth-beats-cores-501k</link>
      <guid>https://dev.to/macyou/run-local-llms-on-a-mac-in-2026-which-chip-runs-which-model-and-why-bandwidth-beats-cores-501k</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://macyou.co/blog/run-local-llms-on-mac" rel="noopener noreferrer"&gt;Macyou blog&lt;/a&gt;. Disclosure up front: I run Macyou - we rent dedicated Apple Silicon Macs for AI. This post is about the hardware math, which is the same whether the Mac is on your desk or in a rack.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The short answer: &lt;strong&gt;any Apple Silicon Mac with 16 GB of unified memory runs 7B-14B models well&lt;/strong&gt;, a 64 GB M4 Pro runs 70B-class models at usable speeds, and a 256 GB Mac Studio M3 Ultra runs 200B-class models that no single consumer GPU can hold. Generation speed is set almost entirely by memory bandwidth, so the chip tier matters more than the year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Mac runs which model
&lt;/h2&gt;

&lt;p&gt;The rule that decides everything: a model has to fit in unified memory at the quantization you choose, with a few gigabytes left for the context window and the OS. Once it fits, tokens per second scale with memory bandwidth. The M4 row below is measured (&lt;a href="https://macyou.co/benchmarks" rel="noopener noreferrer"&gt;methodology and raw JSON, CC BY 4.0&lt;/a&gt;); the other rows are bandwidth-scaled estimates until measured columns land.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mac&lt;/th&gt;
&lt;th&gt;Bandwidth&lt;/th&gt;
&lt;th&gt;Comfortable models (Q4)&lt;/th&gt;
&lt;th&gt;What to expect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;M4 Mac mini, 16 GB&lt;/td&gt;
&lt;td&gt;120 GB/s&lt;/td&gt;
&lt;td&gt;3B-14B&lt;/td&gt;
&lt;td&gt;Measured: Llama 3.2 3B 46.7 tok/s, Llama 3.1 8B 21.2, Qwen 2.5 14B 11.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M4 Mac mini, 24-32 GB&lt;/td&gt;
&lt;td&gt;120 GB/s&lt;/td&gt;
&lt;td&gt;14B comfortably, 32B at the edge&lt;/td&gt;
&lt;td&gt;Same speeds as 16 GB - extra memory buys model size, not tok/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M4 Pro Mac mini, 48-64 GB&lt;/td&gt;
&lt;td&gt;273 GB/s&lt;/td&gt;
&lt;td&gt;32B comfortably, 70B Q4 at 64 GB&lt;/td&gt;
&lt;td&gt;~2x the base M4 at equal model size; 70B at ~5-6 tok/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M4 Max Mac Studio, 128 GB&lt;/td&gt;
&lt;td&gt;546 GB/s&lt;/td&gt;
&lt;td&gt;70B Q8, 123B Q4&lt;/td&gt;
&lt;td&gt;~4x the base M4; 70B Q4 in the low teens tok/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M3 Ultra Mac Studio, 256 GB&lt;/td&gt;
&lt;td&gt;819 GB/s&lt;/td&gt;
&lt;td&gt;200B-class Q4, 70B FP16&lt;/td&gt;
&lt;td&gt;Largest single-box option; 405B still needs clustering&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The RAM math in one line
&lt;/h2&gt;

&lt;p&gt;Weights in GB = parameters (billions) x bits per weight / 8, plus about 15% runtime overhead, plus context. At Q4_K_M (~4.85 bits) an 8B model is ~4.9 GB of weights and ~6 GB in memory; a 32B model is ~20 GB; a 70B model is ~42 GB; a 123B model is ~75 GB. Q8_0 roughly doubles those numbers, FP16 roughly quadruples them. Add 1-4 GB for a 32K context, more for 128K.&lt;/p&gt;

&lt;p&gt;That is why 16 GB tops out at 14B, 64 GB is the 70B threshold, and 128 GB is where 100B+ dense models become practical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why speed is about bandwidth, not cores
&lt;/h2&gt;

&lt;p&gt;Generating one token means reading every active weight once. A 4.9 GB model on a 120 GB/s bus can therefore never exceed ~24 tok/s - and we measured 21.2, about 87% of the theoretical ceiling. The same arithmetic predicts the M4 Pro (273 GB/s) at ~2x and the M4 Max (546 GB/s) at ~4x for the same model, which matches what the community consistently reports.&lt;/p&gt;

&lt;p&gt;Two consequences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More GPU cores on the same bandwidth barely help generation.&lt;/li&gt;
&lt;li&gt;Mixture-of-experts models only read their active experts per token, so they run far faster than their parameter count suggests - a 35B-A3B MoE can out-run a dense 8B.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prompt processing is the exception: it is compute-bound, and it varies about 2x between model families at equal size. We measured Qwen 2.5 7B at 1,130 prompt tok/s against Llama 3.1 8B at 587. If your workload is long-prompt/short-answer (RAG, classification), that gap matters more than generation speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ollama vs LM Studio vs MLX vs llama.cpp
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ollama&lt;/strong&gt; - the default for anything headless or scripted: one command to pull a model, a REST API on port 11434, and an OpenAI-compatible endpoint. Runs llama.cpp underneath.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LM Studio&lt;/strong&gt; - the best GUI: model browser, chat window, and a local server that speaks the OpenAI API. Same engine class as Ollama, so same speeds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MLX&lt;/strong&gt; - Apple's own array framework. Fastest on some models and the natural choice for fine-tuning on a Mac; it's a Python library, not an app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;llama.cpp&lt;/strong&gt; - the raw engine when you want every flag, the newest quant formats, or a C/C++ embed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Five-minute setup with Ollama
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;ollama
ollama serve &amp;amp;
ollama pull llama3.1:8b
ollama run llama3.1:8b &lt;span class="s2"&gt;"Explain unified memory in two sentences."&lt;/span&gt;

&lt;span class="c"&gt;# OpenAI-compatible endpoint for your existing code:&lt;/span&gt;
curl http://localhost:11434/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"model":"llama3.1:8b","messages":[{"role":"user","content":"Hi"}]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Point any OpenAI SDK at &lt;code&gt;http://localhost:11434/v1&lt;/code&gt; with a dummy API key and it works. Before pulling a bigger model, do the RAM math - a 70B build on a 16 GB machine downloads 40 GB and then fails to load.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Buying GPU cores instead of memory.&lt;/strong&gt; A 24 GB Mac with more GPU cores runs the same 8B model no faster than a 16 GB one on the same chip; the next tier of bandwidth is what changes speed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring the context window.&lt;/strong&gt; A model that "fits" with 1 GB to spare will swap and crawl the moment you paste a long document. Leave 2-4 GB free, more for RAG.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Running production on a laptop.&lt;/strong&gt; Thermal throttling, sleep, and a residential uplink turn a 21 tok/s machine into an unreliable one. Anything that needs to be up 24/7 belongs on a desktop-class Mac with a real network connection - yours or rented.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  When a cloud Mac makes more sense than buying
&lt;/h2&gt;

&lt;p&gt;If you need a local-class model available around the clock, reachable by your team or your app, the honest comparison is not laptop vs cloud but &lt;a href="https://macyou.co/compare/buy-vs-rent" rel="noopener noreferrer"&gt;buying a Mac mini vs renting one&lt;/a&gt;. Owning wins on raw hardware cost over three years; renting wins the moment you count hosting, a static IP, power, remote-access setup, and being your own on-call. That's the niche we built Macyou for - a dedicated M4 Mac mini from $79/mo with Ollama pre-installed and the OpenAI endpoint already exposed, up to a 256 GB M3 Ultra.&lt;/p&gt;

&lt;p&gt;Per-model requirements, quant tables, and the cheapest chip that fits each model are in our &lt;a href="https://macyou.co/models" rel="noopener noreferrer"&gt;model guides&lt;/a&gt;. Questions about a specific model or Mac - ask in the comments, I'll answer with numbers where we have them.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>macos</category>
      <category>ollama</category>
    </item>
  </channel>
</rss>
