<?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: Paul Crinigan</title>
    <description>The latest articles on DEV Community by Paul Crinigan (@paulcrinigan).</description>
    <link>https://dev.to/paulcrinigan</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%2F4016742%2F907d8a95-0aa5-48ee-816a-54db6658869b.png</url>
      <title>DEV Community: Paul Crinigan</title>
      <link>https://dev.to/paulcrinigan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/paulcrinigan"/>
    <language>en</language>
    <item>
      <title>Branching Stories Are Expensive, Responsive Ones Are Not</title>
      <dc:creator>Paul Crinigan</dc:creator>
      <pubDate>Sun, 26 Jul 2026 00:19:39 +0000</pubDate>
      <link>https://dev.to/paulcrinigan/branching-stories-are-expensive-responsive-ones-are-not-2l80</link>
      <guid>https://dev.to/paulcrinigan/branching-stories-are-expensive-responsive-ones-are-not-2l80</guid>
      <description>&lt;p&gt;Narrative design is the part of a game that most small teams either skip or overbuild, and both failures look the same from the outside: players finish and remember nothing.&lt;/p&gt;

&lt;p&gt;The fix is not more writing. It is deciding which parts of the story your systems carry, and refusing to pay for the parts players never notice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Story, Narrative, And Lore Are Three Different Jobs
&lt;/h2&gt;

&lt;p&gt;Story is what happens. The hero leaves home, finds a threat, wins or loses.&lt;/p&gt;

&lt;p&gt;Narrative is how the player experiences it, through cutscenes, dialogue, environment, and their own actions.&lt;/p&gt;

&lt;p&gt;Lore is why the world is the way it is, the ancient war, the founding of the kingdom, the rules of the magic.&lt;/p&gt;

&lt;p&gt;The common mistake is overinvesting in lore. A wiki of world history gives a player no reason to care in the present tense. Soulsborne games get away with deep fragmented lore because the moment to moment play already has you, and the lore rewards you afterwards. For a browser game, a clear character with a clear goal facing a clear obstacle beats twenty pages of mythology every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Players Actually Notice About Choice
&lt;/h2&gt;

&lt;p&gt;True branching is exponential. If every choice creates two paths, five choices is 32 unique routes, each needing writing, scripting, testing, and possibly voice. Almost nobody can pay for that, which is why most choice systems converge back to the same beats.&lt;/p&gt;

&lt;p&gt;That is fine, because players are not auditing the branch count. They notice three things:&lt;/p&gt;

&lt;p&gt;Did the game acknowledge my choice immediately.&lt;/p&gt;

&lt;p&gt;Does this character treat me differently now.&lt;/p&gt;

&lt;p&gt;Did the choice pay off later, in a way that felt earned or interestingly challenged.&lt;/p&gt;

&lt;p&gt;Deliver those three and a mostly linear story feels deeply responsive. Skip any of them and genuinely complex branching still feels hollow and mechanical. The Walking Dead built its reputation on exactly this, with a critical path that barely moved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Narrative Models And What They Cost
&lt;/h2&gt;

&lt;p&gt;Linear is the cheapest to produce and the easiest to write well, because it is closest to traditional storytelling. The risk is a story that feels bolted onto the gameplay.&lt;/p&gt;

&lt;p&gt;Branching buys replayability and investment, and the cost scales with the number of branches. The trap is uneven quality, since one thin branch makes players distrust the whole system.&lt;/p&gt;

&lt;p&gt;Emergent narrative comes from systems rather than authored content. It needs the least writing and the most game design, because the systems have to generate events that are varied, consequential, and readable enough for players to turn into stories.&lt;/p&gt;

&lt;p&gt;Hub and spoke keeps a linear spine with optional detours, which is usually the sane middle for a small team.&lt;/p&gt;

&lt;p&gt;For an indie or web project, the practical shape is narrow branching: mostly linear, two or three real variation points, each visible and consequential inside the scope you can actually finish.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Write the story engine first, then add lore as decoration. Spend the branching budget on acknowledgement, reaction, and payoff rather than on paths nobody will replay to find.&lt;/p&gt;

&lt;p&gt;The full guide, covering agency, environmental storytelling, dialogue, and how AI is changing narrative work, is here: &lt;a href="https://www.abratabia.com/game-narrative/" rel="noopener noreferrer"&gt;https://www.abratabia.com/game-narrative/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>writing</category>
    </item>
    <item>
      <title>Guardrails Are Code, Not Prompt Wording</title>
      <dc:creator>Paul Crinigan</dc:creator>
      <pubDate>Sat, 25 Jul 2026 18:24:32 +0000</pubDate>
      <link>https://dev.to/paulcrinigan/guardrails-are-code-not-prompt-wording-259e</link>
      <guid>https://dev.to/paulcrinigan/guardrails-are-code-not-prompt-wording-259e</guid>
      <description>&lt;p&gt;Every production LLM application eventually runs into the same wall. The system prompt says one thing, the model does another, and there is no version of "be more explicit in the prompt" that fixes it. A language model produces the most probable next token given its context. It does not check that token against your content policy, your privacy obligations, or reality.&lt;/p&gt;

&lt;p&gt;Guardrails are the layer that does that checking. They are ordinary software you write or deploy around the model, and they are what turns a soft instruction into an enforced rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two Insertion Points, Both Required
&lt;/h2&gt;

&lt;p&gt;Input guardrails run before the model sees the message. They catch prompt injection attempts, filter off-topic or abusive input, redact sensitive data that should never be sent to a third party endpoint, and confirm the request is inside the system's intended scope.&lt;/p&gt;

&lt;p&gt;Output guardrails run before the response reaches the user. They catch hallucinated claims, filter harmful content, redact anything sensitive the model generated on its own, check answers against grounding sources, and enforce format and policy rules.&lt;/p&gt;

&lt;p&gt;Neither one covers the other's gap. An input guard cannot stop the model from producing something harmful in response to a completely benign question. An output guard cannot undo the fact that you already shipped a customer's private data to an external API. If you only build one layer, you have a partial control, not a control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cheap Checks First
&lt;/h2&gt;

&lt;p&gt;A guardrail pipeline is a cost problem as much as a safety problem. Every check adds latency, and when the check is itself a model, tokens.&lt;/p&gt;

&lt;p&gt;The pattern that holds up is tiering. Fast deterministic checks run on everything: regex for card numbers and identifiers, allowlists, length and format validation, simple classifier passes. Expensive checks run only on what survives and only where the risk justifies them: secondary classifiers, embedding similarity, entailment models for factual verification, knowledge graph lookups.&lt;/p&gt;

&lt;p&gt;Most of your traffic never reaches the expensive tier, which is the whole point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Memory Changes The Math
&lt;/h2&gt;

&lt;p&gt;A stateless guardrail evaluates one message at a time, which makes some attacks and some failures effectively invisible. Injection attempts spread over several turns look harmless individually. A fabricated fact that contradicts something the same system said an hour ago reads fine in isolation.&lt;/p&gt;

&lt;p&gt;Persistent memory of what was asked, what was answered, and what was already verified gives the guardrail layer something to compare against. Contradiction checks become possible. Repeated probing becomes a pattern instead of a series of unrelated messages. Verified facts do not need re-verification on every turn, which pulls the cost back down.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Compliance Case Is Already Here
&lt;/h2&gt;

&lt;p&gt;This is no longer forward looking. The EU AI Act requires human oversight, transparency, and safety mechanisms for high risk systems. SOC 2 for AI systems requires demonstrable controls over data handling and output quality. HIPAA covered entities have to keep protected health information out of model outputs. GDPR's right to erasure applies to data an AI system processes.&lt;/p&gt;

&lt;p&gt;None of those are satisfied by prompt engineering. They are satisfied by code that inspects, blocks, and logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Get Back
&lt;/h2&gt;

&lt;p&gt;The practical benefit is speed, not only safety. A team that can state its hallucination detection rate and its content filtering accuracy ships new AI features faster than a team relying on manual review and good intentions. Guardrails are what makes a probabilistic system reviewable.&lt;/p&gt;

&lt;p&gt;The full breakdown, including architecture patterns and the performance trade-offs, is here: &lt;a href="https://www.adaptiverecall.com/ai-guardrails/" rel="noopener noreferrer"&gt;https://www.adaptiverecall.com/ai-guardrails/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>security</category>
      <category>ai</category>
    </item>
    <item>
      <title>Web Game Performance: Where the Milliseconds Actually Go</title>
      <dc:creator>Paul Crinigan</dc:creator>
      <pubDate>Sat, 25 Jul 2026 12:32:58 +0000</pubDate>
      <link>https://dev.to/paulcrinigan/web-game-performance-where-the-milliseconds-actually-go-53m2</link>
      <guid>https://dev.to/paulcrinigan/web-game-performance-where-the-milliseconds-actually-go-53m2</guid>
      <description>&lt;p&gt;A web game does not get the benefit of the doubt that a native game does. Nobody committed to a download, nobody waited through an install. They clicked a link, and the back button is one gesture away. That single fact should shape the whole engineering plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Game Competes With the Back Button
&lt;/h2&gt;

&lt;p&gt;The browser adds constraints that native platforms do not have. JavaScript runs on one main thread. GPU access is mediated through WebGL or WebGPU rather than direct hardware APIs. Every asset travels over HTTP before it can be decoded. The garbage collector can pause your loop without asking.&lt;/p&gt;

&lt;p&gt;Those are not weaknesses, they are the design parameters. A well built web game holds a steady 60 frames per second on mid range hardware and gets interactive in under three seconds, but only if performance was a requirement from the first commit rather than a cleanup task before launch.&lt;/p&gt;

&lt;p&gt;The payoff compounds. A smaller texture atlas downloads faster, decodes faster, occupies less GPU memory and draws faster. Almost no optimization here is wasted work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tiering the Load So the First Frame Arrives Early
&lt;/h2&gt;

&lt;p&gt;The median web page in 2026 pulls about 2.5 megabytes. A web game can pass 20 megabytes before a level is playable. The fix is not to shrink everything equally, it is to decide what has to arrive first.&lt;/p&gt;

&lt;p&gt;Tier one is whatever renders the first interactive frame: the loading screen, the UI font, a low resolution background, the core loop code. Tier two is the current level. Tier three is everything else, fetched while the player is already busy. With that split, a game with a 50 megabyte total budget still shows something playable in one to two seconds.&lt;/p&gt;

&lt;p&gt;HTTP/2 and HTTP/3 multiplexing makes many small requests much cheaper than they used to be, so splitting assets is no longer punished the way it was under HTTP/1.1. Bundling related assets into atlases still wins on decode and request overhead, so the target is a handful of well organized bundles rather than one giant download or ten thousand tiny files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Textures Are the Budget
&lt;/h2&gt;

&lt;p&gt;Textures, audio and meshes are 80 to 95 percent of what a player downloads, and textures usually lead. One uncompressed 2048x2048 RGBA texture is 16 megabytes of GPU memory. A few dozen of those and mobile browsers start killing the tab.&lt;/p&gt;

&lt;p&gt;GPU compressed formats fix both problems at once. Basis Universal and KTX2 deliver textures as ASTC, BC7 or ETC2, which the GPU samples directly with no decompression step. That is 4x to 8x less download and 4x to 8x less GPU memory compared to PNG, and Three.js, Babylon.js and PlayCanvas all support the transcoding path.&lt;/p&gt;

&lt;p&gt;Atlases matter for a different reason. Two hundred separate sprite images mean two hundred texture binds per frame. The same sprites packed into four atlases mean four. On a GPU constrained device that change alone can double the frame rate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meshes, Audio and the Rest of the Pipeline
&lt;/h2&gt;

&lt;p&gt;For geometry, glTF with Draco or Meshopt is the default answer. Draco can remove 90 percent or more of mesh size. Meshopt optimizes vertex ordering for GPU cache behavior, which helps at draw time rather than download time. Distant objects should use lower detail versions, with higher detail streamed in as the camera approaches.&lt;/p&gt;

&lt;p&gt;Audio compresses well with Opus, which beats AAC at equivalent quality and is supported everywhere that matters. Long music tracks should stream rather than fully decode before playback, and the Web Audio API can decode off the main thread so audio work does not stall the game loop.&lt;/p&gt;

&lt;p&gt;Animation data is the piece people forget. Skeletal clips for characters with many bones get large quickly, and quantizing bone transforms from 32 bit floats down to 16 bit is usually invisible in motion while cutting the data substantially.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Load time and frame rate are not separate projects. They are both downstream of the asset pipeline, and the asset pipeline is where the biggest wins live. Compress textures for the GPU rather than for disk, tier what loads when, and measure on the slowest device you are willing to support rather than the machine you build on.&lt;/p&gt;

&lt;p&gt;The full guide, covering load fundamentals through profiling tools, is here: &lt;a href="https://www.abratabia.com/web-game-performance/" rel="noopener noreferrer"&gt;https://www.abratabia.com/web-game-performance/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>gamedev</category>
      <category>performance</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Reading Your Own Numbers: A Statistics Refresher for People Building With AI</title>
      <dc:creator>Paul Crinigan</dc:creator>
      <pubDate>Fri, 24 Jul 2026 22:22:15 +0000</pubDate>
      <link>https://dev.to/paulcrinigan/reading-your-own-numbers-a-statistics-refresher-for-people-building-with-ai-5ej</link>
      <guid>https://dev.to/paulcrinigan/reading-your-own-numbers-a-statistics-refresher-for-people-building-with-ai-5ej</guid>
      <description>&lt;p&gt;Most teams shipping AI features are making statistical claims all day without calling them that. An eval score went from 71 to 74. A new prompt "feels better" on a handful of examples. A test showed 60 percent of users preferred version A. Every one of those is a claim about a population made from a sample, which means the rules of sampling apply whether anyone invokes them or not.&lt;/p&gt;

&lt;p&gt;Here is the short refresher that catches most of the damage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Small Samples Lie
&lt;/h2&gt;

&lt;p&gt;The core problem is that small samples swing. If you ask 50 users which version they prefer and 30 of them say A, that 60 percent has enough wobble in it that a rerun the following week can land the other way. Nothing changed except which 50 people you happened to ask.&lt;/p&gt;

&lt;p&gt;This is not a reason to distrust data, it is a reason to know how much data you have. The law of large numbers says sample averages converge on the true value as the sample grows. Flip a fair coin ten times and seven heads is unremarkable. Flip it ten thousand times and the proportion sits close to 0.50. Your eval set of 40 prompts is the ten flip version of the experiment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an Interval Tells You That an Average Cannot
&lt;/h2&gt;

&lt;p&gt;A single number hides its own uncertainty. An interval carries it.&lt;/p&gt;

&lt;p&gt;"74 percent" and "74 percent, plus or minus 6" are the same measurement, but only one of them tells you that the 71 percent you measured last month is inside the range and therefore not clearly worse. Teams that report intervals stop shipping changes that were never distinguishable from noise, and they stop rolling back changes that actually worked.&lt;/p&gt;

&lt;p&gt;The habit costs nothing. Report the number, then the interval, then the sample size that produced both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Eval Scores Go Wrong
&lt;/h2&gt;

&lt;p&gt;Three failure modes come up over and over in model and prompt work.&lt;/p&gt;

&lt;p&gt;The first is peeking. Someone watches a running comparison and stops the moment it crosses the threshold they wanted. Stopping on a high point inflates the effect and quietly destroys the guarantee the test was supposed to provide.&lt;/p&gt;

&lt;p&gt;The second is the multiple comparisons problem. Run twenty prompt variants against the same eval set and one of them will look significantly better by chance alone. If you only report that one, you have published noise.&lt;/p&gt;

&lt;p&gt;The third is the wrong denominator. Cost per run, accuracy per attempt and latency per call all look reasonable until you remember that failed runs get retried. Cost per successful task is the number that survives contact with production, and it moves differently from the one on the dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;You do not need graduate statistics to avoid the expensive mistakes. You need four habits: decide the sample size before you look, report intervals rather than bare numbers, count how many comparisons you actually ran, and check that your denominator matches the thing you care about.&lt;/p&gt;

&lt;p&gt;Everything else is refinement. These four are the ones that decide whether the number in your changelog means anything.&lt;/p&gt;

&lt;p&gt;If you want the underlying material in one place, from descriptive statistics and distributions through hypothesis testing and regression, this guide covers it in plain language: &lt;a href="https://www.learnhowtoscience.com/learn-statistics/" rel="noopener noreferrer"&gt;https://www.learnhowtoscience.com/learn-statistics/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>statistics</category>
      <category>ai</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Shipping Software Without a Dev Team: What Actually Works</title>
      <dc:creator>Paul Crinigan</dc:creator>
      <pubDate>Fri, 24 Jul 2026 16:38:33 +0000</pubDate>
      <link>https://dev.to/paulcrinigan/shipping-software-without-a-dev-team-what-actually-works-16c6</link>
      <guid>https://dev.to/paulcrinigan/shipping-software-without-a-dev-team-what-actually-works-16c6</guid>
      <description>&lt;p&gt;Every argument about AI replacing developers focuses on the same thing: can a model write the code. It is the wrong question, because writing the first draft of the code was never what made shipping software slow.&lt;/p&gt;

&lt;p&gt;What makes it slow is everything around the code. Reviewing it. Documenting it. Standing up accounts, a database, an API and billing for the fifth time. Building another customer portal that looks like the last four. Deciding whether the model has to run on your own hardware because of the data going through it.&lt;/p&gt;

&lt;p&gt;That is the work agents are genuinely good at right now, and conveniently it is the work nobody wanted to do anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottleneck Was Never Writing the Code
&lt;/h2&gt;

&lt;p&gt;Ask anyone who has shipped a product alone where the time actually went. It is rarely the feature work. It is the pull request that sat for three days, the docs that drifted out of sync six commits ago, the auth flow rebuilt from scratch because the last one was in a different framework.&lt;/p&gt;

&lt;p&gt;None of that is intellectually hard. It is bounded, repetitive and checkable, which is exactly the profile of work you can hand to an agent and verify afterwards. The parts that genuinely need judgment, the data model, the architecture, what you refuse to build, stay with you.&lt;/p&gt;

&lt;p&gt;The teams getting real value out of coding agents are not asking for a whole product. They are handing over the parts that were never the interesting bit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Coding Agents Actually Earn Their Keep
&lt;/h2&gt;

&lt;p&gt;Three places, in rough order of payoff.&lt;/p&gt;

&lt;p&gt;Code review is first. An agent reviewing every pull request against your real project catches the boring class of bug consistently, and it never gets tired at 6pm on a Friday. It will not replace a senior reviewer on architecture, but it removes most of what a senior reviewer spends time on.&lt;/p&gt;

&lt;p&gt;Documentation is second, and it is underrated because nobody enjoys it. Docs generated from the source stay in step with the source. The failure mode of hand-written docs is not that they are bad, it is that they were correct nine months ago and nobody noticed when they stopped being correct.&lt;/p&gt;

&lt;p&gt;Delegated feature work is third. It works when the task is well specified and the agent can run the tests. It fails when neither of those is true, which is most of the time people complain about it.&lt;/p&gt;

&lt;p&gt;The pattern is that agents do well anywhere there is a fast, honest feedback signal. Give one a test suite it can execute and it converges. Take that away and it guesses confidently.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Boring Parts of a SaaS
&lt;/h2&gt;

&lt;p&gt;Every MVP needs the same scaffolding. User accounts. A database. An API. Billing. A dashboard. A way for a customer to log in and see their own data.&lt;/p&gt;

&lt;p&gt;This is the part that quietly kills side projects, because it is weeks of work that produces nothing a user would ever describe as a feature. It is also almost entirely solved. Building it by hand for the fifth time is a choice, not a requirement.&lt;/p&gt;

&lt;p&gt;Customer portals are the same story. Branded login, dashboards, database-backed pages, a webhook API. The requirements barely change between products, which is exactly why it should not consume a month of your life each time.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Self-Hosting Is Worth It
&lt;/h2&gt;

&lt;p&gt;Running your own models is worth it in three situations, and it is a distraction in all the others.&lt;/p&gt;

&lt;p&gt;It is worth it when the data legally cannot leave your infrastructure. It is worth it when your workload is high volume and predictable, because at that point the per-token math stops favouring an API. And it is worth it when you need the behaviour to be frozen, because a hosted model that silently improves is a hosted model that silently changes your output.&lt;/p&gt;

&lt;p&gt;If none of those apply, self-hosting is usually a way to spend a month on infrastructure instead of on the product. The honest version of this advice is that most projects should start on an API and move later, once the volume is real enough to justify the operational cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;The useful framing is not whether an agent can write code. It is which parts of your process have a clear definition of done and a way to check it.&lt;/p&gt;

&lt;p&gt;Review, docs, tests, scaffolding and the fifth identical billing integration all qualify. Architecture, product decisions and knowing what not to build do not, and probably will not for a while.&lt;/p&gt;

&lt;p&gt;Hand over the first category, keep the second, and the amount of software one person can ship changes considerably.&lt;/p&gt;

&lt;p&gt;Guides for each of those pieces, coding agents, automated code review, technical documentation, building a SaaS, customer portals and self-hosted AI, are collected here: &lt;a href="https://www.aiappsapi.com/ai-development/" rel="noopener noreferrer"&gt;https://www.aiappsapi.com/ai-development/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Five Layers of a Self-Hosted AI Stack</title>
      <dc:creator>Paul Crinigan</dc:creator>
      <pubDate>Fri, 24 Jul 2026 02:40:58 +0000</pubDate>
      <link>https://dev.to/paulcrinigan/the-five-layers-of-a-self-hosted-ai-stack-4g7f</link>
      <guid>https://dev.to/paulcrinigan/the-five-layers-of-a-self-hosted-ai-stack-4g7f</guid>
      <description>&lt;p&gt;Self-hosting AI gets pitched as either trivial (just run Ollama) or impossible (you need a data center). Both miss the same thing: a working stack is five layers, and the model is only one of them. Here is how the layers fit and why skipping one is what usually breaks a self-hosted setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inference: The Layer Everyone Starts With
&lt;/h2&gt;

&lt;p&gt;The inference layer runs the model itself. Tools like Ollama make this the easy part now, a single command on a mid-range GPU. Because it is easy, people stop here and assume the rest will follow. It does not. Inference alone gives you a chat box, not a system that does work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Embeddings And Memory: Where Real Use Cases Live
&lt;/h2&gt;

&lt;p&gt;Embeddings turn your documents into vectors, and a vector store lets the system search them by meaning. Memory is what lets the stack remember past runs instead of starting cold every time. These two layers move you from answering questions to working with your actual data, and they are the layers most first attempts leave out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools And Orchestration: Turning Answers Into Actions
&lt;/h2&gt;

&lt;p&gt;The tool layer lets the model call real functions, hit an API, run a query, write a file. Orchestration is the layer that decides the order, handles handoffs, and keeps multi-step work on track. Without these, you have a smart text generator. With them, you have something that completes tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cost Question
&lt;/h2&gt;

&lt;p&gt;The reason to bother is control and cost. Every byte stays on hardware you own, and for steady high-volume workloads a self-hosted stack tends to break even against cloud APIs within three to six months, on hardware that can start around a single mid-range GPU.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Small, Add Layers
&lt;/h2&gt;

&lt;p&gt;Stand up inference first, confirm it works, then add embeddings and memory, then tools and orchestration, one verified layer at a time. The full breakdown of each layer and what to run for it is here: &lt;a href="https://www.autolearningagents.com/self-hosted-ai-stack/" rel="noopener noreferrer"&gt;https://www.autolearningagents.com/self-hosted-ai-stack/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>selfhosted</category>
      <category>llm</category>
    </item>
    <item>
      <title>How to Choose an AI Image Generator Without Wasting Credits</title>
      <dc:creator>Paul Crinigan</dc:creator>
      <pubDate>Thu, 23 Jul 2026 20:47:24 +0000</pubDate>
      <link>https://dev.to/paulcrinigan/how-to-choose-an-ai-image-generator-without-wasting-credits-1m55</link>
      <guid>https://dev.to/paulcrinigan/how-to-choose-an-ai-image-generator-without-wasting-credits-1m55</guid>
      <description>&lt;p&gt;AI image generators went from a novelty to a crowded market in a very short time, and the hardest part is no longer making an image. It is choosing which tool to make it in without spending a week of credits finding out the one you picked is wrong for the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  What These Tools Actually Do
&lt;/h2&gt;

&lt;p&gt;An AI image generator turns a text description, a reference image, or both into original visuals using models trained on enormous sets of image and text pairs. The output has moved well past the blurry, six-fingered era into photorealistic images, clean illustrations, and usable commercial artwork produced in seconds. That leap is exactly why the market fragmented, because different models got very good at different things.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Generators Worth Knowing in 2026
&lt;/h2&gt;

&lt;p&gt;The useful way to think about the field is by strength, not by ranking. Midjourney still leads on artistic style and mood. Adobe Firefly is the safer option when commercial rights and clean training data matter. Ideogram is the one that reliably renders readable text inside an image, which most models still fumble. Flux is the choice for people who want open weights they can run and tune themselves. Picking by reputation alone is how credits get wasted, because the best tool depends on whether you need art, product mockups, or text-heavy graphics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Prompting Decides Output Quality
&lt;/h2&gt;

&lt;p&gt;The same model can produce a masterpiece or a mess depending entirely on the prompt. Specific subjects, described lighting, a named style, and a clear composition consistently beat a vague one-liner. Learning how a given model reads prompts is a bigger lever on quality than switching models, and it is the cheapest skill to build because it costs nothing but attention.&lt;/p&gt;

&lt;h2&gt;
  
  
  Copyright and Commercial Use
&lt;/h2&gt;

&lt;p&gt;The part people skip until it bites is ownership. Whether you can sell what you generate, and whether the training data exposes you to any claim, varies by tool and by plan. If the work is going on a product or in an ad, the commercial terms of the generator matter as much as the image quality, and this is where a purpose-built tool like Firefly earns its place.&lt;/p&gt;

&lt;p&gt;The short version is to choose by use case, learn to prompt the tool you pick, and read the commercial terms before you ship anything. The full comparison of the current generators by quality, price, and best-fit use is here: &lt;a href="https://www.aitools9.com/ai-image-generator/" rel="noopener noreferrer"&gt;https://www.aitools9.com/ai-image-generator/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Why a Self-Learning Agent Should Not Trust Its First Success</title>
      <dc:creator>Paul Crinigan</dc:creator>
      <pubDate>Thu, 23 Jul 2026 12:25:58 +0000</pubDate>
      <link>https://dev.to/paulcrinigan/why-a-self-learning-agent-should-not-trust-its-first-success-51no</link>
      <guid>https://dev.to/paulcrinigan/why-a-self-learning-agent-should-not-trust-its-first-success-51no</guid>
      <description>&lt;p&gt;Most agent systems that claim to learn from experience are really just logging. They record what happened, feed some of it back into the next prompt, and call it memory. When that produces a better result once, the approach gets treated as proven. When it produces a worse result once, it gets thrown out. Either way a single run is deciding future behavior, and a single run is noise.&lt;/p&gt;

&lt;p&gt;The interesting design question is not whether an agent can learn from experience. It is how much evidence should be required before that experience is allowed to change what the agent does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pending Patterns and Confirmed Patterns
&lt;/h2&gt;

&lt;p&gt;The approach we settled on separates a pattern from a rule.&lt;/p&gt;

&lt;p&gt;When the system reviews past work, it looks for clusters of similar situations with similar outcomes. If the same approach keeps succeeding, or keeps failing, that gets recorded as a tentative pattern with pending status. Pending means noticed, not trusted.&lt;/p&gt;

&lt;p&gt;A pending pattern needs five separate confirming observations from later work before it is promoted to confirmed and treated as guidance the agents actually follow. If contradicting evidence shows up three times, the pattern deactivates automatically.&lt;/p&gt;

&lt;p&gt;Those two numbers are the whole safeguard. Five confirmations means a pattern has to hold across independent situations, not just the one where it happened to work. Three contradictions means a rule that stopped being true stops being enforced without anyone having to file a bug.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ten Kinds of Memory, Not One Log
&lt;/h2&gt;

&lt;p&gt;Retrieval quality depends on knowing what kind of thing you are looking for, so the memory bank is typed rather than being one undifferentiated pile of history.&lt;/p&gt;

&lt;p&gt;Skills store reusable approaches to categories of problems. Tools catalog every script and procedure the system can run. Projects track ongoing work so the system does not rebuild something it already has. Memories record short term events with their outcomes. Experience holds knowledge that stays true indefinitely. Rewards hold the behavioral rules, both the ones humans set and the ones learned from observation. Questions track what has been asked, with answers where they are known. Ideas park untested proposals. Cross references point at where information lives. People store what the system knows about the humans it works with.&lt;/p&gt;

&lt;p&gt;Every query is ranked by semantic relevance using local vector embeddings, not keyword matching. Searching for how to deploy code surfaces entries about pushing to production, build processes and release management even when none of those entries contain the word deploy. The system returns a minimum of three results so an agent always has something to work with, and up to twenty when many entries are genuinely relevant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning That Runs Without You
&lt;/h2&gt;

&lt;p&gt;Three pipelines run continuously rather than waiting to be asked.&lt;/p&gt;

&lt;p&gt;The self learning pipeline reviews recent work in three phases. It brainstorms improvements without restriction, then switches to a critical mindset and scores each idea honestly, discarding the ones not worth pursuing, then implements what survives as actual changes to how the system behaves.&lt;/p&gt;

&lt;p&gt;The adaptive coding pipeline handles building and modifying software. It identifies what needs to exist, plans it, writes it, reviews its own output for bugs and quality problems, fixes what it finds, and verifies the result before calling the task complete.&lt;/p&gt;

&lt;p&gt;The adaptive research pipeline goes and learns whatever the system does not know yet. It explores a subject broadly, searches for specifics, cross checks findings for accuracy, and files what survives into searchable knowledge every other agent can reach.&lt;/p&gt;

&lt;p&gt;A brain agent sits above all three, reviewing logs, checking work for consistency, extracting behavioral patterns, and deciding what to prioritize next based on your goals.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Threshold Is the Product
&lt;/h2&gt;

&lt;p&gt;It is easy to build an agent that remembers things. It is harder to build one whose memory is worth trusting, and the difference is almost entirely about what standard of evidence you hold it to.&lt;/p&gt;

&lt;p&gt;An agent that learns from every outcome will confidently tell you nonsense within a week. An agent that never updates is just an expensive script. The useful range is in between, and where you set the confirmation threshold is the real design decision.&lt;/p&gt;

&lt;p&gt;The full breakdown of the pipelines, the memory types and the rewards engine is at &lt;a href="https://www.aiappsapi.com/autonomousagents/" rel="noopener noreferrer"&gt;https://www.aiappsapi.com/autonomousagents/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why Scientific Python Is a Different Stack Than Web Python</title>
      <dc:creator>Paul Crinigan</dc:creator>
      <pubDate>Wed, 22 Jul 2026 21:57:57 +0000</pubDate>
      <link>https://dev.to/paulcrinigan/why-scientific-python-is-a-different-stack-than-web-python-15i3</link>
      <guid>https://dev.to/paulcrinigan/why-scientific-python-is-a-different-stack-than-web-python-15i3</guid>
      <description>&lt;p&gt;Most developers meet Python through a web framework or a scripting task, then get handed a research codebase and find that almost none of their instincts transfer. The syntax is identical. Nearly everything else is not.&lt;/p&gt;

&lt;p&gt;The gap is not that scientific code is harder. It is that the two worlds optimize for different things, and the habits that make web Python maintainable can make numerical Python unusably slow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Ecosystem Is the Language
&lt;/h2&gt;

&lt;p&gt;In web Python, the standard library plus a framework gets you most of the way, and you reach for packages to fill the gaps. In scientific Python, the packages are the point. NumPy, pandas, matplotlib, SciPy and Jupyter are not convenience layers, they are the actual runtime where the work happens.&lt;/p&gt;

&lt;p&gt;That shift matters because performance lives below the Python line. A NumPy array operation dispatches down to compiled C and BLAS routines, so a single vectorized expression can run a hundred times faster than the loop that expresses the same idea.&lt;/p&gt;

&lt;p&gt;This is why the most common performance bug in research code is a Python for loop over array elements. It is not slightly slower. It steps off the compiled path entirely and drops back into the interpreter, one boxed object at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where NumPy and pandas Actually Split
&lt;/h2&gt;

&lt;p&gt;Newcomers often treat NumPy and pandas as interchangeable, then pick the wrong one for the job.&lt;/p&gt;

&lt;p&gt;NumPy is for homogeneous numeric arrays with a known shape. Simulation grids, image buffers, signal windows, anything where every element is the same type and position itself carries meaning.&lt;/p&gt;

&lt;p&gt;pandas is for heterogeneous labeled tables. Field data with missing values, mixed types, timestamps that need aligning, and the messy work of getting real measurements into a shape a model can consume.&lt;/p&gt;

&lt;p&gt;Choosing wrong is not a style question. Running numerical kernels through a DataFrame adds per column overhead you do not need, and forcing labeled experimental data into a raw array throws away exactly the alignment logic pandas exists to provide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproducibility Is the Hard Part
&lt;/h2&gt;

&lt;p&gt;Web code is judged by whether it works now. Research code is judged by whether the number it produced can be produced again, sometimes years later, by someone else.&lt;/p&gt;

&lt;p&gt;That changes what counts as technical debt. An unpinned dependency is not a minor cleanup item, it is the most common reason a result stops reproducing, and it fails silently instead of crashing.&lt;/p&gt;

&lt;p&gt;Notebooks deserve the same scrutiny. Jupyter is excellent for exploration and genuinely useful as a lab notebook, but hidden execution order means a notebook can display a result that no clean run would reproduce. The practical rule is to explore in the notebook and move anything you actually depend on into a real module.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Coming from web Python, the instinct is to write clear loops, keep dependencies flexible, and refactor for readability. In scientific Python, vectorize instead of looping, pin the environment hard, and treat the notebook as a scratchpad rather than a source of truth.&lt;/p&gt;

&lt;p&gt;The libraries are the skill, not the syntax. For the full map of the stack, including SciPy, matplotlib and the domain libraries for physics, chemistry, biology and astronomy, the complete guide is here: &lt;a href="https://www.learnhowtoscience.com/python-for-science/" rel="noopener noreferrer"&gt;https://www.learnhowtoscience.com/python-for-science/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>datascience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Why Your AI Assistant Forgets, and What a Memory Layer Actually Has to Do</title>
      <dc:creator>Paul Crinigan</dc:creator>
      <pubDate>Wed, 22 Jul 2026 16:13:00 +0000</pubDate>
      <link>https://dev.to/paulcrinigan/why-your-ai-assistant-forgets-and-what-a-memory-layer-actually-has-to-do-12b5</link>
      <guid>https://dev.to/paulcrinigan/why-your-ai-assistant-forgets-and-what-a-memory-layer-actually-has-to-do-12b5</guid>
      <description>&lt;p&gt;Every few weeks someone rebuilds the same disappointment. You wire an assistant up to a vector database, feed it a year of notes, ask it something you clearly wrote down, and get a confident answer that is simply wrong. The model is not the problem. The retrieval is.&lt;/p&gt;

&lt;p&gt;Storing text is easy now. Deciding what should come back, and how much to trust it, is where memory systems actually live or die.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Vector Search Is Not Memory
&lt;/h2&gt;

&lt;p&gt;The standard setup is one embedding per note and a cosine similarity search at query time. One strategy, one shot, no learning. It works well right up to the moment your question is phrased differently than the note was.&lt;/p&gt;

&lt;p&gt;Ask "what did we decide about refunds" when the note says "chargebacks get handled manually until Q3" and similarity scoring has no reason to connect them. The note is sitting right there in the database and never surfaces. Worse, the search returns something, so the model answers anyway, from whatever weakly related chunks did come back.&lt;/p&gt;

&lt;p&gt;Cosine similarity also has no opinion about time, frequency, or contradiction. A stale note from fourteen months ago and one written yesterday score the same if the wording matches. That is not how anybody actually remembers anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Four Parallel Retrieval Paths Buy You
&lt;/h2&gt;

&lt;p&gt;The fix is not a better embedding model. It is refusing to bet the answer on a single retrieval strategy.&lt;/p&gt;

&lt;p&gt;Adaptive Recall runs four at once: vector similarity for semantic closeness, temporal recency for what happened lately, full text keyword for the exact term the user typed, and knowledge graph traversal for facts reachable through entities rather than through wording.&lt;/p&gt;

&lt;p&gt;The refunds question above fails on vector search and succeeds on graph traversal, because "refunds" and "chargebacks" both connect to the same billing entity. A question about last Tuesday fails on similarity and succeeds on recency. A question containing a product code fails on semantics and succeeds instantly on keyword.&lt;/p&gt;

&lt;p&gt;Running them in parallel means the system does not have to guess which kind of question it just received. It learns, per query type, which strategies have been earning their place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scoring Memories the Way People Do
&lt;/h2&gt;

&lt;p&gt;Retrieval gets you candidates. Ranking decides what the model actually sees, and this is where cognitive science turns out to be more useful than search engineering.&lt;/p&gt;

&lt;p&gt;ACT-R is an activation model out of thirty years of research on human memory. It says a memory's availability depends on how recently it was used, how often it has been used, and how strongly it connects to whatever is currently in focus. Adaptive Recall ranks candidates with that same activation math, so a fact you touch constantly outranks one you wrote once and abandoned, and a fact tied to the entity under discussion outranks a floating stranger with a slightly better embedding score.&lt;/p&gt;

&lt;p&gt;It is a small shift with a large effect. Relevance stops being purely about text and starts including use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memories That Change Their Mind
&lt;/h2&gt;

&lt;p&gt;The last piece is the one most systems skip entirely. A stored memory is treated as permanently true, which means a thing you said once, in passing, possibly wrong, has the same standing forever as a thing confirmed by five later events.&lt;/p&gt;

&lt;p&gt;Real memory does not work that way, and neither should a memory layer. Confidence should rise as corroborating evidence arrives and fall when something contradicts it. Memories nothing ever touches should fade rather than sit in the index competing for attention. That lifecycle is what keeps a store from slowly turning into a swamp of half true fragments, which is the usual fate of a year old vector database.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;If your assistant keeps forgetting, resist the urge to change models. Look at what happens between the question and the answer.&lt;/p&gt;

&lt;p&gt;One retrieval strategy is a guess. Several strategies with learned weighting is a system. Ranking by activation rather than by text similarity is what makes results feel like memory rather than search. And a confidence lifecycle is what keeps the whole thing honest a year in.&lt;/p&gt;

&lt;p&gt;The full breakdown of the retrieval strategies and the scoring model is here: &lt;a href="https://www.adaptiverecall.com/" rel="noopener noreferrer"&gt;https://www.adaptiverecall.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>What Running Your Own Email Sender Actually Involves</title>
      <dc:creator>Paul Crinigan</dc:creator>
      <pubDate>Wed, 22 Jul 2026 02:39:43 +0000</pubDate>
      <link>https://dev.to/paulcrinigan/what-running-your-own-email-sender-actually-involves-771</link>
      <guid>https://dev.to/paulcrinigan/what-running-your-own-email-sender-actually-involves-771</guid>
      <description>&lt;p&gt;Sending email is easy. Landing in the inbox is the hard part, and the gap between a 95 percent inbox placement rate and a 40 percent one has almost nothing to do with the code that pushes the message out.&lt;/p&gt;

&lt;p&gt;If you are thinking about moving off a hosted platform and running your own sender, here is what the job actually consists of, in the order it tends to bite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication Is the Entry Ticket
&lt;/h2&gt;

&lt;p&gt;SPF, DKIM and DMARC are not optional extras any more. Gmail and Yahoo both made them a requirement for bulk senders in 2024, along with one click List-Unsubscribe headers and a spam complaint rate under 0.3 percent.&lt;/p&gt;

&lt;p&gt;None of this is difficult, it is three DNS records and a signing key. What catches people is that authentication only gets you considered. It does not get you delivered. Passing DMARC means the receiving side believes you are who you say you are, which is the entry ticket, not the prize.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reputation Is Earned Slowly and Lost Instantly
&lt;/h2&gt;

&lt;p&gt;A new sending domain has no history, so mailbox providers throttle it until it builds one. Warming means starting at a low daily volume with your most engaged recipients and increasing gradually over a few weeks, because engagement early on is what the reputation is actually built from.&lt;/p&gt;

&lt;p&gt;The reverse happens much faster. One send to a stale list can undo weeks of warming, which is why the boring hygiene work matters more than the clever copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Suppression List Is the Safety Net
&lt;/h2&gt;

&lt;p&gt;This is the piece most homegrown senders get wrong. Unsubscribes, hard bounces and spam complaints have to land on a permanent suppression list, and that list has to survive a re-import.&lt;/p&gt;

&lt;p&gt;The failure looks like this. Someone exports an old list from a previous platform, imports it into the new system, and the system happily re-mails every person who opted out two years ago. Authentication was fine, the content was fine, and the complaint rate does the damage. If your import path can write an address that is already suppressed, you do not have a suppression list, you have a filter.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Software Has to Do
&lt;/h2&gt;

&lt;p&gt;Strip away the dashboard and a broadcast sender has a short list of real responsibilities. Store contacts and their state. Pace the send across a window instead of dumping everything at once. Sign and relay through an SMTP provider. Parse bounces and complaints back into suppression. Track opens and clicks while filtering out the security scanners that inflate click numbers.&lt;/p&gt;

&lt;p&gt;That is a small enough surface that it does not need a heavy stack. Ours runs as one small app with single file storage and no database server, on ordinary shared hosting, relaying through whichever provider account you bring, which means you keep control of the per message cost and can switch providers without losing the list or the history.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;The reason to self host sending is not that platforms are expensive, though per subscriber pricing does add up. It is that your list, your suppression history and your engagement data are the asset, and they should live somewhere you control.&lt;/p&gt;

&lt;p&gt;The full guide, covering how broadcast systems work, choosing an SMTP provider, domain and IP warming, list hygiene and the mistakes that quietly destroy deliverability, is here: &lt;a href="https://www.aiappsapi.com/apps/emailbroadcast.php" rel="noopener noreferrer"&gt;https://www.aiappsapi.com/apps/emailbroadcast.php&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>email</category>
      <category>selfhosted</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why Playwright Became the Default for New Browser Automation Projects</title>
      <dc:creator>Paul Crinigan</dc:creator>
      <pubDate>Tue, 21 Jul 2026 19:53:57 +0000</pubDate>
      <link>https://dev.to/paulcrinigan/why-playwright-became-the-default-for-new-browser-automation-projects-2l48</link>
      <guid>https://dev.to/paulcrinigan/why-playwright-became-the-default-for-new-browser-automation-projects-2l48</guid>
      <description>&lt;p&gt;Every team that writes browser tests eventually hits the same wall. The suite passes locally, fails in CI, passes again on a rerun, and nobody can explain why. The usual response is to add waits and retries until the noise drops to a tolerable level. That works right up until the suite is slow enough that people quietly stop running it.&lt;/p&gt;

&lt;p&gt;A lot of that noise is not the application being unstable. It is the automation tool sitting in the wrong place relative to the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Source Of Flaky Tests
&lt;/h2&gt;

&lt;p&gt;There are two ways to automate a browser. You can inject code into the page and run inside it, or you can drive the browser process from the outside through its own protocol. Cypress takes the first approach, Playwright takes the second.&lt;/p&gt;

&lt;p&gt;Running inside the page is simpler to reason about at first, and it is why in-page tools feel fast to adopt. The cost shows up at the boundaries. A flow that opens a second tab, or crosses an origin, or drops into an iframe is not a normal step for an in-page runner, it is an exception that needs a workaround. Those workarounds are where flakiness accumulates.&lt;/p&gt;

&lt;p&gt;Driving the browser from the outside removes the whole category. A second tab is just another page. An iframe is a frame you address directly. Multi origin is not special, because the runner was never scoped to one origin to begin with.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Cross Browser Support Actually Buys You
&lt;/h2&gt;

&lt;p&gt;Playwright ships with Chromium, Firefox and WebKit. Most teams run everything on Chromium day to day and check the other two before a release, which sounds like a minor benefit right up until one WebKit specific bug reaches production and costs a week.&lt;/p&gt;

&lt;p&gt;The other half of the story is language bindings. Playwright has official support for JavaScript and TypeScript, Python, Java and .NET, with the same API across all of them. That matters when your test suite and your team's main language do not agree. A Python backend team should not have to maintain a JavaScript test suite because that was the only option on the table.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where The Speed Actually Comes From
&lt;/h2&gt;

&lt;p&gt;The feature that changes CI time the most is route interception. You can block requests by pattern before they ever leave the browser, so images, fonts, analytics scripts and ad exchanges never load in a test run that does not care about them.&lt;/p&gt;

&lt;p&gt;On a content heavy page that can cut load time by more than half. It also removes a whole class of flakiness, the kind where a third party script times out and drags the test down with it. The same trick applies to scraping, where you usually want the DOM and not the media.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Selenium And Puppeteer Still Fit
&lt;/h2&gt;

&lt;p&gt;Selenium still has the widest browser and version coverage and a deep ecosystem of grid infrastructure and third party integrations. If you have to test an old browser version, or you have years of Selenium infrastructure already running, those are real reasons to stay.&lt;/p&gt;

&lt;p&gt;Puppeteer is lighter. If you only need Chrome, only write JavaScript, and want minimal dependencies, it is a smaller thing to carry.&lt;/p&gt;

&lt;p&gt;Cypress has the most opinionated developer experience, and the teams that like its interactive runner genuinely like it. That preference is legitimate. The tradeoff is the in-page architecture described above.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;For a new project in 2026 the sensible default is Playwright, and the burden of proof sits with anything else. Not because it wins every single comparison, but because its architecture removes a class of problems that the other tools ask you to work around.&lt;/p&gt;

&lt;p&gt;If you want the longer breakdown, including selectors and locators, the built in test runner, and the detailed comparisons against Selenium and Puppeteer, the full guide is here: &lt;a href="https://www.webbrowserbot.com/playwright/" rel="noopener noreferrer"&gt;https://www.webbrowserbot.com/playwright/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>playwright</category>
      <category>testing</category>
      <category>automation</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
