<?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: Matthew Gladding</title>
    <description>The latest articles on DEV Community by Matthew Gladding (@glad_labs).</description>
    <link>https://dev.to/glad_labs</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%2F3860296%2Fe75c4ed2-993e-403f-a24b-dd72bc83c85d.png</url>
      <title>DEV Community: Matthew Gladding</title>
      <link>https://dev.to/glad_labs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/glad_labs"/>
    <language>en</language>
    <item>
      <title>Llama.cpp vs vLLM vs SGLang</title>
      <dc:creator>Matthew Gladding</dc:creator>
      <pubDate>Tue, 15 Sep 2026 23:40:56 +0000</pubDate>
      <link>https://dev.to/glad_labs/llamacpp-vs-vllm-vs-sglang-5aao</link>
      <guid>https://dev.to/glad_labs/llamacpp-vs-vllm-vs-sglang-5aao</guid>
      <description>&lt;p&gt;Type "llama.cpp vs" into Google and it finishes the sentence for you: vllm, sglang. That's not us guessing at what people care about -- that's autocomplete rank one, which means enough people are typing this exact comparison that Google's learned to expect it. Good. Because we went through this exact decision ourselves a few months back, and the honest answer surprised us.&lt;/p&gt;

&lt;p&gt;Short version up front: these three tools are not competing for the same job. llama.cpp is the lightweight, run-anywhere engine. vLLM and SGLang are built for serving lots of people at once. Picking between them isn't a benchmark exercise -- it's a question about who's actually hitting your server.&lt;/p&gt;

&lt;h2&gt;
  
  
  What each one actually is
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;llama.cpp&lt;/strong&gt; is the C++ inference engine that started the whole local-LLM movement. It's the thing Ollama wraps under the hood. It runs GGUF-format quantized models on almost anything -- CPU, a single consumer GPU, Apple Silicon, a Raspberry Pi if you're patient. The project lives on &lt;a href="https://github.com/ggerganov/llama.cpp" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and its defining feature is flexibility: it supports variable-bit quantization, which lets you trade a little quality for a lot of memory headroom. That one knob -- how aggressively you quantize -- matters more on a consumer card than most benchmark charts let on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vLLM&lt;/strong&gt; exists to answer a different question: how do you serve one model to a hundred people at once without falling over? It does this with continuous batching -- instead of processing requests one at a time, it interleaves them, filling GPU compute that would otherwise sit idle waiting on the next token. That's its whole reason for existing, and it's a real one, if you have the load to justify it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SGLang&lt;/strong&gt; sits next to vLLM in the same "serious concurrent serving" category, but it leans harder into structured generation -- constrained decoding, complex multi-turn programs, cases where you're not just asking one question but running a whole decision tree through the model. Think of it as the tool you reach for when your workload looks more like a pipeline of prompts than a chat window.&lt;/p&gt;

&lt;p&gt;None of these three is "the best." That's not a cop-out -- the right choice depends on model format, hardware, and concurrency, not a tokens-per-second chart you found on Reddit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The question we actually asked ourselves
&lt;/h2&gt;

&lt;p&gt;Here's where this stops being theoretical. A few months into running Glad Labs on a self-hosted &lt;a href="https://www.gladlabs.io/go/asus-rog-astral-nvidia-geforce-rtx?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;ASUS ROG Astral RTX 5090&lt;/a&gt; with 64GB of system RAM, we asked the obvious question: should we switch our inference stack from Ollama to vLLM?&lt;/p&gt;

&lt;p&gt;The pitch made sense on paper. We're an AI-operated content shop -- writer agent, reviser agent, topic researcher, QA rails, a voice agent, video generation prompts, all hammering the same box. Surely that adds up to real concurrency, right? Surely vLLM's batching wins there?&lt;/p&gt;

&lt;p&gt;The honest answer, after looking at our own call logs, is no. Don't switch.&lt;/p&gt;

&lt;p&gt;The reason comes down to load shape, not raw capability. vLLM's advantage shows up when many simultaneous requests hit the same model -- that's where continuous batching starts filling GPU cycles that would otherwise sit empty. Our actual traffic looks nothing like that. It's one to three concurrent calls at most -- the writer, maybe a voice session, maybe a background worker -- against roughly fifty calls a day total. At that load there is nothing for batching to amortize, so a heavier serving layer is overhead we would pay on every single call.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Fcharts%2Fab0c49db.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Fcharts%2Fab0c49db.webp" alt="Bar chart comparing median decode speeds of local models, showing raw decode and delivered to caller performance in..." width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That chart is the whole argument in one picture. A model's raw decode speed -- tokens per second, measured in isolation -- is not the number that reaches your application. What reaches you is throughput after batching overhead, queuing, and scheduling take their cut. vLLM's batching machinery is designed to close that gap when you've got a stack of concurrent requests to amortize it across. When you don't, that machinery is pure overhead sitting between you and the model.&lt;/p&gt;

&lt;p&gt;This is the trap in a lot of "vLLM vs llama.cpp" content: the benchmarks are almost always run at high concurrency, because that's where vLLM was built to win. If your actual production traffic is a handful of sequential calls a day, you're reading a benchmark for a workload you don't have.&lt;/p&gt;

&lt;h2&gt;
  
  
  So where does SGLang fit for us
&lt;/h2&gt;

&lt;p&gt;We haven't put SGLang into production, and we're not going to pretend otherwise. But the audit made its niche clear by contrast. SGLang's structured-generation strengths -- enforcing a JSON schema across a long multi-step prompt chain, running RadixAttention-style prefix caching across a family of related requests -- matter most when your workload is a pipeline of many related generations sharing common context, not a single chat turn.&lt;/p&gt;

&lt;p&gt;Our content pipeline does chain prompts -- the writer feeds into the reviser, the reviser feeds into the QA rails -- but those stages run through different models and different providers, not repeated calls into one SGLang server holding shared context. If we ever build something that looks like SGLang's ideal case -- a fixed template hammered thousands of times a day with heavy prefix overlap -- it goes back on the table. Right now it's a tool without a job on our stack.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dev.to/sreeraj-sreenivasan/the-complete-guide-to-local-llm-inference-tools-in-july-2026-llamacpp-ollama-vllm-sglang-and-4mh1"&gt;dev.to guide to 2026 local inference tools&lt;/a&gt; frames this whole ecosystem as three layers -- desktop tools, lightweight servers, and heavy concurrent-serving engines -- and that framing matches what we found in practice. llama.cpp and Ollama are layer one and two. vLLM and SGLang are layer three. You don't "upgrade" from one layer to the next just because a new tool released. You move up a layer when your traffic pattern actually changes shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hardware wrinkle nobody mentions in the comparison charts
&lt;/h2&gt;

&lt;p&gt;Here's a detail that doesn't show up in most "vLLM vs llama.cpp" writeups but bit us directly: neither Ollama nor the llama.cpp backend underneath it can pool GPUs from different vendors into one shared VRAM space. If you've got an RTX 5090 sitting next to an AMD card, you cannot combine them into a single bigger memory pool for one model. Ollama picks one compute backend per model load -- CUDA or ROCm, never both -- so a model either lives entirely on the NVIDIA card or entirely on the AMD one. Multi-GPU support in this stack assumes a matched set: multiple NVIDIA cards, or multiple AMD cards, not a mixed pair.&lt;/p&gt;

&lt;p&gt;That constraint matters more than people expect when they're planning hardware. It's part of why we've written before about &lt;a href="https://www.gladlabs.io/posts/the-vram-currency-problem-bb10de87?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;VRAM as the real currency in local LLM work&lt;/a&gt; -- the bottleneck usually isn't compute, it's whether the model and its context fit in one coherent memory space, on one vendor's stack, at once. Our &lt;a href="https://www.gladlabs.io/posts/the-32gb-threshold-how-the-rtx-5090-redefines-loca-433d67bd?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;piece on the RTX 5090's 32GB threshold&lt;/a&gt; goes into what that extra headroom buys you specifically, and this GPU-pooling limitation is exactly why that headroom on a single card matters more than assembling a mismatched multi-card rig.&lt;/p&gt;

&lt;p&gt;vLLM and SGLang, by contrast, are built with distributed multi-GPU serving as a first-class feature -- tensor parallelism across a matched cluster of NVIDIA cards is a core use case, not an afterthought. If your actual plan is a rack of identical GPUs serving real concurrent traffic, that's a genuine point in their favor. It's just not our situation, and it's probably not most solo developers' situation either.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually changed for us instead
&lt;/h2&gt;

&lt;p&gt;The audit didn't end with "stay on Ollama and move on." It ended somewhere more useful: the real problem wasn't which inference engine we were running, it was that our application code was wired directly to Ollama's client. Switching engines meant rewriting call sites, not swapping a config value.&lt;/p&gt;

&lt;p&gt;So the fix wasn't picking a different serving engine. It was putting a router in front of all of them. We run &lt;a href="https://github.com/BerriAI/litellm" rel="noopener noreferrer"&gt;LiteLLM&lt;/a&gt; as the provider layer now, and we're actively working it toward being the default path for standard-tier generation, with the old hand-rolled Ollama client getting retired from the generation path over time. LiteLLM speaks the same interface whether the backend is Ollama, a cloud model, or -- if the load profile ever genuinely calls for it -- vLLM or SGLang sitting behind an OpenAI-compatible endpoint.&lt;/p&gt;

&lt;p&gt;That's the actual lesson from this whole exercise: the llama.cpp-vs-vLLM-vs-SGLang question stops being a one-time architecture bet once you decouple the application from the engine. You get to answer it per-workload instead of once for the whole company. Our writer agent can sit on a local Ollama instance running a quantized GGUF model. A future high-concurrency customer-facing endpoint, if we ever build one, can sit behind vLLM without touching a single call site upstream. Right now, every generation call in our pipeline -- writer, reviser, topic researcher, voice agent -- routes through that same layer regardless of which engine answers it, which is the only way this decision doesn't have to be relitigated every time traffic shape changes.&lt;/p&gt;

&lt;p&gt;We're not there yet with SGLang specifically. But the point of putting LiteLLM in the middle is that adding it later is a config change, not a rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  A decision framework that isn't a chart
&lt;/h2&gt;

&lt;p&gt;Skip the tokens-per-second leaderboard. Ask three questions instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How many concurrent requests actually hit this model, at the same time, in a typical hour?&lt;/strong&gt; If the honest answer is one to three, llama.cpp -- via Ollama or bare -- wins on latency and simplicity. If it's routinely far higher, vLLM's continuous batching starts paying for itself. That is the actual fork in the road, not raw throughput numbers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is the workload a chat turn, or a pipeline?&lt;/strong&gt; A single question in, single answer out -- that's llama.cpp territory, full stop. A chain of structured, related generations sharing heavy context -- schema-constrained extraction, multi-step agent programs -- that's the shape SGLang was built for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What GPUs do you actually own, and are they matched?&lt;/strong&gt; A single well-provisioned card, running one model at a time for a handful of concurrent users -- that's the whole case for staying lightweight. A matched cluster of identical NVIDIA cards intended for real concurrent serving -- that's when the distributed-serving design in vLLM and SGLang starts to earn its operational complexity.&lt;/p&gt;

&lt;p&gt;If you answered "one to three, chat turn, single card" to all three -- and if you've read this far you probably did -- you don't need vLLM or SGLang. You need llama.cpp, probably wrapped in Ollama for convenience, and you need to stop reading benchmark charts that were never measuring your situation in the first place. We covered getting that stack running well in our post on &lt;a href="https://www.gladlabs.io/posts/from-data-silos-to-smart-answers-building-a-local--735689d4?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;building a local RAG pipeline with Ollama and pgvector&lt;/a&gt;, and the broader case for going local at all is in &lt;a href="https://www.gladlabs.io/posts/the-offline-revolution-why-local-llms-are-the-back-1a51d7e0?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;our piece on the offline shift in 2026 development&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this actually leaves you
&lt;/h2&gt;

&lt;p&gt;The comparison charts treat this like a single winner-take-all question, and that's the wrong frame. llama.cpp isn't losing to vLLM and SGLang -- it's not entering the same competition. It's the tool for one machine serving a handful of requests with minimal fuss, and that description covers most solo developers, most small teams, and honestly most production workloads that aren't customer-facing chat products with real concurrent traffic.&lt;/p&gt;

&lt;p&gt;vLLM earns its complexity the moment your concurrency numbers stop being a rounding error -- eight, ten, fifty simultaneous requests against one model, where batching turns idle GPU cycles into served tokens. SGLang earns its place when the shape of your work is less "answer a question" and more "run a structured program through a model, over and over, with shared context worth caching."&lt;/p&gt;

&lt;p&gt;We looked at our own call logs before deciding, and they said stay put. That's the actual process worth copying -- not "which engine benchmarks fastest," but "what does my traffic actually look like, this week, on this hardware." Answer that first. The engine choice falls out of it, and if you've put a router in front of your application the way we did, you get to keep answering it as your traffic changes instead of committing to one answer forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ggerganov/llama.cpp" rel="noopener noreferrer"&gt;https://github.com/ggerganov/llama.cpp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/sreeraj-sreenivasan/the-complete-guide-to-local-llm-inference-tools-in-july-2026-llamacpp-ollama-vllm-sglang-and-4mh1"&gt;https://dev.to/sreeraj-sreenivasan/the-complete-guide-to-local-llm-inference-tools-in-july-2026-llamacpp-ollama-vllm-sglang-and-4mh1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/BerriAI/litellm" rel="noopener noreferrer"&gt;https://github.com/BerriAI/litellm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gladlabs.io/posts/llamacpp-vs-vllm-vs-sglang-38cba265?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;www.gladlabs.io&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vllm</category>
      <category>llamacpp</category>
      <category>sglang</category>
      <category>llminferenceengine</category>
    </item>
    <item>
      <title>Nobody Clicks Anymore: Building Content for Zero-Click Extraction</title>
      <dc:creator>Matthew Gladding</dc:creator>
      <pubDate>Tue, 15 Sep 2026 15:40:56 +0000</pubDate>
      <link>https://dev.to/glad_labs/nobody-clicks-anymore-building-content-for-zero-click-extraction-33cj</link>
      <guid>https://dev.to/glad_labs/nobody-clicks-anymore-building-content-for-zero-click-extraction-33cj</guid>
      <description>&lt;p&gt;You type a question into Google. Or you ask ChatGPT. Or you scroll past a LinkedIn post that already has the number you needed in the first line. Either way, you get your answer and you move on. No tab opened, no page loaded, no bounce recorded because there was never a visit to bounce from.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F4f4fc1a2287e.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F4f4fc1a2287e.webp" alt="A hand holds a smartphone with a bright white screen against a gray background." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's zero-click content, and it's not a trend anymore, it's the default. Every major platform -- Google, LinkedIn, TikTok, Facebook -- is built to keep people inside the platform for as long as possible, and that means surfacing the answer directly instead of sending anyone away to get it, as &lt;a href="https://chad-wyatt.com/seo-and-content/zero-click-content-in-2025-what-is-it-and-how-to-use-it/" rel="noopener noreferrer"&gt;the team at Chad Wyatt lays out&lt;/a&gt;. The click-through rate that used to be the whole point of content marketing is dying, on purpose, by platform design.&lt;/p&gt;

&lt;p&gt;We've written before about why the old keyword-volume playbook is already dead for a related reason -- see &lt;a href="https://www.gladlabs.io/posts/why-first-party-content-strategy-is-the-only-one-l-d1979ebb?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;Why First-Party Content Strategy Is the Only One Left Standing&lt;/a&gt;. Zero-click content is the other half of that same collapse. If nobody clicks through to read your 2,000-word article anyway, the article was never the asset. The fact inside it was.&lt;/p&gt;

&lt;h2&gt;
  
  
  What zero-click content actually is
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://blog.hootsuite.com/zero-click-content/" rel="noopener noreferrer"&gt;Hootsuite&lt;/a&gt; frames it plainly: give the audience the value up front, inside the post, instead of gating it behind a link. No "read more" wall. No forced funnel step. The insight, the number, the answer -- right there where the user already is.&lt;/p&gt;

&lt;p&gt;For B2B specifically, &lt;a href="https://intentamplify.com/blog/impacts-of-zero-click-content/" rel="noopener noreferrer"&gt;IntentAmplify&lt;/a&gt; frames this as instant value for decision-makers who don't have time to click through six sources to find one usable number. The content that wins is the content that answers the question before the reader has to leave the app to find the answer somewhere else.&lt;/p&gt;

&lt;p&gt;And as &lt;a href="https://www.linkedin.com/pulse/why-zero-click-content-actually-your-biggest-lead-generator-c9aic/" rel="noopener noreferrer"&gt;a LinkedIn analysis from March&lt;/a&gt; argues, AI-driven search has made this worse -- or better, depending which side of the fence you're on. Ask an AI assistant a question now and it just answers. No ranking page, no snippet competition, no visit at all. The information got extracted from somewhere, synthesized, and delivered. The "somewhere" doesn't get credit unless the answer itself was good enough, specific enough, or structured well enough to get pulled and cited.&lt;/p&gt;

&lt;p&gt;That last part is the part that matters for anyone building content infrastructure right now. If the AI is going to lift your fact out of your page and hand it to a user without ever sending them to you, the only leverage you have left is whether your fact was worth lifting. Authorship stopped being the product. Information became the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why authorship stops being the unit of value
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fd62776d64ab2.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fd62776d64ab2.webp" alt="A hand holds a fountain pen over a notebook, drawing glowing green geometric shapes and lines on the page." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Old content strategy was built around bylines, tone, voice, "our take." All of that assumes a reader who arrives at your page, reads your framing, and forms an opinion of your brand along the way. Zero-click breaks that assumption at the root. If the reader never lands on your page, your voice never gets heard. What gets extracted is the fact -- the number, the definition, the specific claim -- stripped of your framing entirely.&lt;/p&gt;

&lt;p&gt;That's a genuinely uncomfortable realization if your whole content operation was built around "good writing." Good writing doesn't survive extraction. A well-turned sentence gets summarized into a bullet point by whatever's doing the summarizing. What survives is the underlying claim, and whether it's true.&lt;/p&gt;

&lt;p&gt;We went through this exact realization building our own content pipeline. The system we run generates blog content across AI/ML, gaming, and PC hardware, and for a long time the instinct was to optimize the writing -- better hooks, tighter prose, stronger CTAs. That instinct isn't wrong, but it's now secondary. The thing that actually gets pulled into a zero-click answer box is a specific, checkable claim. We wrote about the difference between content that reads well and content that's actually true in &lt;a href="https://www.gladlabs.io/posts/faithfulness-in-ai-content-isnt-about-tone-its-abo-faa0a9c6?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;Faithfulness in AI Content Isn't About Tone -- It's About Whether Claims Are True&lt;/a&gt;, and this is the same fault line. Tone doesn't survive zero-click extraction. Facts do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building for extraction instead of arrival
&lt;/h2&gt;

&lt;p&gt;Once you accept that the reader might never arrive, you stop optimizing the page and start optimizing the fact. That's an actual architecture change, not a tone change.&lt;/p&gt;

&lt;p&gt;At Glad Labs, our content pipeline runs on Poindexter, and one of the things we built into it was converting raw content-writing capability into something closer to a ranking engine -- using Google Search Console data to enrich keywords and identify what's actually being searched for, rather than guessing at topics from a keyword-volume tool. That's a direct response to the zero-click problem: if you can't rely on the click to validate whether your content mattered, you need to know, from real query data, whether the fact you're publishing answers a question anyone's actually asking.&lt;/p&gt;

&lt;p&gt;The other half of the problem is speed. If the unit of value is now a fact instead of an essay, you need to produce many small, correct facts fast, in the format each platform wants them in, rather than one long article and hoping it ranks.&lt;/p&gt;

&lt;p&gt;The harder engineering problem is making sure those fast, small facts are actually true. Our faithfulness QA rails ground generated content against the same research corpus that fed the retrieval context in the first place -- that corpus isn't just an input for writing anymore, it's the reference the pipeline checks its own claims against before anything ships. That's the same retrieval-grounding approach we described in &lt;a href="https://www.gladlabs.io/posts/the-architecture-of-zero-downtime-ai-moving-beyond-07ec9e9d?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;The Architecture of Zero-Downtime AI&lt;/a&gt;, just pointed at a different problem: not "does this sound right," but "does this claim survive being pulled out of context and handed to someone as a standalone answer."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Fscreenshots%2Fpipeline-4a92c5a5.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Fscreenshots%2Fpipeline-4a92c5a5.webp" alt="A dashboard showing an approval queue and pipeline operations with metrics like awaiting approvals, avg quality..." width="800" height="575"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's what our pipeline dashboard tracks day to day -- throughput, quality scores, and where content gets rejected in QA. In a zero-click world, the rejection breakdown matters more than usual, because a rejected claim isn't just a bad paragraph in an article nobody reads start to finish. It's a fact that would've been extracted and served as a standalone answer, wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  The throughput problem nobody talks about
&lt;/h2&gt;

&lt;p&gt;Here's the part that gets skipped in most zero-click content advice: producing lots of small, fast, correct facts is a different infrastructure problem than producing one long, well-researched article. You need higher volume, faster turnaround, and -- crucially -- you need to know your actual generation throughput, not the number on the model's spec sheet.&lt;/p&gt;

&lt;p&gt;Raw decode speed and the throughput your application actually receives are not the same number. Batching, context length, queueing, and the difference between a model card benchmark and a live production call all eat into that gap.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Fcharts%2F09dabaf6.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Fcharts%2F09dabaf6.webp" alt="Bar chart comparing decode speeds of local models, showing median output tokens per second for raw decode and..." width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We track this ourselves across models in our own cost logs, and the gap between what a model can theoretically decode and what our pipeline actually gets delivered per call is the number that determines whether "generate a fact per query in real time" is even a realistic design goal, or whether you need to pre-generate and cache. If you're building a zero-click content system -- an FAQ engine, a live-answer widget, anything that has to respond inline rather than batch overnight -- this is the number to measure before you commit to an architecture, not after.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distribution changes shape too
&lt;/h2&gt;

&lt;p&gt;Zero-click content also changes what "amplification" means. We've argued before that great content dies without a system that pushes it out to where readers already are -- see &lt;a href="https://www.gladlabs.io/posts/why-great-content-dies-without-an-amplification-sy-e311bcc1?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;Why Great Content Dies Without an Amplification System&lt;/a&gt; -- and zero-click sharpens that argument instead of contradicting it. The destination isn't your site. The destination is the platform's own answer surface: the featured snippet, the AI overview, the LinkedIn post that never needs a link, the social card that has the number right there in the caption.&lt;/p&gt;

&lt;p&gt;That means the automation you build for distribution has to produce platform-native, standalone units, not just teaser copy pointing at a full article. We cover the practical mechanics of that automation in &lt;a href="https://www.gladlabs.io/posts/automating-ai-content-workflows-511012cc?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;Automating AI Content Workflows&lt;/a&gt; -- the same pipeline that generates the long-form post also needs to spin off the atomic, self-contained version of each claim for the platforms that will never send anyone back to read the source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the facts actually come from
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F0848206b2c77.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F0848206b2c77.webp" alt="A translucent crystal with iridescent reflections sits atop a gray rock matrix." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;None of this works if the facts themselves are generic. If your "unique fact" is the same stat everyone else already published, extraction doesn't help you -- the AI assistant or the platform snippet will just as happily pull it from a competitor with better SEO plumbing. The only durable moat in a zero-click world is first-party information nobody else has: your own measurements, your own support ticket patterns, your own usage data.&lt;/p&gt;

&lt;p&gt;We've made that case at length in &lt;a href="https://www.gladlabs.io/posts/first-party-knowledge-as-the-engine-81f4377a?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;First-Party Knowledge as the Engine&lt;/a&gt; and in &lt;a href="https://www.gladlabs.io/posts/why-first-party-content-strategy-is-the-only-one-l-d1979ebb?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;Why First-Party Content Strategy Is the Only One Left Standing&lt;/a&gt;. Zero-click content is the sharpest argument yet for that position. If a platform is going to strip away your framing and serve only the fact, you'd better own a fact nobody else has to serve.&lt;/p&gt;

&lt;p&gt;That's also, not coincidentally, the cheapest thing to produce at scale once you have it. Manual content production doesn't scale to "generate a hundred small, verified, platform-native facts a week" -- we've written about that operational bottleneck directly in &lt;a href="https://www.gladlabs.io/posts/the-operational-cost-of-manual-content-21425fe2?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;The Operational Cost of Manual Content&lt;/a&gt;. A human writer optimizing for voice and structure is solving the wrong problem for this environment. A pipeline optimizing for verified, extractable, first-party facts is solving the right one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to actually do about it
&lt;/h2&gt;

&lt;p&gt;If you're building content infrastructure right now, treat authorship as a cost center and information as the product. Structure content so the standalone claim survives being lifted out of context -- lead with the number, the definition, the comparison, not the narrative windup. Build your fact-checking against your own source corpus, not against "does this sound plausible," because the thing that gets served to a user with no visit to your site had better be true on its own, with no surrounding paragraph to soften it.&lt;/p&gt;

&lt;p&gt;Measure your actual generation throughput, not the benchmark number, before you promise real-time answers to anyone. And put your resources into the data only you have -- your own usage patterns, your own experiments, your own logs -- because that's the only fact a platform can't pull from somewhere else instead of you.&lt;/p&gt;

&lt;p&gt;The click isn't coming back. Neither is the reader who used to arrive, read your byline, and form an opinion of your voice along the way. What's left is the fact itself, standing alone, judged on whether it's true and whether it was worth knowing. Build for that, and the traffic model underneath it stops mattering nearly as much as you think it does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://chad-wyatt.com/seo-and-content/zero-click-content-in-2025-what-is-it-and-how-to-use-it/" rel="noopener noreferrer"&gt;https://chad-wyatt.com/seo-and-content/zero-click-content-in-2025-what-is-it-and-how-to-use-it/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.hootsuite.com/zero-click-content/" rel="noopener noreferrer"&gt;https://blog.hootsuite.com/zero-click-content/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://intentamplify.com/blog/impacts-of-zero-click-content/" rel="noopener noreferrer"&gt;https://intentamplify.com/blog/impacts-of-zero-click-content/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/pulse/why-zero-click-content-actually-your-biggest-lead-generator-c9aic/" rel="noopener noreferrer"&gt;https://www.linkedin.com/pulse/why-zero-click-content-actually-your-biggest-lead-generator-c9aic/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gladlabs.io/posts/nobody-clicks-anymore-building-content-for-zero-cl-0bce0e39?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;www.gladlabs.io&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>zeroclickcontent</category>
      <category>contentmarketingstrategy</category>
      <category>clickthroughrate</category>
      <category>informationextraction</category>
    </item>
    <item>
      <title>Decode Speed Lies: phi4:14b Loses 79.7% of Its Throughput Before You See a Token</title>
      <dc:creator>Matthew Gladding</dc:creator>
      <pubDate>Tue, 15 Sep 2026 03:40:55 +0000</pubDate>
      <link>https://dev.to/glad_labs/decode-speed-lies-phi414b-loses-797-of-its-throughput-before-you-see-a-token-2flo</link>
      <guid>https://dev.to/glad_labs/decode-speed-lies-phi414b-loses-797-of-its-throughput-before-you-see-a-token-2flo</guid>
      <description>&lt;p&gt;Every local LLM benchmark you've ever read reports one thing: tokens per second during generation. Ollama calls it &lt;code&gt;eval_duration&lt;/code&gt;. It's the purest possible measurement -- how fast the model spits out tokens once it's already loaded, already warm, already running. It's also not what your application receives.&lt;/p&gt;

&lt;p&gt;We pulled 2,218 instrumented production calls from our own &lt;code&gt;cost_logs&lt;/code&gt; table over the last 30 days and split every call into two numbers. Decode speed is the Ollama-reported generation rate. Delivered speed is wall-clock -- what the calling code actually waited for, queue time and VRAM reload included. The gap between those two numbers is the whole post.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the gap actually looks like
&lt;/h2&gt;

&lt;p&gt;Here's the spread, model by model, decode speed against delivered speed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;phi4:14b&lt;/strong&gt;: 124.7 tok/s decode, 25.3 tok/s delivered. That's 79.7% of the advertised throughput gone before it reaches the caller. Median overhead per call: 8,872 ms. (243 calls.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;qwen2.5:7b&lt;/strong&gt;: 236.7 tok/s decode, 105.5 tok/s delivered. 55.4% lost. Overhead 2,068 ms. (114 calls.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;qwen3-vl:30b&lt;/strong&gt;: 162.8 tok/s decode, 84.8 tok/s delivered. 47.9% lost. Overhead 2,636 ms. (940 calls.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;gemma-4-31B-it-qat&lt;/strong&gt;: 62.2 tok/s decode, 36.1 tok/s delivered. 42% lost. Overhead 5,322 ms. (804 calls.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;qwen3.6:27b&lt;/strong&gt;: 124.6 tok/s decode, 99.2 tok/s delivered. 20.4% lost. Overhead 6,019 ms. (83 calls.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;glm-4.7-5090:latest&lt;/strong&gt;: 177 tok/s decode, 172.2 tok/s delivered. Only 2.7% lost. Overhead 591 ms. (34 calls.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Look at that last row against the first. &lt;code&gt;phi4:14b&lt;/code&gt; decodes slower on paper than &lt;code&gt;qwen2.5:7b&lt;/code&gt; and &lt;code&gt;qwen3-vl:30b&lt;/code&gt;, but the number that matters -- what actually reaches your app -- puts it dead last. Meanwhile &lt;code&gt;glm-4.7-5090&lt;/code&gt; sits in the middle of the pack on raw decode speed and comes out on top on delivered speed, losing almost nothing.&lt;/p&gt;

&lt;p&gt;Same hardware. Same Ollama runtime. A 30-point spread in how much of the advertised speed you actually get to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's not that one model is slower. It's how often it's asked to leave
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fa167ca8b282b.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fa167ca8b282b.webp" alt="A person in a blue shirt pushes a large glowing cube in a dark room with server racks." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The instinct here is to rank these models by "how slow they really are." That's the wrong frame, and it'll send you chasing the wrong fix.&lt;/p&gt;

&lt;p&gt;The mechanism is residency. A model that's resident in VRAM answers a request immediately -- the GPU already has the weights loaded, decode starts on the first token. A model that gets called intermittently gets evicted between calls, and the next request pays the full cost of loading it back into VRAM before a single token comes out. That reload cost lands entirely inside "overhead," and overhead is exactly what benchmark decode numbers never measure.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;glm-4.7-5090&lt;/code&gt; loses almost nothing not because it's architecturally special, but because our pipeline keeps it warm -- it gets called often enough, and pinned deliberately enough, that it rarely gets evicted. &lt;code&gt;phi4:14b&lt;/code&gt; loses 80% because it's the intermittently-invoked model in our stack -- the one that sits idle between calls and gets swapped out, so nearly every call pays a full reload. Put &lt;code&gt;phi4:14b&lt;/code&gt; on a hot path and that number changes. Put &lt;code&gt;glm-4.7-5090&lt;/code&gt; on a cold path and it'll post its own ugly overhead figure. The model isn't the variable. The calling pattern is.&lt;/p&gt;

&lt;p&gt;This matches something we ran into directly while building &lt;a href="https://www.gladlabs.io/posts/speculative-decoding-for-local-llm-inference-how-a-a5594ce1?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;speculative decoding for local inference&lt;/a&gt; -- decode-time optimizations only pay off once you've already dealt with whatever's eating time outside the decode loop. A faster draft model doesn't help you if the target model just got evicted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the public benchmarks miss this entirely
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F22a76e865a8e.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F22a76e865a8e.webp" alt="A blue Lamborghini sports car drives on a winding road at night." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This isn't a knock on the benchmark writers -- it's a structural blind spot in how local LLM benchmarks get built. A recent &lt;a href="https://www.kunalganglani.com/blog/local-ai-coding-benchmark-ditch-cloud" rel="noopener noreferrer"&gt;$500 GPU coding benchmark&lt;/a&gt; tests Qwen3-Coder against Claude on 50 developer tasks, and &lt;a href="https://atomic.chat/blog/guides/best-local-llms-for-coding" rel="noopener noreferrer"&gt;a comparison of Qwen3-Coder, Qwen3.6 27B, and Gemma 4 26B&lt;/a&gt; clocks one model at 220 tokens per second as "the fastest model in our test by a wide margin." Those numbers are real and useful for what they measure. But they're measuring a single model, warm, running one task after another, with no eviction pressure and no competing workload fighting for the same GPU.&lt;/p&gt;

&lt;p&gt;Production doesn't look like that. In a real pipeline you've got several models sharing one card, called at different rates, some hot and some cold, some fighting a queue. A hardware sizing guide for local LLMs will tell you what a mid-range GPU can theoretically push through on Llama 3.3 70B, and a benchmark-ranked model guide will rank models by VRAM tier and coding accuracy. None of that tells you what happens when three of those models are sharing a 5090 and two of them are cold nine times out of ten.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to actually do with this
&lt;/h2&gt;

&lt;p&gt;If you're picking a model off a leaderboard, decode speed tells you the ceiling. It doesn't tell you what you'll get. The question that actually matters is: how often will this model be resident when the request comes in?&lt;/p&gt;

&lt;p&gt;If a model sits on a hot path -- called constantly, worth keeping pinned -- its decode number and its delivered number will converge, the way &lt;code&gt;glm-4.7-5090&lt;/code&gt; does at 2.7% overhead. If it's a cold-path model -- a critic, a fallback, something invoked occasionally -- expect the overhead to dominate regardless of how fast its raw decode looks on paper, the way &lt;code&gt;phi4:14b&lt;/code&gt; does at nearly 80%.&lt;/p&gt;

&lt;p&gt;The fix isn't picking a different model. It's deciding, deliberately, what stays resident and what gets evicted, and then measuring the thing you'll actually experience -- wall-clock, queue included -- instead of the thing a leaderboard reports. We didn't get this from reasoning about it. We got it from instrumenting 2,218 real calls and looking at the two columns side by side. If you're running a multi-model local stack, that's the only version of this measurement worth trusting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.kunalganglani.com/blog/local-ai-coding-benchmark-ditch-cloud" rel="noopener noreferrer"&gt;https://www.kunalganglani.com/blog/local-ai-coding-benchmark-ditch-cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://atomic.chat/blog/guides/best-local-llms-for-coding" rel="noopener noreferrer"&gt;https://atomic.chat/blog/guides/best-local-llms-for-coding&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gladlabs.io/posts/decode-speed-lies-phi414b-loses-797-of-its-through-56060812?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;www.gladlabs.io&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>localllms</category>
      <category>ollama</category>
      <category>tokenspersecond</category>
      <category>decodespeed</category>
    </item>
    <item>
      <title>This From-Scratch Transformer Trained in 1.5 Hours Isn't an LLM--And That's the Point</title>
      <dc:creator>Matthew Gladding</dc:creator>
      <pubDate>Mon, 14 Sep 2026 11:40:54 +0000</pubDate>
      <link>https://dev.to/glad_labs/this-from-scratch-transformer-trained-in-15-hours-isnt-an-llm-and-thats-the-point-3bmi</link>
      <guid>https://dev.to/glad_labs/this-from-scratch-transformer-trained-in-15-hours-isnt-an-llm-and-thats-the-point-3bmi</guid>
      <description>&lt;p&gt;In early September, someone posted a link to a static site with no branding and a plain-text title: "I trained a small transformer in 1.5hrs and it beats many LLMs." It hit the front page of &lt;a href="https://news.ycombinator.com/item?id=49519939" rel="noopener noreferrer"&gt;Hacker News&lt;/a&gt; and stayed there. By the time the thread cooled off it had pulled in 167 comments -- the kind of engagement number that usually means either a flame war or a genuine "wait, what?" moment. This was the second one.&lt;/p&gt;

&lt;p&gt;The author showed up in the comments under the handle evilmathkid, and the first thing they did was correct the record before anyone else could misread it: "This is NOT an LLM. its a small ar transformer trained from scratch. One of the points was that extremely complex problems can be tackled without LLMs." That single line is the whole story, compressed. Everyone assumed this was another distillation trick, another small model riding on the coattails of a big one. It wasn't. It was a from-scratch autoregressive transformer, small enough to train on one GPU in the time it takes to watch two movies, and it landed a result that -- until this -- only LLMs or their derivatives had touched.&lt;/p&gt;

&lt;p&gt;That's worth sitting with for a second. We've written before about the industry's slow pivot away from parameter-count chest-thumping and toward inference efficiency -- smaller "student" models distilled from bigger "teachers," doing more with less. This is a different animal entirely. Nothing here was distilled from anything. It was built and trained cold, and it still cleared a bar that had previously belonged to models with orders of magnitude more parameters.&lt;/p&gt;

&lt;p&gt;It's also worth noticing why the comment section reacted the way it did. Most "small model punches above its weight" stories in the last two years have followed a predictable shape: take a large model's outputs, use them as training signal for a smaller model, and call the smaller model "efficient." That's a legitimate technique, and it's produced genuinely useful systems, but it's also a shape people have gotten used to discounting a little -- because the small model is, in a real sense, still leaning on the big one's shoulders. Somewhere in its training data, however indirectly, is the reasoning of a much larger network. Take that scaffolding away entirely and the assumption is that performance collapses. That's the assumption this project broke, which is exactly why a comment thread full of people who build models for a living spent 167 replies arguing about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually got built
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fd39094be12ff.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fd39094be12ff.webp" alt="A graphics card with three fans installed in a computer case with RGB lighting and a CPU cooler." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;According to the writeup covered by &lt;a href="https://mangodeveloper.com/articles/a-15-hour-transformer-beats-llms-on-arc-agi-and-it-costs-pocket-change" rel="noopener noreferrer"&gt;Mango Developer&lt;/a&gt;, the model was trained from scratch in 1.5 hours on a single &lt;a href="https://www.gladlabs.io/go/asus-rog-astral-nvidia-geforce-rtx?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;RTX 5090&lt;/a&gt;, and it hit 44% on ARC-1 -- a score that matches specialized architectures built specifically for this benchmark, referred to in the piece as TRM and HRM. No pretraining corpus scraped from the internet. No fine-tune of an existing checkpoint. Just an architecture, a training loop, and a consumer GPU that most of you reading this could buy today.&lt;/p&gt;

&lt;p&gt;Put the training cost in perspective. An RTX 5090 is a card you can order from a retail site, not a rack of A100s or H100s you need a cloud contract and a procurement team to access. Ninety minutes of wall-clock time on that single card is roughly the electricity and depreciation cost of leaving a gaming PC running through a movie. Compare that to the training budgets behind the general-purpose LLMs this result is being measured against -- budgets that run into the tens or hundreds of millions of dollars, distributed across thousands of accelerators, over weeks or months. The gap isn't "this is a bit cheaper." It's closer to five or six orders of magnitude in compute, for a task where the small model is competitive rather than merely "not embarrassing."&lt;/p&gt;

&lt;p&gt;ARC-1 is not a benchmark you cheese with vocabulary tricks or clever prompting. It's part of the ARC-AGI family, built explicitly to resist memorization -- every puzzle is novel, abstract, and requires the model to infer a transformation rule from a handful of examples and apply it to something it's never seen. A typical ARC-1 task hands you two or three small colored grids as "before" and "after" pairs -- say, a 5x5 grid where every isolated blue square gets surrounded by a ring of yellow, and every red square stays untouched -- and then gives you a fourth "before" grid and asks you to produce the "after." There's no vocabulary to memorize and no pattern you could have seen in a training corpus, because the puzzle was generated to be unlike anything that came before it. You either infer the rule from the examples in front of you, on the spot, or you don't. It's the benchmark researchers reach for specifically because language models, even huge ones, tend to faceplant on it -- a model can have ingested the entire internet and still have no leverage on a grid transformation it's never encountered, because raw scale doesn't substitute for the specific skill of rapid rule induction from a tiny number of examples. A &lt;a href="https://m.youtube.com/watch?v=tEfBCnyg5BQ" rel="noopener noreferrer"&gt;YouTube breakdown of the result&lt;/a&gt; frames it the same way: a small transformer trained in 1.5 hours hit 44% on ARC-1, outperforming general-purpose LLMs that cost orders of magnitude more to run.&lt;/p&gt;

&lt;p&gt;If you're used to the Hugging Face &lt;a href="https://huggingface.co/models" rel="noopener noreferrer"&gt;Model Hub&lt;/a&gt; and the &lt;a href="https://huggingface.co/spaces/open-llm-leaderboard/open_llm_leaderboard" rel="noopener noreferrer"&gt;Open LLM Leaderboard&lt;/a&gt; as your mental map of "what's good," this doesn't show up on either. It's not competing in that arena. It's not an LLM entry at all -- it's a specialist, and specialists don't always play by the leaderboard's rules. A leaderboard built around benchmarks like MMLU or HellaSwag is measuring breadth: how well a model handles thousands of different task types with a single set of weights. ARC-1 measures something narrower and, in some ways, harder -- the ability to generalize to a genuinely new rule from almost no examples. Those are different axes, and a model that's mediocre on the first can still be excellent on the second, which is exactly the position this small transformer occupies.&lt;/p&gt;

&lt;h2&gt;
  
  
  The design choices that made it work
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F7df9fc585a73.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F7df9fc585a73.webp" alt="A glowing blue network of interconnected nodes forming a geometric structure against a black background." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The technical detail that jumped out to us -- and the part that separates this from a lucky architecture guess -- is the ablation study. Per the Mango Developer breakdown, the approach uses test-time training on task-specific puzzles, combined with 3D RoPE embeddings and per-task learned embeddings. Both of those pieces turned out to be load-bearing. Strip either one out and accuracy drops to roughly 24% -- almost half the final score, gone. That's not a marginal tweak. That's the difference between "works" and "doesn't."&lt;/p&gt;

&lt;p&gt;An ablation study, for anyone who hasn't run one, is exactly what it sounds like: you build the full system, measure it, then remove one piece at a time and remeasure, to find out which pieces were actually doing work versus which were just along for the ride. It's easy to end up with a pile of design choices that all felt necessary at the time and never find out that half of them were dead weight. The fact that this team ran that process and published the numbers -- rather than just publishing the 44% headline number and letting people assume the whole architecture was equally important -- is part of why the result is credible rather than just viral.&lt;/p&gt;

&lt;p&gt;Test-time training is the part worth explaining if you haven't run into it. Instead of training once and freezing the weights before inference, the model keeps learning at inference time, adapting to the specific puzzle in front of it using the few examples it's given. It's closer to how you'd solve an IQ-test puzzle yourself -- you don't apply a fixed rule you memorized in school, you look at the three examples, infer the pattern, and apply it to the fourth. Baking that into the training loop, rather than bolting it on after, is what let a small model compete with approaches that lean on raw scale.&lt;/p&gt;

&lt;p&gt;Concretely, this means the model isn't just doing a single forward pass over the puzzle at inference time the way a standard LLM would when you paste a prompt into it. It's taking the handful of example input/output grid pairs that come bundled with each ARC-1 task, running a lightweight training update using those examples as its own miniature dataset, and only then attempting the held-out test grid. Each puzzle effectively gets its own brief, private training run before the model commits to an answer. That's expensive per-puzzle compared to a single forward pass, but it's cheap in absolute terms because the base model is small and the puzzle-specific adaptation is short. It's also a fundamentally different bet than the one general LLMs make: instead of trying to have already seen enough patterns during pretraining to recognize this one by analogy, the model is explicitly re-deriving the rule from scratch, every single time, using only the examples the puzzle itself provides.&lt;/p&gt;

&lt;p&gt;3D RoPE -- rotary position embeddings extended into a third dimension -- and per-task learned embeddings are both about giving the model a better sense of &lt;em&gt;where&lt;/em&gt; it is inside a grid-shaped puzzle and &lt;em&gt;which&lt;/em&gt; puzzle it's currently solving. Standard RoPE, the kind used in most modern language models, encodes position along a single sequence axis -- token 1, token 2, token 3, and so on down a line of text. That works fine for sentences, because sentences are one-dimensional: word order is really the only spatial relationship that matters. ARC-1 tasks are spatial grids, not linear text, so a position encoding scheme built for sentences doesn't naturally fit -- a cell's meaning depends on its row, its column, and often its relationship to cells diagonally or across the grid, not just its position in some flattened left-to-right token stream. Extending RoPE into a third dimension lets the model encode row, column, and an additional axis -- plausibly something like which example within the task, or a channel for color/value -- directly into the position signal, instead of forcing the model to reconstruct 2D or 3D spatial structure indirectly from a 1D encoding the way a plain LLM would have to. Per-task learned embeddings, layered on top, give the model an explicit signal for "this is puzzle A, not puzzle B" when it's being trained or adapted across many different tasks, so it doesn't have to re-infer from scratch, purely from the grid content, which family of rules it should even be considering. Adapting the geometry to the actual shape of the problem, rather than forcing text-shaped assumptions onto a grid-shaped task, is the kind of decision that looks obvious in hindsight and invisible until someone actually tries it and measures the gap -- and the ablation numbers are the proof that it wasn't cosmetic. Losing it costs roughly twenty points of accuracy, which on a benchmark this hard is the difference between a model that's genuinely competitive and one that's barely functional.&lt;/p&gt;

&lt;h2&gt;
  
  
  The loss function twist nobody expected
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fe649053ac462.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fe649053ac462.webp" alt="A man in a lab coat sits at a laptop, looking concerned as a graph shows a downward trend and a trophy appears above it." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The detail that should make anyone who's fine-tuned a model sit up is the loss function finding. Switching from a standard loss to a supervised loss computed only on the output tokens improved accuracy from 40% to 44% -- despite the validation loss getting &lt;em&gt;worse&lt;/em&gt; in the process. Per the same Mango Developer coverage, this exposes a real failure mode: using validation loss as a stand-in for sample efficiency can straight-up lie to you.&lt;/p&gt;

&lt;p&gt;To unpack why this is a real distinction and not just a technicality: a standard autoregressive loss, applied naively, computes error across every token the model produces during training -- including tokens that are effectively just scaffolding, formatting, or restating the input before the model gets to the part that actually constitutes the answer. A loss that's computed only on the output tokens ignores all of that scaffolding and grades the model exclusively on the grid cells it's actually predicting as the solution. Both losses can go down over the course of training, but they're rewarding different things -- one is partly rewarding "predict the input format correctly," the other is entirely rewarding "predict the right answer." It's not hard to see, once it's spelled out, why a model optimized purely on the second objective would end up better at the thing you actually care about, even if its aggregate loss number -- which still includes all that scaffolding -- looks worse by comparison.&lt;/p&gt;

&lt;p&gt;That's a bigger deal than it sounds. Most of the machine learning tooling ecosystem treats val loss as the north star -- it's the number your training dashboard plots, the number early-stopping callbacks watch, the number you eyeball at 2am to decide whether the run is working. Here, the number that looked worse produced the model that actually performed better on the thing you care about. If you've ever killed a promising training run early because the loss curve ticked the wrong direction, this is the cautionary tale. The metric you're watching and the outcome you want are not always the same axis.&lt;/p&gt;

&lt;p&gt;It's worth stating plainly what the practical takeaway is, because it generalizes well beyond this one project: validation loss is a proxy, not the target. It's a proxy that happens to correlate with the target often enough that it's become the default thing everyone watches, but "often enough" is not "always," and this project is a clean, measured example of a case where the correlation breaks down. Anyone iterating on a training loop -- not just on ARC-style puzzles, but on any task where the loss is computed over a mix of "answer" tokens and "everything else" tokens -- should take this as a prompt to check whether their loss function is actually weighting the tokens they care about, or just averaging over everything and calling it a metric.&lt;/p&gt;

&lt;p&gt;The writeup also mentions an optimizer called NorMuon in the mix. According to the &lt;a href="https://arxiv.org/abs/2510.05491" rel="noopener noreferrer"&gt;NorMuon paper&lt;/a&gt;, it's a neuron-wise normalized variant of the Muon optimizer that pairs matrix-level orthogonalization with adaptive per-neuron scaling, addressing shortcomings in both Adam and standard Muon -- the kind of optimizer choice that squeezes more sample efficiency out of a short, compute-constrained training run rather than one built for massive distributed pretraining. The distinction matters in a training run this short: with only 1.5 hours on the clock, there's no budget for an optimizer that needs thousands of steps to find its footing. Adam is the default choice for most training loops because it's robust and forgiving, but it's not necessarily the fastest optimizer to converge per-step on every architecture. Muon's matrix-level orthogonalization keeps weight updates from collapsing into redundant directions -- a common failure mode where different neurons end up learning near-duplicate representations, wasting capacity. NorMuon's addition of per-neuron adaptive scaling on top of that orthogonalization is aimed at fixing a known weakness of plain Muon, where treating all neurons with the same update scale can shortchange the ones that need larger or smaller steps. In a regime where every training step is precious because there are so few of them, an optimizer that converges in fewer steps isn't a nice-to-have, it's close to a prerequisite for the whole approach being feasible at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "it's not an LLM" is the actual headline
&lt;/h2&gt;

&lt;p&gt;It would be easy to read this story as "small model beats big model" and file it next to every other distillation story from the past year. That misses what evilmathkid was pointing at in that HN comment. The interesting claim isn't that a small model can match a big one on a task -- that's been demonstrated plenty, in distillation papers, in quantization papers, in retrieval-augmented setups where a small model borrows a bigger one's knowledge through a search index instead of through its own weights. The interesting claim is that you don't need an LLM's machinery at all to hit a benchmark that, until now, only LLM-shaped systems had cracked. No transformer trained on internet-scale text, no tokenizer built around vocabulary and grammar, no chain-of-thought prompting borrowed from a much larger sibling model. Just an architecture shaped like the problem, trained directly on the problem, for less time than it takes to fly cross-country.&lt;/p&gt;

&lt;p&gt;That distinction matters for anyone deciding what to build next. If your instinct, every time you hit a hard reasoning problem, is to reach for a bigger model or a longer prompt chain, this result is a data point against that reflex. Task-specific architecture, trained cold, with the right position encoding and the right loss function, beat the "throw an LLM at it" approach on its own turf. Not every problem needs a general-purpose language model wrapped around it. Some problems need a purpose-built structure and a training loop that actually understands the shape of the puzzle.&lt;/p&gt;

&lt;p&gt;It's worth being precise about what this does and doesn't imply, because it would be easy to overreach in the other direction too. This isn't evidence that LLMs are obsolete, or that general-purpose language ability doesn't matter -- an LLM's whole value proposition is breadth, the ability to handle an open-ended range of tasks it was never specifically built for, and no purpose-built 44%-on-ARC-1 architecture is going to write an email, summarize a contract, or hold a conversation. What this result narrows down is the specific claim that general-purpose scale is the &lt;em&gt;only&lt;/em&gt; route to strong performance on hard reasoning benchmarks. It demonstrates a second route: identify the actual shape of the problem -- grid-structured, rule-inducible from a handful of examples -- and build the smallest system that fits that shape exactly, rather than the largest system that fits everything approximately.&lt;/p&gt;

&lt;p&gt;We've made a version of this argument before, when we looked at how fine-tuning existing models often costs more than it saves compared to building something purpose-fit from the start. This project is the sharpest version of that argument we've seen yet: not "fine-tuning is worse than building from scratch" in some abstract efficiency sense, but a working system, with published ablations, that took ninety minutes on one consumer GPU to reach a score that specialized ARC architectures and general-purpose LLMs alike had to work much harder to reach. The lesson isn't "abandon LLMs." It's "check whether the problem in front of you actually needs one before you reach for it" -- and this is as clean a demonstration of that check paying off as you're likely to find in a Hacker News thread.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=49519939" rel="noopener noreferrer"&gt;https://news.ycombinator.com/item?id=49519939&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://m.youtube.com/watch?v=tEfBCnyg5BQ" rel="noopener noreferrer"&gt;https://m.youtube.com/watch?v=tEfBCnyg5BQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/models" rel="noopener noreferrer"&gt;https://huggingface.co/models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/spaces/open-llm-leaderboard/open_llm_leaderboard" rel="noopener noreferrer"&gt;https://huggingface.co/spaces/open-llm-leaderboard/open_llm_leaderboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2510.05491" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2510.05491&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gladlabs.io/posts/this-from-scratch-transformer-trained-in-15-hours-0075ba6d?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;www.gladlabs.io&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>smalltransformer</category>
      <category>autoregressivetransformer</category>
      <category>modeldistillation</category>
      <category>machinelearningefficiency</category>
    </item>
    <item>
      <title>A Parent Built Their 8-Year-Old a MUD to Teach Real Code, and Hacker News Argued About It</title>
      <dc:creator>Matthew Gladding</dc:creator>
      <pubDate>Thu, 10 Sep 2026 11:40:35 +0000</pubDate>
      <link>https://dev.to/glad_labs/a-parent-built-their-8-year-old-a-mud-to-teach-real-code-and-hacker-news-argued-about-it-1c5n</link>
      <guid>https://dev.to/glad_labs/a-parent-built-their-8-year-old-a-mud-to-teach-real-code-and-hacker-news-argued-about-it-1c5n</guid>
      <description>&lt;p&gt;A parent builds a text adventure for their eight-year-old. Not a course. Not a certificate. A dungeon with rooms and doors and a dragon that says something rude if you type the wrong verb. They post it to Hacker News. Two hundred and sixty-nine points, then the comments show up, and half of them are oddly hostile for a project that isn't trying to sell anyone anything. One commenter on the &lt;a href="https://news.ycombinator.com/item?id=49272631" rel="noopener noreferrer"&gt;original thread&lt;/a&gt; says it plainly: this is a fun collaboration between a parent and a kid, it doesn't compete with anything, and it doesn't need to.&lt;/p&gt;

&lt;p&gt;That's the whole pitch, and it's a good one. A MUD -- a multi-user dungeon, the text-based ancestor of every MMO you've played -- is a command interpreter wearing a costume. You type &lt;code&gt;go north&lt;/code&gt;. Something reads that string, breaks it into tokens, decides what it means, and changes the state of the world. That's not a metaphor for programming. That is programming, the exact shape of it, minus the part where your kid has to care about &lt;code&gt;for&lt;/code&gt; loops before they've seen anything worth looping over.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the command parser is the actual lesson
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F569b602799e3.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F569b602799e3.webp" alt="Two hands typing on a dark gray keyboard with a USB symbol key on a wooden surface." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every serious coding-for-kids product on the market solves the motivation problem by wrapping code in something that isn't a terminal. CodeMonkey has you write CoffeeScript and Python to catch bananas. codingforkids.io puts you in a code editor next to a dungeon map and has you type &lt;code&gt;player.move_forward()&lt;/code&gt; to walk toward an exit. Both are honest about the trick: hide the syntax behind a payoff a kid actually wants.&lt;/p&gt;

&lt;p&gt;A MUD does the same trick, but it does it with a parser your kid built or watched get built, instead of one hidden inside somebody else's platform. That distinction matters more than it sounds like it should. When &lt;code&gt;player.move_forward()&lt;/code&gt; doesn't do anything, the kid on codingforkids.io hits a wall the product author designed. When your homemade parser doesn't recognize &lt;code&gt;open door&lt;/code&gt;, you and your kid are debugging the same function together, and the fix is visible, not abstracted behind a vendor's runtime.&lt;/p&gt;

&lt;p&gt;We've written before about why lexing and parsing still matter as a discipline even in an era of code-generating models -- the &lt;a href="https://www.gladlabs.io/posts/why-a-2021-textbook-on-compilers-still-matters-f7a9ce17?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;2021 compiler theory&lt;/a&gt; that describes tokenizing input and building a semantic model of intent hasn't gone stale just because an LLM can spit out a working parser in ten seconds. A MUD's verb handler is that same theory at toy scale: tokenize the input, match it against a grammar of verbs and nouns, resolve what the player means, mutate state. Get a kid comfortable with that loop and you've quietly taught them the shape of every interpreter they'll ever touch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where the LLM actually earns its keep
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fd9f5ab9b91f8.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fd9f5ab9b91f8.webp" alt="A yellow hand holds a pen, drawing on a 3D building plan with yellow interior, gray walls, and blue grid background." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The HN commenter's point about using an LLM for the base project is the right instinct, applied narrowly. Scaffolding a room graph, a starter inventory system, a handful of NPC dialogue trees -- that's boilerplate, and boilerplate is exactly what you want a model to burn through so the actual teaching time goes to the parts that require a human explaining why the code does what it does.&lt;/p&gt;

&lt;p&gt;But scaffolding isn't the same as abdication. Treating AI output as done work rather than a draft is how bugs, security holes, and outdated patterns quietly move from a training corpus into your codebase -- engineers need to keep doing algorithm analysis, design pattern recognition, and code review even when the first draft came from a model, because the model doesn't know your requirements, it knows what similar code has looked like before. If you're generating the base MUD engine with an assistant, sit down and read the room-loading function with your kid before you ship it. That's not extra homework. That's the actual lesson. The code review is the curriculum.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing as play, not as a chore bolted on afterward
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F61096f3a1b0d.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F61096f3a1b0d.webp" alt="A blocky cartoon figure with white hair and blue gem necklace stands before a stone-arched wooden door with a..." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A MUD gives you test-driven development for free, if you let it. "Open the locked door" should fail until the key-checking logic exists. Write that failing case first, watch it fail, then write the minimum code that makes it pass -- that's the TDD discipline in one sentence, and it works exactly the same whether the thing under test is a payment processor or a wizard's tower with a stuck door. The difference with a kid is that the failing test isn't red text in a terminal, it's their character walking into a wall and getting an error message they wrote themselves. That's a far better hook into "why do we write tests before code" than any abstract explanation involving invoices or unit conversions.&lt;/p&gt;

&lt;h3&gt;
  
  
  The build itself is a small, sturdy stack
&lt;/h3&gt;

&lt;p&gt;If you're standing up a MUD server rather than hand-rolling sockets, a lightweight Python API framework does the job well -- we've made the case elsewhere for &lt;a href="https://www.gladlabs.io/posts/the-fast-track-to-efficiency-why-fastapi-is-the-se-8ae7b1dd?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;FastAPI&lt;/a&gt; as a low-ceremony way to expose endpoints without a framework fighting you the whole way, and a MUD's command endpoint (take input, mutate world state, return a description) maps onto that shape cleanly. The harder problem, and the one people underestimate, is persistence: your kid quits after twenty minutes and comes back tomorrow expecting the dragon to still be dead. That's the same state-continuity problem we ran into building persistent memory for coding agents -- the gap between a session that remembers nothing and one that &lt;a href="https://www.gladlabs.io/posts/the-claude-code-memory-gap-bridging-the-divide-wit-474?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;carries state forward&lt;/a&gt; is the difference between a toy and a world that feels real. A MUD world file, saved to disk between sessions, is the same idea at a scale a kid can hold in their head.&lt;/p&gt;

&lt;h3&gt;
  
  
  The alternatives, and why building beats buying here
&lt;/h3&gt;

&lt;p&gt;If you don't want to build anything, the market has options. Machine Learning for Kids leans further into ML concepts, having kids train a classifier rather than write imperative logic. And one developer, watching their ten-year-old close the laptop by lesson three of a standard Python course and go back to YouTube, &lt;a href="https://dev.to/zhutoulala/i-built-a-free-browser-game-that-teaches-kids-to-code-in-python-302c"&gt;built a browser-based dungeon crawler&lt;/a&gt; from scratch specifically because the tutorial format had already lost. That's the pattern across every one of these projects: the platforms that stick aren't the ones with the most polished curriculum, they're the ones where the kid wants to see what's behind the next door.&lt;/p&gt;

&lt;p&gt;A store-bought platform will always out-polish a parent's weekend project. It will not out-collaborate it. The kid working through CodeMonkey's banana-catching levels is alone with a product. The kid working through a MUD you built together is debugging a shared thing, watching you read a stack trace out loud, learning that "it doesn't work" is a starting point, not a verdict. That's the actual pitch of teaching a kid to code with a MUD, and it's worth building even if the comment section doesn't get it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=49272631" rel="noopener noreferrer"&gt;https://news.ycombinator.com/item?id=49272631&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/zhutoulala/i-built-a-free-browser-game-that-teaches-kids-to-code-in-python-302c"&gt;https://dev.to/zhutoulala/i-built-a-free-browser-game-that-teaches-kids-to-code-in-python-302c&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gladlabs.io/posts/a-parent-built-their-8-year-old-a-mud-to-teach-rea-34877671?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;www.gladlabs.io&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>teachingkidstocode</category>
      <category>modernmud</category>
      <category>textadventuregame</category>
      <category>commandparser</category>
    </item>
    <item>
      <title>Our Google Autocomplete Topic Source Ran for 6 Weeks and Produced Zero Topics: A Postmortem</title>
      <dc:creator>Matthew Gladding</dc:creator>
      <pubDate>Wed, 09 Sep 2026 23:40:34 +0000</pubDate>
      <link>https://dev.to/glad_labs/our-google-autocomplete-topic-source-ran-for-6-weeks-and-produced-zero-topics-a-postmortem-32i1</link>
      <guid>https://dev.to/glad_labs/our-google-autocomplete-topic-source-ran-for-6-weeks-and-produced-zero-topics-a-postmortem-32i1</guid>
      <description>&lt;p&gt;We turned on a Google autocomplete topic source for our content pipeline back in June. Config seeded, feature flag on, plugin enabled for the niche. By every dashboard we had, it looked live.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F62dddcce50c9.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F62dddcce50c9.webp" alt="An isometric view of a complex digital machine with many glowing green lights and switches all set to 'on', but the..." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It produced zero topics. For six weeks.&lt;/p&gt;

&lt;p&gt;Nobody noticed, because nothing was throwing an error. The source existed. It just never ran. Turns out a plugin row only grants a niche &lt;em&gt;permission&lt;/em&gt; to use a source -- it doesn't schedule anything. Ingestion is driven by a separate per-niche tap row, and that row didn't exist. We'd built the engine and forgotten to bolt it to the car.&lt;/p&gt;

&lt;p&gt;The mental model we'd been carrying around was wrong in a specific way: we treated "plugin enabled" as a verb, when it's actually a noun. Enabling a plugin for a niche just inserts a row that says this niche &lt;em&gt;may&lt;/em&gt; draw from this source if something asks it to. It's a capability grant, not a subscription. The thing that actually asks -- the tap -- is a completely separate table, keyed by niche and source, carrying its own schedule, its own cursor, its own last-run timestamp. Nothing in the plugin table points at it, and nothing in the plugin dashboard reads from it either. So the UI we were checking every few days showed a green checkmark next to &lt;code&gt;search_autocomplete&lt;/code&gt; for the entire six weeks, and the green checkmark was telling the truth about the wrong question. It was answering "is this niche allowed to use this source," which was yes, instead of "is anything actually calling this source on a schedule," which was no.&lt;/p&gt;

&lt;p&gt;This is the quiet failure mode that eats automated pipelines: a thing that is "on" in every config you'd think to check, and "off" in the one place that actually fires the cron job. We've hit this shape of bug before, in the queueing layer that runs our background jobs -- see &lt;a href="https://www.gladlabs.io/posts/the-solo-developers-background-job-dilemma-d39d051a?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;The Solo Developer's Background Job Dilemma&lt;/a&gt; for the Postgres LISTEN/NOTIFY version of the same lesson. A subscriber that never subscribes looks identical to a subscriber that has nothing to say.&lt;/p&gt;

&lt;p&gt;We fixed it with a migration: added &lt;code&gt;search_autocomplete&lt;/code&gt; and &lt;code&gt;gsc_query_gap&lt;/code&gt; tap rows for the Glad Labs niche, and gave both a 1.5x boost in the batch pre-rank, which up to that point only scored candidates on fit-to-goals and had no concept of actual search demand behind them. The boost wasn't arbitrary -- before the fix, a topic's score was a function of how well it matched our stated content goals, with no term in the equation for whether anyone was actually searching for it. That meant a beautifully on-strategy topic with zero search volume behind it would outrank a slightly-off-strategy topic that fifty people typed into Google that week. The 1.5x multiplier on tap-sourced candidates was our way of putting a thumb on the scale for "real demand exists," without letting it completely override fit -- a topic still has to clear a minimum fit bar before the demand boost even applies. Within minutes of deploy, the tap fired and the pool filled with real completions: "run llm locally on mac," "gguf quantization types," "llama.cpp vs ollama." Not personas. Not guesses. What people actually type.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we picked autocomplete over the alternatives
&lt;/h2&gt;

&lt;p&gt;We didn't default to autocomplete because it was easy. We had three real candidates for a search-demand source and had to pick one to build first: Google autocomplete, Reddit question mining, and Google Trends via pytrends.&lt;/p&gt;

&lt;p&gt;Trends gives you relative volume for a term you already have -- a validator, not a discovery tool. It can tell you if "gguf quantization" is trending up, but it can't hand you the term in the first place. You feed pytrends a keyword, and it hands back a normalized interest-over-time series for that exact keyword -- useful for deciding which of two topics you already know about is worth writing first, completely useless for finding a third topic you hadn't thought of. Reddit mining gets you real human questions, which is a different content shape entirely: you're answering a question someone posted, not ranking for a phrase someone typed into a box. A Reddit thread titled "why does my 7B model output garbage after quantizing" is a fully formed problem with context, frustration, and specifics baked in -- great source material for a troubleshooting post, but it's not a search query, and optimizing a title around it doesn't help you rank for the shorter, blunter phrase someone actually types when they hit the same wall. Useful, but not a substitute.&lt;/p&gt;

&lt;p&gt;Autocomplete does something neither of those does: it surfaces the literal query shape, generated from actual search behavior, for free, no API key. Type "run llm" into a search box and the completions you get back are exactly what other people finished typing before you. According to &lt;a href="https://neilpatel.com/blog/google-autocomplete/" rel="noopener noreferrer"&gt;Neil Patel&lt;/a&gt;, Google built the feature to save typing time -- by their own numbers, autocomplete cuts typing time by 25%. That's the pitch for users. For us, the side effect is the interesting part: it's a live, continuously-updated map of demand, expressed in the exact words people use.&lt;/p&gt;

&lt;p&gt;That's why we picked it first. It's the most direct substitute for traditional keyword research that doesn't cost anything to query. There's no volume number attached to any given completion, no way to know if "gguf quantization types" gets ten searches a month or ten thousand -- but the ranking of the suggestions themselves is a rough proxy, and for a solo pipeline with no keyword-tool budget, a rough proxy that costs nothing beats a precise number that costs a subscription. We can always layer Trends on top later to rank the completions we've already mined; we can't use Trends to generate the completions in the first place. That ordering -- discovery first, validation second -- is the whole reason autocomplete went in before either of the other two.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure mode that makes this dangerous
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F34eafe9f41f0.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F34eafe9f41f0.webp" alt="A stylized close-up of a mechanical hand attempting to fit a square peg into a round hole, where the peg is made of..." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the part that should worry anyone plugging a search box into an automated content pipeline: the words matter, and getting them wrong doesn't fail loudly.&lt;/p&gt;

&lt;p&gt;We'd already hit this once, with a different topic source. Our &lt;code&gt;web_search&lt;/code&gt; source had a tap configured with no seed queries and no categories, so it fell through to its last resort: build a query out of the niche name plus its target-audience tags. Those tags were things like &lt;code&gt;indie-devs&lt;/code&gt;, &lt;code&gt;ai-curious&lt;/code&gt;, &lt;code&gt;future-matt&lt;/code&gt; -- personas we use internally to describe &lt;em&gt;who reads the blog&lt;/em&gt;, not phrases anyone would ever type into a search engine. The system dutifully searched "Glad Labs indie-devs," got nothing useful back, and searched "Glad Labs" on its own -- which returned our own homepage, plus a couple of unrelated acronym collisions from unrelated labs and LinkedIn profiles that happen to share the initials. Three of five candidates in that batch were essentially the pipeline Googling itself.&lt;/p&gt;

&lt;p&gt;Walk through what that actually looked like downstream, because the batch didn't come back labeled "garbage" -- it came back looking like ordinary output. One candidate topic amounted to an explanation of what Glad Labs is, built from our own homepage title tag. It scored fine against our fit-to-goals rubric, because explaining what your own company does is a perfectly reasonable thing to write about in the abstract. Another candidate was built from a LinkedIn profile snippet belonging to someone at an unrelated company with the same initials, and it scored low but not zero, because the rubric had no term for "this entity is not us." Nothing in the scoring path asks "does this topic's source material actually describe the thing we think it describes." It just asks "does this material fit our stated goals," and self-referential noise fits almost anything, because it's vague enough to fit almost anything.&lt;/p&gt;

&lt;p&gt;Nothing downstream caught it. There was no check anywhere in the topic-source path that says "hey, don't recommend a blog post about our own homepage." That's the same failure category as the missing tap row -- silent, structurally invisible, and only obvious in hindsight once you trace the actual query string back to its source. In both cases the fix wasn't a smarter algorithm, it was a dumber, more literal check: does this tap row exist, does this query string contain the niche's own name paired with nothing else meaningful. Neither check requires any judgment. They just require someone to have thought to ask the question before the batch shipped, instead of after.&lt;/p&gt;

&lt;p&gt;If you're building anything that turns a search box into a content decision, that's the lesson: audit the literal string that gets sent to the query, not just the config that produced it. It's tempting to review the seed queries, the categories, the tags -- the inputs you deliberately wrote -- and assume that if those look reasonable, whatever the system builds from them will be reasonable too. That assumption is exactly where this bug lived. The seed config was empty, which looked like an oversight but not a dangerous one, right up until you traced what the fallback path actually did with an empty config. We wrote about the moment this clicked for us in &lt;a href="https://www.gladlabs.io/posts/the-poindexter-philosophy-68252b36?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;The Poindexter Philosophy&lt;/a&gt; -- typing a half-formed phrase into a search bar and discovering what actually comes back is a different exercise than assuming you know.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autocomplete isn't just a discovery tool -- it's also a liability
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F42e44d8b3da8.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F42e44d8b3da8.webp" alt="A stylized figure seen from behind, looking into a mirror. The reflection is not the person, but a fragmented..." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a second dimension to this that doesn't show up in a topic-source config at all: what autocomplete does to your reputation once it's attached your name to something you didn't say.&lt;/p&gt;

&lt;p&gt;Autocomplete surfaces what other people searched, not what's true about you. If enough people search "Glad Labs scam" or "Glad Labs lawsuit," Google will happily suggest it to the next person before they finish typing, regardless of whether it's accurate. &lt;a href="https://searchengineland.com/google-autocomplete-online-reputation-432106" rel="noopener noreferrer"&gt;Search Engine Land&lt;/a&gt; calls this exactly what it is: a silent threat to online reputation, because negative autocomplete suggestions shape a searcher's first impression before they've clicked anything. The mechanism is the same one we're exploiting for content ideas -- frequency of prior queries -- which means the exact feature we're using to find "run llm locally on mac" is, for someone else, surfacing "LM Studio refund complaints" to a prospective customer who hadn't even typed the word "refund" yet.&lt;/p&gt;

&lt;p&gt;And you can't fix it by yelling at the platform. Mike Masnick at Techdirt has covered this pattern repeatedly -- targeting a search engine directly over an unflattering autocomplete suggestion tends to make the problem worse, not better, because the complaint itself becomes a new signal, a new story, a new thing people search for. A takedown request, a public callout of Google, a lawsuit threat -- all of it generates coverage, and coverage generates searches, and searches are the raw material autocomplete is built from. The fix is never "make them take it down." It's changing the underlying search behavior that produced the suggestion in the first place, which is slow and mostly out of your hands.&lt;/p&gt;

&lt;p&gt;That's worth sitting with if you're treating autocomplete purely as a content-mining opportunity, the way we do. The same signal that tells you what people want to read about you is also, on the flip side, telling everyone else what people are already saying about you. It's a two-way mirror. You can point it outward to find demand. You can't stop other people from pointing it at you.&lt;/p&gt;

&lt;p&gt;Worth noting: this is a different "autocomplete" than the one an ecommerce site builds into its own search box -- the kind &lt;a href="https://www.doofinder.com/en/blog/autocomplete-in-search-engine" rel="noopener noreferrer"&gt;Doofinder&lt;/a&gt; writes best practices for, where the goal is conversions on your own site. On your own site's search box, you control the index, you control the ranking logic, and you can hand-tune a suggestion the moment it looks wrong -- it's your product surface end to end. Google's public autocomplete is a signal you can only read, never author. Don't confuse the two -- we've also written about a completely different sense of the word, code-editor autocomplete, in &lt;a href="https://www.gladlabs.io/posts/beyond-autocomplete-navigating-the-landscape-of-ai-510?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;Beyond Autocomplete: Navigating the Landscape of AI Coding Assistants in 2026&lt;/a&gt;. Three products, one overloaded term. There's even a whole party game built around guessing Google's completions -- Google Feud -- which tells you something about how deeply this feature has embedded itself in how people think about search.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mining demand is only half the job
&lt;/h2&gt;

&lt;p&gt;Getting real demand into the topic pool doesn't automatically mean you write something worth ranking. We learned that the hard way while fixing the tap-row bug, because the same pull request that added the autocomplete taps also shipped a completely separate fix: a gate on the titles those topics turn into.&lt;/p&gt;

&lt;p&gt;The problem: a topic can be exactly what people are searching for and still get written up under a title with no searchable entity in it -- nothing a person would actually type, no digit, no proper noun, no term pulled from the article's own keywords. A topic sourced straight from the phrase "gguf quantization types" could still ship under a title like "Understanding the Nuances of Modern Model Compression" -- accurate, on-brand, completely disconnected from the query that justified writing it in the first place. The demand signal did its job; the title-generation step just didn't preserve it. We went back through our own published titles and found the pattern held cleanly: every page that had ever earned a click passed a rule requiring a digit, a proper noun, or a term lifted from the article's own tags. Titles like "GGUF Quantization Types Explained" or "Llama.cpp vs Ollama: Which One Should You Run" cleared the bar on a proper noun alone. Titles like "4 Ways to Speed Up Local Inference" cleared it on the digit. Every title from a stretch of zero-click pages in our history failed that same rule -- the vague, adjective-heavy, entity-free kind, the sort of headline that reads fine to a human skimming a list but matches nothing anyone typed into a search box. That's not a coincidence you can argue with -- it's the data telling you what a searchable title actually looks like.&lt;/p&gt;

&lt;p&gt;So we added a gate. A canonical title has to clear that bar now. If it doesn't, the system gets one corrective regeneration, prompted with the article's own concrete terms pulled straight from its headings -- not a generic "make this more clickable" instruction, but the actual nouns and numbers already sitting in the body of the piece, fed back in as the raw material the rewrite has to work with. If the rewrite clears the bar, it ships. If it still doesn't, the original title ships anyway, but it lands on our findings board tagged &lt;code&gt;title_no_searchable_entity&lt;/code&gt; -- visible, not silently swallowed.&lt;/p&gt;

&lt;p&gt;That last part matters more than it sounds. We've had the opposite failure before too -- a ranking system quietly falling back to a weaker method a large share of the time, with that fallback rate treated as a rotated-out warning instead of a standing finding on the board. That's the failure mode we wrote about in &lt;a href="https://www.gladlabs.io/posts/the-trap-nobody-notices-until-output-breaks-249a74ca?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;The Trap Nobody Notices Until Output Breaks&lt;/a&gt;: output that looks finished, ships clean, and only reveals the gap once someone goes looking for why nothing is landing. A title that fails the searchability gate and gets buried in a log is exactly that trap -- one bad title is a rounding error, nobody checks, and a month later a quarter of your published titles are running on autopilot with nothing a search engine can latch onto, and the only way to find that out is to go digging through logs nobody had a reason to open. A title that fails the gate and shows up as a finding is a system you can actually act on: it accumulates on a board you already check, it's countable, and a spike in that count is itself a signal that something upstream -- a prompt, a model, a source -- degraded before it costs you a month of traffic.&lt;/p&gt;

&lt;p&gt;Put those two fixes side by side and you get the real shape of the autocomplete dilemma for anyone building an automated content pipeline. It's not enough to mine the right demand signal. You also have to make sure what you produce from that signal is shaped the way the signal itself is shaped -- as a phrase a real person would type, recognize, and click.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this actually means if you're building your own
&lt;/h2&gt;

&lt;p&gt;If you're a solo dev wiring a search-demand source into anything -- a content pipeline, a product-discovery tool, an internal search box -- take three things from this:&lt;/p&gt;

&lt;p&gt;First, "enabled" and "running" are not the same state, and your dashboards will lie to you about the difference unless you specifically check for it. A feature flag on, a config seeded, a plugin permission granted -- none of that guarantees a scheduler actually picked the job up. Verify the thing fired, not that it was allowed to. Concretely: don't trust a green checkmark next to a source's name unless you know exactly which table it's reading from, and whether that table records permission or execution. If you can't answer that question in ten seconds, go check the actual last-run timestamp on the thing you think is running, not the toggle that says it's supposed to be.&lt;/p&gt;

&lt;p&gt;Second, audit the literal string your system sends to a search box, not the config that generated it. Persona tags, category labels, internal shorthand -- none of that behaves like a search query, and nothing downstream will stop it from being treated like one unless you build that check yourself. We didn't have one, and it cost us a batch of candidates that were essentially the pipeline Googling its own homepage. The check itself is cheap once you know to write it: does the outbound query contain the niche or brand name with nothing else substantive attached, and if so, throw it out before it ever reaches the search API, rather than trusting the results that come back to look obviously wrong.&lt;/p&gt;

&lt;p&gt;Third, remember that a public autocomplete feed cuts both ways. You can read it to find demand. You cannot control what it says about you, and trying to strong-arm the platform into removing an unflattering suggestion tends to backfire rather than fix anything. Treat it as a one-way instrument for discovery, and treat your own reputation on it as something you influence slowly, by changing what people actually search, not by complaining about what the box shows.&lt;/p&gt;

&lt;p&gt;We're running with all of this now -- two demand taps live, a rank weight that actually values them, and a title gate that won't let a topic slip through with nothing searchable in its headline. It took a silent six-week gap and a self-search bug to get there. If you're building the same kind of pipeline, you can skip both of those and go straight to the version that works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://neilpatel.com/blog/google-autocomplete/" rel="noopener noreferrer"&gt;https://neilpatel.com/blog/google-autocomplete/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://searchengineland.com/google-autocomplete-online-reputation-432106" rel="noopener noreferrer"&gt;https://searchengineland.com/google-autocomplete-online-reputation-432106&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.doofinder.com/en/blog/autocomplete-in-search-engine" rel="noopener noreferrer"&gt;https://www.doofinder.com/en/blog/autocomplete-in-search-engine&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gladlabs.io/posts/our-google-autocomplete-topic-source-ran-for-6-wee-0748922a?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;www.gladlabs.io&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>searchautocomplete</category>
      <category>contentpipeline</category>
      <category>googleautocomplete</category>
      <category>dataingestion</category>
    </item>
    <item>
      <title>Faithfulness in AI Content Isn't About Tone--It's About Whether Claims Are True</title>
      <dc:creator>Matthew Gladding</dc:creator>
      <pubDate>Tue, 08 Sep 2026 11:40:34 +0000</pubDate>
      <link>https://dev.to/glad_labs/faithfulness-in-ai-content-isnt-about-tone-its-about-whether-claims-are-true-5ckn</link>
      <guid>https://dev.to/glad_labs/faithfulness-in-ai-content-isnt-about-tone-its-about-whether-claims-are-true-5ckn</guid>
      <description>&lt;p&gt;Type "faithful content creation" into a search bar and you'll mostly get ministry blogs. Christian social media agencies talk about it as sharing faith, building trust, inspiring real connection. The Orthodox Church frames it as the newest arena for an old proclamation -- the Gospel adapted to whatever medium the age demands, as one recent essay puts it. Both are honest uses of the word. Neither is the one we mean.&lt;/p&gt;

&lt;p&gt;In an AI content pipeline, "faithful" has a narrower, colder definition. It means: does the output match the source. Nothing more mystical than that. And it turns out that definition is harder to hit than it sounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "faithful" actually measures
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.llamaindex.ai/glossary/content-faithfulness" rel="noopener noreferrer"&gt;According to LlamaIndex's glossary&lt;/a&gt;, content faithfulness is a foundational quality metric in both AI-generated and human-authored workflows -- it measures how accurately output reflects its source material. That's the whole spec. Not "is it well-written." Not "does it sound smart." Does the claim in paragraph three trace back to something that's actually true, or did the model just produce something plausible-sounding and confident?&lt;/p&gt;

&lt;p&gt;Concretely: a model asked to summarize a GPU launch might write that a card "delivers 40% faster ray tracing than its predecessor at the same power draw." That sentence is fluent, specific, and exactly the kind of claim a reader would quote elsewhere. It's also either true or false, and the model has no internal mechanism that distinguishes "I read this number in the source doc" from "this is the kind of number that usually appears in sentences like this." Faithfulness is the metric that asks, after the fact, which of those two things actually happened.&lt;/p&gt;

&lt;p&gt;That distinction matters more the bigger your pipeline gets. A human writer who fudges a stat gets caught by an editor who knows the beat. An LLM generating fifty posts a week doesn't have that instinct -- it has a next-token predictor that's very good at sounding certain about things it made up. Content faithfulness is the metric you build specifically because that failure mode is invisible until someone checks.&lt;/p&gt;

&lt;p&gt;We found this out the hard way. We run a pipeline that publishes technical content on AI, gaming, and hardware -- not devotional content, not ministry copy, but the same underlying problem: a system generating text at volume needs a way to know when that text has drifted from the truth. Faithfulness isn't a nice-to-have feature. It's the thing that decides whether your business is a content generator or a bullshit generator with good production values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Grounding output instead of hoping for the best
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F2d60d8cebfd7.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F2d60d8cebfd7.webp" alt="A stylized isometric view of a digital pipeline. On one side, a chaotic cloud of floating fragments enters; in the..." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The naive approach to AI content is: prompt the model, take what it gives you, ship it. That works until it doesn't -- and when it fails, it fails in ways that are hard to catch because the output reads fine. Grammatically correct, confidently stated, wrong.&lt;/p&gt;

&lt;p&gt;We solve this with retrieval-augmented generation instead of relying on the model's internal weights. RAG pipelines pull from specific, verified data before the model writes a word, rather than letting it reconstruct facts from training-time memory. That's the difference between a model recalling something it half-remembers and a model quoting something it was just handed. Take the ray-tracing example above: a RAG step means the draft is written against a retrieved benchmark table, not against the model's fuzzy sense of "cards in this generation are usually faster." If the retrieved table says 28%, the draft says 28%, and there's a document trail showing where that number came from. Without that step, the model is free to round up, or to borrow a number from a different card entirely, because both errors are statistically indistinguishable from a correct answer at generation time.&lt;/p&gt;

&lt;p&gt;For technical hardware and ML coverage specifically -- where a wrong GPU spec or a misattributed benchmark is instantly checkable and instantly embarrassing -- that grounding step isn't optional.&lt;/p&gt;

&lt;p&gt;We wrote more about the mechanics of this in &lt;a href="https://www.gladlabs.io/posts/automating-ai-content-workflows-511012cc?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;Automating AI Content Workflows&lt;/a&gt;: the RAG layer, the agent architecture, the shift from manual prompting toward autonomous systems that read a spec and execute it. The faithfulness question sits underneath all of that. Automation without grounding just means you can produce unfaithful content faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  QA is the enforcement mechanism, not the marketing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F3d55bf0d1ed0.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F3d55bf0d1ed0.webp" alt="A stylized figure of a quality assurance engineer standing before a massive, glowing neon gate." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ensuring content accuracy through integrated QA processes is what actually builds customer trust and smooths onboarding -- not a claim about writing quality in the abstract, but a specific operational bet: readers trust a source once it's been wrong zero times, and they stop trusting it the first time it's caught fabricating.&lt;/p&gt;

&lt;p&gt;That means faithfulness can't live in a style guide. It has to live in a rail -- an automated check that runs on every piece before it ships, catching hallucinated claims, invented statistics, and quotes that don't trace to a real source.&lt;/p&gt;

&lt;p&gt;We run exactly this. Every post goes through an approval pass before it's published, and we track the rejection rate over time, not just the approval rate -- because a QA system that never rejects anything isn't checking, it's rubber-stamping. The per-reviewer breakdown matters too: if one reviewer approves everything and another catches issues constantly, that's a signal about calibration, not just about content quality.&lt;/p&gt;

&lt;p&gt;The same instinct shows up on the findings side. When a probe flags a fabricated stat, an unsupported claim, or a citation that points nowhere, that finding needs a severity and a routing policy -- does it block publication outright, or get flagged for human review, or pass with a note. A fabricated benchmark number in a headline is a block: it's the kind of claim a reader will screenshot and share, and it's wrong in a way that damages the outlet the moment it's caught. A vague but directionally true claim -- "the new chip is significantly more efficient" without a cited figure -- might get flagged for a human to tighten rather than killed outright, since the underlying claim is probably fine even if the phrasing is loose. A broken link in a citation that still points to the right domain, just the wrong page, might pass with a note to fix in the next editing pass. Not every faithfulness failure is equally dangerous, and treating them all the same either buries your reviewers in noise or lets the real ones through.&lt;/p&gt;

&lt;h2&gt;
  
  
  The morse code lesson
&lt;/h2&gt;

&lt;p&gt;We've been burned by this before, and we wrote about it plainly rather than pretending it didn't happen. In &lt;a href="https://www.gladlabs.io/posts/a-morse-code-headline-slipped-past-our-content-fil-28431849?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;A Morse Code Headline Slipped Past Our Content Filter&lt;/a&gt;, a headline got through review encoding something the filter wasn't built to catch, because the filter was checking for the failure modes we'd already thought of, not the ones we hadn't.&lt;/p&gt;

&lt;p&gt;That's the real lesson about faithful content creation at scale: your QA system is only as faithful as the failure modes you've anticipated. A rail built to catch hallucinated statistics won't catch an encoded message hiding in plain text. A rail built to catch broken citations won't catch a subtly reworded claim that changes the meaning of a real source -- the kind of edit where "the study found a modest correlation" quietly becomes "the study proved a strong link," and nothing about the surface form trips a citation checker because the citation itself is still perfectly valid. Faithfulness isn't a single check you bolt on once. It's a set of overlapping checks that grows every time you find a gap -- and you will find gaps, because the space of ways an automated system can drift from the truth is bigger than any one team's imagination on day one.&lt;/p&gt;

&lt;p&gt;We don't treat that incident as an embarrassment to bury. We treat it as the reason the QA rail has more layers now than it did before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where curation quietly breaks faithfulness
&lt;/h2&gt;

&lt;p&gt;There's a popular argument in AI content circles right now that says: don't create, curate. Aggregate what's already out there, wrap it in a bit of commentary, ship it faster than the people doing original work. We made the opposite case in &lt;a href="https://www.gladlabs.io/posts/the-curation-trap-why-builders-should-ignore-the-c-264c2e71?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;The Curation Trap: Why Builders Should Ignore the "Curation Over Creation" Trend&lt;/a&gt;, and faithfulness is a big part of why.&lt;/p&gt;

&lt;p&gt;Curation without verification is a faithfulness problem wearing a productivity costume. If you're summarizing fifty sources and you didn't check any of them, you've just laundered someone else's unfaithfulness -- or your model's misreading of it -- into your own byline. Picture a curation pipeline pulling in five articles about the same product launch: if one of the five already contains a slightly wrong spec, and your model's job is to synthesize a consensus summary across all five, that wrong spec doesn't get diluted out by the four correct sources. It gets folded in as one data point among several, and depending on how the summarization prompt weighs sources, it can just as easily survive the merge as get corrected by it. The errors compound instead of resetting. First-party reporting, grounded in sources you actually pulled and verified, is slower per-post but faithful by construction. Curation at volume is fast and unfaithful by default, unless you build the same verification rails into it that a first-party pipeline needs anyway -- at which point you haven't actually saved the work, you've just relabeled it.&lt;/p&gt;

&lt;p&gt;We made a related argument in &lt;a href="https://www.gladlabs.io/posts/why-first-party-content-strategy-is-the-only-one-l-d1979ebb?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;Why First-Party Content Strategy Is the Only One Left Standing&lt;/a&gt;: once everyone's LLM can regurgitate the same secondhand summary of an event, the only content with any value is the content that was actually grounded in something real to begin with. Faithfulness and first-party sourcing aren't two separate priorities. They're the same priority described from two angles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is a trust problem, not a style problem
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fb1b5c6ebad3f.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fb1b5c6ebad3f.webp" alt="A close-up of a stylized porcelain vase with one single, jagged black crack running down the side." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's tempting to file "faithfulness" under editorial quality, next to tone and grammar. That's a mistake. Faithfulness is a trust problem, and trust is transactional in a way tone isn't.&lt;/p&gt;

&lt;p&gt;A reader who catches your outlet in one fabricated statistic doesn't downgrade their opinion of your writing style. They downgrade their confidence in everything else you've published, retroactively. That's the asymmetry that makes faithfulness worth building rails for instead of hoping for. You can recover from a clunky sentence. You don't recover from a reader deciding your numbers can't be trusted -- they just stop reading, and they don't come back to check if you fixed it. Worse, they don't just distrust the piece with the error; they start re-reading your archive with suspicion, which means the cost of one bad statistic isn't one bad post, it's a discount rate applied to your entire back catalog.&lt;/p&gt;

&lt;p&gt;That's also why faithfulness matters more, not less, as AI content scales. A single human writer publishing twice a week can carry a reputation on the strength of their judgment alone. A pipeline publishing daily, across topics, with agents executing autonomously against a spec, doesn't have that luxury. The judgment has to be encoded into the system -- into the RAG layer that grounds the draft, into the QA rail that checks it, into the findings dashboard that tells you which kind of failure just got caught and whether it needs a human before it ships.&lt;/p&gt;

&lt;h2&gt;
  
  
  What faithful actually costs
&lt;/h2&gt;

&lt;p&gt;None of this is free. Grounding every claim in retrieved source data is slower than letting the model free-associate. Running a QA pass on every post before publication is slower than shipping the first draft. Building overlapping checks after every incident -- the way we did after the morse code headline got through -- is slower than declaring the filter "done" and moving on.&lt;/p&gt;

&lt;p&gt;The alternative is faster and it's also a trap. Content that isn't faithful doesn't fail loudly. It fails quietly, one reader at a time, until the aggregate trust in your outlet is gone and you're wondering why traffic that used to convert doesn't anymore. Faithfulness is the unglamorous infrastructure work that makes everything downstream of it -- onboarding, retention, being cited by other people as a source -- actually work.&lt;/p&gt;

&lt;p&gt;That's the version of "faithful content creation" worth building a business around. Not a devotional practice. An engineering discipline: ground the claim, check the claim, route the failures by severity, and treat every incident where something slipped through as a reason to add another layer instead of a reason to apologize and move on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.llamaindex.ai/glossary/content-faithfulness" rel="noopener noreferrer"&gt;https://www.llamaindex.ai/glossary/content-faithfulness&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gladlabs.io/posts/faithfulness-in-ai-content-isnt-about-tone-its-abo-faa0a9c6?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;www.gladlabs.io&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>faithfulnessinai</category>
      <category>aicontentaccuracy</category>
      <category>groundingaioutput</category>
      <category>contentfaithfulnessmetric</category>
    </item>
    <item>
      <title>How a GPU Lock Bug Was Quietly Wrecking Our RAG Sweep</title>
      <dc:creator>Matthew Gladding</dc:creator>
      <pubDate>Thu, 03 Sep 2026 22:40:49 +0000</pubDate>
      <link>https://dev.to/glad_labs/how-a-gpu-lock-bug-was-quietly-wrecking-our-rag-sweep-4f9b</link>
      <guid>https://dev.to/glad_labs/how-a-gpu-lock-bug-was-quietly-wrecking-our-rag-sweep-4f9b</guid>
      <description>&lt;p&gt;We run a sweep. Every cycle, a job walks through a queue of documents, hits the GPU, pulls context, writes results, moves to the next one. Simple in theory. In practice, it's a fight over a shared resource that doesn't want to share.&lt;/p&gt;

&lt;p&gt;That's what "sweep process optimization" means to us on a Tuesday afternoon. Not the elegant math version. The version where a pipeline validation run on 2026-06-19 exposed a GPU lock bug that had been quietly wrecking our internal RAG sweep, and we spent the day exorcising it (see &lt;a href="https://www.gladlabs.io/posts/fixing-the-gpu-lock-and-taming-the-internal-rag-sw-8d56383c?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;Fixing the GPU lock and taming the internal RAG sweep&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  What a sweep actually is
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Ffbf0cb4ab119.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Ffbf0cb4ab119.webp" alt="Man in dark clothing reaches toward a glowing blue grid with swirling light trails against a dark blue background." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A sweep process, stripped down, is a loop that has to stay inside a boundary that keeps moving. In our case, the boundary was GPU availability. The sweep job assumed the resource would be there when it asked. It wasn't always there. Other processes were holding the lock, releasing it late, or not releasing it at all. The sweep didn't fail loudly -- it just slowed, stalled, backed up, and started producing garbage timing under load.&lt;/p&gt;

&lt;p&gt;That's not a coincidence of naming. There's a whole branch of control theory built around exactly this shape of problem. A sweeping process, first studied by Moreau in the 1970s, describes a point that has to stay inside a set that's constantly in motion -- and the control problem is figuring out how to steer that point without letting it get shoved outside the boundary when the set moves. Uncontrolled versions have been around for decades; the controlled case, where you actually get to influence the moving set, is newer and has drawn serious attention from applied researchers in the last several years.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the math matters for a pipeline, not just a proof
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fc144c9795335.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fc144c9795335.webp" alt="Padlock with internal gears and U-shaped shackle." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You don't need to solve a variational inequality to fix a lock bug. But the framing is useful. Our GPU lock issue was, functionally, a perturbed constraint. The "safe set" for the sweep -- GPU free, memory available, no contention -- kept shifting because of other jobs on the box. When we treated the lock as static and just retried on failure, the sweep degraded unpredictably. Once we treated GPU availability as a moving boundary and built the sweep to track it explicitly -- checking state before committing, backing off cleanly, releasing early -- the whole thing stabilized.&lt;/p&gt;

&lt;p&gt;That maps onto research on &lt;a href="https://arxiv.org/html/2407.18469v1" rel="noopener noreferrer"&gt;perturbed sweeping processes&lt;/a&gt;, where the moving set isn't clean -- it's noisy, disturbed, reacting to outside forces. The convergence analysis in that line of work exists precisely because real systems don't get a tidy, predictable constraint. Ours didn't either. Our cadvisor leak and the OOM cascade that nearly took down the WSL2 VM was the same pattern wearing a different hat: a resource boundary moving under us while a loop kept assuming it was fixed (see &lt;a href="https://www.gladlabs.io/posts/taming-the-cadvisor-leak-and-cleaning-up-llm-garba-3361e7c5?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;Taming the cadvisor leak and cleaning up LLM garbage&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  The practical version
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F4e71c7b973cd.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F4e71c7b973cd.webp" alt="Finger touches a knob with glowing purple ring on dark device; other knobs visible." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're running any kind of sweep -- a batch inference loop, a training scheduler, a scraper hammering a rate-limited API -- assume your constraint set moves. Don't hardcode "GPU is free" or "rate limit resets every 60 seconds" as gospel. Check state at the point of contact. Build in backoff that reacts to the actual boundary, not the boundary you expected an hour ago.&lt;/p&gt;

&lt;p&gt;The formal theory, including work presented by &lt;a href="https://www.youtube.com/watch?v=0QmbFM0qyho" rel="noopener noreferrer"&gt;Boris Mordukhovich on optimal control of perturbed sweeping processes&lt;/a&gt;, exists because this is a hard problem even with clean math. Our version had cadvisor logs and a GPU that didn't want to let go. Different mess, same shape.&lt;/p&gt;

&lt;p&gt;Optimize the sweep by respecting the boundary, not by pretending it holds still.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2407.18469v1" rel="noopener noreferrer"&gt;https://arxiv.org/html/2407.18469v1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=0QmbFM0qyho" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=0QmbFM0qyho&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gladlabs.io/posts/how-a-gpu-lock-bug-was-quietly-wrecking-our-rag-sw-9bdb7f9a?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;www.gladlabs.io&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>sweepprocess</category>
      <category>gpulockbug</category>
      <category>ragpipeline</category>
      <category>pipelinevalidation</category>
    </item>
    <item>
      <title>When the Page-View Cursor Outruns the Data</title>
      <dc:creator>Matthew Gladding</dc:creator>
      <pubDate>Tue, 01 Sep 2026 13:08:14 +0000</pubDate>
      <link>https://dev.to/glad_labs/when-the-page-view-cursor-outruns-the-data-4lfa</link>
      <guid>https://dev.to/glad_labs/when-the-page-view-cursor-outruns-the-data-4lfa</guid>
      <description>&lt;p&gt;&lt;em&gt;What we shipped on 2026-09-01&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We spent today chasing ghosts in our telemetry, starting with a silent failure in &lt;code&gt;SyncCloudflareAnalyticsJob&lt;/code&gt; (PR #3523). We discovered that Cloudflare Analytics Engine has a non-zero visibility delay--a data point is written, but it isn't queryable the instant &lt;code&gt;writeDataPoint&lt;/code&gt; returns. Because we were using a high-water-mark cursor (&lt;code&gt;WHERE timestamp &amp;gt; '{since}'&lt;/code&gt;), any row that surfaced after our poll had already advanced the watermark was effectively deleted from our history. On low-traffic pages, where empty responses often pushed the cursor straight to &lt;code&gt;now()&lt;/code&gt;, we were simply losing page views forever without a single error log to warn us.&lt;/p&gt;

&lt;p&gt;While auditing infrastructure, we found another "loaded gun" in our affiliate redirect Worker (PR #3520). The &lt;code&gt;wrangler.toml&lt;/code&gt; committed to git had placeholders for the R2 host, but the live Worker was running with the real production URL. Since &lt;code&gt;wrangler deploy&lt;/code&gt; is declarative, any clean-checkout deployment would have overwritten the working binding and taken every &lt;code&gt;/go/&amp;lt;slug&amp;gt;&lt;/code&gt; link offline. We've moved these to deploy-proof secrets now that we know exactly how close we were to a total redirect blackout.&lt;/p&gt;

&lt;p&gt;The QA pipeline had also gone quiet in a way we didn't notice immediately (PR #3519). Three of our LLM rails--&lt;code&gt;deepeval_g_eval&lt;/code&gt;, &lt;code&gt;deepeval_faithfulness&lt;/code&gt;, and &lt;code&gt;ragas_eval&lt;/code&gt;--were returning zero reviews on 100% of passes. The culprit was the constrained-decoding fix from a previous sprint: we were sending &lt;code&gt;response_format={"type":"json_object"}&lt;/code&gt; to thinking judges. Because these models must emit a reasoning trace before the JSON answer, the constraint forced them into an immediate stop, resulting in empty content and &lt;code&gt;JSONDecodeError&lt;/code&gt;. Withholding JSON mode for thinking judges revived all three rails instantly.&lt;/p&gt;

&lt;p&gt;On the GPU side, we had to fix a regression we shipped an hour prior (PR #3524). We realized that &lt;code&gt;/unload&lt;/code&gt; lacked an in-flight guard, meaning a concurrent VRAM reclaim could self-exit the process while a render was still active. We've now mirrored our WAN contract: we track in-flight generations and decline unloads until they finish. In this case, obeying the reclaim request is strictly worse than declining it, as the running render is exactly what that VRAM is currently serving. This ties into a broader effort to verify every hard reclaim rung across ComfyUI, wan, image-gen, and stable-audio (PR #3516).&lt;/p&gt;

&lt;p&gt;We also finally broke the "upload once" limitation of our YouTube integration (PR #3518). Previously, we had no way to fix metadata for videos already on the channel--meaning twelve videos were stuck with 4,800-character markdown walls in their descriptions. We implemented &lt;code&gt;adapter.update_metadata()&lt;/code&gt; using a read-modify-write pattern to ensure that updating the description doesn't accidentally blank the title or category IDs.&lt;/p&gt;

&lt;p&gt;We closed out the day by admitting our README was rotting (PR #3522). Our marketing stats--live post counts, test totals, and DB settings--were hand-typed and stale. We've refreshed them and wired them into a nightly sync using &lt;code&gt;collect_stats()&lt;/code&gt; (PR #3526, PR #3527), so the README and CLAUDE.md can no longer drift apart from reality.&lt;/p&gt;

&lt;p&gt;It was a day of closing gaps--some in our data, some in our infrastructure, and some in our documentation. We're moving toward a state where the system tells us it's broken before the users do.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Auto-compiled by Poindexter from today's commits and PRs. &lt;a href="https://github.com/Glad-Labs/poindexter" rel="noopener noreferrer"&gt;See the work: github.com/Glad-Labs/poindexter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Glad-Labs/poindexter" rel="noopener noreferrer"&gt;https://github.com/Glad-Labs/poindexter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gladlabs.io/posts/when-the-page-view-cursor-outruns-the-data-5c51d839?utm_source=devto&amp;amp;utm_medium=syndication" rel="noopener noreferrer"&gt;www.gladlabs.io&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cloudflareanalyticsengine</category>
      <category>highwatermarkcursor</category>
      <category>visibilitydelay</category>
      <category>wranglerdeploysecrets</category>
    </item>
    <item>
      <title>A 4-Bit Model Just Beat Its Full-Precision Original</title>
      <dc:creator>Matthew Gladding</dc:creator>
      <pubDate>Mon, 31 Aug 2026 18:40:48 +0000</pubDate>
      <link>https://dev.to/glad_labs/a-4-bit-model-just-beat-its-full-precision-original-416n</link>
      <guid>https://dev.to/glad_labs/a-4-bit-model-just-beat-its-full-precision-original-416n</guid>
      <description>&lt;p&gt;Here's the sentence that should stop you mid-scroll: a compressed, 4-bit model that outperforms its full-precision parent. Not "close to." Not "acceptable loss." Better.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fe293c88c6112.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fe293c88c6112.webp" alt="Large black server rack with yellow/blue cables emits blue light toward smaller black server unit" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We've written before about the VRAM tax you pay to run anything decent locally -- 140GB for a 70B model in FP16, which is why quantization exists in the first place. You shrink the weights, you pay in accuracy, you hope the tradeoff is worth it. That's been the deal since day one. A new paper says the deal just changed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The recipe
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fe02cf756d729.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fe02cf756d729.webp" alt="Human heart merged with glowing blue circuitry patterns on a black background." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A team including researchers from Multiverse Computing published &lt;a href="https://arxiv.org/abs/2608.20953v1" rel="noopener noreferrer"&gt;Quantization-Aware Healing&lt;/a&gt;, or QAH -- a recovery method for models that have been both structurally compressed (fewer parameters) and quantized down to 4 bits. That's two compounding cuts, and the paper's framing is blunt about what they do to a model: they degrade reasoning, math, coding, and long-context behavior enough that you need a healing stage before you'd ship the thing.&lt;/p&gt;

&lt;p&gt;The industry-standard fix for that has been quantization-aware training, QAT -- bake the quantization noise into training itself so the model learns to compensate. It works, but it's slow and finicky. The QAH team skipped it. Instead, according to the &lt;a href="https://huggingface.co/papers/2608.20953" rel="noopener noreferrer"&gt;paper's abstract&lt;/a&gt;, they distill directly from the original uncompressed model into the compressed one. The teacher is the full-precision model. The student is the 4-bit version. The student's job isn't to relearn the task from scratch -- it's to match the teacher's behavior while operating inside a much smaller weight space.&lt;/p&gt;

&lt;p&gt;That distinction matters more than it sounds like. QAT tries to make quantization hurt less during training. QAH treats quantization as done and then heals what broke, using the original model as the ground truth the whole way through. The paper reports this converges faster and more stably than QAT -- a straightforwardly practical win before you even get to the headline result.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why "outperforms" isn't a typo
&lt;/h3&gt;

&lt;p&gt;The genuinely strange part is the outcome, not just the efficiency of getting there: the healed 4-bit model doesn't just recover lost ground, it comes out ahead of the original. If you've spent time picking between &lt;a href="https://www.gladlabs.io/posts/choosing-a-quantization-format-for-local-llm-infer-5466fd20" rel="noopener noreferrer"&gt;Q4_K_M, Q5_K_M, and Q8_0 quantization formats&lt;/a&gt; for local inference, you know the mental model everyone operates on: higher precision is a ceiling, quantization always gives some of it back. QAH says that ceiling was never fixed -- it was a function of how the compressed model was trained, not an inherent property of the bit width.&lt;/p&gt;

&lt;p&gt;That reframes what "4-bit" means. It's not automatically "smaller, worse, cheaper." Distillation-based healing turns the compression step into an opportunity to re-teach the model, and if the teacher signal is good enough, the student can end up sharper than the model it was copied from.&lt;/p&gt;

&lt;h3&gt;
  
  
  What this means if you're running local models
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Ffb75052b8d97.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Ffb75052b8d97.webp" alt="A stylized figure of a developer sitting at a desk with a single, small consumer GPU." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're serving models cheaply -- which is the exact framing the QAH paper opens with -- this is the direction to watch. A model that's structurally smaller and 4-bit and still beats FP16 on the tasks you care about isn't a compromise. It's just a better model that happens to fit in less memory. We've talked about squeezing more context out of a fixed VRAM budget with &lt;a href="https://www.gladlabs.io/posts/why-kv-cache-quantization-matters-for-long-context-ce1f7499" rel="noopener noreferrer"&gt;KV cache quantization&lt;/a&gt;; QAH is the same instinct applied to the weights themselves -- stop treating compression as a tax and start treating it as a training signal you can optimize against. If distillation-based healing generalizes past this paper, "full precision" stops being the ceiling anyone quotes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2608.20953v1" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2608.20953v1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/papers/2608.20953" rel="noopener noreferrer"&gt;https://huggingface.co/papers/2608.20953&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>quantizationawarehealing</category>
      <category>qah</category>
      <category>modelcompression</category>
      <category>bitquantization</category>
    </item>
    <item>
      <title>Why Great Content Dies Without an Amplification System</title>
      <dc:creator>Matthew Gladding</dc:creator>
      <pubDate>Mon, 31 Aug 2026 06:40:48 +0000</pubDate>
      <link>https://dev.to/glad_labs/why-great-content-dies-without-an-amplification-system-4mjj</link>
      <guid>https://dev.to/glad_labs/why-great-content-dies-without-an-amplification-system-4mjj</guid>
      <description>&lt;p&gt;You can write the best technical breakdown of &lt;a href="https://www.gladlabs.io/go/asus-rog-astral-nvidia-geforce-rtx" rel="noopener noreferrer"&gt;ASUS ROG Astral RTX 5090&lt;/a&gt; memory bandwidth on the internet. Nobody cares. Not because it's bad -- because it's invisible. It sits on your site with zero backlinks, zero social signal, and a robots.txt file for company. Content amplification is the answer to that problem, and most technical teams treat it like an afterthought instead of a system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F5bd1763b1156.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F5bd1763b1156.webp" alt="Low-poly human figure holds glowing blue tablet against black backdrop." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Content amplification is the practice of pushing your published content out to a wider audience through paid, earned, and owned channels rather than waiting for people to stumble onto it. Simple definition. Hard execution. We've covered &lt;a href="https://www.gladlabs.io/posts/automating-ai-content-workflows-511012cc" rel="noopener noreferrer"&gt;automating AI content workflows&lt;/a&gt; elsewhere, and we care a lot about the generation side. Amplification is the other half of that equation, and it's the half most people skip.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why generation without distribution is a dead end
&lt;/h2&gt;

&lt;p&gt;We built &lt;a href="https://www.gladlabs.io/posts/scaling-your-content-pipeline-without-the-ai-spam-937c35bb" rel="noopener noreferrer"&gt;Poindexter&lt;/a&gt; to scale our own content pipeline without turning into an AI spam farm. That solved a real bottleneck -- the operational drag of humans manually writing, editing, and publishing every post, which we broke down in &lt;a href="https://www.gladlabs.io/posts/the-operational-cost-of-manual-content-21425fe2" rel="noopener noreferrer"&gt;our piece on the operational cost of manual content&lt;/a&gt;. But solving throughput doesn't solve reach. A pipeline that publishes fifty well-researched posts a month into a void is just an expensive void.&lt;/p&gt;

&lt;p&gt;This is the trap: teams optimize the part they can measure easily -- words shipped, posts live, cadence hit -- and skip the part that's harder to instrument, which is whether anyone actually saw the thing. &lt;a href="https://cognitiveseo.com/blog/13363/content-amplification/" rel="noopener noreferrer"&gt;Cognitive SEO found that businesses using structured amplification techniques saw traffic gains of 327% more compared to publishing alone.&lt;/a&gt; That's not a subtle difference. That's the difference between a strategy and a hobby.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distribution channels are infrastructure, not marketing fluff
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F07efb71c054d.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F07efb71c054d.webp" alt="White hub with 16 outer dots connected by lines on teal background" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Treat your distribution channels the same way you'd treat your build pipeline: as infrastructure that needs monitoring, versioning, and failure handling. Barry Feldman's framework, covered on BuzzSumo, breaks amplification into owned, earned, and paid -- and the mistake most technical teams make is assuming owned channels (your blog, your newsletter, your GitHub) will amplify themselves. They won't. Owned channels are necessary but not sufficient.&lt;/p&gt;

&lt;p&gt;We've argued before that &lt;a href="https://www.gladlabs.io/posts/why-first-party-content-strategy-is-the-only-one-l-d1979ebb" rel="noopener noreferrer"&gt;first-party content strategy is the only one left standing&lt;/a&gt; as third-party platforms tighten their algorithms and kill referral traffic. That's still true. But first-party ownership only wins if you're actively pushing traffic toward it -- syndication to relevant communities, cross-posting to platforms where your audience already lives, paid boosts on posts that are already converting organically. Owning the asset means nothing if nobody's directed at the door.&lt;/p&gt;

&lt;h2&gt;
  
  
  Amplification without validation is how bad content scales fast
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fa4914a628785.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2Fa4914a628785.webp" alt="A person stands beside a gray machine emitting red cubes with blue accents." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the part that gets skipped in every "content amplification" listicle: amplification multiplies whatever you feed it. Good content, amplified, compounds. Bad content, amplified, compounds faster and does more damage.&lt;/p&gt;

&lt;p&gt;We learned this the hard way. A &lt;a href="https://www.gladlabs.io/posts/a-morse-code-headline-slipped-past-our-content-fil-28431849" rel="noopener noreferrer"&gt;morse code headline slipped past our content filter&lt;/a&gt; -- a validation gap that, if it had hit a post already in an amplification loop, would have pushed a broken headline to every channel we syndicate to instead of just sitting quietly on our own site. The fix isn't "amplify less." The fix is "validate before you amplify." Treat your content QA the same way you'd treat a CI gate before a deploy -- nothing goes to the distribution layer until it passes.&lt;/p&gt;

&lt;p&gt;This is also why we're skeptical of amplification tactics that prioritize velocity over fit. &lt;a href="https://influxjuice.com/content-that-generates-traffic-smart-amplification-strategies-for-growth/" rel="noopener noreferrer"&gt;Influx Juice&lt;/a&gt; points out that most businesses fail to generate real traffic not because they lack content, but because they don't understand what their audience is actually searching for or how to convey it clearly. Amplifying content that doesn't match search intent just gets you more bounces, faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this looks like technically
&lt;/h2&gt;

&lt;p&gt;For us, that means a few concrete things. Every post gets a validation pass before it enters the distribution queue -- not just spellcheck, a semantic check that the headline matches the body and the claims are grounded. Amplification channels are tiered: owned first (our site, our RSS, our newsletter), then targeted syndication to communities where indie devs and hardware tinkerers actually hang out, then paid boosts reserved for posts that already show organic pull. We don't spray content across every channel simultaneously -- that's how you end up amplifying noise. We covered the broader shift toward AI-driven distribution logic in &lt;a href="https://www.gladlabs.io/posts/the-secret-weapon-quietly-transforming-your-market-1d6a9318" rel="noopener noreferrer"&gt;how AI is quietly transforming marketing strategy&lt;/a&gt;, and amplification is the sharpest edge of that shift: the tools for targeting and timing distribution are getting good enough that "spray and pray" is now a strictly worse strategy than targeted, validated pushes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;Content amplification isn't a marketing bolt-on you add after the writing is done. It's infrastructure -- with its own failure modes, its own gates, and its own dependency on the quality of what you're feeding it. Build the validation layer first. Then build the distribution layer on top of it. Skip the order and you'll just be amplifying your mistakes at scale, which is a much worse problem than not being seen at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cognitiveseo.com/blog/13363/content-amplification/" rel="noopener noreferrer"&gt;https://cognitiveseo.com/blog/13363/content-amplification/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://influxjuice.com/content-that-generates-traffic-smart-amplification-strategies-for-growth/" rel="noopener noreferrer"&gt;https://influxjuice.com/content-that-generates-traffic-smart-amplification-strategies-for-growth/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>contentamplification</category>
      <category>technicalcontentdistribution</category>
      <category>paidearnedownedchannels</category>
      <category>contentpipelinescaling</category>
    </item>
    <item>
      <title>Spring Boot's 53.7% Admiration Score Explains Java's 2026 Framework Landscape</title>
      <dc:creator>Matthew Gladding</dc:creator>
      <pubDate>Fri, 28 Aug 2026 18:40:47 +0000</pubDate>
      <link>https://dev.to/glad_labs/spring-boots-537-admiration-score-explains-javas-2026-framework-landscape-e5b</link>
      <guid>https://dev.to/glad_labs/spring-boots-537-admiration-score-explains-javas-2026-framework-landscape-e5b</guid>
      <description>&lt;p&gt;You already know Spring Boot won. You knew it in 2023. You probably knew it in 2019. But "won" is doing a lot of work in that sentence, and if you're picking a framework for a new service this quarter, the interesting question isn't who's on top -- it's what's happening underneath.&lt;/p&gt;

&lt;p&gt;Here's the number, since you'll want it: Spring Boot sits at roughly 14.7% usage across all web frameworks in the 2025 Stack Overflow Developer Survey, with a 53.7% admiration score. That admiration number matters more than the usage share. Plenty of tech gets used because it's already there -- legacy, momentum, whatever. Admiration means people who use it by choice would choose it again. Spring Boot clears both bars.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Spring Boot still eats the room
&lt;/h3&gt;

&lt;p&gt;Largest ecosystem. Best docs. Most active community. Strongest cloud-native tooling. That's &lt;a href="https://rollbar.com/blog/most-popular-java-web-frameworks/" rel="noopener noreferrer"&gt;the case laid out by Rollbar's 2026 comparison&lt;/a&gt;, and none of it is controversial -- it's just true. If you're starting a new Java web project this year, you should probably just use Spring Boot. Not because it's exciting. Because it's the default for a reason, and the reason hasn't gone away.&lt;/p&gt;

&lt;p&gt;What has changed is what's bolted on top of it. Spring AI shipped built-in support for wiring LLM calls, embeddings, and vector stores directly into the Spring context -- the same dependency-injection model you already use for a database connection now works for a model call. If you've been following our writing on local RAG pipelines with Ollama and pgvector, this is the same idea showing up inside the Spring ecosystem instead of a bespoke Python service. You don't need a separate microservice just to hit an embedding model anymore. That's a real shift in how enterprise Java teams are architecting AI features, and it's arguably the biggest thing that's happened to Spring in years -- not a new core feature, but a new category bolted onto the old core.&lt;/p&gt;

&lt;h3&gt;
  
  
  The specialists didn't go away -- they got sharper
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F29ea1cbd276c.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F29ea1cbd276c.webp" alt="Laser cutter emits bright orange beam on clear glass surface." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Spring Boot winning the popularity contest doesn't mean the alternatives are dying. They're doing the opposite: getting more specific about what they're for.&lt;/p&gt;

&lt;p&gt;Quarkus has matured into a serious cloud-native option, built around sub-second startup times. If you're running containers that scale to zero and back, or you're paying per cold start on a serverless platform, that number isn't a nice-to-have. It's the difference between a request timing out and a request succeeding.&lt;/p&gt;

&lt;p&gt;Micronaut goes further in the same direction -- minimal memory footprint, tuned specifically for serverless, according to daily.dev's 2026 framework rundown. If your bill is dominated by memory-seconds rather than raw compute, that's the framework doing the actual cost optimization for you, not a config flag you have to hunt down.&lt;/p&gt;

&lt;p&gt;Jakarta EE is still there for the standards crowd -- enterprise teams that need portability across app servers and vendors, where "we can swap providers if we need to" is a contractual requirement, not a preference.&lt;/p&gt;

&lt;p&gt;And Vaadin sits in its own lane entirely: full-stack web development in pure Java, no separate frontend framework, no context-switching between Java on the backend and TypeScript on the frontend. That's a real productivity argument for teams where the whole stack is Java people, and hiring a dedicated frontend engineer isn't in the budget.&lt;/p&gt;

&lt;p&gt;None of these are trying to dethrone Spring Boot. They're each solving a problem Spring Boot solves adequately but not optimally -- cold starts, memory, standards compliance, frontend duplication. That's a healthy ecosystem. A framework landscape where everything converges on one tool is usually a sign the tool is mediocre and nobody's built anything better yet. This is the opposite -- one dominant generalist, several sharp specialists, and clear reasons to pick each one.&lt;/p&gt;

&lt;h3&gt;
  
  
  What this means if you're actually shipping something
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F1a016cef0277.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F1a016cef0277.webp" alt="A stylized illustration of a software engineer standing before two paths: one is a wide, well-lit paved highway with..." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't pick a framework because it's the most popular. Pick it because your constraints match what it's optimized for.&lt;/p&gt;

&lt;p&gt;If you're building a standard web service, internal tool, or API and you're not fighting cold-start latency or a tight memory budget, Spring Boot is the boring, correct choice. The ecosystem does the heavy lifting -- you'll find a library for whatever you're missing, and Stack Overflow already has the answer to whatever error you're staring at.&lt;/p&gt;

&lt;p&gt;If you're deploying into a serverless or heavily containerized environment where startup time and memory directly hit your cloud bill, look hard at Quarkus or Micronaut before you default to Spring. The sub-second startup Quarkus is built around isn't marketing -- it's the actual mechanism that makes scale-to-zero economical instead of painful.&lt;/p&gt;

&lt;p&gt;If you're locked into a regulated environment that demands vendor portability, Jakarta EE is your answer, and you probably already know that, because someone above you already told you.&lt;/p&gt;

&lt;p&gt;And if your team is Java-only and you don't want to hire or maintain a separate frontend stack, Vaadin removes an entire category of coordination overhead -- no API contract negotiations between backend and frontend teams, because there's only one team.&lt;/p&gt;

&lt;h3&gt;
  
  
  The AI layer is the actual story for 2026
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F2e4c3ad152dc.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub-1432fdefa18e47ad98f213a8a2bf14d5.r2.dev%2Fimages%2Finline%2F2e4c3ad152dc.webp" alt="Blue polyhedral cubes connected by glowing golden rods; one central cube with surrounding cubes." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Strip away the framework names and the real headline is this: Java's AI tooling caught up. For a couple of years, if you wanted to build something with LLMs, you reached for Python almost by reflex -- the libraries were there, the Java equivalents weren't. Spring AI closes that gap inside the framework most Java developers already use daily. That matters more for adoption than any startup-time benchmark, because it removes the reason enterprise teams were quietly spinning up parallel Python services just to touch a model.&lt;/p&gt;

&lt;p&gt;We've written before about how developer productivity tooling quietly evolved in 2026 -- less about flashy new tools, more about existing tools absorbing capabilities that used to require a separate stack. Spring AI is that pattern playing out inside Java specifically. The framework didn't get replaced. It got wider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where this leaves you
&lt;/h3&gt;

&lt;p&gt;Spring Boot is still the default, and defaults win for good reasons -- ecosystem depth, hiring pool, documentation, the fact that any problem you hit has already been hit by ten thousand people before you. But "default" isn't the same as "only correct answer." If your constraints are cold starts, memory, standards compliance, or frontend duplication, one of the specialists will save you real engineering time that Spring Boot would cost you fighting the same problem with extra configuration.&lt;/p&gt;

&lt;p&gt;Pick based on your constraints, not the leaderboard. The leaderboard tells you what most teams need. It doesn't tell you what yours does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://rollbar.com/blog/most-popular-java-web-frameworks/" rel="noopener noreferrer"&gt;https://rollbar.com/blog/most-popular-java-web-frameworks/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javaframeworks2026</category>
      <category>springboot</category>
      <category>springai</category>
      <category>cloudnativetooling</category>
    </item>
  </channel>
</rss>
