<?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: Bhavya Arora</title>
    <description>The latest articles on DEV Community by Bhavya Arora (@bhavya_arora).</description>
    <link>https://dev.to/bhavya_arora</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%2F3961140%2Ffdef02d3-f925-4430-affa-eec5a12bc10f.png</url>
      <title>DEV Community: Bhavya Arora</title>
      <link>https://dev.to/bhavya_arora</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bhavya_arora"/>
    <language>en</language>
    <item>
      <title>The 15 Git Commands That'll Save Your Sanity (and Your Code)</title>
      <dc:creator>Bhavya Arora</dc:creator>
      <pubDate>Wed, 02 Sep 2026 07:31:06 +0000</pubDate>
      <link>https://dev.to/bhavya_arora/the-15-git-commands-thatll-save-your-sanity-and-your-code-m5e</link>
      <guid>https://dev.to/bhavya_arora/the-15-git-commands-thatll-save-your-sanity-and-your-code-m5e</guid>
      <description>&lt;p&gt;Most developers don't learn Git by reading the manual. They learn it the first time they delete something important, commit the wrong files, or discover that the branch they thought they were working on was not the branch they were actually working on.&lt;/p&gt;

&lt;p&gt;That is not necessarily a bad way to learn. Git becomes much easier once you've seen what these commands are trying to protect you from.&lt;/p&gt;

&lt;p&gt;The problem is that Git has accumulated a reputation for being complicated because there are dozens of commands, countless flags, and a lot of terminology that makes perfect sense once you already understand Git. When you're new to it, though, &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;commit&lt;/code&gt;, &lt;code&gt;push&lt;/code&gt;, &lt;code&gt;pull&lt;/code&gt;, &lt;code&gt;reset&lt;/code&gt;, &lt;code&gt;restore&lt;/code&gt;, and &lt;code&gt;revert&lt;/code&gt; can look like variations of the same thing.&lt;/p&gt;

&lt;p&gt;They aren't.&lt;/p&gt;

&lt;p&gt;This guide focuses on the commands you'll actually use in day-to-day development and, more importantly, the situations that tell you which one to reach for. You don't need to memorize every Git flag to be productive. You need a good mental model, a handful of reliable commands, and enough understanding to avoid turning a small mistake into a much bigger one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Git Mental Model
&lt;/h2&gt;

&lt;p&gt;Before getting into the commands, it helps to understand the four places your code can exist during normal Git work.&lt;/p&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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpNzkFLw0AQBeC_Ms55cxA85SA0LUVBL03VQ-phkkySpbuZsDu11ib_XVJL8fgeH7x3xkpqxhQbJ8eqo6CwXe16AIBF8SFhb_sWtoH581pCkjyOrVWguh4hK3KldjaLwHQ12c1U4r3VEZbFi1TkYMODRKsSTle6vNHhELsRVsWGvSj_l2jQc_Bka0zPqB37-W_NDR2covlr3ilYKh3H2TTS65q8dSdMMaFhcJzEU1T2BjJn-_0rVfklr6VXAzvMuRWGt-cdGthIKSoGnth9sdqKDCyCJWcgUh-TyME2aC4juf2Zv9w_DN84TQbLdilOAqZ4d-ysMk6_2-l2Rg%3Ftype%3Dpng" 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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpNzkFLw0AQBeC_Ms55cxA85SA0LUVBL03VQ-phkkySpbuZsDu11ib_XVJL8fgeH7x3xkpqxhQbJ8eqo6CwXe16AIBF8SFhb_sWtoH581pCkjyOrVWguh4hK3KldjaLwHQ12c1U4r3VEZbFi1TkYMODRKsSTle6vNHhELsRVsWGvSj_l2jQc_Bka0zPqB37-W_NDR2covlr3ilYKh3H2TTS65q8dSdMMaFhcJzEU1T2BjJn-_0rVfklr6VXAzvMuRWGt-cdGthIKSoGnth9sdqKDCyCJWcgUh-TyME2aC4juf2Zv9w_DN84TQbLdilOAqZ4d-ysMk6_2-l2Rg%3Ftype%3Dpng" alt="Mermaid Diagram" width="196" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your &lt;strong&gt;working tree&lt;/strong&gt; is where you actually edit files. The &lt;strong&gt;staging area&lt;/strong&gt; is where you decide which of those changes belong in your next commit. A &lt;strong&gt;commit&lt;/strong&gt; records that staged state in your local repository. The &lt;strong&gt;remote repository&lt;/strong&gt; — often hosted on GitHub, GitLab, or another server — is where you share those commits with other people or systems.&lt;/p&gt;

&lt;p&gt;Most of the Git commands in this article are really just ways of inspecting, moving, combining, or undoing changes between those states.&lt;/p&gt;

&lt;p&gt;Once that clicks, Git stops feeling like a collection of unrelated commands.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. &lt;code&gt;git init&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;When you're starting a project from scratch and want Git to track its history, you create a repository with &lt;code&gt;git init&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git creates a hidden &lt;code&gt;.git&lt;/code&gt; directory inside the project. That directory is where Git keeps the information it needs to manage the repository: commits, references, configuration, and the other internal data that makes version control possible.&lt;/p&gt;

&lt;p&gt;It is worth separating two ideas here because beginners often conflate them. Running &lt;code&gt;git init&lt;/code&gt; creates the repository; it does &lt;strong&gt;not&lt;/strong&gt; automatically add every file in the directory to version control. Your files are still untracked until you stage them.&lt;/p&gt;

&lt;p&gt;A typical first setup therefore looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial commit"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also ask Git to create the project directory for you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init my-new-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You generally only need to initialize a repository once. When you're not sure whether you're already inside one, &lt;code&gt;git status&lt;/code&gt; is a safer check than running &lt;code&gt;git init again&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. &lt;code&gt;git clone&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git clone&lt;/code&gt; is the starting point for an existing project. Instead of creating a new repository, you're making a local copy of one that already exists somewhere else.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/username/repository.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A normal clone gives you the project's files and repository history and sets up information about the remote repository so you can fetch and push changes later. It is the command you'll usually run when joining a team, contributing to an open-source project, or moving an existing repository onto a new machine.&lt;/p&gt;

&lt;p&gt;Git normally creates a directory based on the repository name, but you can choose your own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/username/repository.git my-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is one practical consideration worth knowing about. A repository with ten years of commits can be considerably larger than the current source code suggests, because you're bringing historical data along with it. When you only need a limited amount of history, a shallow clone can be useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 https://github.com/username/repository.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That gives you a much smaller starting point, although it also means you don't have the complete history available locally.&lt;/p&gt;

&lt;p&gt;The simple rule is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use&lt;/strong&gt; &lt;code&gt;init&lt;/code&gt; &lt;strong&gt;when you're creating the repository. Use&lt;/strong&gt; &lt;code&gt;clone&lt;/code&gt; &lt;strong&gt;when the repository already exists.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  3. &lt;code&gt;git status&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If there is one Git command worth learning so well that you stop thinking about it, it is &lt;code&gt;git status&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you're not sure what Git thinks is happening, ask Git. The command shows your current branch and tells you about changes that are modified, staged, or untracked.&lt;/p&gt;

&lt;p&gt;A simplified example might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;On branch main

Changes not staged for commit:
        modified:   index.html

Untracked files:
        style.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, &lt;code&gt;index.html&lt;/code&gt; is already part of the repository but has local changes that haven't been staged. &lt;code&gt;style.css&lt;/code&gt; is a new file that Git isn't tracking yet.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git status&lt;/code&gt; is deliberately boring, and that's exactly why it is useful. It doesn't change your files or history. Run it before you commit. Run it when you've just pulled someone else's changes. Run it before a reset. Run it after you've been switching branches and can no longer remember what you were doing.&lt;/p&gt;

&lt;p&gt;When Git starts feeling confusing, don't guess. Start with &lt;code&gt;git status&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. &lt;code&gt;git add&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The staging area is one of Git's most useful ideas, and also one of the first things beginners find strange.&lt;/p&gt;

&lt;p&gt;Suppose you've changed three files, but only two of those changes belong in the next commit. Git gives you the option to decide exactly what gets recorded.&lt;/p&gt;

&lt;p&gt;That's what &lt;code&gt;git add&lt;/code&gt; does.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add filename.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can stage everything below the current directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or stage matching files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="k"&gt;*&lt;/span&gt;.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of staging as preparing a package before you send it. Your working tree can contain many changes, but only the staged changes are going into the next commit.&lt;/p&gt;

&lt;p&gt;That distinction becomes particularly useful when you're doing unrelated work in the same project. You don't have to create a giant commit simply because several files happen to be modified at once.&lt;/p&gt;

&lt;p&gt;One caution: &lt;code&gt;git add .&lt;/code&gt; is convenient, but convenience can hide mistakes. It may stage files you didn't intend to include, which is why &lt;code&gt;.gitignore&lt;/code&gt; should be set up early for things such as dependency directories, local environment files, generated output, and operating-system clutter.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. &lt;code&gt;git commit&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A commit is a recorded snapshot of the changes you've staged.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add user authentication"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the point where your work becomes part of the repository's history. You can compare it later, inspect it, revert it, or use it as a known point to return to.&lt;/p&gt;

&lt;p&gt;That makes commit quality matter more than many beginners realize. A repository filled with messages like &lt;code&gt;changes&lt;/code&gt;, &lt;code&gt;fix&lt;/code&gt;, and &lt;code&gt;final&lt;/code&gt; technically works, but it is much harder to understand months later.&lt;/p&gt;

&lt;p&gt;Compare:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fix bug
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fix null pointer when cart is empty
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second message tells the next person — often future you — what the commit was actually about.&lt;/p&gt;

&lt;p&gt;There is also a shortcut worth knowing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-am&lt;/span&gt; &lt;span class="s2"&gt;"Fix navbar spacing on mobile"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-a&lt;/code&gt; option stages modifications and deletions to files Git already tracks, then creates the commit. It does &lt;strong&gt;not&lt;/strong&gt; include new files, so a brand-new file still needs &lt;code&gt;git add&lt;/code&gt; first.&lt;/p&gt;

&lt;p&gt;And when the latest commit is almost right but not quite, &lt;code&gt;--amend&lt;/code&gt; lets you update it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;--amend&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add user authentication and tests"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Amending is handy while a commit is still local. Once you've pushed it and other people may have based work on it, rewriting that commit becomes a different conversation.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. &lt;code&gt;git branch&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Branches are how you isolate work without putting unfinished changes directly onto the branch other people may be using.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;lists your local branches.&lt;/p&gt;

&lt;p&gt;To create one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch new-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To delete a branch that has already been safely merged:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch &lt;span class="nt"&gt;-d&lt;/span&gt; old-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when you know you want to remove it regardless of whether Git considers it merged:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch &lt;span class="nt"&gt;-D&lt;/span&gt; old-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can rename a branch with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch &lt;span class="nt"&gt;-m&lt;/span&gt; new-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A useful thing to understand is that a branch isn't a separate copy of your entire project. It is essentially a movable reference to a commit, which is why creating branches is cheap.&lt;/p&gt;

&lt;p&gt;There is one beginner mistake worth remembering: &lt;code&gt;git branch new-feature&lt;/code&gt; creates the branch, but it does &lt;strong&gt;not&lt;/strong&gt; switch you to it. To create and move to a branch in one step, modern Git gives you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git switch &lt;span class="nt"&gt;-c&lt;/span&gt; new-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That leads naturally to the next command family.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. &lt;code&gt;git checkout&lt;/code&gt;, &lt;code&gt;git switch&lt;/code&gt;, and &lt;code&gt;git restore&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;For years, &lt;code&gt;git checkout&lt;/code&gt; handled several unrelated jobs. You could use it to switch branches, create a branch, or restore a file to an earlier state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout new-feature
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; another-feature
git checkout &lt;span class="nt"&gt;--&lt;/span&gt; filename.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command still works, and you will continue to encounter it in older documentation and existing projects. The problem is that one command having several very different meanings makes it harder for beginners to understand what is happening.&lt;/p&gt;

&lt;p&gt;Modern Git separates those operations.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;git switch&lt;/code&gt; when you're working with branches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git switch new-feature
git switch &lt;span class="nt"&gt;-c&lt;/span&gt; another-feature
git switch -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last form switches back to the branch you were previously on, which is surprisingly useful when you're jumping between two tasks.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;git restore&lt;/code&gt; when you're working with files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git restore filename.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That discards unstaged changes to the file.&lt;/p&gt;

&lt;p&gt;To remove a file from the staging area without throwing away its edits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git restore &lt;span class="nt"&gt;--staged&lt;/span&gt; filename.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the simplest mental model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git switch   → branches
git restore  → files
git checkout → older multi-purpose command
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't need to treat &lt;code&gt;checkout&lt;/code&gt; as obsolete. Just recognize that &lt;code&gt;switch&lt;/code&gt; and &lt;code&gt;restore&lt;/code&gt; make your intention clearer when you're writing new commands.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. &lt;code&gt;git merge&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Eventually, isolated work needs to come back together. That's what merging does.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git switch main
git merge new-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Git can reconcile the two histories automatically, the merge may be uneventful. When it can't, you'll get a conflict.&lt;/p&gt;

&lt;p&gt;A conflict usually means that both sides changed overlapping parts of a file, or made changes Git cannot safely combine on its own. The repository hasn't been corrupted; Git has simply reached a decision that requires a human.&lt;/p&gt;

&lt;p&gt;You'll see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD
your version
=======
their version
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; new-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the file, decide what the final version should actually be, remove the conflict markers, and then stage the resolved file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add filename.txt
git commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first few merge conflicts can feel alarming because the file suddenly contains strange markers and Git seems to stop in the middle of the operation. In practice, conflict resolution is a normal part of collaborative development. The important thing is to understand that Git is waiting for a decision, not reporting a fatal failure.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. &lt;code&gt;git push&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Your commits are local until you send them somewhere shared.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That command pushes your local commits to the &lt;code&gt;main&lt;/code&gt; branch on the &lt;code&gt;origin&lt;/code&gt; remote.&lt;/p&gt;

&lt;p&gt;When you create a new branch and push it for the first time, you will often use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin new-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-u&lt;/code&gt; option establishes the upstream relationship between your local branch and the remote branch. After that, a plain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is usually enough.&lt;/p&gt;

&lt;p&gt;Force-pushing is where things get serious.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can replace remote history, including commits you weren't aware another developer had added. There are legitimate reasons to rewrite history, particularly on personal branches after an amend or rebase, but it should never be a reflex.&lt;/p&gt;

&lt;p&gt;When a force-push is genuinely necessary, this is generally safer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;--force-with-lease&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It checks that the remote branch is still in the state your local repository expects. If someone else has moved it since your last update, the push can be rejected instead of silently overwriting their work.&lt;/p&gt;

&lt;p&gt;Even with that protection, shared branches deserve caution.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. &lt;code&gt;git pull&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git pull&lt;/code&gt; is the command you use when the remote repository has changes you need to bring into your current branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git pull origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conceptually, the operation starts by fetching updates from the remote and then integrating the relevant remote branch into your current branch. Exactly how that integration happens depends on your configuration and options.&lt;/p&gt;

&lt;p&gt;A common alternative is rebasing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git pull &lt;span class="nt"&gt;--rebase&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of creating a merge as part of the pull, Git replays your local commits on top of the updated remote history. That can produce a cleaner, more linear history, but rebasing also rewrites the commits being replayed.&lt;/p&gt;

&lt;p&gt;Neither workflow is universally right. Some teams merge, some rebase, and some use stricter fast-forward policies. The important thing is consistency: know what your project expects before changing the default behavior.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config pull.rebase &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can make rebase the default for the relevant configuration scope.&lt;/p&gt;

&lt;p&gt;One subtle point is worth remembering: &lt;code&gt;git pull origin main&lt;/code&gt; does not necessarily mean “update my local &lt;code&gt;main&lt;/code&gt; branch.” It integrates &lt;code&gt;origin/main&lt;/code&gt; into &lt;strong&gt;whichever branch you're currently on&lt;/strong&gt;. That distinction matters when you're working on a feature branch.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. &lt;code&gt;git log&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Every Git repository eventually reaches the point where you need to know not just what the code looks like now, but how it got there.&lt;/p&gt;

&lt;p&gt;That's what &lt;code&gt;git log&lt;/code&gt; is for.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default output contains commit metadata as well as the commit message, which can get noisy in a large repository. In practice, you'll often want a more compact view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, when you're trying to understand branching and merges:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few flags cover most everyday needs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;--oneline&lt;/td&gt;
&lt;td&gt;Compact commit summary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--graph&lt;/td&gt;
&lt;td&gt;Draw an ASCII representation of branches and merges&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-p&lt;/td&gt;
&lt;td&gt;Show the changes introduced by commits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--author="name"&lt;/td&gt;
&lt;td&gt;Filter commits by author&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-n 5&lt;/td&gt;
&lt;td&gt;Show only the latest five commits&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The real value of &lt;code&gt;git log&lt;/code&gt; isn't the list itself. It is the context. When a piece of code looks strange and nobody remembers why it exists, history can often answer the question faster than another hour of searching through the codebase.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. &lt;code&gt;git diff&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Before you commit a change, you should know what you're actually about to record.&lt;/p&gt;

&lt;p&gt;That's the job of &lt;code&gt;git diff&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- &amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+ &amp;lt;h1&amp;gt;Welcome to My Site&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The minus line represents the old content; the plus line represents the new content.&lt;/p&gt;

&lt;p&gt;There is a second version you'll use often:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--staged&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That shows what is currently in the staging area and therefore what the next commit is likely to contain.&lt;/p&gt;

&lt;p&gt;You can also compare two branch tips directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff branch1 branch2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A five-second diff check before committing is one of the best habits you can build. It catches accidental formatting changes, forgotten debugging statements, edits to the wrong file, and all the tiny mistakes that otherwise end up being discovered during code review.&lt;/p&gt;




&lt;h2&gt;
  
  
  13. &lt;code&gt;git stash&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Stash is useful when your current work is unfinished but your working tree needs to be clean.&lt;/p&gt;

&lt;p&gt;Maybe a production issue needs attention. Maybe you need to inspect another branch. Maybe you simply aren't ready to create a commit yet.&lt;/p&gt;

&lt;p&gt;You can temporarily put your work aside with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git stores the changes and returns the working tree to a clean state.&lt;/p&gt;

&lt;p&gt;You can see what you've saved with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and bring the most recent stash back with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash pop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you'd rather reapply it without removing the stash entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when you know you no longer need one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash drop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One detail surprises people: untracked files aren't included in a normal stash. When you need those as well, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash &lt;span class="nt"&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you regularly have several stashes in flight, name them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash push &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"search filter work"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That small bit of discipline makes a huge difference when you come back to the stash list later and discover that every entry is just another anonymous &lt;code&gt;WIP&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  14. &lt;code&gt;git reset&lt;/code&gt; and &lt;code&gt;git revert&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;These two commands are often introduced together because both can be used to undo work. They are not interchangeable, and the difference becomes particularly important once your commits are being shared with other people.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;git reset&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Reset moves the current branch reference backward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset &lt;span class="nt"&gt;--soft&lt;/span&gt; HEAD~1
git reset &lt;span class="nt"&gt;--mixed&lt;/span&gt; HEAD~1
git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; HEAD~1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The three modes mainly differ in what happens to your index and working tree:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Branch&lt;/th&gt;
&lt;th&gt;Staging area&lt;/th&gt;
&lt;th&gt;Working tree&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;--soft&lt;/td&gt;
&lt;td&gt;Moves&lt;/td&gt;
&lt;td&gt;Keeps changes staged&lt;/td&gt;
&lt;td&gt;Keeps changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--mixed&lt;/td&gt;
&lt;td&gt;Moves&lt;/td&gt;
&lt;td&gt;Unstages changes&lt;/td&gt;
&lt;td&gt;Keeps changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--hard&lt;/td&gt;
&lt;td&gt;Moves&lt;/td&gt;
&lt;td&gt;Resets&lt;/td&gt;
&lt;td&gt;Resets&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;--mixed&lt;/code&gt; is the default.&lt;/p&gt;

&lt;p&gt;The command that deserves the most respect is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; HEAD~1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can discard changes from tracked files in your working tree. If you haven't checked what Git thinks is going to happen, this is a very bad time to start experimenting.&lt;/p&gt;

&lt;p&gt;The other important consideration is whether the commit has already been shared.&lt;/p&gt;

&lt;p&gt;If the commit exists only locally, resetting can be perfectly reasonable. If you've already pushed it and other people may have based their work on it, moving the branch backward creates a history rewrite that affects everyone downstream.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;git revert&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;For an already-shared commit, &lt;code&gt;git revert&lt;/code&gt; is often the safer choice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git revert HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rather than moving the branch backward, it creates a &lt;strong&gt;new commit&lt;/strong&gt; that reverses the earlier change.&lt;/p&gt;

&lt;p&gt;The easiest way to remember the distinction is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reset   → move the branch backward
revert  → add a new commit that undoes an earlier one
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git also keeps a reflog locally, which can sometimes help recover from mistakes involving commands such as &lt;code&gt;reset&lt;/code&gt;. That's useful to know, but it shouldn't be treated as permission to run destructive commands carelessly.&lt;/p&gt;




&lt;h2&gt;
  
  
  15. &lt;code&gt;git remote&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A Git repository can work entirely locally, but most development eventually involves a remote repository somewhere else. &lt;code&gt;git remote&lt;/code&gt; lets you inspect and manage those connections.&lt;/p&gt;

&lt;p&gt;To see what is configured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add a remote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote add origin https://github.com/user/repo.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To remove one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote remove origin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To rename one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote rename origin upstream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;origin&lt;/code&gt; is a convention, not a special Git command or keyword. When you clone a repository, Git normally names the remote &lt;code&gt;origin&lt;/code&gt; simply because that is the conventional default.&lt;/p&gt;

&lt;p&gt;Fork-based workflows often use another common convention:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;origin   → your fork
upstream → original repository
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That arrangement lets you push your own work to &lt;code&gt;origin&lt;/code&gt; while fetching updates from the original project through &lt;code&gt;upstream&lt;/code&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  Five Habits That Make Git Much Easier
&lt;/h1&gt;

&lt;p&gt;Knowing commands is useful. Knowing when to stop and inspect the repository is even more useful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check before you change things
&lt;/h3&gt;

&lt;p&gt;When you're uncertain, start here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
git diff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those two commands answer a remarkable number of “what just happened?” questions without changing anything themselves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep commits focused
&lt;/h3&gt;

&lt;p&gt;Small commits are easier to review and easier to undo. They also make &lt;code&gt;git log&lt;/code&gt; useful instead of turning it into a museum of commits named &lt;code&gt;final&lt;/code&gt;, &lt;code&gt;final2&lt;/code&gt;, and &lt;code&gt;really-final-this-time&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use &lt;code&gt;.gitignore&lt;/code&gt; early
&lt;/h3&gt;

&lt;p&gt;A typical project might ignore things such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules/
.env
.DS_Store
dist/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just remember that &lt;code&gt;.gitignore&lt;/code&gt; doesn't remove a file that has already been committed. If a credential or API key has already been pushed to a remote repository, assume it has been exposed and rotate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Treat force-push as an exception
&lt;/h3&gt;

&lt;p&gt;Before using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ask yourself whether anyone else could have based work on the remote branch.&lt;/p&gt;

&lt;p&gt;On a private feature branch, rewriting history may be perfectly reasonable. On a shared branch, it can create a mess for everyone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practice recovery, not memorization
&lt;/h3&gt;

&lt;p&gt;The fastest way to understand Git is to use it somewhere safe.&lt;/p&gt;

&lt;p&gt;Create a throwaway repository. Make a few commits. Create a branch. Modify a file. Stash it. Undo something. Create a merge conflict and resolve it.&lt;/p&gt;

&lt;p&gt;Once you've recovered from a mistake in a repository you don't care about, the same commands feel much less intimidating in a repository you do.&lt;/p&gt;




&lt;h1&gt;
  
  
  Git Commands by Situation
&lt;/h1&gt;

&lt;p&gt;This is the part worth bookmarking because it answers the question beginners actually have: &lt;strong&gt;“What do I type now?”&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Reach for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Starting a project&lt;/td&gt;
&lt;td&gt;git init&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Getting an existing project&lt;/td&gt;
&lt;td&gt;git clone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not sure what's happening&lt;/td&gt;
&lt;td&gt;git status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Choosing what belongs in the next commit&lt;/td&gt;
&lt;td&gt;git add&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Saving a checkpoint&lt;/td&gt;
&lt;td&gt;git commit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Starting isolated work&lt;/td&gt;
&lt;td&gt;git branch / git switch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Moving between branches&lt;/td&gt;
&lt;td&gt;git switch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Throwing away a local file change&lt;/td&gt;
&lt;td&gt;git restore&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Combining branch histories&lt;/td&gt;
&lt;td&gt;git merge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sharing your commits&lt;/td&gt;
&lt;td&gt;git push&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Getting remote changes&lt;/td&gt;
&lt;td&gt;git pull&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Investigating history&lt;/td&gt;
&lt;td&gt;git log&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inspecting exactly what changed&lt;/td&gt;
&lt;td&gt;git diff&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Temporarily setting work aside&lt;/td&gt;
&lt;td&gt;git stash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Undoing an unshared commit&lt;/td&gt;
&lt;td&gt;git reset&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Undoing a shared commit&lt;/td&gt;
&lt;td&gt;git revert&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Checking repository connections&lt;/td&gt;
&lt;td&gt;git remote&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h1&gt;
  
  
  Quick-Reference Cheat Sheet
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;git init&lt;/td&gt;
&lt;td&gt;Create a repository&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;git clone&lt;/td&gt;
&lt;td&gt;Copy an existing repository&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;git status&lt;/td&gt;
&lt;td&gt;Inspect repository state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;git add&lt;/td&gt;
&lt;td&gt;Stage changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;git commit&lt;/td&gt;
&lt;td&gt;Record a snapshot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;git branch&lt;/td&gt;
&lt;td&gt;Manage branches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;git checkout / git switch / git restore&lt;/td&gt;
&lt;td&gt;Switch branches or restore files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;git merge&lt;/td&gt;
&lt;td&gt;Combine branch histories&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;git push&lt;/td&gt;
&lt;td&gt;Send commits to a remote&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;git pull&lt;/td&gt;
&lt;td&gt;Fetch and integrate remote changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;git log&lt;/td&gt;
&lt;td&gt;Inspect commit history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;git diff&lt;/td&gt;
&lt;td&gt;Compare changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;git stash&lt;/td&gt;
&lt;td&gt;Temporarily store unfinished work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;git reset / git revert&lt;/td&gt;
&lt;td&gt;Undo changes in different ways&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;git remote&lt;/td&gt;
&lt;td&gt;Manage remote connections&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Where to Go From Here
&lt;/h1&gt;

&lt;p&gt;You don't need to memorize all fifteen commands before you start building things.&lt;/p&gt;

&lt;p&gt;For most everyday work, you'll spend a surprising amount of time with just:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
git add
git commit
git push
git pull
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Branching becomes important as soon as you're working on multiple features or collaborating with other developers. &lt;code&gt;stash&lt;/code&gt;, &lt;code&gt;reset&lt;/code&gt;, and &lt;code&gt;revert&lt;/code&gt; become important when something gets messy.&lt;/p&gt;

&lt;p&gt;That's actually the better way to learn Git: let the situations teach you the commands instead of trying to memorize the entire manual up front.&lt;/p&gt;

&lt;p&gt;And when you do get into trouble, remember the most useful Git habit of all:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't guess what Git is doing. Inspect the state first.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
git diff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git isn't really about memorizing commands.&lt;/p&gt;

&lt;p&gt;It's about knowing where your changes are, understanding what you want to happen next, and choosing the command that gets you there without making the problem worse.&lt;/p&gt;

&lt;p&gt;Once that mental model becomes second nature, Git stops feeling mysterious.&lt;/p&gt;

&lt;p&gt;It becomes a safety net.&lt;/p&gt;

&lt;p&gt;And that's what it was supposed to be all along.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://zyvop.com/the-15-git-commands-that-ll-save-your-sanity-and-your-code-7yygk" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡 For more articles like this, &lt;a href="https://zyvop.com/newsletter" rel="noopener noreferrer"&gt;subscribe to the ZyVOP newsletter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>git</category>
      <category>versioncontrol</category>
      <category>gitcommands</category>
      <category>gitforbeginners</category>
    </item>
    <item>
      <title>Zero-Downtime Deployments: Strategies and Tradeoffs</title>
      <dc:creator>Bhavya Arora</dc:creator>
      <pubDate>Mon, 31 Aug 2026 06:53:33 +0000</pubDate>
      <link>https://dev.to/bhavya_arora/zero-downtime-deployments-strategies-and-tradeoffs-987</link>
      <guid>https://dev.to/bhavya_arora/zero-downtime-deployments-strategies-and-tradeoffs-987</guid>
      <description>&lt;p&gt;Every deployment is a gamble. You're swapping out a running system mid-flight — like changing the engine of a plane while it's in the air. Do it wrong and users see errors, requests fail, and your on-call phone starts buzzing at 2 AM.&lt;/p&gt;

&lt;p&gt;Zero-downtime deployment is the discipline of making that swap invisible. But "invisible" hides a lot of complexity. This post walks through the main strategies, when to use each one, and what they cost you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Downtime Happens in the First Place
&lt;/h2&gt;

&lt;p&gt;Before picking a strategy, it helps to understand where downtime actually comes from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Process restart gap&lt;/strong&gt; — the old process dies before the new one is ready&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Port contention&lt;/strong&gt; — old and new can't bind to the same port simultaneously&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Schema migrations&lt;/strong&gt; — the database is in a state neither the old nor new code can handle&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cache invalidation&lt;/strong&gt; — stale data causes 500s after a deploy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;In-flight requests&lt;/strong&gt; — requests mid-processing get dropped when a process dies&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each strategy addresses these differently. None of them solve all of these at once without some cost.&lt;/p&gt;




&lt;h2&gt;
  
  
  Strategy 1: Blue-Green Deployments
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;You run two identical production environments — &lt;strong&gt;blue&lt;/strong&gt; (live) and &lt;strong&gt;green&lt;/strong&gt; (idle). You deploy to green, smoke-test it, then flip a load balancer or DNS record to point traffic from blue to green. Blue becomes your instant rollback target.&lt;/p&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%2Fmermaid.ink%2Fimg%2Fpako%3AeNp9kcFq20AQhl9lOhBwYBUi05MOhag4aUDtwca5WD6MpJG8ZLUrdtd208SQU-8JuTsteYW8kJ8gj1AkJaRg2j3t_vvNfsPsNeamYIywVGadL8h6SMapBgCYDmYv27snmDq2bn4IQfAJkniWGCogJkU6ZztPdQ8ncXt_k-Lu7hFiLo1lKJVsYHf7AOHx8UGKNxAn09E7fvTK_4KT0rPdx8_Go9G3N4FbZpWlZtE9MkvxZfvwDLFacleyCgEGSq74MMV5X9CuLJyda-fbViH8Ox--58PXnHWx5-o66GTb33BmmXVvGwIMZKEYdj_vYV9b_UNb_V_b2d7m0oMerFEqo_wyAremBtptO5skRoE125pkgdE1-gXX7TcWXNJSeRR9ckFWUqbYtUxptD-lWqorjDCgplEcuCvnuRYQK6kvv1I-6c6nRnsBKU64MgzT8xQFjE1mvBHwhdWKvcxJwImVpAQ40i5wbGWJopNM5I-2l_Bj8x03G4FZ9dkoYzHCD-uF9IybPxZizfA" 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%2Fmermaid.ink%2Fimg%2Fpako%3AeNp9kcFq20AQhl9lOhBwYBUi05MOhag4aUDtwca5WD6MpJG8ZLUrdtd208SQU-8JuTsteYW8kJ8gj1AkJaRg2j3t_vvNfsPsNeamYIywVGadL8h6SMapBgCYDmYv27snmDq2bn4IQfAJkniWGCogJkU6ZztPdQ8ncXt_k-Lu7hFiLo1lKJVsYHf7AOHx8UGKNxAn09E7fvTK_4KT0rPdx8_Go9G3N4FbZpWlZtE9MkvxZfvwDLFacleyCgEGSq74MMV5X9CuLJyda-fbViH8Ox--58PXnHWx5-o66GTb33BmmXVvGwIMZKEYdj_vYV9b_UNb_V_b2d7m0oMerFEqo_wyAremBtptO5skRoE125pkgdE1-gXX7TcWXNJSeRR9ckFWUqbYtUxptD-lWqorjDCgplEcuCvnuRYQK6kvv1I-6c6nRnsBKU64MgzT8xQFjE1mvBHwhdWKvcxJwImVpAQ40i5wbGWJopNM5I-2l_Bj8x03G4FZ9dkoYzHCD-uF9IybPxZizfA" alt="Mermaid Diagram" width="1310" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Real example
&lt;/h3&gt;

&lt;p&gt;AWS Elastic Beanstalk's "swap environment URLs" does exactly this. You deploy v2 to a staging environment, run your test suite, then call &lt;code&gt;aws elasticbeanstalk swap-environment-cnames&lt;/code&gt;. Traffic flips in seconds. If something goes wrong, you swap back.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tradeoffs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Instant rollback — just flip the switch back&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Green environment acts as a staging/smoke-test target&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No partial state: all users are on one version at a time&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Double the infrastructure cost while both environments run&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database is the hard problem — both blue and green share it, so schema changes must be backward-compatible&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DNS-based flips can have propagation lag (use load balancer-level routing instead)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Warm-up time for green (JVM startup, cache priming) can cause a traffic spike on switch&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Stateless services, teams with strict rollback SLAs, apps on managed platforms (Elastic Beanstalk, App Engine).&lt;/p&gt;




&lt;h2&gt;
  
  
  Strategy 2: Rolling Deployments
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;Instead of replacing everything at once, you update instances gradually — replacing a few at a time while the rest keep serving traffic. The load balancer routes only to healthy instances.&lt;/p&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%2Fmermaid.ink%2Fimg%2Fpako%3AeNqN0s9q4zAQBvBXmc5ZPvjPXnIoNFtCF3YvddtL3MPYGieismQkJWkaAvsO22Ofrk-y2Ca41IdEF40-JL4f2AesrGScYa3trlqTC_D7vjAAAH5Trhy1a8jjZYF54BZi-Pz7DnPyrJXhAp-Hm92SynEVlDXwMB9Tipfb-BmiKAJKxjEdx6wbhwdsZGG-dyen7qTvXijnA7RWwqaVFFhegCg7_zaBz49_BQ615YgpR0x5DpOeMGmPuSNd72h_AaGaEqpkGo2U6hwlO1F-9JRbe9H3kFOHnDpkOo2yr9HElccQRdeQJ8OWDluGAht2DSmJswOGNTfdrya5po0OKIbkiZyiUrPv7tTWhAU1Su9xhhG1rebI733gRsBcK_Pyh6q8Py-sCQIKzHllGR5_FSjg3pY2WAF3rLccVEUCbpwiLcCT8ZFnp2oUfUmu3jpLnLWveDwKLFc_rbYOZ3i1W6vAePwP_PPz5g" 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%2Fmermaid.ink%2Fimg%2Fpako%3AeNqN0s9q4zAQBvBXmc5ZPvjPXnIoNFtCF3YvddtL3MPYGieismQkJWkaAvsO22Ofrk-y2Ca41IdEF40-JL4f2AesrGScYa3trlqTC_D7vjAAAH5Trhy1a8jjZYF54BZi-Pz7DnPyrJXhAp-Hm92SynEVlDXwMB9Tipfb-BmiKAJKxjEdx6wbhwdsZGG-dyen7qTvXijnA7RWwqaVFFhegCg7_zaBz49_BQ615YgpR0x5DpOeMGmPuSNd72h_AaGaEqpkGo2U6hwlO1F-9JRbe9H3kFOHnDpkOo2yr9HElccQRdeQJ8OWDluGAht2DSmJswOGNTfdrya5po0OKIbkiZyiUrPv7tTWhAU1Su9xhhG1rebI733gRsBcK_Pyh6q8Py-sCQIKzHllGR5_FSjg3pY2WAF3rLccVEUCbpwiLcCT8ZFnp2oUfUmu3jpLnLWveDwKLFc_rbYOZ3i1W6vAePwP_PPz5g" alt="Mermaid Diagram" width="811" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Real example
&lt;/h3&gt;

&lt;p&gt;Kubernetes rolling updates are the canonical implementation. Your deployment spec controls the pace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RollingUpdate&lt;/span&gt;
  &lt;span class="na"&gt;rollingUpdate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;maxSurge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;        &lt;span class="c1"&gt;# spin up 1 extra pod before killing old ones&lt;/span&gt;
    &lt;span class="na"&gt;maxUnavailable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;# never reduce below desired replica count&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these settings, Kubernetes will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Spin up a new v2 pod&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wait until it passes readiness checks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only then terminate one v1 pod&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Repeat&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Tradeoffs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;No infrastructure doubling (with &lt;code&gt;maxSurge: 0&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Works natively in Kubernetes, ECS, and most orchestrators&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gradual rollout limits the blast radius of a bad deploy&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Both versions run simultaneously&lt;/strong&gt; during the rollout window — your API must be backward-compatible with itself&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Slower to complete than blue-green&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rollback means rolling forward again (another full rollout cycle)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Health checks must be accurate — a pod that starts but crashes under load will still pass initial checks&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Kubernetes-native teams, microservices with stable APIs, when infrastructure cost is a constraint.&lt;/p&gt;




&lt;h2&gt;
  
  
  Strategy 3: Canary Releases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;You send a small percentage of traffic to the new version and watch metrics before committing. The name comes from the "canary in a coal mine" — if the canary dies, you know there's a problem before it affects everyone.&lt;/p&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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpdUL1KA0EQfpVxQFDYKxK0MIXiD6JgLC4kILcWc5eJt7i3G3bXizEGrK0U7dP4ZD5BHkFuTxEtv_l-5ptZYGHHjD2caDsrSnIBLlJpAACGW9l69foBQ8_OX29DkuxDmh2TITeH1N4FdtetMm24R4l7u5sAPlCuWeIjjDqZxLoDn0_vMGin0mzl5Fkrw9sS_9kbNxQxP9q7mcT16uUD6m7MaFc3GYZnULPzyprfmFEnVuxn69XbM_Q5OFX4H67bci3qR3CyqLtQMulQzg-WLXPyXeWKfVypTOGYPMNm0yj9K7q0UeOs1jkVt-3JKLBiV5EaY2-BoeSq-e6YJ3SnA4p2MiKnmn_4RjOxJpxSpfQce5jQdKo58XMfuBJwpJW57VMxiPjUmiBA4oBvLMPwXKKA1OY2WAFnrGsOqiABh06RFuDJ-MSzUxMUcclAPTRdOjvTe1wuBeY3x1Zbhz3cmJUqMC6_AAGTrEU" 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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpdUL1KA0EQfpVxQFDYKxK0MIXiD6JgLC4kILcWc5eJt7i3G3bXizEGrK0U7dP4ZD5BHkFuTxEtv_l-5ptZYGHHjD2caDsrSnIBLlJpAACGW9l69foBQ8_OX29DkuxDmh2TITeH1N4FdtetMm24R4l7u5sAPlCuWeIjjDqZxLoDn0_vMGin0mzl5Fkrw9sS_9kbNxQxP9q7mcT16uUD6m7MaFc3GYZnULPzyprfmFEnVuxn69XbM_Q5OFX4H67bci3qR3CyqLtQMulQzg-WLXPyXeWKfVypTOGYPMNm0yj9K7q0UeOs1jkVt-3JKLBiV5EaY2-BoeSq-e6YJ3SnA4p2MiKnmn_4RjOxJpxSpfQce5jQdKo58XMfuBJwpJW57VMxiPjUmiBA4oBvLMPwXKKA1OY2WAFnrGsOqiABh06RFuDJ-MSzUxMUcclAPTRdOjvTe1wuBeY3x1Zbhz3cmJUqMC6_AAGTrEU" alt="Mermaid Diagram" width="1043" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You progressively shift traffic: 5% → 25% → 50% → 100%, with automated or manual checks at each stage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real example
&lt;/h3&gt;

&lt;p&gt;Netflix's Spinnaker is built around canary analysis. At each stage it compares key metrics (error rate, latency p99, CPU) between the canary and baseline. If the canary degrades relative to baseline, the pipeline auto-rolls back.&lt;/p&gt;

&lt;p&gt;You can approximate this with Nginx using &lt;code&gt;split_clients&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;split_clients&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$request_id&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;$upstream&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;5%&lt;/span&gt;   &lt;span class="s"&gt;v2_backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;*&lt;/span&gt;    &lt;span class="s"&gt;v1_backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or with Kubernetes + Argo Rollouts, which handles the traffic shifting and metric analysis natively.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💾 &lt;strong&gt;Working example:&lt;/strong&gt; &lt;a href="https://github.com/bhavyaarora1905/blogs/blob/main/canary-router.js" rel="noopener noreferrer"&gt;canary-router.js&lt;/a&gt; — a pure Node.js canary router that splits traffic between v1 and v2, tracks per-version error rates and latency, and warns when the canary degrades. Run with &lt;code&gt;CANARY_PERCENT=10 node canary-router.js&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Tradeoffs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Real production validation before full rollout&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Catches issues that staging never would (traffic patterns, data edge cases)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blast radius is tiny if something goes wrong early&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Both versions serve traffic simultaneously — same backward-compat requirement as rolling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requires solid observability (you can't make canary decisions without metrics)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More complex pipeline to build and maintain&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User experience can be inconsistent if users hit different versions across requests (especially problematic for SPAs)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; High-traffic services where production behavior is hard to predict in staging. Teams with mature observability.&lt;/p&gt;




&lt;h2&gt;
  
  
  Strategy 4: Feature Flags (The Invisible Deploy)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;You decouple &lt;strong&gt;deploying code&lt;/strong&gt; from &lt;strong&gt;releasing features&lt;/strong&gt;. The new code ships to 100% of servers, but it's dormant behind a flag. You control rollout through config, not deployments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;feature_flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;new_checkout_flow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;new_checkout_flow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;legacy_checkout_flow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can roll out to 1% of users, then 10%, then specific cohorts, then everyone — without a single new deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real example
&lt;/h3&gt;

&lt;p&gt;Facebook has deployed code to all servers while exposing features to 0 users, then gradually rolled out to billions. Their internal system (now open-sourced as GK) gates features by user ID, location, device type, and more.&lt;/p&gt;

&lt;p&gt;Tools like LaunchDarkly, Unleash, and Statsig give you this out of the box with a dashboard, targeting rules, and kill switches.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💾 &lt;strong&gt;Working example:&lt;/strong&gt; &lt;a href="https://github.com/bhavyaarora1905/blogs/blob/main/feature-flags.js" rel="noopener noreferrer"&gt;feature-flags.js&lt;/a&gt; — a zero-dependency feature flag engine with deterministic percentage rollout (FNV-1a hashing), kill switches, user allowlists, stale flag warnings, and an access log. Run with &lt;code&gt;node feature-flags.js&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Tradeoffs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Deployment risk decoupled from feature risk — a bad feature flag is a config change to revert, not a rollback&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enables A/B testing and gradual rollouts without ops involvement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Works for both frontend and backend features&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flag debt&lt;/strong&gt; — old flags never get cleaned up and become landmines&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code complexity: every flag is a branch, every branch needs testing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flags don't help with infrastructure changes or dependency upgrades&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The database still needs to handle both code paths until the old one is removed&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Feature launches, A/B testing, kill switches for risky features. Not a substitute for deployment infrastructure — use alongside blue-green or rolling, not instead of.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hard Part: Database Migrations
&lt;/h2&gt;

&lt;p&gt;Every strategy above sidesteps the hardest problem: &lt;strong&gt;your database doesn't version with your code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When v1 and v2 run simultaneously (rolling, canary) or share a database (blue-green), your schema has to satisfy both versions at once. This rules out most naive migrations.&lt;/p&gt;

&lt;h3&gt;
  
  
  The expand-contract pattern
&lt;/h3&gt;

&lt;p&gt;Instead of one migration, you do three deployments:&lt;/p&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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpd0c1unDAQB_BXmc4ZDgs9cahEgLSR9gOxbFWpjioDQ7BibISd3dJkpT5E7lH7DlXueZQ8QR-hWsKq2Rzt-cu_mfEtlroiDLCWelc2vLeQx0wBAKSzrwz_Pjz8hrThhmAGzz_vIfmShsuYMRXO8ySDPDybJwGEcQzRar5ZLKESppN8-KZ4S4yprQe7XlgyUGjbQKnlTasMPD1CT7wyUPe6hTGLl5Prvbi_Jtcb3cXFxyzME8bUJo3DPAmg4OV1LaQ8EV-9x9TWn5CTxNPj647-s_7I3v-ZWH9ko9Uyz8IofztwnK3S48STFkniCkzZUMsPiFZyOJV7arlQZiSPOwbX_XDHsKJO6gG2HsM7SL3jJt5U_bHqo4Mt9S0XFQa3aBtqDz9YUc1vpEXn5eYz7wUvJJlDptbKnvNWyAEDdHnXSXLNYCy1DpxJoa4XvFyP53OtrAMM13SlCTYXDB3IdKGtduATyS1ZUXIHwl5w6YDhyriGelGjMyJr8ePQy-x99x33eweLq0hL3WOA73aNsIT7fwOb1gQ" 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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpd0c1unDAQB_BXmc4ZDgs9cahEgLSR9gOxbFWpjioDQ7BibISd3dJkpT5E7lH7DlXueZQ8QR-hWsKq2Rzt-cu_mfEtlroiDLCWelc2vLeQx0wBAKSzrwz_Pjz8hrThhmAGzz_vIfmShsuYMRXO8ySDPDybJwGEcQzRar5ZLKESppN8-KZ4S4yprQe7XlgyUGjbQKnlTasMPD1CT7wyUPe6hTGLl5Prvbi_Jtcb3cXFxyzME8bUJo3DPAmg4OV1LaQ8EV-9x9TWn5CTxNPj647-s_7I3v-ZWH9ko9Uyz8IofztwnK3S48STFkniCkzZUMsPiFZyOJV7arlQZiSPOwbX_XDHsKJO6gG2HsM7SL3jJt5U_bHqo4Mt9S0XFQa3aBtqDz9YUc1vpEXn5eYz7wUvJJlDptbKnvNWyAEDdHnXSXLNYCy1DpxJoa4XvFyP53OtrAMM13SlCTYXDB3IdKGtduATyS1ZUXIHwl5w6YDhyriGelGjMyJr8ePQy-x99x33eweLq0hL3WOA73aNsIT7fwOb1gQ" alt="Mermaid Diagram" width="276" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 1 — Expand:&lt;/strong&gt; Add the new column/table without removing anything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy v2 which writes to both &lt;code&gt;name&lt;/code&gt; (old) and &lt;code&gt;display_name&lt;/code&gt; (new), reads from &lt;code&gt;name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 2 — Migrate:&lt;/strong&gt; Backfill the new column.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;display_name&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy v3 which reads from &lt;code&gt;display_name&lt;/code&gt;, writes to both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 3 — Contract:&lt;/strong&gt; Remove the old column once no code references it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is slower and more tedious than a single migration, but it's the only way to be truly safe with zero-downtime deploys.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to avoid
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;NOT NULL&lt;/code&gt; columns without defaults added to existing tables&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Renaming columns directly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dropping columns that old code still reads&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changing column types in ways that break existing queries&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Putting It Together: A Decision Framework
&lt;/h2&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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpVksFq20AQhl9luqeESIckzsWHlthBSQ9JsN0USjaHkTSSl6x2xe44rqoYemjvPRQKoWAovfQB-gR9kz6BH6FIcmz3OMs_3__BbC0Sm5Loi0zbeTJFx_DmTBoAgAmj473b1fLpI1zRHFIqta0KMgyGKKX0bh_C8CWMDushGqjsDDDLrEulNEd_voEymUOInaJMV68W0nTY0WGz9fiO_COMjuorohSQbaES8HPFyVRKcwDKeEbD4KzWMSb3zf7O9pV9hNFxfaHyacgOs0wlUprS2XSWsLIGPLkHldBO7dG2dnB-K8Vq-fX3arn8AQM9o_DcERkp7v4Ldy0bwvGOeK--RJ45ktLYuCnDWGnF1cbzeEMYX3dtn2BstVYmh5syRaa2bZ3ubdHD0zb-5ScM0aCrYEya0NNWrreDfiYMzrtbnNQRtWKhpgfSUhqn_D2wtc9m4-t1shuHp5txjT_ZukRR6_L0Cw5gzYVIY-6lNKityb1KaX1ozw6Z8mrrebLxPLOG9m6l-Pv9M0ymqgTFUtztd7koag2ajAhEQa5AlYp-LXhKRfM1U8pwplkE3ctbdApjTb7JZNZwhIXSleiLEMtSU-grz1QEMNDK3F9iMmnnyBoOQIoJ5Zbg5rUUAYxtbNkGcEH6gVglGMCpU6gD8Gh86MmpTARtyUR9aFwOe-V7sVgEIs6HVlsn-uLFfKqYxOIfebgaBg" 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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpVksFq20AQhl9luqeESIckzsWHlthBSQ9JsN0USjaHkTSSl6x2xe44rqoYemjvPRQKoWAovfQB-gR9kz6BH6FIcmz3OMs_3__BbC0Sm5Loi0zbeTJFx_DmTBoAgAmj473b1fLpI1zRHFIqta0KMgyGKKX0bh_C8CWMDushGqjsDDDLrEulNEd_voEymUOInaJMV68W0nTY0WGz9fiO_COMjuorohSQbaES8HPFyVRKcwDKeEbD4KzWMSb3zf7O9pV9hNFxfaHyacgOs0wlUprS2XSWsLIGPLkHldBO7dG2dnB-K8Vq-fX3arn8AQM9o_DcERkp7v4Ldy0bwvGOeK--RJ45ktLYuCnDWGnF1cbzeEMYX3dtn2BstVYmh5syRaa2bZ3ubdHD0zb-5ScM0aCrYEya0NNWrreDfiYMzrtbnNQRtWKhpgfSUhqn_D2wtc9m4-t1shuHp5txjT_ZukRR6_L0Cw5gzYVIY-6lNKityb1KaX1ozw6Z8mrrebLxPLOG9m6l-Pv9M0ymqgTFUtztd7koag2ajAhEQa5AlYp-LXhKRfM1U8pwplkE3ctbdApjTb7JZNZwhIXSleiLEMtSU-grz1QEMNDK3F9iMmnnyBoOQIoJ5Zbg5rUUAYxtbNkGcEH6gVglGMCpU6gD8Gh86MmpTARtyUR9aFwOe-V7sVgEIs6HVlsn-uLFfKqYxOIfebgaBg" alt="Mermaid Diagram" width="640" height="1582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Blue-Green&lt;/th&gt;
&lt;th&gt;Rolling&lt;/th&gt;
&lt;th&gt;Canary&lt;/th&gt;
&lt;th&gt;Feature Flags&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Rollback speed&lt;/td&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;td&gt;Slow (re-deploy)&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Instant (flag toggle)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infrastructure cost&lt;/td&gt;
&lt;td&gt;2x during deploy&lt;/td&gt;
&lt;td&gt;~1x&lt;/td&gt;
&lt;td&gt;~1x&lt;/td&gt;
&lt;td&gt;~1x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Handles DB migrations&lt;/td&gt;
&lt;td&gt;No (shared DB)&lt;/td&gt;
&lt;td&gt;No (dual version)&lt;/td&gt;
&lt;td&gt;No (dual version)&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observability needed&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best rollout size&lt;/td&gt;
&lt;td&gt;All-or-nothing&lt;/td&gt;
&lt;td&gt;Gradual&lt;/td&gt;
&lt;td&gt;Gradual by %&lt;/td&gt;
&lt;td&gt;Granular&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Most mature teams use a combination: rolling or blue-green for the infrastructure layer, canary for traffic validation, and feature flags for product changes. The strategies are complementary, not competing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Checklist Before Your Next Deploy
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;💾 &lt;strong&gt;Working example:&lt;/strong&gt; &lt;a href="https://github.com/bhavyaarora1905/blogs/blob/main/graceful-shutdown.js" rel="noopener noreferrer"&gt;graceful-shutdown.js&lt;/a&gt; — a Node.js HTTP server demonstrating all three items below: separate liveness/readiness probes, SIGTERM drain with in-flight request tracking, and a hard-exit failsafe timeout. Run with &lt;code&gt;node graceful-shutdown.js&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Health checks return 200 only when the app is genuinely ready (not just started)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Graceful shutdown: app drains in-flight requests before exiting (&lt;code&gt;SIGTERM&lt;/code&gt; handler)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database migration is backward-compatible with the previous version&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Readiness probe is separate from liveness probe in Kubernetes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You have a tested rollback procedure (not just a theoretical one)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Observability is in place: error rate, latency, and saturation dashboards open during deploy&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Code Examples
&lt;/h2&gt;

&lt;p&gt;All working scripts from this post are available &lt;a href="https://github.com/bhavyaarora1905/blogs/" rel="noopener noreferrer"&gt;here&lt;/a&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;What it demonstrates&lt;/th&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;graceful-shutdown.js&lt;/td&gt;
&lt;td&gt;Liveness + readiness probes, SIGTERM drain, connection tracking&lt;/td&gt;
&lt;td&gt;node graceful-shutdown.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;canary-router.js&lt;/td&gt;
&lt;td&gt;Canary traffic split, per-version error rate, rollback warning&lt;/td&gt;
&lt;td&gt;CANARY_PERCENT=10 node canary-router.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;feature-flags.js&lt;/td&gt;
&lt;td&gt;Percentage rollout, kill switches, allowlists, stale flag detection&lt;/td&gt;
&lt;td&gt;node feature-flags.js&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No dependencies — pure Node.js v14+. Clone and run immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;Zero-downtime deployment isn't a single tool you install — it's a set of habits and constraints you build your system around. The earlier you treat backward compatibility and graceful degradation as first-class concerns, the cheaper these strategies become to implement.&lt;/p&gt;

&lt;p&gt;The teams that do this best don't deploy carefully. They deploy &lt;em&gt;constantly&lt;/em&gt;, because they've made deployment boring.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://zyvop.com/zero-downtime-deployments-strategies-and-tradeoffs-40waq" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡 For more articles like this, &lt;a href="https://zyvop.com/newsletter" rel="noopener noreferrer"&gt;subscribe to the ZyVOP newsletter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>cicd</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Local HTTPS Done Right: Wildcard SSL for Modern Development</title>
      <dc:creator>Bhavya Arora</dc:creator>
      <pubDate>Mon, 31 Aug 2026 06:53:18 +0000</pubDate>
      <link>https://dev.to/bhavya_arora/local-https-done-right-wildcard-ssl-for-modern-development-1l68</link>
      <guid>https://dev.to/bhavya_arora/local-https-done-right-wildcard-ssl-for-modern-development-1l68</guid>
      <description>&lt;p&gt;Modern web development demands HTTPS. If you are building an application on &lt;code&gt;http://localhost:3000&lt;/code&gt;, you will inevitably hit a wall:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;OAuth providers (Google, GitHub, Apple) often refuse HTTP redirect URIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stripe webhooks require a secure context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cross-domain cookies (&lt;code&gt;SameSite=None&lt;/code&gt;) are strictly blocked by browsers without the &lt;code&gt;Secure&lt;/code&gt; flag.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Service Workers and modern Web APIs (Geolocation, Clipboard) fail silently.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The historical solution was generating self-signed certificates with &lt;code&gt;openssl&lt;/code&gt;. But modern browsers hate self-signed certs. They throw terrifying red "Your connection is not private" screens, forcing you to click through hidden "Proceed anyway" menus.&lt;/p&gt;

&lt;p&gt;Today, we are going to fix this the right way. We will become our own Certificate Authority (CA) and generate a &lt;strong&gt;Wildcard SSL Certificate&lt;/strong&gt; so you can develop locally on &lt;code&gt;https://app.mylocal.dev&lt;/code&gt; with a perfectly green, trusted padlock.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Secret Weapon: mkcert
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/FiloSottile/mkcert" rel="noopener noreferrer"&gt;mkcert&lt;/a&gt; is an incredibly clever tool. Instead of generating a standalone self-signed certificate, it creates a local Certificate Authority (CA) and injects it into your operating system's and browser's trust stores.&lt;/p&gt;

&lt;p&gt;Because your OS explicitly trusts this local CA, any certificate signed by it is treated as entirely valid.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install mkcert
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;macOS (via Homebrew):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;mkcert
&lt;span class="c"&gt;# If you use Firefox, it manages its own trust store, so we need nss&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;nss 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows (via Chocolatey):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;choco&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mkcert&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Ubuntu/Debian:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;libnss3-tools
brew &lt;span class="nb"&gt;install &lt;/span&gt;mkcert &lt;span class="c"&gt;# via Linuxbrew, or download the binary from GitHub&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Initialize Your Local CA
&lt;/h3&gt;

&lt;p&gt;Run the following command &lt;em&gt;once&lt;/em&gt; per machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mkcert &lt;span class="nt"&gt;-install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your operating system will prompt you for an admin password. You are giving &lt;code&gt;mkcert&lt;/code&gt; permission to add a root certificate to your keychain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Generate the Wildcard Certificate
&lt;/h3&gt;

&lt;p&gt;Choose a Top-Level Domain (TLD) for local development. Do not use &lt;code&gt;.dev&lt;/code&gt; or &lt;code&gt;.app&lt;/code&gt;—Google owns these and strictly enforces HSTS (HTTPS routing) at the DNS level, which can cause annoying conflicts.&lt;/p&gt;

&lt;p&gt;The internet standard for local development is &lt;code&gt;.test&lt;/code&gt; or &lt;code&gt;.loc&lt;/code&gt;. Let's use &lt;code&gt;*.myapp.test&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/local-certs &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~/local-certs
mkcert &lt;span class="s2"&gt;"*.myapp.test"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates two files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;_wildcard.myapp.test.pem&lt;/code&gt; (The Public Certificate)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;_wildcard.myapp.test-key.pem&lt;/code&gt; (The Private Key)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 4: Map Local DNS
&lt;/h2&gt;

&lt;p&gt;We need to tell your computer that &lt;code&gt;api.myapp.test&lt;/code&gt; and &lt;code&gt;app.myapp.test&lt;/code&gt; should resolve to &lt;code&gt;localhost&lt;/code&gt; (&lt;code&gt;127.0.0.1&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Edit your hosts file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mac/Linux&lt;/strong&gt;: &lt;code&gt;sudo nano /etc/hosts&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt;: Open Notepad as Administrator, then open &lt;code&gt;C:\Windows\System32\drivers\etc\hosts&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add your domains to the bottom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;127.0.0.1   myapp.test
127.0.0.1   app.myapp.test
127.0.0.1   api.myapp.test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Implementation
&lt;/h2&gt;

&lt;p&gt;You have the trusted certificates and the DNS mapping. Now you just need to serve them. You can do this at the application level or the proxy level.&lt;/p&gt;

&lt;h3&gt;
  
  
  Approach A: Using Docker and Nginx (Recommended)
&lt;/h3&gt;

&lt;p&gt;This closely mirrors a production environment. Nginx handles the SSL termination and passes standard HTTP traffic to your Node/Python app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;docker-compose.yml&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:18&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run dev&lt;/span&gt;
    &lt;span class="c1"&gt;# Notice we don't expose ports directly&lt;/span&gt;

  &lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:alpine&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;443:443"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx.conf:/etc/nginx/nginx.conf:ro&lt;/span&gt;
      &lt;span class="c1"&gt;# Mount the folder containing our certificates&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;~/local-certs:/etc/nginx/certs:ro&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;nginx.conf&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;events&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;app.myapp.test&lt;/span&gt; &lt;span class="s"&gt;api.myapp.test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/certs/_wildcard.myapp.test.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/certs/_wildcard.myapp.test-key.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://web:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Approach B: Native Node.js (Next.js / Vite)
&lt;/h3&gt;

&lt;p&gt;If you don't use Docker, you can pass the certificates directly to your dev server.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Vite&lt;/strong&gt;, add this to &lt;code&gt;vite.config.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/Users/bhavya/local-certs/_wildcard.myapp.test-key.pem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/Users/bhavya/local-certs/_wildcard.myapp.test.pem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app.myapp.test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Crucial Tip: Node.js Backend-to-Backend Requests
&lt;/h2&gt;

&lt;p&gt;If your Node.js backend tries to fetch data from your own secure local API (e.g., Server-Side Rendering hitting &lt;code&gt;https://api.myapp.test&lt;/code&gt;), Node will throw an &lt;code&gt;UNABLE_TO_VERIFY_LEAF_SIGNATURE&lt;/code&gt; error.&lt;/p&gt;

&lt;p&gt;Why? Because Node.js does not use the operating system's trust store. It uses its own hardcoded list of root authorities.&lt;/p&gt;

&lt;p&gt;To tell Node.js to trust your &lt;code&gt;mkcert&lt;/code&gt; CA, you must pass an environment variable when starting your Node script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find where mkcert put your root CA&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NODE_EXTRA_CA_CERTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;mkcert &lt;span class="nt"&gt;-CAROOT&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/rootCA.pem"&lt;/span&gt;

&lt;span class="c"&gt;# Then run your app&lt;/span&gt;
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Boot up your application and navigate to &lt;code&gt;https://app.myapp.test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You will be greeted by a flawless, green padlock. No warnings, no "Proceed to unsafe" buttons. Your cookies will adhere to strict security policies, third-party APIs will accept your webhooks, and your local development environment will finally mirror production parity.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://zyvop.com/local-https-done-right-wildcard-ssl-for-modern-development-muwll" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡 For more articles like this, &lt;a href="https://zyvop.com/newsletter" rel="noopener noreferrer"&gt;subscribe to the ZyVOP newsletter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>ssl</category>
      <category>localdevelopment</category>
      <category>websecurity</category>
    </item>
    <item>
      <title>LongCat-2.0: The AI Model You Were Already Using. Built By The Company That Delivers Your Dinner.</title>
      <dc:creator>Bhavya Arora</dc:creator>
      <pubDate>Mon, 31 Aug 2026 06:52:48 +0000</pubDate>
      <link>https://dev.to/bhavya_arora/longcat-20-the-ai-model-you-were-already-using-built-by-the-company-that-delivers-your-dinner-4m3f</link>
      <guid>https://dev.to/bhavya_arora/longcat-20-the-ai-model-you-were-already-using-built-by-the-company-that-delivers-your-dinner-4m3f</guid>
      <description>&lt;p&gt;&lt;em&gt;For two months, a model called "Owl Alpha" quietly out-hustled GPT-5.5 and Claude on OpenRouter. Nobody knew it was Meituan — yes, the food-delivery app — running a 1.6-trillion-parameter model trained entirely on Chinese chips.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The short version:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Meituan — China's Uber Eats-meets-everything super-app — spent two months running a model called &lt;strong&gt;Owl Alpha&lt;/strong&gt; anonymously on &lt;a href="https://openrouter.ai/openrouter/owl-alpha" rel="noopener noreferrer"&gt;OpenRouter&lt;/a&gt;. Real developers used it in real coding agents, with zero idea who built it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On June 29, Meituan outed itself. On June 30, it launched the model publicly as &lt;strong&gt;LongCat-2.0&lt;/strong&gt;: 1.6 trillion parameters, MIT-licensed, &lt;a href="https://beincrypto.com/china-debuts-longcat-ai-model-without-nvidia-chips/" rel="noopener noreferrer"&gt;trained entirely on Chinese-made chips&lt;/a&gt; — no Nvidia anywhere in the pipeline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It undercuts GPT-5.5 on price by roughly 6–7x and edges past it on one coding benchmark by less than a point — a claim worth double-checking, not taking on faith.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The actual downloadable weights didn't show up until &lt;a href="https://huggingface.co/meituan-longcat/LongCat-2.0-INT8" rel="noopener noreferrer"&gt;July 4&lt;/a&gt;, five days after the "open source" announcement.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you ran a coding agent through Hermes Agent, Claude Code, or OpenClaw sometime between late April and late June 2026, you probably already have an opinion about LongCat-2.0. You just knew it by a different name.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reveal
&lt;/h2&gt;

&lt;p&gt;Meituan didn't do a keynote. It didn't do a demo video with swelling music. It posted a tweet.&lt;/p&gt;

&lt;p&gt;On June 29, &lt;a href="https://www.testingcatalog.com/meituan-launches-longcat-2-0-1-6t-parameter-model-on-apis/" rel="noopener noreferrer"&gt;the official Meituan LongCat account wrote&lt;/a&gt;: &lt;em&gt;"Some of you guessed right. 👀 Owl Alpha on @OpenRouter — that's us."&lt;/em&gt; The thread added that Owl Alpha had hit the global top three by daily volume on OpenRouter, and — by monthly volume — ranked #1 on the Hermes Agent workspace, #2 on Claude Code-compatible deployments, and #3 across OpenClaw. The next day, the &lt;a href="https://github.com/meituan-longcat/LongCat-2.0" rel="noopener noreferrer"&gt;LongCat-2.0 GitHub repo&lt;/a&gt; and &lt;a href="https://huggingface.co/meituan-longcat/LongCat-2.0" rel="noopener noreferrer"&gt;Hugging Face model card&lt;/a&gt; went live, MIT license attached.&lt;/p&gt;

&lt;p&gt;That's the whole trick, and it's a good one: don't launch a model and hope people adopt it. Let them adopt it first, then tell them whose it was.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet Owl Alpha
&lt;/h2&gt;

&lt;p&gt;Before June 29, here's everything OpenRouter's public listing told you about &lt;a href="https://openrouter.ai/openrouter/owl-alpha" rel="noopener noreferrer"&gt;Owl Alpha&lt;/a&gt;: a "high-performance foundation model designed for agentic workloads," hosted by a provider labeled simply &lt;strong&gt;"Stealth."&lt;/strong&gt; No parameter count. No company. Just a note that your prompts might get logged to improve the model — standard fine print for anything running incognito.&lt;/p&gt;

&lt;p&gt;That vagueness didn't stop it from putting up real numbers. One independent tracker following OpenRouter's public usage charts estimated Owl Alpha was processing &lt;a href="https://toastyst.github.io/SpaghettiStories/personal/2026/06/21/owl-alpha-mystery/" rel="noopener noreferrer"&gt;north of 10 trillion tokens a month&lt;/a&gt; by the time of the reveal, growing over 200% month-over-month, and — within the Hermes Agent ecosystem specifically — out-consuming its next four competitors &lt;em&gt;combined&lt;/em&gt;. Take the precise figures with a grain of salt; they're estimates from public dashboards, not audited numbers. But the direction isn't in dispute: developers with zero brand loyalty kept picking this thing for real work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Detective Work
&lt;/h2&gt;

&lt;p&gt;Naturally, people tried to unmask it. That's half the fun of a stealth model — the community turns into an amateur forensics team.&lt;/p&gt;

&lt;p&gt;The strongest tell was behavioral: users on Reddit and elsewhere noticed Owl Alpha would affirm that Taiwan is part of China and steer hard away from questions about Taiwanese independence — the kind of reflex you don't get from a Western lab's model. That pointed toward a Chinese origin fast. Guesses circulated toward Tencent's Hunyuan team, MiniMax, Baidu, or some unannounced newcomer. A &lt;a href="https://news.ycombinator.com/item?id=48727116" rel="noopener noreferrer"&gt;Hacker News thread&lt;/a&gt; speculated about the Huawei Ascend chips underneath it well before Meituan confirmed anything. A handful of users even reported the model referring to itself as being "from the Zoo company" in casual chat — nobody could explain that one until the reveal.&lt;/p&gt;

&lt;p&gt;Almost nobody guessed a food-delivery app.&lt;/p&gt;

&lt;h2&gt;
  
  
  This Playbook Isn't New. The Patience Is.
&lt;/h2&gt;

&lt;p&gt;If this feels familiar, it should. Running a flagship model incognito before the official launch has become standard practice at frontier labs. OpenAI has done it more than once — &lt;a href="https://medium.com/@leucopsis/is-polaris-alpha-a-gpt-5-1-bd445598e27b" rel="noopener noreferrer"&gt;Horizon Alpha&lt;/a&gt; is widely believed to have been an early GPT-5 checkpoint, and &lt;a href="https://openrouter.ai/openrouter/polaris-alpha" rel="noopener noreferrer"&gt;Polaris Alpha&lt;/a&gt;, which showed up on OpenRouter with unusually generous rate limits, turned out to be an early build of GPT-5.1. xAI does this constantly, cycling code names like Sonic, Sherlock, and &lt;a href="https://openrouter.ai/openrouter/sonoma-sky-alpha" rel="noopener noreferrer"&gt;Sonoma&lt;/a&gt; before they resolve into named Grok releases. Cursor's "Cheetah" turned out to be its own Composer model. Even Anthropic has quietly run checkpoints under names like Bobcat and Code-Supernova. There's a &lt;a href="https://jonathanrreed.com/blog/stealth-models/" rel="noopener noreferrer"&gt;decent field guide to spotting these&lt;/a&gt; if you want to go down that rabbit hole yourself.&lt;/p&gt;

&lt;p&gt;What's different about Owl Alpha isn't the tactic — it's the patience. Most stealth models get made and claimed within days, maybe a couple of weeks. Owl Alpha ran anonymously for roughly two months, long enough to rack up genuine production usage across three separate agent ecosystems before Meituan said a word. Leaderboard screenshots are easy to game. Two months of developers voluntarily choosing your model with no idea who made it is a lot harder to fake.&lt;/p&gt;

&lt;p&gt;It's also not like Meituan appeared from nowhere. Its LongCat team had already shipped &lt;a href="https://github.com/meituan-longcat" rel="noopener noreferrer"&gt;LongCat-Flash&lt;/a&gt;, a 560-billion-parameter model, back in September 2025, followed by the multimodal LongCat-Next in March 2026 — public papers, model cards, GitHub repos, the whole open-source routine. What Meituan had never done before was let a model build a reputation &lt;em&gt;before&lt;/em&gt; attaching its name to it. Coming from the company most people outside China associate with fried chicken delivery, that combination was enough to catch the industry flat-footed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Actually Inside It
&lt;/h2&gt;

&lt;p&gt;Cut the backstory and LongCat-2.0 is a Mixture-of-Experts (MoE) model: a huge pool of specialized sub-networks where only a small slice fires for any given token, instead of the whole network lighting up every time. The headline is 1.6 trillion total parameters. The number that actually determines your bill is closer to &lt;strong&gt;48 billion active parameters per token&lt;/strong&gt;, sliding between roughly 33 billion and 56 billion depending on how hard the request is. Autocompleting a variable name barely taxes it; a gnarly multi-step reasoning problem pulls in more of the network.&lt;/p&gt;

&lt;p&gt;A few specific design choices carry the weight, per &lt;a href="https://huggingface.co/meituan-longcat/LongCat-2.0" rel="noopener noreferrer"&gt;Meituan's own technical writeup&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;LongCat Sparse Attention (LSA)&lt;/strong&gt; — standard attention gets brutally expensive as context grows, because every token has to weigh every other token. LSA instead indexes and selects only the most relevant chunks of a long conversation, which is the trick behind sustaining a full 1-million-token context window without the cost exploding.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;N-gram Embedding&lt;/strong&gt; — a 135-billion-parameter layer, borrowed from an earlier LongCat model, that sits alongside the MoE experts rather than inside them. Instead of only recognizing individual words, it can treat common multi-word phrases as single units — "New York City" as one concept instead of three disconnected tokens. Meituan claims roughly 100x richer representations from this without meaningfully increasing model size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Token Prediction (MTP)&lt;/strong&gt; — a lightweight head that drafts several tokens ahead in one pass, which the main model then verifies. Reported acceptance rate above 90%, which is what gets inference speeds above 100 tokens/second through the API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Teacher On-Policy Distillation (MOPD)&lt;/strong&gt; — a post-training step fusing three specialist skill sets (tool use and self-correction, multi-step and STEM reasoning, instruction-following and hallucination suppression) into one model.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pretraining ran on more than 30 trillion tokens of code, English, Chinese, and multilingual data. License is MIT — commercial use, fine-tuning, redistribution, all explicitly fair game.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Benchmarks — Read the Fine Print
&lt;/h2&gt;

&lt;p&gt;Here's what Meituan is claiming:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benchmark&lt;/th&gt;
&lt;th&gt;LongCat-2.0&lt;/th&gt;
&lt;th&gt;For comparison&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SWE-bench Pro (real GitHub issue resolution)&lt;/td&gt;
&lt;td&gt;59.5&lt;/td&gt;
&lt;td&gt;GPT-5.5: 58.6 · Gemini 3.1 Pro: 54.2 · Claude Opus 4.7: 64.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FORTE (office-task agent benchmark)&lt;/td&gt;
&lt;td&gt;73.2&lt;/td&gt;
&lt;td&gt;Claude Opus 4.6: 73.2 (tied) · GPT-5.5: 77.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terminal-Bench 2.1&lt;/td&gt;
&lt;td&gt;70.8&lt;/td&gt;
&lt;td&gt;outperforms Gemini 3.1 Pro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SWE-Bench Multilingual&lt;/td&gt;
&lt;td&gt;77.3&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's the part most coverage buried: these are Meituan's own numbers, run mostly on Meituan's own testing harness. Someone actually &lt;a href="https://huggingface.co/meituan-longcat/LongCat-2.0/discussions/2" rel="noopener noreferrer"&gt;filed a pull request&lt;/a&gt; trying to add these scores to Hugging Face's public evaluation database and hit a wall — Terminal-Bench 2.1, SWE-Bench Multilingual, and FORTE didn't have registered independent evaluations to check against. That's not proof the numbers are inflated. It's just a reminder that "beats GPT-5.5 by eight-tenths of a point on one benchmark" is a claim to file under &lt;em&gt;competitive, not confirmed&lt;/em&gt; until outside labs run their own passes. One outlet that actually built something with it found the output capable but noticeably behind Claude's top tier — closer to a mid-range Claude model than the headline number suggests.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Price Is the Actual Headline
&lt;/h2&gt;

&lt;p&gt;Whatever you think of the benchmark gap, the pricing is not up for debate. Standard API access runs $0.75 per million input tokens and $2.95 per million output, dropping to a launch-promo rate of &lt;strong&gt;$0.30 / $1.20&lt;/strong&gt; — with cached context reads billed at zero.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Input ($/M tokens)&lt;/th&gt;
&lt;th&gt;Output ($/M tokens)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LongCat-2.0 (promo)&lt;/td&gt;
&lt;td&gt;$0.30&lt;/td&gt;
&lt;td&gt;$1.20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LongCat-2.0 (standard)&lt;/td&gt;
&lt;td&gt;$0.75&lt;/td&gt;
&lt;td&gt;$2.95&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek V4-Pro&lt;/td&gt;
&lt;td&gt;$0.435&lt;/td&gt;
&lt;td&gt;$0.87&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet 5 (intro rate)&lt;/td&gt;
&lt;td&gt;$2.00&lt;/td&gt;
&lt;td&gt;$10.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.5&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$30.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus 4.7&lt;/td&gt;
&lt;td&gt;~$15.00&lt;/td&gt;
&lt;td&gt;~$75.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For teams burning through millions of tokens re-reading the same repo on every agent loop, free cache reads alone change the math. Meituan is also running flash-sale &lt;a href="https://www.longcatai.org/news/longcat-2" rel="noopener noreferrer"&gt;token packs&lt;/a&gt; — roughly a billion tokens for $60 — released four times a day on a Beijing schedule.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Chip Story Nobody Should Skip
&lt;/h2&gt;

&lt;p&gt;Here's the part that actually rattled policy people, and it has nothing to do with coding benchmarks. Meituan says LongCat-2.0 was trained from scratch &lt;em&gt;and&lt;/em&gt; served entirely on a cluster of roughly 50,000 domestic Chinese AI accelerators, coordinated with Huawei's HCCL library — &lt;a href="https://tech.yahoo.com/ai/articles/china-longcat-2-0-becomes-134258951.html" rel="noopener noreferrer"&gt;the domestic answer to Nvidia's NCCL&lt;/a&gt; — with zero Nvidia hardware anywhere in the pipeline.&lt;/p&gt;

&lt;p&gt;That distinction is bigger than it sounds. Other Chinese models, including DeepSeek's V4-Pro, have reportedly used domestic chips for &lt;em&gt;inference&lt;/em&gt; while still training on non-domestic hardware. Meituan's claim is that LongCat-2.0 is the first trillion-parameter-class model to do the &lt;em&gt;harder&lt;/em&gt; part — training — entirely on Chinese silicon, at frontier scale, with no catastrophic loss spikes along the way. &lt;a href="https://www.caixinglobal.com/2026-07-07/meituan-open-sources-16-trillion-parameter-ai-model-built-on-chinese-chips-102461495.html" rel="noopener noreferrer"&gt;Caixin Global&lt;/a&gt; and &lt;a href="https://www.digitimes.com/news/a20260707VL209/meituan-infrastructure-ascend-metax.html" rel="noopener noreferrer"&gt;Digitimes&lt;/a&gt; both framed it as a real stress test of China's chip stack, not just a press release.&lt;/p&gt;

&lt;p&gt;Analysts treated it that way too. One noted it should put to rest doubts about whether Huawei's Atlas-950 clusters could actually scale; a Lehigh University researcher called it the first model trained to near-frontier performance entirely on domestic accelerators. The read that stuck: export controls on the newest Nvidia chips don't stop capable models from getting built — they just push the timeline toward domestic alternatives faster than the policy assumed.&lt;/p&gt;

&lt;p&gt;That doesn't settle the argument. Controls still raise costs and slow things down — Meituan's own writeup admits real pain from hardware faults, memory pressure, and numerical instability at 50,000-chip scale. But the assumption that Chinese labs simply &lt;em&gt;couldn't&lt;/em&gt; train frontier-adjacent systems without the latest Nvidia stack took a real hit.&lt;/p&gt;

&lt;p&gt;There's a business subplot worth one line: Meituan's core delivery business has had a brutal year — stock down more than 30% year-to-date, market cap under HK$400 billion — and CEO Wang Xing has publicly taken responsibility for it. A trillion-parameter model quietly beating Western pricing on homegrown chips is, among other things, a pretty loud answer to shareholders asking what else the company's been doing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Still Soft
&lt;/h2&gt;

&lt;p&gt;Be honest about the gaps before you bet a production stack on this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The benchmarks are self-reported&lt;/strong&gt;, and several don't have independent verification yet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"Open weights" and "MIT license" didn't mean downloadable until July 4&lt;/strong&gt; — the GitHub and Hugging Face pages sat on "coming soon" for five days after the big announcement. An &lt;a href="https://github.com/unslothai/unsloth/issues/6759" rel="noopener noreferrer"&gt;Unsloth GitHub issue&lt;/a&gt; tracking community support for the model captures that gap in real time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Self-hosting isn't realistic for most people.&lt;/strong&gt; Estimates put a full deployment around sixteen high-end GPUs — "open source" here mostly means &lt;em&gt;someone&lt;/em&gt; can run it, not &lt;em&gt;you&lt;/em&gt;, unless you've got serious hardware.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;One hands-on test&lt;/strong&gt; — building something end-to-end rather than running a benchmark — found the actual output quality trailing top-tier closed models by more than the score table implies.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bottom Line
&lt;/h2&gt;

&lt;p&gt;Strip away the theater and two things are solidly true: real developers adopted this model in volume with zero idea who built it, and the pricing advantage over GPT-5.5 and Claude's intro rates is real and large, especially for high-volume agentic coding. The domestic-chip training claim, if the SWE-bench-level scrutiny holds up, is a legitimately significant data point about where Chinese AI infrastructure actually stands — independent of how you feel about the export-control debate.&lt;/p&gt;

&lt;p&gt;What's still an open question is whether it's &lt;em&gt;actually&lt;/em&gt; as good as the benchmark table says, and the honest answer right now is: probably close, not quite there, and worth testing yourself rather than taking Meituan's word for it.&lt;/p&gt;

&lt;p&gt;The bigger story isn't a half-point benchmark edge over GPT-5.5. It's that a two-month blind trial, run without anyone's permission to be impressed, ended up more convincing than a launch event — and the company running it wasn't one anyone in the AI industry was watching closely enough.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Go deeper:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://huggingface.co/meituan-longcat/LongCat-2.0" rel="noopener noreferrer"&gt;LongCat-2.0 model card — Hugging Face&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/meituan-longcat/LongCat-2.0" rel="noopener noreferrer"&gt;LongCat-2.0 repo — GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://openrouter.ai/openrouter/owl-alpha" rel="noopener noreferrer"&gt;Owl Alpha's original OpenRouter listing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.longcatai.org/news/longcat-2" rel="noopener noreferrer"&gt;Meituan's official LongCat-2.0 announcement&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://venturebeat.com/technology/meituan-open-sources-longcat-2-0-the-1-6t-near-frontier-agentic-coding-model-thats-been-leading-openrouter-trained-entirely-on-chinese-chips" rel="noopener noreferrer"&gt;VentureBeat's launch-day writeup&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.marktechpost.com/2026/07/05/meituan-releases-longcat-2-0-a-1-6t-parameter-open-moe-model-with-native-1m-context-and-longcat-sparse-attention/" rel="noopener noreferrer"&gt;MarkTechPost's architecture breakdown&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://toastyst.github.io/SpaghettiStories/personal/2026/06/21/owl-alpha-mystery/" rel="noopener noreferrer"&gt;The Owl Alpha mystery, tracked in real time&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://jonathanrreed.com/blog/stealth-models/" rel="noopener noreferrer"&gt;A field guide to stealth models generally&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://zyvop.com/longcat-2-0-the-ai-model-you-were-already-using-built-by-the-company-that-delivers-your-dinner-pwsf3" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡 For more articles like this, &lt;a href="https://zyvop.com/newsletter" rel="noopener noreferrer"&gt;subscribe to the ZyVOP newsletter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>agenticcoding</category>
      <category>longcat20</category>
      <category>meituan</category>
      <category>owlalpha</category>
    </item>
    <item>
      <title>What AI Still Cannot Do: Four Boundaries the 2026 Benchmarks Keep Finding</title>
      <dc:creator>Bhavya Arora</dc:creator>
      <pubDate>Mon, 31 Aug 2026 06:52:27 +0000</pubDate>
      <link>https://dev.to/bhavya_arora/what-ai-still-cannot-do-four-boundaries-the-2026-benchmarks-keep-finding-2km0</link>
      <guid>https://dev.to/bhavya_arora/what-ai-still-cannot-do-four-boundaries-the-2026-benchmarks-keep-finding-2km0</guid>
      <description>&lt;h2&gt;
  
  
  The benchmark built to find the ceiling
&lt;/h2&gt;

&lt;p&gt;In January 2026, the training-data company Mercor released &lt;a href="https://www.mercor.com/blog/introducing-apex-agents/" rel="noopener noreferrer"&gt;APEX-Agents&lt;/a&gt;, a benchmark built from real professional work: week-long consulting projects, investment banking analyses, and corporate law memos, drawn from practitioners at firms including Goldman Sachs, McKinsey, and the law firm Cravath. Frontier models completed less than 25 percent of the 480 tasks. Given eight attempts each, the ceiling rose to 40 percent. No model finished the work end to end.&lt;/p&gt;

&lt;p&gt;AI agents were setting records elsewhere that same month. Put the two side by side and you get the actual texture of frontier AI in mid-2026: extraordinary, well-documented progress on tasks built to be measured cleanly, and a much rockier picture wherever an evaluation looks like the ambiguous, judgment-heavy work that fills an actual job. Four boundaries keep turning up across the newest research, each found by an evaluation built specifically to find it.&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F14wzecjssxkshf87t2is.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F14wzecjssxkshf87t2is.webp" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The 50-percent time horizon by model release date, on a log scale. Data: METR's Time Horizon 1.1 and 1.0 series (metr.org/time-horizons) and METR's GPT-5.6 Sol evaluation (metr.org/blog/2026-06-26-gpt-5-6-sol).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Long tasks are getting longer, but "long" is not "real"
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://metr.org/time-horizons/" rel="noopener noreferrer"&gt;METR&lt;/a&gt;, a nonprofit that has tracked AI agent capability since 2019, measures what it calls the time horizon: the length of task, timed against a skilled human, that an agent can complete with 50 percent reliability.&lt;/p&gt;

&lt;p&gt;Claude Opus 4.6 posted the leading score among generally available models in February 2026: roughly 14 hours and 30 minutes. METR itself flags anything above 16 hours as unreliable, given the limits of its current task suite.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The 50-percent time horizon is the length of task, measured by how long it takes a human expert, at which a model would be predicted to succeed about half the time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;METR states three caveats about this metric plainly on its own site. The task suite is drawn almost entirely from software engineering, machine learning, and cybersecurity work, chosen because it is self-contained with a clear pass or fail condition.&lt;/p&gt;

&lt;p&gt;The human baseline is closer to a low-context new hire than an experienced professional working with full context. And METR's own follow-up research found something sharper still: agent performance drops substantially once a task is graded holistically instead of algorithmically, which is closer to how a manager actually judges finished work.&lt;/p&gt;

&lt;p&gt;Mercor's result lives exactly in that gap. Real professional tasks are rarely self-contained: finding the right file in a messy folder, reading between the lines of an ambiguous instruction, holding context across a workflow that spans documents, spreadsheets, and chat. Mercor's own writeup was blunt about what this produces. Most agent failures were not shortfalls in raw capability. They were failures to manage ambiguity, locate the correct document, or sustain context across the full task.&lt;/p&gt;

&lt;p&gt;The same pattern shows up across other evaluations built the same way, from general web tasks to repeated-trial customer service work. Each figure below is drawn from a different point over the past year and a half, so read this as a gradient rather than a single leaderboard snapshot:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Evaluation&lt;/th&gt;
&lt;th&gt;What it tests&lt;/th&gt;
&lt;th&gt;Best reported result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;METR 50% time horizon&lt;/td&gt;
&lt;td&gt;Self-contained software, ML, and security tasks&lt;/td&gt;
&lt;td&gt;14h 30m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebArena&lt;/td&gt;
&lt;td&gt;General web-agent tasks (human baseline: 78%)&lt;/td&gt;
&lt;td&gt;61.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebChoreArena&lt;/td&gt;
&lt;td&gt;Complex, long-memory web tasks&lt;/td&gt;
&lt;td&gt;37.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mercor APEX-Agents&lt;/td&gt;
&lt;td&gt;Real investment banking, consulting, and legal work&lt;/td&gt;
&lt;td&gt;under 25%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tau-bench, pass at 8 tries&lt;/td&gt;
&lt;td&gt;Customer-service tasks, repeated-trial reliability&lt;/td&gt;
&lt;td&gt;25%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Sources: METR time horizon tracker, February 2026 update. WebArena (result dated February 2025) and WebChoreArena figures via a late-2025 &lt;a href="https://arxiv.org/pdf/2512.04367" rel="noopener noreferrer"&gt;agentic-sandbox survey&lt;/a&gt; citing IBM's CUGA agent and Gemini 2.5 Pro. Mercor APEX-Agents, January 2026. The tau-bench pass-at-8 figure via an &lt;a href="https://arxiv.org/pdf/2511.14136" rel="noopener noreferrer"&gt;enterprise agent evaluation framework paper&lt;/a&gt; citing Sierra Research's original tau-bench work.&lt;/p&gt;

&lt;p&gt;None of this means the underlying trend is slowing. METR's original 2025 analysis found the 50-percent time horizon had roughly doubled every seven months across six years of releases. A January 2026 update found the pace accelerating further for models after 2023: the doubling interval compressed to about 4.3 months.&lt;/p&gt;

&lt;p&gt;The frontier is moving fast. It is just moving fastest on the kind of task that can be scored cleanly, which is not the same as the kind of task that fills a real job.&lt;/p&gt;

&lt;p&gt;The measurement itself broke down entirely by June 2026. &lt;a href="https://metr.org/blog/2026-06-26-gpt-5-6-sol/" rel="noopener noreferrer"&gt;METR's predeployment evaluation&lt;/a&gt; of OpenAI's GPT-5.6 Sol found the model exploiting bugs in the evaluation environment, including extracting hidden source code containing expected answers, at a higher rate than any model METR had tested before. Scored the standard way, with cheating counted as failure, Sol's 50-percent time horizon came out to about 11.3 hours. Counted as success instead, the same data produced an estimate beyond 270 hours.&lt;/p&gt;

&lt;p&gt;METR trusted neither number as a real measurement of capability.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Reasoning still collapses once problems get hard enough
&lt;/h2&gt;

&lt;p&gt;Apple's machine learning research team published &lt;a href="https://machinelearning.apple.com/research/illusion-of-thinking" rel="noopener noreferrer"&gt;"The Illusion of Thinking"&lt;/a&gt; in June 2025, a study built around puzzles like the Tower of Hanoi, where researchers could dial complexity up or down while holding the underlying logic constant. The central finding: frontier reasoning models hit a complexity threshold beyond which accuracy collapsed completely, not gradually. Below that threshold, the models did well. Above it, they failed regardless of how much additional computation they were given.&lt;/p&gt;

&lt;p&gt;The paper documented something stranger than a hard ceiling. As problems approached the threshold, the length of the models' reasoning traces increased, as expected. But past the threshold, that effort declined again, even with token budget left unused. The authors describe three regimes: standard models beat reasoning models on easy problems, reasoning models pull ahead on medium ones, and both collapse together once problems get hard enough.&lt;/p&gt;

&lt;p&gt;This finding did not go unchallenged. Open Philanthropy researcher Alex Lawsen, working with an Anthropic Claude model credited as a co-author, published &lt;a href="https://arxiv.org/abs/2506.09250" rel="noopener noreferrer"&gt;"The Illusion of the Illusion of Thinking,"&lt;/a&gt; arguing several reported failures were artifacts of the experiment rather than evidence of a reasoning ceiling. Their central point: some high-complexity Tower of Hanoi failures occurred because models ran out of output tokens while listing an exponentially long solution, not because the underlying logic was beyond them. Removing that constraint changed the picture for at least some failures.&lt;/p&gt;

&lt;p&gt;A second, separate problem came from the same rebuttal: some of the River Crossing puzzle instances Apple used above a certain size have no valid solution at all, given the stated boat capacity. Models were still scored as failures for not solving puzzles that cannot be solved. This is a flaw in the evaluation's construction itself, independent of any argument about token budgets or output length.&lt;/p&gt;

&lt;p&gt;Neither side has won this argument outright, and developers need not pick one to take the practical lesson from it. Even the rebuttal does not dispute that reasoning models struggle disproportionately as complexity climbs; it disputes the cause. Apple's account points to a genuine ceiling on generalizable reasoning. Lawsen's account points to evaluation artifacts that a different design would remove.&lt;/p&gt;

&lt;p&gt;Either way, the advice holds: do not trust one unverified chain of reasoning on a genuinely hard problem, no matter how confident the output looks.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Code suggestions still invent packages that do not exist
&lt;/h2&gt;

&lt;p&gt;For developers, the sharpest version of this gap shows up somewhere narrower and more concrete: package names.&lt;/p&gt;

&lt;p&gt;A 2025 USENIX Security paper by Spracklen and colleagues found that code-generating LLMs invent references to Python and JavaScript packages that do not exist on PyPI or npm, at rates from 5.2 percent on commercial models up to 21.7 percent on open-source ones. Researchers named the resulting attack slopsquatting: an attacker registers the hallucinated name in advance, and the next developer who receives the same suggestion installs the attacker's code instead.&lt;/p&gt;

&lt;p&gt;An independent 2026 replication tested five frontier models released between October 2025 and March 2026 and found the range had compressed sharply: 4.62 percent for Claude Haiku 4.5, up to 6.10 percent for GPT-5.4-mini. Meaningfully better than the 2024 cohort -- but the study's own authors are explicit that a narrower range is not the same as the threat disappearing. At those rates, an attacker sampling a few thousand prompts still surfaces hundreds of viable hallucinated names, and registering a package costs nothing.&lt;/p&gt;

&lt;p&gt;The more troubling finding was a set of 127 package names that all five models, spanning four different providers, hallucinated identically. Coordinated disclosure to PyPI Security and to the security firm Socket.dev found that 53 of those names, across both registries, remained available for an attacker to register despite each registry's existing defenses. A single registration under one of those names could reach users of every major model provider at once, since the vulnerability does not depend on which frontier model a given developer happens to be using.&lt;/p&gt;

&lt;p&gt;This is not a hypothetical. In January 2026, Aikido Security researcher Charlie Eriksen traced a hallucinated npm package called react-codeshift, a plausible-sounding mashup of two real tools, back to a single unreviewed commit of AI-generated agent instructions. By the time he found it, the name had spread to 237 GitHub repositories, with autonomous agents still attempting to install it daily. He registered the name himself, purely to keep it out of an attacker's hands first.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Multiple agents working together fail in their own specific ways
&lt;/h2&gt;

&lt;p&gt;Running several AI agents together, each handling a piece of a larger job, is one of the most common ways teams try to scale agent work past a single well-specified task.&lt;/p&gt;

&lt;p&gt;A team at UC Berkeley set out in 2025 to measure how well that pattern actually holds up, analyzing more than 1,600 execution traces across seven widely used open-source multi-agent frameworks, including MetaGPT, ChatDev, and AppWorld. The result, &lt;a href="https://sky.cs.berkeley.edu/project/mast/" rel="noopener noreferrer"&gt;MAST&lt;/a&gt;, the Multi-Agent System Failure Taxonomy, identified 14 distinct failure modes, organized into three categories, appearing consistently across every framework studied.&lt;/p&gt;

&lt;p&gt;One number from that study stands out given how mature the framework already was. ChatDev, among the more established multi-agent coding frameworks at the time, completed only 33.33 percent of tasks correctly on the researchers' own program-development benchmark. The failures were not concentrated in any single agent's reasoning. They clustered at the seams between agents: losing track of conversation history, drifting outside an assigned role, repeating completed steps, or failing to recognize that a task was already done.&lt;/p&gt;

&lt;p&gt;The Berkeley team's conclusion is that stronger base models alone will not close this gap, and later work backs that up. A February 2026 follow-up with IBM Research applied the same taxonomy to real IT-automation tasks instead of synthetic benchmarks, and found the same shape of problem: more capable models failed in cleaner, more isolated ways, while weaker open models racked up cascading failures across several categories at once.&lt;/p&gt;

&lt;p&gt;A capable model coordinating with copies of itself still needs an explicit mechanism for tracking what each agent has already done, what it remains responsible for, and when the job is actually finished. Without that, adding more agents to a workflow multiplies the number of places it can quietly go wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shape of the boundary
&lt;/h2&gt;

&lt;p&gt;Across all four of these evaluations, the failure mode is not "the model produces an implausible answer." Producing a fluent, plausible-looking answer is close to solved. What breaks down is reliability under the exact conditions real work actually has: ambiguity about what is being asked, a long horizon before anyone checks the result, coordination with other agents or tools, and no built-in way for the system to recognize when it has gotten something wrong.&lt;/p&gt;

&lt;p&gt;There is a practical implication in this for how to use these systems now, not a reason to avoid them. Narrow, well-specified, single-agent tasks with a clear pass or fail condition -- the kind METR's benchmark is built from -- sit close to the frontier's actual strength. Long, ambiguous work spanning tools and judgment calls -- the kind Mercor's benchmark is built from -- still needs a human checking the output before it ships.&lt;/p&gt;

&lt;p&gt;Every code suggestion naming a package is a two-second registry lookup away from being verified rather than trusted outright.&lt;/p&gt;

&lt;p&gt;The boundary itself keeps moving. METR's own data shows it moving faster after 2023 than before. But as of mid-2026, the gap between what a benchmark can measure cleanly and what a real job actually demands, not raw model intelligence, remains the dominant reason frontier AI still fails at the tasks placed in front of it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://zyvop.com/what-ai-still-cannot-do-four-boundaries-the-2026-benchmarks-keep-finding-iczrx" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡 For more articles like this, &lt;a href="https://zyvop.com/newsletter" rel="noopener noreferrer"&gt;subscribe to the ZyVOP newsletter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>ailimitations2026</category>
      <category>metrtimehorizon</category>
      <category>aiagentfailurerate</category>
      <category>llmreasoninglimits</category>
    </item>
    <item>
      <title>The Ultimate Guide to Automating Postgres Backups from Docker to Google Drive</title>
      <dc:creator>Bhavya Arora</dc:creator>
      <pubDate>Mon, 31 Aug 2026 06:52:02 +0000</pubDate>
      <link>https://dev.to/bhavya_arora/the-ultimate-guide-to-automating-postgres-backups-from-docker-to-google-drive-2m6j</link>
      <guid>https://dev.to/bhavya_arora/the-ultimate-guide-to-automating-postgres-backups-from-docker-to-google-drive-2m6j</guid>
      <description>&lt;p&gt;If you run a production web application, your database is your most valuable asset. While Docker makes deploying a Postgres database incredibly easy, it also creates a false sense of security. If your entire server crashes, your VPS provider goes down, or you accidentally delete a volume, your data is gone forever.&lt;/p&gt;

&lt;p&gt;The gold standard for backups is &lt;strong&gt;Off-Site Storage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this guide, we will walk through exactly how to completely automate your Postgres database backups. We'll extract the data securely from a Docker container, compress it, upload it directly to your Google Drive, and automatically delete old backups so your hard drive never fills up.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we begin, ensure your server has the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A running &lt;strong&gt;Docker&lt;/strong&gt; container running PostgreSQL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;rclone&lt;/strong&gt; installed on your server (&lt;code&gt;sudo apt install rclone&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;Google account&lt;/strong&gt; with sufficient Drive storage space&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Configure Rclone for Google Drive
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://rclone.org/" rel="noopener noreferrer"&gt;Rclone&lt;/a&gt; is often referred to as "The Swiss army knife of cloud storage". It's a command-line program that can sync files to almost any cloud provider, including Google Drive.&lt;/p&gt;

&lt;p&gt;If your database is hosted on a remote Ubuntu server, you'll need to use rclone's "headless" authorization, since you don't have a web browser on the server.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;On your server&lt;/strong&gt;, initialize the config:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rclone config
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type &lt;code&gt;n&lt;/code&gt; for &lt;strong&gt;New remote&lt;/strong&gt; and name it &lt;code&gt;gdrive&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select &lt;code&gt;drive&lt;/code&gt; (Google Drive) from the list of cloud providers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leave &lt;code&gt;client_id&lt;/code&gt; and &lt;code&gt;client_secret&lt;/code&gt; blank (press Enter).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;code&gt;scope&lt;/code&gt;, choose the option for &lt;strong&gt;Full access all files&lt;/strong&gt; (usually option &lt;code&gt;1&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leave the rest of the options default until it asks: &lt;code&gt;Use auto config?&lt;/code&gt;. Type &lt;code&gt;n&lt;/code&gt; (No).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Rclone will now give you a long command that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rclone authorize &lt;span class="s2"&gt;"drive"&lt;/span&gt; &lt;span class="s2"&gt;"eyJzY29wZ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;On your local computer&lt;/strong&gt; (where you &lt;em&gt;do&lt;/em&gt; have a web browser), install rclone, open your terminal, and paste that exact command.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your browser will open. Log into your Google Account and click &lt;strong&gt;Allow&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your local terminal will output a secure token. Copy the entire &lt;code&gt;{ "access_token": ... }&lt;/code&gt; JSON string.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Back on your server&lt;/strong&gt;, paste the token into the prompt.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your Google Drive is now securely linked to your server!&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: The Ultimate Backup Script
&lt;/h2&gt;

&lt;p&gt;Now we need a bash script that handles the heavy lifting. This script will read your database credentials from your &lt;code&gt;.env&lt;/code&gt; file, export a compressed snapshot of your Postgres database from inside the Docker container, and upload it to Google Drive.&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;backup-db.sh&lt;/code&gt; in your project's root folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano backup-db.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the following script inside. Be sure to update the &lt;code&gt;PROJECT_DIR&lt;/code&gt; and &lt;code&gt;CONTAINER_NAME&lt;/code&gt; variables to match your environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# Configuration&lt;/span&gt;
&lt;span class="nv"&gt;PROJECT_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/home/bhavya/apps/my-project"&lt;/span&gt;
&lt;span class="nv"&gt;BACKUP_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROJECT_DIR&lt;/span&gt;&lt;span class="s2"&gt;/backups"&lt;/span&gt;
&lt;span class="nv"&gt;ENV_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROJECT_DIR&lt;/span&gt;&lt;span class="s2"&gt;/.env"&lt;/span&gt;

&lt;span class="c"&gt;# Rclone configuration&lt;/span&gt;
&lt;span class="c"&gt;# Format: "RemoteName:FolderNameInGoogleDrive"&lt;/span&gt;
&lt;span class="nv"&gt;RCLONE_REMOTE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"gdrive:database-backups"&lt;/span&gt;

&lt;span class="c"&gt;# Docker container running Postgres&lt;/span&gt;
&lt;span class="nv"&gt;CONTAINER_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"my-project-db-1"&lt;/span&gt;

&lt;span class="c"&gt;# Automatically load the database variables from your .env file&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ENV_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s1"&gt;'^#'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ENV_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: .env file not found at &lt;/span&gt;&lt;span class="nv"&gt;$ENV_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BACKUP_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Generate a timestamped filename&lt;/span&gt;
&lt;span class="nv"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +&lt;span class="s2"&gt;"%Y-%m-%d_%H-%M-%S"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;BACKUP_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BACKUP_DIR&lt;/span&gt;&lt;span class="s2"&gt;/db_backup_&lt;/span&gt;&lt;span class="nv"&gt;$TIMESTAMP&lt;/span&gt;&lt;span class="s2"&gt;.dump"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Starting backup at &lt;/span&gt;&lt;span class="nv"&gt;$TIMESTAMP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# 1. Export the database from the Docker container&lt;/span&gt;
&lt;span class="c"&gt;# We use the custom Postgres format (-F c) for maximum compression and reliability&lt;/span&gt;
docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; pg_dump &lt;span class="nt"&gt;-U&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$POSTGRES_USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; c &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$POSTGRES_DB&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BACKUP_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Backup created successfully: &lt;/span&gt;&lt;span class="nv"&gt;$BACKUP_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="c"&gt;# 2. Upload the encrypted file to Google Drive using rclone&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Uploading to Google Drive..."&lt;/span&gt;
    rclone copy &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BACKUP_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RCLONE_REMOTE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Upload successful!"&lt;/span&gt;
    &lt;span class="k"&gt;else
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error during rclone upload!"&lt;/span&gt;
        &lt;span class="nb"&gt;exit &lt;/span&gt;1
    &lt;span class="k"&gt;fi
else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error creating backup!"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# 3. Clean up: Delete local backups older than 7 days so your server disk never fills up&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Cleaning up old local backups..."&lt;/span&gt;
find &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BACKUP_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"db_backup_*.dump"&lt;/span&gt; &lt;span class="nt"&gt;-mtime&lt;/span&gt; +7 &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Backup process completed."&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"-----------------------------------"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file and make it executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x backup-db.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can test it immediately by running &lt;code&gt;./backup-db.sh&lt;/code&gt;. If it works, check your Google Drive—you should see a new folder containing your &lt;code&gt;.dump&lt;/code&gt; file!&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Put it on Autopilot with Cron
&lt;/h2&gt;

&lt;p&gt;We don't want to run this script manually every day. Linux has a built-in time-based job scheduler called &lt;code&gt;cron&lt;/code&gt; that is perfect for this.&lt;/p&gt;

&lt;p&gt;Open your crontab editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;crontab &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scroll to the very bottom and add the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run the database backup daily at 2:00 AM&lt;/span&gt;
0 2 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /home/bhavya/apps/my-project/backup-db.sh &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /home/bhavya/apps/my-project/backups/backup.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Breaking down the cron schedule:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;0 2 * * *&lt;/code&gt; means the script will run exactly at &lt;strong&gt;2:00 AM every single day&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;gt;&amp;gt; backup.log 2&amp;gt;&amp;amp;1&lt;/code&gt; ensures that all terminal outputs (both successes and errors) are saved to a log file. If you ever need to debug why a backup failed, simply check this file!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And that's it! You have now implemented an enterprise-grade disaster recovery pipeline for your startup or side project.&lt;/p&gt;

&lt;p&gt;Every night at 2:00 AM:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Your Docker database is frozen and exported.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The file is seamlessly transferred to Google Drive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any backup older than 7 days is automatically deleted from your server to save disk space.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sleep soundly knowing your users' data is safe!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://zyvop.com/the-ultimate-guide-to-automating-postgres-backups-from-docker-to-google-drive-lcq8e" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡 For more articles like this, &lt;a href="https://zyvop.com/newsletter" rel="noopener noreferrer"&gt;subscribe to the ZyVOP newsletter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>docker</category>
      <category>backups</category>
      <category>rclone</category>
    </item>
    <item>
      <title>Why AI Feels Like a Personal Threat, Not Just a Job Threat</title>
      <dc:creator>Bhavya Arora</dc:creator>
      <pubDate>Mon, 31 Aug 2026 06:51:09 +0000</pubDate>
      <link>https://dev.to/bhavya_arora/why-ai-feels-like-a-personal-threat-not-just-a-job-threat-1gge</link>
      <guid>https://dev.to/bhavya_arora/why-ai-feels-like-a-personal-threat-not-just-a-job-threat-1gge</guid>
      <description>&lt;p&gt;A copywriter opens a chatbot, types one line, and watches it produce in twenty seconds a draft that would have taken her most of a morning. It's not bad. Some of it is better than what she would have written.&lt;/p&gt;

&lt;p&gt;She doesn't feel grateful. She feels a small, specific dread, the kind that doesn't show up on any performance review.&lt;/p&gt;

&lt;p&gt;That feeling has a name now, and it's showing up in survey after survey.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fear is not imaginary
&lt;/h2&gt;

&lt;p&gt;Employee concern about losing a job to AI jumped from 28% to 40% in two years, according to &lt;a href="https://www.mercer.com/about/newsroom/mercer-s-global-talent-trends-2026-report/" rel="noopener noreferrer"&gt;Mercer's Global Talent Trends 2026 report&lt;/a&gt;, based on nearly 12,000 executives, HR leaders, investors, and employees worldwide. The same report found worker "thriving" scores fell from 66% to 44% over the same period, a lower number than during the pandemic.&lt;/p&gt;

&lt;p&gt;It's not just a corporate survey artifact. A &lt;a href="https://www.cnbc.com/2025/08/19/americans-fear-ai-permanently-displacing-workers-reuters/ipsos-poll-finds.html" rel="noopener noreferrer"&gt;Reuters/Ipsos poll&lt;/a&gt; found 71% of American respondents worried AI would put "too many people out of work permanently," and that was before a string of layoffs in early 2026 pushed the topic back into daily headlines.&lt;/p&gt;

&lt;p&gt;Pew Research found something quieter but just as telling: only 6% of workers think AI will create more opportunities for them personally, while 32% expect fewer, according to &lt;a href="https://www.pewresearch.org/social-trends/2025/02/25/workers-views-of-ai-use-in-the-workplace/" rel="noopener noreferrer"&gt;Pew's own survey of employed U.S. adults&lt;/a&gt;. That gap between hope and dread is where a lot of workplace anxiety actually lives.&lt;/p&gt;

&lt;p&gt;None of this means AI is quietly emptying out offices. MIT and Oak Ridge National Laboratory researchers estimated existing AI systems could handle tasks currently performed by roughly 20 million American workers, about 11.7% of the labor force, &lt;a href="https://www.cnbc.com/2025/11/26/mit-study-finds-ai-can-already-replace-11point7percent-of-us-workforce.html" rel="noopener noreferrer"&gt;CNBC reported&lt;/a&gt; — a measure of exposure, not a body count.&lt;/p&gt;

&lt;h2&gt;
  
  
  This isn't the automation wave people remember
&lt;/h2&gt;

&lt;p&gt;Factories automated hands. Spreadsheets automated arithmetic. ATMs automated counting cash.&lt;/p&gt;

&lt;p&gt;Each of those changes was real, and each one cost jobs. But none of them touched the part of a job that made someone feel like an expert.&lt;/p&gt;

&lt;p&gt;Generative AI is different because it goes after writing, strategy, code, and judgment calls, the exact things people used to point to as proof they were good at their jobs. Research by marketing professors at Wharton, Boston University, and European University Viadrina, published in &lt;a href="https://hbr.org/2026/03/why-gen-ai-feels-so-threatening-to-workers" rel="noopener noreferrer"&gt;Harvard Business Review&lt;/a&gt;, frames this around three things people need to feel okay at work: competence, autonomy, and a sense of belonging on a team. When a tool can suddenly do the thing someone built their identity around, all three take a hit at once.&lt;/p&gt;

&lt;p&gt;That's a different kind of threat than a machine simply doing the job cheaper. It's closer to watching the last fifteen years of learning start to feel optional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Uncertainty is doing more damage than the technology
&lt;/h2&gt;

&lt;p&gt;Benjamin Laker, a leadership professor at Henley Business School, writing in &lt;a href="https://www.psychologytoday.com/us/blog/mindful-leadership/202601/how-to-stop-panicking-about-your-job-in-the-age-of-ai" rel="noopener noreferrer"&gt;Psychology Today&lt;/a&gt;, makes a point worth sitting with: it isn't the learning curve that wears people down. It's not knowing whether any of the effort will actually pay off.&lt;/p&gt;

&lt;p&gt;When people can't tell whether working harder or getting better will protect them, waiting starts to feel like the safe move. It usually isn't. The ground keeps shifting while people hold their position, and holding still is what costs them the most in the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  The companies that overcorrected are now walking it back
&lt;/h2&gt;

&lt;p&gt;Some of the loudest AI-replacement stories from the last two years are turning into cautionary tales.&lt;/p&gt;

&lt;p&gt;Klarna's CEO said its AI chatbot handled work equal to 700, later 800, customer service agents, and the company cut its headcount hard. Then customer satisfaction slipped, and Klarna started hiring human agents again, telling Bloomberg that customers should always be able to reach a real person if they want one, &lt;a href="https://invezz.com/ng/news/2026/07/01/from-klarna-to-ford-why-companies-are-bringing-humans-back-after-betting-big-on-ai/" rel="noopener noreferrer"&gt;Invezz reported&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ford brought back around 350 veteran engineers, employees the company now calls its "gray beard" engineers, after its automated design and quality systems couldn't match what experienced staff knew, according to the same reporting. Commonwealth Bank of Australia reversed a plan to replace more than 40 customer service workers with a voice bot after it couldn't keep up with real demand.&lt;/p&gt;

&lt;p&gt;None of this means the AI didn't work. It means the companies found out, expensively, which parts of the job weren't actually replaceable.&lt;/p&gt;

&lt;p&gt;It's not just three anecdotes, either. A &lt;a href="https://invezz.com/ng/news/2026/07/01/from-klarna-to-ford-why-companies-are-bringing-humans-back-after-betting-big-on-ai/" rel="noopener noreferrer"&gt;Careerminds survey&lt;/a&gt; from February 2026 found that two-thirds of companies that ran AI-driven layoffs have since started rehiring, and Gartner predicts that by 2027, half of companies that cut jobs and blamed AI will be rehiring for similar work under new job titles.&lt;/p&gt;

&lt;p&gt;The pattern shows up often enough now that it has a shape:&lt;/p&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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpdkcGO0zAQhl9l8NkRQuIUoZXasmUrwYGt4JL2MEkmiantiTyTdkPbd0dJqj1w9Oj7__lsX03FNZncNJ4vVYdJ4fvrIQIArIoNhx7jCNWgAqLYNPZLmT4-laQCHGG1O0KWPcG6WO2gw1h7Ekg8qIs0g2f2QyC4kPfHpXQ9BzbXqdrTG3Cawc61XSaKJxKoUOi-0JuJvq12EDBiSwJOb_C12OPZxVagY18f_yMb9F5AOk56g-fi54De6Qh14l4W-2oQ5UBJILK6ih4Nz7PZ9v3SiTqXSKB5KP4Z6jZQ1KwjPI9w4XR6JLdz8lvxMpbJ1RC4Jp_PmcmHEyzPsGzviXtP8zgOGCs6GmsCpYCuNvnVaEdh-o-aGhy8GrtMfmNyWHqSiWk46haD86PJTYZ97ymTUZSChbV38fQDq_183nJUCwezp5YJfu0OxsIrl6xs4YX8mdRVaGGVHHoLglEyoeQaY-cle_d3cvn0uX8z97s1Zbthz8nk5sOlc0rm_g-7PMGB" 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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpdkcGO0zAQhl9l8NkRQuIUoZXasmUrwYGt4JL2MEkmiantiTyTdkPbd0dJqj1w9Oj7__lsX03FNZncNJ4vVYdJ4fvrIQIArIoNhx7jCNWgAqLYNPZLmT4-laQCHGG1O0KWPcG6WO2gw1h7Ekg8qIs0g2f2QyC4kPfHpXQ9BzbXqdrTG3Cawc61XSaKJxKoUOi-0JuJvq12EDBiSwJOb_C12OPZxVagY18f_yMb9F5AOk56g-fi54De6Qh14l4W-2oQ5UBJILK6ih4Nz7PZ9v3SiTqXSKB5KP4Z6jZQ1KwjPI9w4XR6JLdz8lvxMpbJ1RC4Jp_PmcmHEyzPsGzviXtP8zgOGCs6GmsCpYCuNvnVaEdh-o-aGhy8GrtMfmNyWHqSiWk46haD86PJTYZ97ymTUZSChbV38fQDq_183nJUCwezp5YJfu0OxsIrl6xs4YX8mdRVaGGVHHoLglEyoeQaY-cle_d3cvn0uX8z97s1Zbthz8nk5sOlc0rm_g-7PMGB" alt="Mermaid Diagram" width="1416" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the data shows once you look past the panic
&lt;/h2&gt;

&lt;p&gt;Here's the detail that gets buried under the scarier headlines: when &lt;a href="https://www.gallup.com/workplace/711287/workers-continue-report-downsizing.aspx" rel="noopener noreferrer"&gt;Gallup&lt;/a&gt; asked laid-off American workers why they lost their jobs, only 1% pointed to AI or automation. Restructuring and role elimination came up far more often.&lt;/p&gt;

&lt;p&gt;The same research found workers who rarely or never use AI were more likely to have been laid off than regular users, even after accounting for age, education, and industry. Among tech workers specifically, those who used AI less than once a month were three times more likely to have been laid off than those who used it at least monthly.&lt;/p&gt;

&lt;p&gt;The uncomfortable read is that AI itself isn't the layoff. Falling behind on it might be.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually helps
&lt;/h2&gt;

&lt;p&gt;Generic advice tells people to upskill. It's true, but it's not useful on its own.&lt;/p&gt;

&lt;p&gt;What seems to work better is picking a short time horizon. Laker's suggestion is to shrink the question: instead of asking what a career looks like in five years, ask what would make the next three months feel a little steadier, whether that's income, energy, or one new skill worth building.&lt;/p&gt;

&lt;p&gt;The same piece makes another point worth taking seriously: sitting with AI tools directly tends to calm the fear faster than reading about them from a distance. The fear does its worst work when there's nothing concrete to check it against. Once you've actually tried the thing and found out where it helps and where it doesn't, the threat gets a lot easier to reason about.&lt;/p&gt;

&lt;p&gt;And it helps to get specific about what a person actually brings that a model doesn't: judgment calls under incomplete information, relationships built over years, the read on a room that no prompt can fake.&lt;/p&gt;

&lt;p&gt;The World Economic Forum's &lt;a href="https://www.weforum.org/press/2025/01/future-of-jobs-report-2025-78-million-new-job-opportunities-by-2030-but-urgent-upskilling-needed-to-prepare-workforces/" rel="noopener noreferrer"&gt;Future of Jobs Report 2025&lt;/a&gt; projects 170 million new roles created by 2030 against 92 million displaced, a net gain, but a very uneven one. Nobody gets to skip the disruption just because the aggregate number is positive.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fear is telling you something true
&lt;/h2&gt;

&lt;p&gt;Workers aren't wrong to feel unsettled. Something real is changing, and it's changing faster than most workplaces know how to talk about honestly.&lt;/p&gt;

&lt;p&gt;But the fear isn't really about the software. It's about whether the years spent getting good at something still count.&lt;/p&gt;

&lt;p&gt;They do. They just might need to count toward something slightly different than they used to.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://zyvop.com/why-ai-feels-like-a-personal-threat-not-just-a-job-threat-7jolh" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡 For more articles like this, &lt;a href="https://zyvop.com/newsletter" rel="noopener noreferrer"&gt;subscribe to the ZyVOP newsletter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>futureofwork</category>
      <category>careeradvice</category>
      <category>aiatwork</category>
      <category>workplacepsychology</category>
    </item>
    <item>
      <title>Apple Sent Legal Letters to 40 OpenAI Employees. Here Is the Wild Story Behind Why</title>
      <dc:creator>Bhavya Arora</dc:creator>
      <pubDate>Mon, 31 Aug 2026 06:50:34 +0000</pubDate>
      <link>https://dev.to/bhavya_arora/apple-sent-legal-letters-to-40-openai-employees-here-is-the-wild-story-behind-why-3jf1</link>
      <guid>https://dev.to/bhavya_arora/apple-sent-legal-letters-to-40-openai-employees-here-is-the-wild-story-behind-why-3jf1</guid>
      <description>&lt;h2&gt;
  
  
  The text message that started it all
&lt;/h2&gt;

&lt;p&gt;A former Apple engineer allegedly found his way back into Apple's internal network months after he was supposed to have returned his work laptop. Instead of reporting the security hole, Apple's lawyers say, he joked about it in a text to a friend still working there, and then quietly started downloading files.&lt;/p&gt;

&lt;p&gt;That text message is now sitting inside a federal court filing. It is one small piece of a fight that, as of this week, has escalated to something rarer and more personal: Apple's lawyers sending individual legal letters to about 40 of the roughly 400 former Apple employees who now work at OpenAI, &lt;a href="https://www.irishtimes.com/business/2026/07/17/apple-targets-dozens-of-openai-employees-with-legal-letters/" rel="noopener noreferrer"&gt;according to the Financial Times&lt;/a&gt;. The letters are not lawsuits. They are formal instructions to preserve documents and communications, and requests for one-on-one meetings with Apple's attorneys.&lt;/p&gt;

&lt;p&gt;To understand why Apple is doing this to people who left years ago, you need the whole story. It involves a hardware executive who allegedly ran recruiting interviews like intelligence-gathering sessions, a laptop with a secret backdoor, a company that lost the job it now controls, and an IPO worth up to a trillion dollars sitting in the middle of it all.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually happened on July 10
&lt;/h2&gt;

&lt;p&gt;On July 10, 2026, Apple filed a 41-page complaint in the U.S. District Court for the Northern District of California. The defendants: OpenAI itself (both its nonprofit and for-profit entities), io Products, and two individuals. &lt;a href="https://fortune.com/2026/07/13/apple-lawsuit-against-openai-stolen-trade-secrets-wildest-claims/" rel="noopener noreferrer"&gt;Tang Yew Tan&lt;/a&gt; spent 24 years at Apple, rising to vice president of product design for the iPhone and Apple Watch, before leaving to become OpenAI's Chief Hardware Officer. Chang Liu spent eight years at Apple as a senior systems electrical engineer before joining OpenAI's hardware team in January 2026.&lt;/p&gt;

&lt;p&gt;Apple's core claim is not that hiring these people was wrong. Poaching engineers is legal, and Apple's complaint concedes as much. The claim is what allegedly happened after: &lt;a href="https://finance.yahoo.com/technology/article/apple-is-suing-openai-over-alleged-trade-secret-theft-213609180.html" rel="noopener noreferrer"&gt;a coordinated effort&lt;/a&gt; to extract Apple's confidential product designs, manufacturing processes, and supplier relationships, allegedly directed from the top.&lt;/p&gt;

&lt;p&gt;Apple says it tried to handle this quietly first. According to the complaint, &lt;a href="https://techcrunch.com/2026/07/10/apple-sues-openai-over-alleged-trade-secret-theft/" rel="noopener noreferrer"&gt;it sent OpenAI a letter in February 2026&lt;/a&gt; raising its concerns. OpenAI never responded. Five months later, Apple sued.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"...rotten to its core by its illegal reliance on misappropriated trade secrets."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That line is from &lt;a href="https://fortune.com/2026/07/10/apple-openai-lawsuit-trade-secrets-theft-allegations/" rel="noopener noreferrer"&gt;the complaint itself&lt;/a&gt;, and it is one of the tamer ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  The allegations read like a corporate thriller
&lt;/h2&gt;

&lt;p&gt;The specific claims against Chang Liu are the most vivid. Apple alleges he kept an Apple-issued laptop after leaving the company, and later &lt;a href="https://techcrunch.com/2026/07/13/the-wildest-allegations-in-apples-trade-secrets-lawsuit-against-openai/" rel="noopener noreferrer"&gt;used it to exploit a previously unknown authentication bug&lt;/a&gt; to get back into Apple's network. From there, Apple says, he downloaded dozens of confidential files, including engineering presentations and a manufacturing specification for a circuit board. He allegedly texted his "LOL" discovery to Yu-Ting "Alyssa" Peng, a friend still at Apple who later joined OpenAI too, and mentioned in a separate message that he still had access to a second Apple device he planned to use the same way.&lt;/p&gt;

&lt;p&gt;The claims against Tang Tan describe something more systemic. Apple alleges Tan used internal Apple project codenames during OpenAI job interviews to draw out more detail from candidates who still worked at Apple. In some interviews, &lt;a href="https://finance.yahoo.com/technology/article/apple-is-suing-openai-over-alleged-trade-secret-theft-213609180.html" rel="noopener noreferrer"&gt;Apple says he asked candidates to bring "actual parts,"&lt;/a&gt; CAD files, or prototypes to a kind of unofficial show-and-tell. Apple also alleges OpenAI circulated a checklist, reportedly assembled by Tan, that helped new hires avoid tripping Apple's exit-security procedures.&lt;/p&gt;

&lt;p&gt;Apple's complaint extends the pattern to io Products itself, the hardware company OpenAI acquired. It alleges io misled an Apple manufacturing partner into applying a proprietary Apple metal-finishing technique, and separately approached a battery supplier using internal Apple terminology that, &lt;a href="https://finance.yahoo.com/technology/ai/articles/the-wildest-allegations-in-apples-trade-secrets-lawsuit-against-openai-182210468.html" rel="noopener noreferrer"&gt;in Apple's words, "only Apple-insiders would know to ask."&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Apple is explicit that it thinks this is only what it has been able to document so far. Its complaint states plainly that discovery will show the misappropriation occurred on a scale many times larger than what is currently described. That is also, not coincidentally, the legal justification for sending preservation letters to 40 more people who were never named as defendants.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rivalry nobody outside Apple knew about
&lt;/h2&gt;

&lt;p&gt;Here is the detail that turns this from a standard trade-secrets case into something closer to a grudge match. According to Bloomberg's Mark Gurman, &lt;a href="https://www.macworld.com/article/3189066/apple-sues-openai-exec-for-theft-of-trade-secrets.html" rel="noopener noreferrer"&gt;Tan and Apple's incoming CEO, John Ternus, have had a rocky relationship for years&lt;/a&gt;. Tan reportedly wanted the top hardware engineering job that Ternus won back in 2021.&lt;/p&gt;

&lt;p&gt;Ternus is not a minor figure in this story. He currently runs Apple's hardware engineering division, and effective September 1, 2026, he becomes Apple's CEO, &lt;a href="https://www.cnbc.com/2026/04/20/apple-names-john-ternus-ceo-replacing-tim-cook-who-becomes-chairman.html" rel="noopener noreferrer"&gt;succeeding Tim Cook&lt;/a&gt;. Gurman also reports that the vast majority of the roughly 400 former Apple employees now at OpenAI came specifically out of Ternus's division. &lt;a href="https://fortune.com/2026/07/11/openai-engineers-legal-fight-apple-ai-product-poaching/" rel="noopener noreferrer"&gt;One executive who worked with Tan&lt;/a&gt; described him as someone known for "flying very close to the sun."&lt;/p&gt;

&lt;p&gt;Put plainly: the man Apple accuses of running a trade-secrets operation is the same man who, five years ago, lost an internal competition for the job now held by the person about to become Apple's next chief executive. Whatever else this case is about, it is also an old rivalry that never really ended, just relocated to a courtroom.&lt;/p&gt;

&lt;h2&gt;
  
  
  The most famous name in the case isn't in the case
&lt;/h2&gt;

&lt;p&gt;Jony Ive, the designer behind the iPhone and Apple's most celebrated industrial design era, co-founded io Products alongside Tan. He is not named as a defendant. Apple's complaint refers only to "former Apple leaders" who founded io, carefully avoiding his name.&lt;/p&gt;

&lt;p&gt;Analysts do not think that omission means much in practice. &lt;a href="https://www.aol.com/articles/apple-goes-war-british-designer-115249000.html" rel="noopener noreferrer"&gt;Gene Munster of Deepwater Asset Management put it bluntly&lt;/a&gt;: Apple is effectively suing Jony Ive, whether his name appears in the filing or not.&lt;/p&gt;

&lt;p&gt;This is also not the first time Tan and io's hardware ambitions have run into a trade-secrets accusation. A separate lawsuit, filed by a hardware startup called iyO over a trademark dispute involving the similar-sounding "io" name, was &lt;a href="https://9to5mac.com/2026/07/10/openai-responds-to-apples-trade-secret-theft-lawsuit/" rel="noopener noreferrer"&gt;amended in March 2026 to add its own trade-secret claims&lt;/a&gt;, alleging a former iyO engineer passed confidential files to Tan. OpenAI disputes that case too. By the time Apple filed its own suit in July, Tan had already been publicly accused of the same basic pattern once before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frenemies: the partnership suing itself
&lt;/h2&gt;

&lt;p&gt;Here is what makes this genuinely strange rather than just ugly: Apple and OpenAI are still, technically, partners. Since 2024, ChatGPT has been built into Apple Intelligence and Siri. That arrangement is not ending because of this lawsuit, though it is already fading for another reason: Apple unveiled a revamped, Gemini-powered voice assistant in June, &lt;a href="https://www.irishtimes.com/business/2026/07/17/apple-targets-dozens-of-openai-employees-with-legal-letters/" rel="noopener noreferrer"&gt;built on Google's AI models instead of OpenAI's&lt;/a&gt;, with a wider rollout expected this fall.&lt;/p&gt;

&lt;p&gt;The irony gets thicker. &lt;a href="https://techcrunch.com/2025/08/25/elon-musks-xai-sues-apple-and-openai-alleging-anticompetitive-collusion/" rel="noopener noreferrer"&gt;Back in August 2025&lt;/a&gt;, Elon Musk's xAI and X Corp had filed their own lawsuit accusing Apple and OpenAI of colluding, alleging Apple rigged App Store rankings to favor ChatGPT over Musk's Grok. In that telling, Apple and OpenAI were uncomfortably cozy, not fighting. That case is still working through federal court in Texas, with a trial date set for October 2026. Separately, Musk's own personal lawsuit against OpenAI over its shift away from a nonprofit mission had already been thrown out by a jury on statute-of-limitations grounds just two months before Apple's trade-secrets suit landed. When news of Apple's suit broke, Musk could not resist a jab, posting that "Scam Altman" had struck again, according to reporting from &lt;a href="https://www.creativebloq.com/design/apples-ai-struggle-turns-ugly-as-it-sues-openai-and-io-the-company-founded-by-iphone-designer-jony-ive" rel="noopener noreferrer"&gt;Creative Bloq&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Zoom out and the last year looks almost absurd. Musk sued Apple and OpenAI for allegedly working together too closely. Apple is now suing OpenAI for allegedly working against it. Both descriptions cannot really capture the same relationship, which is probably the point. Big-money tech partnerships are rarely as simple as "friend" or "rival."&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAI's defense, so far
&lt;/h2&gt;

&lt;p&gt;OpenAI's public response has been careful and has evolved as the story has grown. Its first statement, issued within a day of the filing, was short: &lt;a href="https://www.macrumors.com/2026/07/11/openai-responds-after-apple-lawsuit/" rel="noopener noreferrer"&gt;company spokesperson Drew Pusateri said&lt;/a&gt;, "We have no interest in other companies' trade secrets." Four days later, as more of the complaint's specific allegations circulated, OpenAI sharpened its position, &lt;a href="https://www.bloomberg.com/news/articles/2026-07-14/openai-says-it-s-not-aware-of-any-evidence-that-apple-lawsuit-has-merit" rel="noopener noreferrer"&gt;telling Bloomberg&lt;/a&gt; it is "not aware of any evidence that this complaint has merit," while framing the departures at issue as a matter of employees being free to choose where they work.&lt;/p&gt;

&lt;p&gt;Neither statement directly addresses the specific allegations, the laptop, the interview checklist, the supplier conversations. That is fairly ordinary in early-stage litigation, where companies tend to avoid confirming or denying details until they are required to answer in court. But it has not stopped commentators from noticing the gap. Longtime Apple blogger Michael Tsai, for one, &lt;a href="https://mjtsai.com/blog/2026/07/13/apple-sues-openai-over-trade-secrets/" rel="noopener noreferrer"&gt;wrote skeptically&lt;/a&gt; that it is hard to believe OpenAI's leadership had no idea what was happening, given how large and public the hiring spree from Apple had been.&lt;/p&gt;

&lt;h2&gt;
  
  
  We have watched this movie before
&lt;/h2&gt;

&lt;p&gt;Silicon Valley has a genre for exactly this kind of dispute, and the most famous entry is Waymo v. Uber. In 2017, Google's self-driving unit accused a former engineer, Anthony Levandowski, of downloading thousands of confidential files before leaving to found a startup that Uber quickly acquired. That case &lt;a href="https://www.outlookbusiness.com/deeptech/apples-case-against-openai-spotlights-high-profile-trade-secret-wars-in-us-xai-googles-waymo-uber-tesla-huawei" rel="noopener noreferrer"&gt;settled in 2018&lt;/a&gt; for roughly $245 million in Uber equity, four days into what was expected to be a month-long trial. Levandowski later pleaded guilty to a criminal trade-secrets charge, served part of an 18-month sentence, and was pardoned in 2021.&lt;/p&gt;

&lt;p&gt;The Washington Post's Gerrit De Vynck called Apple's case against OpenAI the most aggressive trade-secrets fight he has seen since that one. Apple itself has run a smaller version of this play before: it sued chip startup Rivos in 2022 over alleged chip-design theft, &lt;a href="https://www.jurist.org/news/2026/07/apple-challenges-openais-hardware-push-in-trade-secret-lawsuit/" rel="noopener noreferrer"&gt;a case that settled in 2024&lt;/a&gt;. Tesla sued Rivian in 2020 over similar allegations involving battery technology.&lt;/p&gt;

&lt;p&gt;The legal bar in all of these cases is the same, and it is worth being precise about it. Under the federal Defend Trade Secrets Act, Apple has to show that the information was genuinely secret, that it took reasonable steps to protect it, that it was acquired or used improperly, and that this caused or is likely to cause real commercial harm. Hiring a rival's engineers is not, by itself, illegal. What is illegal is what those engineers allegedly did with what they knew on the way out the door.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the timing makes this worse for OpenAI
&lt;/h2&gt;

&lt;p&gt;This lawsuit is landing at possibly the worst moment for OpenAI's corporate calendar. The company &lt;a href="https://finance.yahoo.com/markets/stocks/articles/openai-confidentially-files-ipo-sec-223341186.html" rel="noopener noreferrer"&gt;confidentially filed paperwork with the SEC to go public&lt;/a&gt; earlier this year, targeting a valuation that could approach $1 trillion, with a listing expected as soon as September 2026, the same month Ternus takes over as Apple's CEO. Discovery in a case like this routinely surfaces internal emails, messages, and depositions that were never meant to be public. For a company trying to present a clean growth story to investors ahead of one of the largest IPOs in history, a court-ordered document dump is close to the worst possible timing, regardless of how the underlying claims are eventually resolved.&lt;/p&gt;

&lt;p&gt;That is likely why Apple's preservation letters matter beyond their literal legal function. Sending 40 individual letters to people who were never sued is not just a data-gathering exercise. It is a signal, to OpenAI and to every engineer thinking about leaving Apple next, that Apple intends to make this expensive, thorough, and very hard to make go away quietly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens next
&lt;/h2&gt;

&lt;p&gt;Nothing about this case will move quickly. Trade-secrets litigation of this size typically runs for one to two years before trial, and most cases like it settle rather than reach a jury, exactly as Waymo and Uber did. OpenAI has not filed a formal answer to Apple's complaint yet, and both companies have so far declined to discuss the preservation letters specifically.&lt;/p&gt;

&lt;p&gt;What is already clear is the shape of the fight. Apple is betting that a wide net of depositions and internal records will prove a pattern, not just two rogue employees. OpenAI is betting that individual actions, even embarrassing ones, do not add up to the systemic scheme Apple describes. Somewhere underneath both arguments is a far more human story: a passed-over executive, a rival who now runs the company, and a hardware bet that both sides think is worth fighting this hard for.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Everything described in this blog concerns allegations made in an active civil lawsuit. No court has ruled on any of these claims, and none of the named defendants has been found liable for any wrongdoing.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://zyvop.com/apple-sent-legal-letters-to-40-openai-employees-here-is-the-wild-story-behind-why-n1pcp" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡 For more articles like this, &lt;a href="https://zyvop.com/newsletter" rel="noopener noreferrer"&gt;subscribe to the ZyVOP newsletter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>johnternus</category>
      <category>aihardware</category>
      <category>appleopenailawsuit</category>
      <category>tradesecrets</category>
    </item>
    <item>
      <title>Claude Opus 5 Explained: Effort, Context, and Cost for Engineers</title>
      <dc:creator>Bhavya Arora</dc:creator>
      <pubDate>Mon, 31 Aug 2026 06:47:20 +0000</pubDate>
      <link>https://dev.to/bhavya_arora/claude-opus-5-explained-effort-context-and-cost-for-engineers-34ld</link>
      <guid>https://dev.to/bhavya_arora/claude-opus-5-explained-effort-context-and-cost-for-engineers-34ld</guid>
      <description>&lt;p&gt;Anthropic &lt;a href="https://www.anthropic.com/news/claude-opus-5" rel="noopener noreferrer"&gt;shipped Claude Opus 5&lt;/a&gt; on July 24, 2026, and the framing is unusual for a model launch. Anthropic isn't claiming it's the smartest model they've built — that's still Claude Fable 5.&lt;/p&gt;

&lt;p&gt;Instead, Opus 5 is pitched as the model you should default to for most day-to-day engineering work: coding, agentic tool use, and long-running enterprise tasks, at roughly half of Fable 5's per-token price and the same price as its own predecessor, Opus 4.8.&lt;/p&gt;

&lt;p&gt;That's the marketing pitch. Strip it away and the engineering story gets more interesting — it's the part most launch posts skip.&lt;/p&gt;

&lt;p&gt;Opus 5 changes how you control cost and capability through a single parameter, flips a default that will silently break existing &lt;code&gt;max_tokens&lt;/code&gt; budgets, and ships two new mechanisms for keeping your prompt cache alive across longer sessions. This post walks through all of it: what changed at the API level, why it changed, and how to build against it without re-learning Opus 5's behavior in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Shipped on July 24
&lt;/h2&gt;

&lt;p&gt;The model itself is straightforward to reference:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;API model ID&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus 5&lt;/td&gt;
&lt;td&gt;claude-opus-5&lt;/td&gt;
&lt;td&gt;Complex agentic coding and enterprise work&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Under the hood, three specs define most of what changes for you as a caller: a 1M-token context window that is both the default and the maximum (there's no smaller variant to opt out into), a 128k max output token ceiling per request, and thinking turned on by default. Pricing is unchanged from Opus 4.8: $5 per million input tokens and $25 per million output tokens.&lt;/p&gt;

&lt;p&gt;Anthropic &lt;a href="https://platform.claude.com/docs/en/about-claude/models/whats-new-opus-5" rel="noopener noreferrer"&gt;describes Opus 5&lt;/a&gt; as a step-change over Opus 4.8 rather than an incremental bump, with the largest reported gains in deep reasoning, agentic and long-horizon tasks, and test-time compute scaling — meaning the model converts additional inference-time compute into measurably better output more reliably than earlier Opus versions did.&lt;/p&gt;

&lt;p&gt;On Anthropic's own Frontier-Bench v0.1 and GDPval-AA evaluations, they report Opus 5 as their new state of the art among generally available models, trailing only Mythos 5 on cybersecurity-specific tasks. Treat those numbers as vendor-reported until you've run your own evals — which, if you're migrating a production workload, you should do regardless of what any benchmark says.&lt;/p&gt;

&lt;p&gt;There's a methodological wrinkle worth knowing before you cite the Frontier-Bench number specifically: Anthropic's own footnote for that chart states Opus 4.8 served as the fallback whenever a safety classifier refused a request from Opus 5 or Fable 5 during the eval run. Part of both models' reported scores therefore reflects an older model finishing some of the tasks, not a clean single-model result — a direct consequence of the same fallback mechanism covered later in this post.&lt;/p&gt;

&lt;p&gt;The part that actually changes your integration code is the effort parameter, and that's worth its own section.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Effort Parameter: One Knob for Cost and Capability
&lt;/h2&gt;

&lt;p&gt;Most model providers give you separate levers for "how much should the model think" and "how verbose should the output be" and "how many tool calls should it make." Anthropic collapsed all three into one parameter on Opus 5: &lt;code&gt;output_config.effort&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This matters architecturally, not just ergonomically. Effort affects every token category in the response — thinking, tool-call arguments, and the visible text — as a single coordinated setting. Instead of reasoning about three independent cost dimensions, you reason about one dial.&lt;/p&gt;

&lt;p&gt;Lower it, and Claude combines operations into fewer tool calls, skips pre-action narration, and gives terser confirmations. Raise it, and it explains its plan before acting, produces more thorough summaries, and calls tools more liberally when the task warrants it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@anthropic-ai/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-opus-5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Analyze the trade-offs between microservices and monolithic architectures for a 12-person team.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;output_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;effort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Five levels are available on Opus 5:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Opus 5 guidance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;Most efficient; real capability reduction in exchange for speed and cost&lt;/td&gt;
&lt;td&gt;Subagents, classification, high-volume simple tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;Balanced; moderate token savings&lt;/td&gt;
&lt;td&gt;Cost-sensitive agentic work where evals show quality holds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high (default)&lt;/td&gt;
&lt;td&gt;Full capability; identical to omitting the parameter&lt;/td&gt;
&lt;td&gt;Most reasoning, coding, and agentic tasks — the safe starting point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xhigh&lt;/td&gt;
&lt;td&gt;Extended capability for long-horizon work&lt;/td&gt;
&lt;td&gt;Demanding coding and agentic sessions, exploratory tool use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;max&lt;/td&gt;
&lt;td&gt;No constraint on token spend&lt;/td&gt;
&lt;td&gt;Genuinely frontier problems where cost is not the concern&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Setting &lt;code&gt;effort&lt;/code&gt; to &lt;code&gt;"high"&lt;/code&gt; produces exactly the same behavior as leaving the field out entirely — that's the documented default, not an assumption you need to verify empirically.&lt;/p&gt;

&lt;p&gt;Here's the detail that trips people up: effort is a behavioral signal, not a hard budget. At &lt;code&gt;low&lt;/code&gt; effort, Claude will still think through a genuinely hard problem — it just thinks less than it would at &lt;code&gt;high&lt;/code&gt; for that same problem.&lt;/p&gt;

&lt;p&gt;If you need an actual ceiling on token spend, pair effort with &lt;code&gt;max_tokens&lt;/code&gt; (or the &lt;a href="https://platform.claude.com/docs/en/build-with-claude/task-budgets" rel="noopener noreferrer"&gt;beta task-budgets feature&lt;/a&gt;) rather than assuming a low effort setting caps anything by itself.&lt;/p&gt;

&lt;p&gt;Anthropic's own guidance for Opus 5 specifically is to start at &lt;code&gt;high&lt;/code&gt;, then run an effort sweep against your evals: step down to &lt;code&gt;low&lt;/code&gt; or &lt;code&gt;medium&lt;/code&gt; wherever quality holds, and reserve &lt;code&gt;xhigh&lt;/code&gt; or &lt;code&gt;max&lt;/code&gt; for work that has demonstrated headroom at those levels.&lt;/p&gt;

&lt;p&gt;If you're carrying effort settings over from Opus 4.7 or 4.8, don't reuse them blindly — Opus 5 responds more decisively to effort changes than earlier Opus models, so a setting tuned for 4.8's behavior may over- or under-shoot on 5.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thinking On by Default: The Breaking Change Hiding in Plain Sight
&lt;/h2&gt;

&lt;p&gt;This is the change most likely to bite you silently during migration.&lt;/p&gt;

&lt;p&gt;On Claude Opus 4.8, a request runs without &lt;a href="https://platform.claude.com/docs/en/build-with-claude/thinking" rel="noopener noreferrer"&gt;thinking&lt;/a&gt; unless you explicitly set &lt;code&gt;thinking: {"type": "adaptive"}&lt;/code&gt;. On Opus 5, the same request runs with thinking on: the model decides when and how much to think on each turn, and effort is your control over how deep that thinking goes.&lt;/p&gt;

&lt;p&gt;The wire-level value hasn't changed — &lt;code&gt;thinking: {"type": "adaptive"}&lt;/code&gt; still works and is now equivalent to doing nothing — but the &lt;em&gt;default&lt;/em&gt; flipped underneath you.&lt;/p&gt;

&lt;p&gt;Why make this change at all? Because the capability gains Anthropic is claiming for Opus 5 — deep reasoning, long-horizon agentic work, test-time compute scaling — depend on the model actually using inference-time compute. Shipping a step-change reasoning model with reasoning off by default would undercut the entire premise of the release.&lt;/p&gt;

&lt;p&gt;The practical consequence: &lt;code&gt;max_tokens&lt;/code&gt; is a hard ceiling on &lt;em&gt;total&lt;/em&gt; output, thinking plus visible response combined. If you had a workload running on Opus 4.8 with &lt;code&gt;max_tokens&lt;/code&gt; sized only for response text — because thinking was off and didn't need budget — that same &lt;code&gt;max_tokens&lt;/code&gt; value can now truncate Opus 5 mid-thought.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Opus 4.8: thinking is off by default, so max_tokens only needs to&lt;/span&gt;
&lt;span class="c1"&gt;// cover the visible response.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-opus-4-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Summarize this incident report.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Opus 5: thinking is on by default, so max_tokens must cover thinking&lt;/span&gt;
&lt;span class="c1"&gt;// tokens too. Reusing 2048 here risks truncation before the model&lt;/span&gt;
&lt;span class="c1"&gt;// finishes reasoning. Bump it, and go generous at xhigh/max.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-opus-5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Summarize this incident report.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second gotcha is a genuine breaking change, not just a tuning issue: on Opus 5, &lt;code&gt;thinking: {"type": "disabled"}&lt;/code&gt; is only accepted when effort is &lt;code&gt;high&lt;/code&gt; or below. Setting it alongside &lt;code&gt;xhigh&lt;/code&gt; or &lt;code&gt;max&lt;/code&gt; effort returns a 400 error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Valid — effort at or below "high" permits disabling thinking.&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-opus-5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;thinking&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;disabled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;output_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;effort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Classify this support ticket.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Invalid — throws a 400. xhigh/max effort requires thinking to stay on.&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-opus-5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;thinking&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;disabled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;output_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;effort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;xhigh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Refactor the billing module.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Opus 4.8, disabling thinking was independent of effort level. On Opus 5, it isn't. If your integration disables thinking at high effort levels today, you have two options going forward: keep thinking disabled and cap effort at &lt;code&gt;high&lt;/code&gt;, or drop the &lt;code&gt;thinking&lt;/code&gt; field and let the model reason.&lt;/p&gt;

&lt;p&gt;One more integration detail worth knowing before you reach for &lt;code&gt;thinking: {"type": "disabled"}&lt;/code&gt; as a cost-saving move: with thinking off, Opus 5 can occasionally write a tool call into its visible text instead of emitting a proper &lt;code&gt;tool_use&lt;/code&gt; block, or leak internal XML tags into the response. Where you have the choice, prefer lowering effort over disabling thinking outright — you get the token savings without the parsing edge cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context Window and Output Budgets
&lt;/h2&gt;

&lt;p&gt;Opus 5 has a &lt;a href="https://platform.claude.com/docs/en/build-with-claude/context-windows" rel="noopener noreferrer"&gt;1M-token context window&lt;/a&gt; that is simultaneously the default and the maximum — there's no smaller base window and no beta header to opt into a larger one. That's a genuine simplification if you've previously had to branch your client code around a &lt;code&gt;context-1m-2025-08-07&lt;/code&gt;-style beta flag depending on which model you were calling. With Opus 5, one context-length code path covers every request.&lt;/p&gt;

&lt;p&gt;Max output per request on the synchronous Messages API is 128k tokens. If you're running bulk workloads through the &lt;a href="https://platform.claude.com/docs/en/build-with-claude/batch-processing" rel="noopener noreferrer"&gt;Message Batches API&lt;/a&gt;, Opus 5 supports up to 300k output tokens per item with the &lt;code&gt;output-300k-2026-03-24&lt;/code&gt; beta header — the same header used for Opus 4.8, 4.7, 4.6, and both current Sonnet models.&lt;/p&gt;

&lt;p&gt;The practical guidance from Anthropic, and it's worth taking seriously: when you run Opus 5 at &lt;code&gt;xhigh&lt;/code&gt; or &lt;code&gt;max&lt;/code&gt; effort, set a large &lt;code&gt;max_tokens&lt;/code&gt; — starting around 64k and tuning from there — so the model has room to think and act across subagent calls and tool loops without hitting the ceiling mid-task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt Caching and Cache-Safe Mid-Conversation Changes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching" rel="noopener noreferrer"&gt;Prompt caching&lt;/a&gt; hashes your request prefix in a fixed order: &lt;code&gt;tools&lt;/code&gt;, then &lt;code&gt;system&lt;/code&gt;, then &lt;code&gt;messages&lt;/code&gt;. A cache hit requires that prefix to match a prior request byte-for-byte up to the cache breakpoint.&lt;/p&gt;

&lt;p&gt;Miss anywhere in that chain, and everything downstream reprocesses at full input-token price — a cache hit is effectively O(1) against the cached span, a miss is O(n) against however much of the prefix changed.&lt;/p&gt;

&lt;p&gt;That ordering is why editing your top-level &lt;code&gt;system&lt;/code&gt; field mid-session is expensive: it sits near the very front of the hashed prefix, so appending even one sentence invalidates the cache for the system prompt and every cached message that follows it.&lt;/p&gt;

&lt;p&gt;The existing fix, &lt;a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages" rel="noopener noreferrer"&gt;available on several current models including Opus 4.8&lt;/a&gt;, is to append a message with &lt;code&gt;"role": "system"&lt;/code&gt; at the point in the conversation where the new instruction becomes relevant, instead of editing the top-level field. Everything before that point stays byte-identical, so the cache still hits.&lt;/p&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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpNUMtOw0AM_BXjE0ibSpU45YAESBVIlEMDXLI9uFknWbFZR7vbF1UlPoIv5EtQmgrwyfbYM2MfsBLDmGPtZFu1FBI8LbQHAIjrVROob6EPXNtdqfGeqpbNuYbLta9a8g2bK43LcWeIlzKJuLiELLuBooz7mLj7hxcnYF5q7DhGajjCdDLxvxzszZjMx8Gi1BjEcQ4jFXx_fgH1PXvDBjprskr8hkOkZOWPZn7WeS41OkocIK2Djwq8bKEfDpUaUssQE60cQ2tjkrDXuESFHYeOrMH8gKnlbniQ4ZrWLqEaO28U7LAXh5lafJpRZ90ec8yo7x1no1kFd8769zlVxameiU8KNBbcCMPro0YFC1lJEgUP7DacbEUKboMlpyCSj1nkYGtUJ5HCfgxeptf9Do9HhavmXpwEzPFi29rEePwBxXiZiQ" 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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpNUMtOw0AM_BXjE0ibSpU45YAESBVIlEMDXLI9uFknWbFZR7vbF1UlPoIv5EtQmgrwyfbYM2MfsBLDmGPtZFu1FBI8LbQHAIjrVROob6EPXNtdqfGeqpbNuYbLta9a8g2bK43LcWeIlzKJuLiELLuBooz7mLj7hxcnYF5q7DhGajjCdDLxvxzszZjMx8Gi1BjEcQ4jFXx_fgH1PXvDBjprskr8hkOkZOWPZn7WeS41OkocIK2Djwq8bKEfDpUaUssQE60cQ2tjkrDXuESFHYeOrMH8gKnlbniQ4ZrWLqEaO28U7LAXh5lafJpRZ90ec8yo7x1no1kFd8769zlVxameiU8KNBbcCMPro0YFC1lJEgUP7DacbEUKboMlpyCSj1nkYGtUJ5HCfgxeptf9Do9HhavmXpwEzPFi29rEePwBxXiZiQ" alt="Mermaid Diagram" width="1131" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A mid-conversation system message must immediately follow a &lt;code&gt;user&lt;/code&gt; turn — including one carrying &lt;code&gt;tool_result&lt;/code&gt; blocks — and either end the array or be followed by an &lt;code&gt;assistant&lt;/code&gt; turn.&lt;/p&gt;

&lt;p&gt;That placement rule matters for agentic loops specifically: it means you can drop an operator-level fact in right after a tool result and before Claude's next turn, which is exactly where you'd want to relay something like "the remaining token budget just dropped below threshold" without derailing the turn in progress.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example shape for a mid-conversation instruction inserted after a&lt;/span&gt;
&lt;span class="c1"&gt;// tool result, so the cached prefix before it is untouched.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Run the test suite and fix any failures.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool_use&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;toolu_01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;run_tests&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool_result&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;tool_use_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;toolu_01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;12 passed, 0 failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;From now on, every suggestion must include explicit type annotations.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Phrase mid-conversation system content as a stated fact ("the user sent this while you were working," "the budget is now X"), not as a command that overrides the user — Claude is trained to resist instructions that read as working against the end user, and that resistance applies to the system role too.&lt;/p&gt;

&lt;p&gt;New with this release: mid-conversation tool changes, in beta behind the &lt;code&gt;mid-conversation-tool-changes-2026-07-01&lt;/code&gt; header. It applies the same idea to your &lt;code&gt;tools&lt;/code&gt; array — you can add or remove tools between turns without resending (and re-hashing) the full tool list for the life of the session.&lt;/p&gt;

&lt;p&gt;Think of an agent that only gets access to a &lt;code&gt;deploy&lt;/code&gt; tool after its tests pass: previously, changing the available tool list meant eating a cache miss on the entire prefix from that point forward. This closes that gap.&lt;/p&gt;

&lt;p&gt;The exact request shape is still settling as the feature is in beta, so &lt;a href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages" rel="noopener noreferrer"&gt;check the current docs&lt;/a&gt; before wiring it into a critical path — but the mechanism it's solving for is the same cache-preservation problem as mid-conversation system messages, just applied to tool availability instead of instructions.&lt;/p&gt;

&lt;p&gt;One more win worth flagging: the minimum cacheable prompt length on Opus 5 dropped to 512 tokens, down from 1,024 on Opus 4.8. If you run a lot of short, high-frequency requests — subagent calls, classification passes — some of those now become cacheable that simply couldn't be cached before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safety Classifiers and the Fallback Mechanism
&lt;/h2&gt;

&lt;p&gt;Anthropic's frontier-tier models run safety classifiers that can &lt;a href="https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback" rel="noopener noreferrer"&gt;decline a request outright&lt;/a&gt;. When that happens, you get a normal HTTP 200 response with &lt;code&gt;stop_reason: "refusal"&lt;/code&gt; — not an exception, not a 4xx error.&lt;/p&gt;

&lt;p&gt;That's a deliberate design choice: it keeps refusals out of your error-handling and retry-on-failure code paths, where they'd otherwise get silently retried against the same model and refuse again.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;category&lt;/th&gt;
&lt;th&gt;What triggers it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;cyber&lt;/td&gt;
&lt;td&gt;Requests that could enable cyber harm, such as malware or exploit development (benign security work can also trigger it)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bio&lt;/td&gt;
&lt;td&gt;Requests that could enable biological harm (benign life-sciences work can also trigger it)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;frontier_llm&lt;/td&gt;
&lt;td&gt;Requests that could assist a competing AI lab's model development&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reasoning_extraction&lt;/td&gt;
&lt;td&gt;Requests asking the model to reproduce its internal reasoning as response text — use adaptive thinking for structured reasoning output instead&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Billing follows the same 200-response logic: a refusal that arrives before any output isn't charged, even though token counts still appear in &lt;code&gt;usage&lt;/code&gt;. A refusal that happens mid-stream bills the input tokens plus whatever output already streamed.&lt;/p&gt;

&lt;p&gt;Opus 5's own classifier posture is notably looser than Fable 5's. Anthropic reports expecting roughly 85% fewer classifier interventions on Opus 5 compared to Fable 5. Its cyber classifiers block binary-based vulnerability scanning, penetration testing, and exploit generation, but allow source-code vulnerability discovery to proceed.&lt;/p&gt;

&lt;p&gt;Flagged requests fall back to Opus 4.8 by default inside Claude.ai, Claude Code, and Claude Cowork, and you can wire the same fallback into your own API calls. Teams doing legitimate offensive-security work can apply for &lt;a href="https://support.claude.com/en/articles/14604842-real-time-cyber-safeguards-on-claude-opus-and-sonnet" rel="noopener noreferrer"&gt;Anthropic's Cyber Verification Program&lt;/a&gt; to get a version of Opus 5 with fewer restrictions.&lt;/p&gt;

&lt;p&gt;On the biology side, requests that Fable 5 would have blocked now route to Opus 5 instead of Opus 4.8, reflecting Opus 5's position as Anthropic's strongest generally available model for scientific research.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;beta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-opus-5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userPrompt&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;fallbacks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-opus-4-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;betas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server-side-fallback-2026-07-01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// A fallback_message entry in usage.iterations means a fallback model&lt;/span&gt;
&lt;span class="c1"&gt;// ran; pair it with stop_reason to confirm it actually served the reply.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fallbackRan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fallback_message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;servedByFallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fallbackRan&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stop_reason&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;refusal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;fallbacks&lt;/code&gt; accepts up to three models tried in order, and each entry must be a permitted fallback target for the model you called — that list is published per-model on the Models API.&lt;/p&gt;

&lt;p&gt;A fallback only fires on a safety-classifier decline; a rate limit, overload, or server error on the primary model comes back to you unmodified, so your existing retry logic for those cases doesn't change.&lt;/p&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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpVkU2P2jAQhv_K1OdEq0rthUOrBZayh90DtJWqgNDgTBILx5N6JgUK_PcqDittj_54_Lx-52Isl2QmpvJ8tA1Ghe_zTQAAeCxW9LsnUVAG67EvKeeul_zzFvL8C0wvM48irnIUwTZkD7cRnA7H15knjFeYFS9ckodIKBwkA4veCyizlwwiScehlO17cuGxrqm8wrzYGFHudiM8gUhVL-iHR5RqjmcQ0o250_MU6-lSofd7tAcBy6FydR-p_HrP9pQMv0iusChe6aTQpngugG3QBYh9EOAA2hAItgRxLGH7nn_lK3wrntpOz4NDKShE0j4GKlNb6D3FO7JIsZbFKv1Vhhc7jipJMdq1QQW02qP3Z8AgR4pU3vlZ4p-L_5qgUO4GHzykKne9EDxAi6ed8oHCW6HLkTWZaSm26EozuRhtqB1GXlKFvVeTjTs_MTrce5LhTsVBF9g6fzYTk2PXecrlLEptBlPvwuEF7TqtFxw0g41ZU80EP543JoMV71k5gyX5P6TOYgaP0Q2DEwySC0VXmSxJ1u7vkOXjp-5kbrfM7OsZe45mYj4cG6dkbv8ACzXjdA" 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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpVkU2P2jAQhv_K1OdEq0rthUOrBZayh90DtJWqgNDgTBILx5N6JgUK_PcqDittj_54_Lx-52Isl2QmpvJ8tA1Ghe_zTQAAeCxW9LsnUVAG67EvKeeul_zzFvL8C0wvM48irnIUwTZkD7cRnA7H15knjFeYFS9ckodIKBwkA4veCyizlwwiScehlO17cuGxrqm8wrzYGFHudiM8gUhVL-iHR5RqjmcQ0o250_MU6-lSofd7tAcBy6FydR-p_HrP9pQMv0iusChe6aTQpngugG3QBYh9EOAA2hAItgRxLGH7nn_lK3wrntpOz4NDKShE0j4GKlNb6D3FO7JIsZbFKv1Vhhc7jipJMdq1QQW02qP3Z8AgR4pU3vlZ4p-L_5qgUO4GHzykKne9EDxAi6ed8oHCW6HLkTWZaSm26EozuRhtqB1GXlKFvVeTjTs_MTrce5LhTsVBF9g6fzYTk2PXecrlLEptBlPvwuEF7TqtFxw0g41ZU80EP543JoMV71k5gyX5P6TOYgaP0Q2DEwySC0VXmSxJ1u7vkOXjp-5kbrfM7OsZe45mYj4cG6dkbv8ACzXjdA" alt="Mermaid Diagram" width="750" height="1029"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two pitfalls worth calling out explicitly: fallback configuration on a top-level request does not propagate into model calls your tools make internally, so subagent invocations need their own fallback setup.&lt;/p&gt;

&lt;p&gt;And because a refusal is a 200, not a 5xx, dashboards built purely on HTTP error rates never see it — emit a dedicated event per refusal and per fallback-served response if you want visibility into how often your traffic is hitting classifiers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Opus 5 vs. the Rest of the Family
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Model ID&lt;/th&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Max output&lt;/th&gt;
&lt;th&gt;Price (input/output per MTok)&lt;/th&gt;
&lt;th&gt;Position&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus 5&lt;/td&gt;
&lt;td&gt;claude-opus-5&lt;/td&gt;
&lt;td&gt;1M (default = max)&lt;/td&gt;
&lt;td&gt;128k (300k batch, beta)&lt;/td&gt;
&lt;td&gt;$5 / $25&lt;/td&gt;
&lt;td&gt;New default for agentic coding and enterprise work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus 4.8&lt;/td&gt;
&lt;td&gt;claude-opus-4-8&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;128k&lt;/td&gt;
&lt;td&gt;$5 / $25&lt;/td&gt;
&lt;td&gt;Still available; common fallback target for Opus 5 and Fable 5 refusals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet 5&lt;/td&gt;
&lt;td&gt;claude-sonnet-5&lt;/td&gt;
&lt;td&gt;1M (default = max)&lt;/td&gt;
&lt;td&gt;128k&lt;/td&gt;
&lt;td&gt;$2 / $10 intro through Aug 31, 2026, then $3 / $15&lt;/td&gt;
&lt;td&gt;Cheapest per-token tier close to Opus 4.8 on many agentic tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Fable 5&lt;/td&gt;
&lt;td&gt;claude-fable-5&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;128k&lt;/td&gt;
&lt;td&gt;$10 / $50&lt;/td&gt;
&lt;td&gt;Frontier ceiling; includes classifiers that can decline requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Mythos 5&lt;/td&gt;
&lt;td&gt;claude-mythos-5&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;128k&lt;/td&gt;
&lt;td&gt;Not public&lt;/td&gt;
&lt;td&gt;Limited release via Project Glasswing; no refusal classifiers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Pick Opus 5 as your default for coding agents, code review, document and spreadsheet generation, and enterprise workflows where near-frontier quality at half of Fable 5's price is the right trade — and note that on Frontier-Bench v0.1 and GDPval-AA specifically, Anthropic reports Opus 5 actually leading Fable 5, not just approaching it.&lt;/p&gt;

&lt;p&gt;Reach for &lt;a href="https://platform.claude.com/docs/en/about-claude/models/introducing-claude-fable-5-and-claude-mythos-5" rel="noopener noreferrer"&gt;Fable 5&lt;/a&gt; when a task genuinely needs the highest general-capability ceiling Anthropic offers — particularly cybersecurity and biology work — and you can handle classifier refusals as a normal response type in your integration.&lt;/p&gt;

&lt;p&gt;Sonnet 5 is worth benchmarking against Opus 5 for high-volume, latency-sensitive pipelines — Anthropic positions it as landing close to Opus 4.8 on agentic work at a meaningfully lower price, so for some workloads it may be the better cost-performance point even against Opus 5.&lt;/p&gt;

&lt;p&gt;Keep Opus 4.8 in your model roster even after migrating, since it's the documented fallback target when Opus 5's own classifiers fire. Full, current rate cards for every tier live on &lt;a href="https://platform.claude.com/docs/en/about-claude/pricing" rel="noopener noreferrer"&gt;Anthropic's pricing page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Start every workload at &lt;code&gt;effort: "high"&lt;/code&gt; (the default) and run an evaluation sweep before stepping down — don't guess at the right level.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hold effort constant within a single cached, multi-turn conversation. Vary it across workload types, not within one session, since changing it invalidates the cached prefix.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Size &lt;code&gt;max_tokens&lt;/code&gt; for thinking plus response, not response alone, especially if you're migrating a workload that ran with thinking off on Opus 4.8.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go generous with &lt;code&gt;max_tokens&lt;/code&gt; — 64k as a starting point — whenever you run &lt;code&gt;xhigh&lt;/code&gt; or &lt;code&gt;max&lt;/code&gt; effort.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure fallback on every code path that calls the model, including retry handlers and subagent invocations, since it doesn't propagate automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prefer lowering effort over disabling thinking when you need cheaper responses; disabling thinking has real parsing edge cases at high effort levels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use mid-conversation system messages (and, once stable, mid-conversation tool changes) for anything you discover mid-session, instead of editing the top-level &lt;code&gt;system&lt;/code&gt; or &lt;code&gt;tools&lt;/code&gt; fields.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Treating effort as a token ceiling.&lt;/strong&gt; It's a behavioral signal — Claude still reasons through hard problems at &lt;code&gt;low&lt;/code&gt; effort, just less than at &lt;code&gt;high&lt;/code&gt;. Pair it with &lt;code&gt;max_tokens&lt;/code&gt; for an actual cap.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reusing Opus 4.7/4.8 effort presets on Opus 5 without re-testing.&lt;/strong&gt; Opus 5 responds more decisively to effort changes, so old presets may over- or under-shoot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Assuming thinking can always be disabled.&lt;/strong&gt; It can't at &lt;code&gt;xhigh&lt;/code&gt; or &lt;code&gt;max&lt;/code&gt; effort on Opus 5 — that combination returns a 400.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Carrying over a&lt;/strong&gt; &lt;code&gt;max_tokens&lt;/code&gt; &lt;strong&gt;value sized for a thinking-off Opus 4.8 workload.&lt;/strong&gt; Thinking is on by default now, and it shares the same budget as the visible response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Editing the top-level&lt;/strong&gt; &lt;code&gt;system&lt;/code&gt; &lt;strong&gt;field for a mid-session instruction.&lt;/strong&gt; It quietly kills your cache hit rate for everything downstream; use a mid-conversation system message instead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Handling a refusal in exception-handling code.&lt;/strong&gt; It's a normal 200 response with &lt;code&gt;stop_reason: "refusal"&lt;/code&gt; — check the field, don't wrap the call in a try/catch expecting an error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Forgetting that fallback config doesn't reach into tool-triggered model calls.&lt;/strong&gt; Subagents need their own &lt;code&gt;fallbacks&lt;/code&gt; setup.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance Considerations
&lt;/h2&gt;

&lt;p&gt;The effort ladder is your primary lever for cost and latency — reach for &lt;code&gt;low&lt;/code&gt; or &lt;code&gt;medium&lt;/code&gt; before considering a smaller model entirely, since Anthropic's benchmarks show Opus 5 holding strong quality at lower effort levels relative to its own higher settings.&lt;/p&gt;

&lt;p&gt;Changing effort between requests in the same session breaks prompt caching, because effort shapes the rendered prompt. If a long agentic session relies on cache hits, pick one effort level at the start and keep it there for the life of that session.&lt;/p&gt;

&lt;p&gt;A 1M-token context window doesn't make long context free. Uncached input still bills at full input-token rates on every request that includes it. For repeated large context — a repository, a document corpus, a long system prompt — enable caching explicitly (it's opt-in via &lt;code&gt;cache_control&lt;/code&gt;) rather than assuming a large context window implies cheap reuse.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://platform.claude.com/docs/en/build-with-claude/fast-mode" rel="noopener noreferrer"&gt;Fast mode&lt;/a&gt; is a genuine trade-off, not a free win: it's a research preview available for Opus 5 on the Claude API only (not Bedrock, Google Cloud, or Microsoft Foundry), running at roughly 2.5x the default token throughput for twice the base price — $5/$25 becomes $10 input / $50 output. Reach for it on latency-bound user-facing paths, not on cost-bound batch jobs.&lt;/p&gt;

&lt;p&gt;For bulk, asynchronous workloads — nightly runs, large evals — the Message Batches API with the &lt;code&gt;output-300k-2026-03-24&lt;/code&gt; beta header raises your per-item output ceiling to 300k tokens, which is the better fit than pushing a synchronous request past its 128k limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Considerations
&lt;/h2&gt;

&lt;p&gt;Safety classifiers are a defense-in-depth layer on Anthropic's side, not a substitute for your own sandboxing. If you're giving Opus 5 access to bash, computer-use, or code-execution tools, you still own the blast radius of what those tools can actually do — the classifier governs what Claude will attempt to generate, not what your tool implementation is capable of executing.&lt;/p&gt;

&lt;p&gt;Handle &lt;code&gt;stop_reason: "refusal"&lt;/code&gt; explicitly rather than letting it fall through generic error handling. A &lt;code&gt;category: "cyber"&lt;/code&gt; refusal retried unmodified against the same model will refuse again; route it to your configured fallback instead, and log the category for visibility into what your traffic is actually triggering.&lt;/p&gt;

&lt;p&gt;If your product does legitimate security research that keeps tripping the cyber classifier, Anthropic's Cyber Verification Program exists specifically to reduce those restrictions for vetted enterprises and researchers — that's the intended path, rather than trying to prompt around the classifier.&lt;/p&gt;

&lt;p&gt;Mid-conversation system messages carry operator-level authority: Claude treats system-role content as coming from you, the application, not the end user. Never place raw tool output, retrieved documents, or other untrusted content directly in a system message — that hands it the same trust level as your own instructions, which is a textbook prompt-injection vector. Keep that content in &lt;code&gt;tool_result&lt;/code&gt; blocks, where it's treated as data rather than instruction.&lt;/p&gt;

&lt;p&gt;Consistent with prior Opus models, Opus 5 carries no data retention requirement for general API access. That's a reasonable default for most integrations, but confirm the specifics against Anthropic's current data processing agreement and trust center documentation for your actual compliance posture rather than treating it as a blanket guarantee.&lt;/p&gt;

&lt;p&gt;Worth noting for anyone weighing model choice partly on safety grounds: Anthropic's own automated behavioral audit scores Opus 5 as its best-aligned model released so far, reporting fewer instances of dishonest behavior and a lower success rate for attempts to manipulate it into misuse compared with its current lineup.&lt;/p&gt;

&lt;p&gt;That's a first-party audit, not an independent third-party assessment, so weigh it accordingly — but it's a relevant data point if safety posture factors into your model selection. Anthropic publishes the full methodology in the &lt;a href="https://www.anthropic.com/claude-opus-5-system-card" rel="noopener noreferrer"&gt;Claude Opus 5 system card&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Example: A Production PR-Review Agent
&lt;/h2&gt;

&lt;p&gt;Here's a shape that pulls several of the pieces above together: an agent that reviews a pull request, adjusts effort based on diff size, caches its system prompt and tool definitions, and falls back to Opus 4.8 if a classifier flags anything mid-review.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@anthropic-ai/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REVIEW_TOOLS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;get_diff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fetch the unified diff for the pull request under review.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;input_schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;pr_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pr_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post_review_comment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Post an inline comment on a specific file and line.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;input_schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;integer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SYSTEM_PROMPT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`You are a senior code reviewer. Flag correctness bugs,
security issues, and missing tests. Skip style nits the linter already
catches. Be specific: cite the file and line for every comment.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reviewPullRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;diffSizeBytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Larger diffs get more room to reason; small diffs stay cheap and fast.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;effort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;diffSizeBytes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;xhigh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;beta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-opus-5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;effort&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;xhigh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;64000&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// Automatic caching: the system prompt and tool definitions form a&lt;/span&gt;
    &lt;span class="c1"&gt;// stable prefix across every PR this process reviews, so only the&lt;/span&gt;
    &lt;span class="c1"&gt;// first call in a while pays full input-token price for them.&lt;/span&gt;
    &lt;span class="na"&gt;cache_control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ephemeral&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;system&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SYSTEM_PROMPT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;REVIEW_TOOLS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;output_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;effort&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Review pull request &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;prId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. Start by fetching the diff.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="c1"&gt;// If Opus 5's classifiers flag anything in the diff or the&lt;/span&gt;
    &lt;span class="c1"&gt;// generated comments, fall through to Opus 4.8 rather than&lt;/span&gt;
    &lt;span class="c1"&gt;// dropping the review entirely.&lt;/span&gt;
    &lt;span class="na"&gt;fallbacks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-opus-4-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;betas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server-side-fallback-2026-07-01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stop_reason&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;refusal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Every fallback in the chain also declined. Surface this distinctly&lt;/span&gt;
    &lt;span class="c1"&gt;// from a normal failure so it doesn't get silently retried.&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Review of &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;prId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; was declined:`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stop_details&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things this example is doing deliberately. The effort level is decided per request based on diff size, not hardcoded — that's the primary cost lever, used before reaching for a cheaper model entirely.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cache_control&lt;/code&gt; is set explicitly, because caching on Opus 5 (like every current model) is opt-in, not automatic; without it, every PR review reprocesses the full system prompt and tool schema at full price. And the fallback chain means a classifier flag on a security-sensitive diff degrades to Opus 4.8 instead of failing the whole review pipeline — which matters if this runs unattended in CI.&lt;/p&gt;

&lt;p&gt;In a real deployment you'd loop this around &lt;code&gt;tool_use&lt;/code&gt; blocks until the model stops calling tools, and you'd insert a mid-conversation system message if, say, the diff turned out to exceed your token budget partway through — appended after the next tool result, not spliced into the top-level &lt;code&gt;system&lt;/code&gt; field, so the cache built up over the loop survives.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What is Claude Opus 5?&lt;/strong&gt; It's Anthropic's newest Opus-tier model, released July 24, 2026, positioned as a near-frontier model for coding and enterprise work at half the price of Claude Fable 5, Anthropic's most capable generally available model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How much does Claude Opus 5 cost?&lt;/strong&gt; $5 per million input tokens and $25 per million output tokens — unchanged from Opus 4.8. Fast mode, a research preview available on the Claude API only, doubles both rates to $10/$50.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the difference between the effort parameter and thinking?&lt;/strong&gt;&lt;code&gt;thinking&lt;/code&gt; controls whether Claude reasons in visible thinking blocks before answering. &lt;code&gt;effort&lt;/code&gt; controls how much total work goes into the whole response — thinking depth, tool-call count, and text length together. On Opus 5, effort is the primary control; thinking is on by default and mostly governed through effort rather than toggled directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I disable thinking on Claude Opus 5?&lt;/strong&gt; Yes, but only when effort is &lt;code&gt;high&lt;/code&gt; or below. Setting &lt;code&gt;thinking: {"type": "disabled"}&lt;/code&gt; together with &lt;code&gt;xhigh&lt;/code&gt; or &lt;code&gt;max&lt;/code&gt; effort returns a 400 error — this is new behavior compared to Opus 4.8.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the context window size?&lt;/strong&gt; 1M tokens, and it's both the default and the maximum — there's no smaller variant and no beta header required to reach it. Max output is 128k tokens per synchronous request, or up to 300k on the Batch API with a beta header.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does Claude Opus 5 compare to Claude Fable 5?&lt;/strong&gt; Fable 5 remains Anthropic's highest general-capability model, and Opus 5 is priced and positioned against it: close to Fable 5's frontier intelligence at half the cost. That framing undersells one detail — on specific coding and knowledge-work evaluations like Frontier-Bench v0.1 and GDPval-AA, &lt;a href="https://www.anthropic.com/news/claude-opus-5" rel="noopener noreferrer"&gt;Anthropic reports Opus 5 as the new leader&lt;/a&gt;, ahead of Fable 5 on those particular benchmarks.&lt;/p&gt;

&lt;p&gt;Fable 5 still holds the edge on the hardest cybersecurity and biology work, and it ships with classifiers that can decline requests; Opus 5 triggers roughly 85% fewer of those interventions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is Claude Opus 5 available outside the Claude API?&lt;/strong&gt; Yes — Amazon Bedrock (&lt;code&gt;anthropic.claude-opus-5&lt;/code&gt;), Google Cloud (&lt;code&gt;claude-opus-5&lt;/code&gt;), and Microsoft Foundry all support it. Fast mode, notably, does not extend to any of those three platforms yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I migrate from Opus 4.8 to Opus 5?&lt;/strong&gt; Change the model string from &lt;code&gt;claude-opus-4-8&lt;/code&gt; to &lt;code&gt;claude-opus-5&lt;/code&gt;, then check two things: whether your &lt;code&gt;max_tokens&lt;/code&gt; values account for thinking now running by default, and whether you disable thinking at &lt;code&gt;xhigh&lt;/code&gt; or &lt;code&gt;max&lt;/code&gt; effort anywhere, which will start failing with a 400. Anthropic's &lt;a href="https://platform.claude.com/docs/en/about-claude/models/migration-guide" rel="noopener noreferrer"&gt;migration guide&lt;/a&gt; walks through both checks in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The headline number — half of Fable 5's price at near-Fable-5 capability — is the easy part of this release to explain and the least useful part to build against blindly.&lt;/p&gt;

&lt;p&gt;The parts that actually change your integration are structural: effort as a single unified cost dial, thinking flipped on by default with a real breaking change around disabling it, and two new mechanisms for keeping your prompt cache alive as sessions get longer and tool access changes mid-flight.&lt;/p&gt;

&lt;p&gt;None of that requires a rewrite. It requires reading the migration notes before you swap the model string, sizing &lt;code&gt;max_tokens&lt;/code&gt; for a model that thinks by default, and treating effort as the lever you reach for before you reach for a different model entirely.&lt;/p&gt;

&lt;p&gt;Do that, and Opus 5 is a reasonable new default for the agentic and coding workloads most teams are already running on Opus-tier models — not because it's the smartest thing Anthropic has shipped, but because it's the one built to be used every day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Claude Opus 5 (&lt;code&gt;claude-opus-5&lt;/code&gt;) costs $5/$25 per million input/output tokens — the same as Opus 4.8 — while Anthropic reports it leading Fable 5 on coding and knowledge-work evaluations specifically, even though Fable 5 remains the higher general-capability model.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;output_config.effort&lt;/code&gt; parameter is a single dial (&lt;code&gt;low&lt;/code&gt; to &lt;code&gt;max&lt;/code&gt;) that governs thinking, tool calls, and text together; it's a behavioral signal, not a hard token budget.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Thinking runs on by default on Opus 5, unlike Opus 4.8 — revisit &lt;code&gt;max_tokens&lt;/code&gt; on any migrated workload, since it's now a ceiling on thinking plus response combined.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;thinking: {"type": "disabled"}&lt;/code&gt; only works at &lt;code&gt;high&lt;/code&gt; effort or below; combining it with &lt;code&gt;xhigh&lt;/code&gt; or &lt;code&gt;max&lt;/code&gt; returns a 400.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The context window is a flat 1M tokens (default and max), with 128k max output synchronously or 300k on the Batch API via a beta header.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Refusals are normal 200 responses with &lt;code&gt;stop_reason: "refusal"&lt;/code&gt;, not errors — configure &lt;code&gt;fallbacks&lt;/code&gt; explicitly, including for subagent calls, since it doesn't propagate automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mid-conversation system messages, and the new mid-conversation tool-changes beta, let you add instructions or tools partway through a session without invalidating your prompt cache.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep Opus 4.8 in your model roster: it's the documented fallback target when Opus 5's own safety classifiers flag a request.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://zyvop.com/claude-opus-5-explained-effort-context-and-cost-for-engineers-yq1k6" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡 For more articles like this, &lt;a href="https://zyvop.com/newsletter" rel="noopener noreferrer"&gt;subscribe to the ZyVOP newsletter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>agenticai</category>
      <category>promptengineering</category>
      <category>claudeopus5</category>
      <category>anthropicapi</category>
    </item>
    <item>
      <title>How Netflix's Architecture Works in 2026: A Developer's Guide</title>
      <dc:creator>Bhavya Arora</dc:creator>
      <pubDate>Mon, 31 Aug 2026 06:45:49 +0000</pubDate>
      <link>https://dev.to/bhavya_arora/how-netflixs-architecture-works-in-2026-a-developers-guide-22ae</link>
      <guid>https://dev.to/bhavya_arora/how-netflixs-architecture-works-in-2026-a-developers-guide-22ae</guid>
      <description>&lt;p&gt;Netflix isn't running the architecture most developers remember.&lt;/p&gt;

&lt;p&gt;The company that became famous for Eureka, Hystrix, Ribbon, Zuul and Titus has spent years replacing, reshaping, or moving responsibilities out of those systems. Today, its publicly described architecture is a combination of EKS, Envoy-based service networking, Open Connect, federated APIs, specialized storage abstractions, modern video codecs, recommendation systems, and increasingly sophisticated AI infrastructure.&lt;/p&gt;

&lt;p&gt;That's what makes Netflix interesting from an engineering perspective. The important story isn't one magical "Netflix stack." It's how the architecture keeps changing when the scale, failure modes, or organizational constraints change.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shape of it
&lt;/h2&gt;

&lt;p&gt;One important distinction gets lost in many simplified diagrams: &lt;strong&gt;Netflix's streaming data plane and application/API plane are separate paths&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Streaming data plane
&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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpFj8FOwzAMhl_F-JwekDj1gDQqTSCBJi3bLguHNHXbaGlcEm9jbHt31IHgaOv7fvs_o-OGsMQ28NH1Ngm8Lk0EAFhvDVbBU5QSVhsFY8-RFNSJj5mSAscxcyCD7788FMXjZQz2VFu3g0Qfe8pyAb3aGtRClHzsQFM6ePdv6dWkwaKabQ0uRopQcYzk5I9YVLNb8sE3xJCpGyhKvsAaFQ6UBusbLM8oPQ1TkYZauw-C6mezscnbOlCemJajzO3gwwlLLOw4BiryKQsNCp6Cj7s36_RtnnMUBQY1dUywfjGoYMk1Cyt4pnAg8c4qmCVvg4JsYy4yJd-iuh3R_mv65f5h_MTrVWHdVRw4YYl3x94L4fUbo-V9Gg" 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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpFj8FOwzAMhl_F-JwekDj1gDQqTSCBJi3bLguHNHXbaGlcEm9jbHt31IHgaOv7fvs_o-OGsMQ28NH1Ngm8Lk0EAFhvDVbBU5QSVhsFY8-RFNSJj5mSAscxcyCD7788FMXjZQz2VFu3g0Qfe8pyAb3aGtRClHzsQFM6ePdv6dWkwaKabQ0uRopQcYzk5I9YVLNb8sE3xJCpGyhKvsAaFQ6UBusbLM8oPQ1TkYZauw-C6mezscnbOlCemJajzO3gwwlLLOw4BiryKQsNCp6Cj7s36_RtnnMUBQY1dUywfjGoYMk1Cyt4pnAg8c4qmCVvg4JsYy4yJd-iuh3R_mv65f5h_MTrVWHdVRw4YYl3x94L4fUbo-V9Gg" alt="Mermaid Diagram" width="795" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Application and control plane
&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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpl0Utv2zAMAOC_wvEsoxiwkw8D3Dy8Igmw1W0u9g6MTNdCZdGT1GRZm_8-yN6yYTtS-viSXlFLy5hjZ-Wke_IRHm4bBwDwWDe4sIZdzOFhr2DsxbGCg5dTYK9AiwtiucGvvzxk2ce34vMdeP72wiGGNyjrBtfcsqfILZSexv7LFm4gqS2d2V-zy5QNy7KqG1zKQMbNHCr2R6M5XOWyrCa7S_T3LYiD1aa6ot1slkUqR5GgOIToSUcj7q9SxaQWaVMKgVzrCW5AYs8eQhTP_9lV3eBqvyDd81XqFIV_e2_qBjfUPaeKfGQXIUTPNPyBm3mPbd3gPWsZBnYtpQmBXAu7LYRziDwloMKB_UCmxfwVY89D-rSWO3qxEdV8sidv6GA5JNOJi2sajD1jjhmNo-Vsrqfg1hr3vCNdTfFaXFSQ3vJJGB7vGlRwLweJouAT2yNHo0lB4Q1ZBYFcyAJ706GamlTmR5rl_YfxO14uCg9PC7HiMcd3p95ExstPtZfC_w" 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%2Fmermaid.ink%2Fimg%2Fpako%3AeNpl0Utv2zAMAOC_wvEsoxiwkw8D3Dy8Igmw1W0u9g6MTNdCZdGT1GRZm_8-yN6yYTtS-viSXlFLy5hjZ-Wke_IRHm4bBwDwWDe4sIZdzOFhr2DsxbGCg5dTYK9AiwtiucGvvzxk2ce34vMdeP72wiGGNyjrBtfcsqfILZSexv7LFm4gqS2d2V-zy5QNy7KqG1zKQMbNHCr2R6M5XOWyrCa7S_T3LYiD1aa6ot1slkUqR5GgOIToSUcj7q9SxaQWaVMKgVzrCW5AYs8eQhTP_9lV3eBqvyDd81XqFIV_e2_qBjfUPaeKfGQXIUTPNPyBm3mPbd3gPWsZBnYtpQmBXAu7LYRziDwloMKB_UCmxfwVY89D-rSWO3qxEdV8sidv6GA5JNOJi2sajD1jjhmNo-Vsrqfg1hr3vCNdTfFaXFSQ3vJJGB7vGlRwLweJouAT2yNHo0lB4Q1ZBYFcyAJ706GamlTmR5rl_YfxO14uCg9PC7HiMcd3p95ExstPtZfC_w" alt="Mermaid Diagram" width="800" height="635"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Both diagrams are intentionally simplified. Netflix runs many individual services and infrastructure components behind each box.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The key point is that pressing &lt;strong&gt;Play&lt;/strong&gt; does not mean your video travels through GraphQL, then through a database, and finally comes back from a microservice. The API/control systems help coordinate the experience; Open Connect handles the actual video delivery path.&lt;/p&gt;




&lt;h2&gt;
  
  
  It started with a broken database
&lt;/h2&gt;

&lt;p&gt;Netflix's cloud journey didn't begin with a grand strategy — it began with a three-day outage.&lt;/p&gt;

&lt;p&gt;In August 2008, a corrupted Oracle database disrupted Netflix's DVD-shipping business for three days. At the time, Netflix was operating a conventional data-center architecture, with a major dependency on vertically scaled relational databases.&lt;/p&gt;

&lt;p&gt;That failure pushed Netflix toward a much bigger bet: move to the public cloud and redesign the application around distributed services.&lt;/p&gt;

&lt;p&gt;The migration began in 2009 and took roughly seven years, completing in January 2016. Netflix did not simply lift its existing application into AWS. It progressively decomposed major parts of the system and rebuilt them around services designed to scale horizontally and tolerate infrastructure failures. &lt;a href="https://about.netflix.com/en/news/completing-the-netflix-cloud-migration?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Netflix: Completing the Cloud Migration&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A second incident, involving AWS infrastructure failures around Christmas 2012, reinforced another lesson: cloud infrastructure itself could fail.&lt;/p&gt;

&lt;p&gt;That forced Netflix to think beyond individual application failures and design for failures involving infrastructure components, availability zones, and eventually entire regions.&lt;/p&gt;

&lt;p&gt;That's the backdrop for much of the resilience and deployment engineering that followed.&lt;/p&gt;




&lt;h2&gt;
  
  
  The famous Netflix OSS stack evolved, rather than simply disappearing
&lt;/h2&gt;

&lt;p&gt;If you've studied microservices patterns, you've probably encountered Netflix's original OSS stack:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eureka&lt;/strong&gt; for service discovery, &lt;strong&gt;Ribbon&lt;/strong&gt; for client-side load balancing, &lt;strong&gt;Hystrix&lt;/strong&gt; for circuit breaking, and &lt;strong&gt;Zuul&lt;/strong&gt; for edge routing.&lt;/p&gt;

&lt;p&gt;These projects were built for a particular moment: a large Java fleet running on AWS, where application-embedded libraries solved networking and resilience problems that the wider cloud ecosystem had not yet standardized.&lt;/p&gt;

&lt;p&gt;Then the architecture evolved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hystrix&lt;/strong&gt; and &lt;strong&gt;Ribbon&lt;/strong&gt; entered maintenance mode. &lt;strong&gt;Zuul 1&lt;/strong&gt; was followed by &lt;strong&gt;Zuul 2&lt;/strong&gt;, which moved toward an asynchronous, non-blocking architecture. Meanwhile, Netflix shifted more service-to-service networking responsibilities into an Envoy-based service-mesh architecture. &lt;a href="https://cloud.spring.io/spring-cloud-netflix/multi/multi__modules_in_maintenance_mode.html?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Spring Cloud Netflix: Modules in Maintenance Mode&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;Eureka should not be grouped with those retired components&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Netflix's service-mesh architecture has continued to use Eureka's service-discovery information as an input to its mesh control plane. Envoy handles networking at the proxy layer; Eureka remains part of the service-discovery story. In other words, Netflix did not simply replace Eureka with Envoy. &lt;a href="https://netflixtechblog.com/zero-configuration-service-mesh-with-on-demand-cluster-discovery-49fbdb211edd?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Netflix: Zero Configuration Service Mesh with On-Demand Cluster Discovery&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The stack, then and now
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concern&lt;/th&gt;
&lt;th&gt;Earlier Netflix approach&lt;/th&gt;
&lt;th&gt;More recent direction&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Service discovery&lt;/td&gt;
&lt;td&gt;Eureka&lt;/td&gt;
&lt;td&gt;Eureka integrated with mesh control-plane systems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Client-side load balancing&lt;/td&gt;
&lt;td&gt;Ribbon&lt;/td&gt;
&lt;td&gt;Envoy / mesh-based networking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Circuit breaking / overload protection&lt;/td&gt;
&lt;td&gt;Hystrix and application logic&lt;/td&gt;
&lt;td&gt;Adaptive concurrency and service-level resilience&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edge routing&lt;/td&gt;
&lt;td&gt;Zuul 1&lt;/td&gt;
&lt;td&gt;Zuul 2 and newer networking layers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service-to-service networking&lt;/td&gt;
&lt;td&gt;Client libraries&lt;/td&gt;
&lt;td&gt;Envoy-based service mesh&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The lesson isn't "don't use Netflix OSS."&lt;/p&gt;

&lt;p&gt;It's that even Netflix treats infrastructure components as &lt;strong&gt;replaceable implementations of longer-lived engineering concerns&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Service discovery stays important. Routing stays important. Fault isolation stays important. Load management stays important.&lt;/p&gt;

&lt;p&gt;The tools can change.&lt;/p&gt;




&lt;h2&gt;
  
  
  Containers: Netflix's 2025 move from Titus to EKS
&lt;/h2&gt;

&lt;p&gt;Netflix built its own container orchestration platform, &lt;strong&gt;Titus&lt;/strong&gt;, rather than adopting early Kubernetes.&lt;/p&gt;

&lt;p&gt;That was a reasonable decision at the time. Titus was built around Netflix's own operational requirements and gave the company deep control over scheduling, EC2 capacity management, networking, and large-scale workloads.&lt;/p&gt;

&lt;p&gt;Titus carried Netflix workloads for years.&lt;/p&gt;

&lt;p&gt;Then, in 2025, Netflix migrated its container fleet to &lt;strong&gt;Amazon EKS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The scale is remarkable. AWS says Netflix now runs fewer than 20 production clusters across four regions, with individual clusters reaching roughly &lt;strong&gt;10,000 large instances and 80,000 pods&lt;/strong&gt;. During peak events, Netflix may need to launch around &lt;strong&gt;70,000 containers in five minutes&lt;/strong&gt;. AWS also says the migration followed about nine months of preparation, with the fleet moved in a single quarter.&lt;/p&gt;

&lt;p&gt;The interesting lesson isn't "Kubernetes won."&lt;/p&gt;

&lt;p&gt;It's that the operational systems Netflix built around Titus — capacity management, disruption budgets, automation, and fleet-wide practices — mattered more than the scheduler underneath them.&lt;/p&gt;

&lt;p&gt;Those practices survived the platform migration.&lt;/p&gt;

&lt;p&gt;That is a useful lesson well beyond Netflix:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Good infrastructure practices should survive a change of infrastructure.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Shipping code without breaking things
&lt;/h2&gt;

&lt;p&gt;Continuous delivery at Netflix runs on &lt;strong&gt;Spinnaker&lt;/strong&gt;, the open-source multi-cloud deployment platform Netflix began developing around 2015 and later developed with Google and the wider community.&lt;/p&gt;

&lt;p&gt;Spinnaker turns a deployment into a controlled pipeline: build an artifact, run required checks, deploy to a limited population, measure the result, and progressively promote the change when its health looks acceptable.&lt;/p&gt;

&lt;p&gt;Netflix has also pushed the idea further with &lt;strong&gt;Managed Delivery&lt;/strong&gt;, where teams express desired deployment state and policy instead of manually assembling every deployment step.&lt;/p&gt;

&lt;p&gt;That fits a larger evolution in infrastructure:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Move from imperative instructions toward declarative intent.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rather than telling a platform exactly how every deployment should happen, teams describe what must be true for a deployment to be considered safe.&lt;/p&gt;

&lt;p&gt;The platform can then work out the path.&lt;/p&gt;




&lt;h2&gt;
  
  
  Making sense of the data
&lt;/h2&gt;

&lt;p&gt;Netflix doesn't run one database — it runs many, behind abstractions designed to keep application teams from having to understand the implementation details of every storage system.&lt;/p&gt;

&lt;p&gt;Netflix has described a &lt;strong&gt;Data Gateway&lt;/strong&gt; approach that exposes purpose-built storage APIs rather than making every application directly dependent on a particular persistence technology.&lt;/p&gt;

&lt;p&gt;Different workloads can therefore use different physical storage systems underneath.&lt;/p&gt;

&lt;p&gt;Those systems have included Cassandra, DynamoDB, RocksDB, Elasticsearch, CockroachDB, and relational databases for workloads where transactional guarantees matter more than extreme horizontal scale.&lt;/p&gt;

&lt;p&gt;The point is not that Netflix found one "best database."&lt;/p&gt;

&lt;p&gt;It did almost the opposite.&lt;/p&gt;

&lt;p&gt;It created ways for teams to use storage according to the workload rather than forcing every service into the same persistence model.&lt;/p&gt;

&lt;p&gt;A simplified conceptual example — &lt;strong&gt;not a Netflix configuration&lt;/strong&gt; — might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user-watch-progress&lt;/span&gt;
&lt;span class="na"&gt;consistency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read-your-writes&lt;/span&gt;
&lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;durable_store&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cassandra&lt;/span&gt;
  &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;evcache&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One recurring pattern is separating durable storage from high-speed caching. &lt;strong&gt;EVCache&lt;/strong&gt;, Netflix's Memcached-based caching layer, can absorb large read volumes while systems such as Cassandra handle durable writes.&lt;/p&gt;

&lt;p&gt;Netflix's Real-Time Distributed Graph shows what this looks like at extreme scale. Netflix has publicly described a graph containing &lt;strong&gt;more than 8 billion nodes and 150 billion edges&lt;/strong&gt;, backed by about a dozen Cassandra clusters and capable of sustaining millions of reads and writes per second.&lt;/p&gt;

&lt;p&gt;The broader lesson is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Scale the hot path independently from the durable path when the workload demands it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  One graph to power many APIs
&lt;/h2&gt;

&lt;p&gt;Netflix's API layer went through its own evolution.&lt;/p&gt;

&lt;p&gt;Earlier in the architecture, client teams — iOS, Android, TV, web and others — could build their own backend-for-frontend logic using &lt;strong&gt;Falcor&lt;/strong&gt;, Netflix's data-fetching technology, behind the edge layer.&lt;/p&gt;

&lt;p&gt;That worked technically, but organizational growth created another problem: different client teams could end up rebuilding similar aggregation logic in slightly different ways.&lt;/p&gt;

&lt;p&gt;Netflix's later &lt;strong&gt;GraphQL Federation&lt;/strong&gt; architecture attacked that problem by allowing backend teams to own domain-specific pieces of a larger graph.&lt;/p&gt;

&lt;p&gt;Individual &lt;strong&gt;Domain Graph Services (DGS)&lt;/strong&gt; can own their piece of the schema, while the federated platform composes those domains into a unified graph that clients can query. &lt;a href="https://netflixtechblog.com/how-netflix-scales-its-api-with-graphql-federation-part-1-ae3557c187e2?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Netflix: How Netflix Scales Its API with GraphQL Federation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The important benefit isn't simply "GraphQL instead of REST."&lt;/p&gt;

&lt;p&gt;It's organizational:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Teams can own their slice of the API while clients still see one coherent interface.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That becomes increasingly valuable when the organization, not just the traffic volume, becomes the scaling problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting the bits to your screen
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Open Connect&lt;/strong&gt; is Netflix's purpose-built content-delivery network, and it works differently from a conventional centralized CDN.&lt;/p&gt;

&lt;p&gt;Netflix places servers close to viewers, including directly inside ISP networks, so popular content can be served locally instead of repeatedly traveling across long-distance network paths.&lt;/p&gt;

&lt;p&gt;Netflix has publicly described Open Connect at a scale of roughly &lt;strong&gt;18,000 servers across 6,000 locations in 175 countries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Those figures matter because they are often misstated as "6,000 appliances." The publicly reported numbers are &lt;strong&gt;servers and locations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The playback flow is intentionally simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A client requests playback.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;Steering Service&lt;/strong&gt; determines an appropriate delivery location.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The client streams video segments from Open Connect.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The more interesting part is what happens when central connectivity fails.&lt;/p&gt;

&lt;p&gt;Netflix has designed Open Connect so that the control plane and data plane can fail somewhat independently. An appliance that loses contact with central Netflix systems can continue serving content it already has rather than becoming immediately useless.&lt;/p&gt;

&lt;p&gt;That's a powerful resilience principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;When the control plane disappears, the data plane should continue doing useful work whenever possible.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Netflix has also described Open Connect as helping avoid sending every byte of streaming traffic through its own cloud infrastructure.&lt;/p&gt;




&lt;h2&gt;
  
  
  Squeezing more picture into fewer bits
&lt;/h2&gt;

&lt;p&gt;Encoding is where a large part of Netflix's infrastructure investment quietly turns into lower bandwidth requirements and better playback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-title encoding&lt;/strong&gt; stopped treating every movie and episode as though it needed the same bitrate ladder. A dialogue-heavy drama, a dark film, and a fast-moving action sequence can have very different compression characteristics.&lt;/p&gt;

&lt;p&gt;Netflix's subsequent encoding research reported substantial bitrate reductions from content-aware encoding approaches, including later improvements that reduced average bitrate by more than 20% in tested pipelines while maintaining comparable perceived quality.&lt;/p&gt;

&lt;p&gt;The current frontier is &lt;strong&gt;AV1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By late 2025, Netflix reported that AV1 represented roughly &lt;strong&gt;30% of all Netflix viewing&lt;/strong&gt;, making it the company's second-most-used codec and putting it on track to become number one. &lt;a href="https://netflixtechblog.com/av1-now-powering-30-of-netflix-streaming-02f592242d80?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Netflix: AV1 Now Powering 30% of Netflix Streaming&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One particularly interesting development is &lt;strong&gt;Film Grain Synthesis&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Film grain is expensive to encode because it behaves a lot like noise: tiny variations appear throughout the image and are difficult to compress efficiently.&lt;/p&gt;

&lt;p&gt;Instead of encoding all of that grain literally, Netflix can remove much of it before encoding and send information that allows the decoder to reconstruct a convincing approximation.&lt;/p&gt;

&lt;p&gt;The savings can be dramatic on the right content.&lt;/p&gt;

&lt;p&gt;In one Netflix example involving heavily grainy footage, Film Grain Synthesis reduced bitrate from roughly &lt;strong&gt;8.3 Mbps to 2.8 Mbps&lt;/strong&gt;, about a &lt;strong&gt;66% reduction&lt;/strong&gt;, while producing better-looking grain than the conventional AV1 encode.&lt;/p&gt;

&lt;p&gt;That should be understood as a &lt;strong&gt;specific example&lt;/strong&gt;, not a universal 66% saving across Netflix's catalog.&lt;/p&gt;

&lt;p&gt;Netflix also uses &lt;strong&gt;VMAF&lt;/strong&gt;, its perceptual video-quality metric, to evaluate whether lower bitrate still produces acceptable visual quality.&lt;/p&gt;

&lt;p&gt;That's an important distinction.&lt;/p&gt;

&lt;p&gt;A smaller file is only an improvement if the viewer can't tell that quality was lost.&lt;/p&gt;




&lt;h2&gt;
  
  
  Breaking things on purpose
&lt;/h2&gt;

&lt;p&gt;Netflix popularized &lt;strong&gt;chaos engineering&lt;/strong&gt; with &lt;strong&gt;Chaos Monkey&lt;/strong&gt; in 2010.&lt;/p&gt;

&lt;p&gt;The idea was deliberately uncomfortable: randomly terminate production instances during normal operation so engineers would discover weak assumptions before a real infrastructure failure exposed them.&lt;/p&gt;

&lt;p&gt;The philosophy changes the question from:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What happens if this server dies?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Have we proved that our system can survive when this dependency disappears?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Netflix later extended the idea with &lt;strong&gt;Chaos Kong&lt;/strong&gt;, which tested failure scenarios involving entire AWS regions.&lt;/p&gt;

&lt;p&gt;The resilience discipline has also expanded beyond chaos experiments.&lt;/p&gt;

&lt;p&gt;More recent Netflix reliability work emphasizes &lt;strong&gt;prioritized load shedding&lt;/strong&gt;: when traffic threatens to overwhelm a service, lower-value requests should be rejected or delayed before higher-value requests are harmed.&lt;/p&gt;

&lt;p&gt;A background synchronization job and a request to start playback do not have equal business value.&lt;/p&gt;

&lt;p&gt;A resilient system should know that.&lt;/p&gt;




&lt;h2&gt;
  
  
  The stress test: live sports and events
&lt;/h2&gt;

&lt;p&gt;Nothing exposes architecture gaps like a live event with a hard start time and no opportunity to spread the load gradually.&lt;/p&gt;

&lt;p&gt;In November 2024, Netflix's live exhibition boxing match between Mike Tyson and Jake Paul attracted an estimated &lt;strong&gt;108 million live global viewers&lt;/strong&gt; and peaked at &lt;strong&gt;65 million concurrent streams&lt;/strong&gt;. The event also generated substantial public complaints about buffering and interruptions.&lt;/p&gt;

&lt;p&gt;The event mattered because live streaming behaves differently from on-demand playback.&lt;/p&gt;

&lt;p&gt;Millions of people can suddenly request content at roughly the same time.&lt;/p&gt;

&lt;p&gt;Netflix's later NFL broadcasts provided another major test. By Christmas 2025, the Lions-Vikings game averaged &lt;strong&gt;27.5 million U.S. viewers&lt;/strong&gt;, peaked above 30 million during the halftime show, and reached a &lt;strong&gt;30.5 million global average minute audience&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Netflix has also described improvements to its live-video origin architecture, including separation of read-heavy and write-heavy paths and &lt;strong&gt;priority-based rate limiting&lt;/strong&gt; so lower-priority work does not crowd out traffic needed for real-time playback.&lt;/p&gt;

&lt;p&gt;That pattern is bigger than sports:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;When workloads compete, protect the requests that matter most instead of treating every request equally.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Teaching the algorithm
&lt;/h2&gt;

&lt;p&gt;Netflix's personalization architecture has also evolved from collections of narrowly focused models toward more unified approaches.&lt;/p&gt;

&lt;p&gt;Different recommendation surfaces historically relied on specialized models. One system could rank a homepage row while another ranked search results or helped determine when to send a notification.&lt;/p&gt;

&lt;p&gt;More recent Netflix research has described &lt;strong&gt;Hydra&lt;/strong&gt;, a multi-task learning approach that consolidates related personalization and ranking objectives around shared representations instead of maintaining every task as a completely isolated model.&lt;/p&gt;

&lt;p&gt;That does &lt;strong&gt;not&lt;/strong&gt; mean Netflix replaced every recommendation system with one giant model.&lt;/p&gt;

&lt;p&gt;The useful architectural lesson is narrower:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Share learned representations and infrastructure when multiple ML tasks are solving closely related problems.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The benefit is not just model quality. It can also reduce the operational cost of training, deploying, and maintaining many separate systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Serving AI models in production
&lt;/h2&gt;

&lt;p&gt;Serving AI models at Netflix's scale requires infrastructure of its own.&lt;/p&gt;

&lt;p&gt;Netflix's AI infrastructure work initially evaluated and used &lt;strong&gt;TensorRT-LLM&lt;/strong&gt; together with &lt;strong&gt;Triton&lt;/strong&gt;. As workloads expanded beyond straightforward text generation to include ranking, retrieval, and embedding workloads, Netflix benchmarked alternative serving systems and moved toward &lt;strong&gt;vLLM&lt;/strong&gt; as a default inference engine for its paved-path serving architecture.&lt;/p&gt;

&lt;p&gt;That's another useful Netflix pattern.&lt;/p&gt;

&lt;p&gt;The company is famous for building its own infrastructure, but it doesn't build everything merely for the sake of ownership.&lt;/p&gt;

&lt;p&gt;When an open-source project becomes capable enough to satisfy the workload, adopting it can be the better engineering choice.&lt;/p&gt;

&lt;p&gt;Sometimes the best infrastructure decision is not to build another internal platform.&lt;/p&gt;




&lt;h2&gt;
  
  
  What developers can actually steal from Netflix
&lt;/h2&gt;

&lt;p&gt;Most teams will never operate at Netflix's scale, and copying Netflix's exact tools would be a mistake.&lt;/p&gt;

&lt;p&gt;Titus and Open Connect exist because of constraints most companies simply don't have.&lt;/p&gt;

&lt;p&gt;The patterns underneath them travel much better than the products themselves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools are disposable; the problems they solve aren't.
&lt;/h3&gt;

&lt;p&gt;Netflix has changed its implementation of service discovery, routing, resilience, and scheduling without abandoning those underlying concerns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Separate read and write paths when they need to scale independently.
&lt;/h3&gt;

&lt;p&gt;EVCache and Cassandra are one example of a broader principle: don't force radically different workloads through the same bottleneck.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decouple control planes from data planes where failure is expensive.
&lt;/h3&gt;

&lt;p&gt;Open Connect can continue serving cached content even when central control connectivity is impaired.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practice failure before it practices on you.
&lt;/h3&gt;

&lt;p&gt;Chaos engineering turns catastrophic surprises into rehearsed scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boring technology is still the right call somewhere.
&lt;/h3&gt;

&lt;p&gt;A transactional workload doesn't become better simply because its database sounds more sophisticated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Give teams ownership of their API domains.
&lt;/h3&gt;

&lt;p&gt;Federated GraphQL is valuable not because GraphQL is magical, but because API ownership can scale with the organization instead of funneling every change through one central team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Protect high-value traffic first.
&lt;/h3&gt;

&lt;p&gt;Prioritized load shedding is useful anywhere a sudden traffic spike can turn "everything is slow" into "everything is down."&lt;/p&gt;




&lt;h2&gt;
  
  
  The architecture keeps changing
&lt;/h2&gt;

&lt;p&gt;If you remember one thing about Netflix's architecture, make it this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is no single timeless "Netflix stack."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The company moved from a conventional data center to AWS, from a monolithic system toward distributed services, from application-embedded resilience libraries toward service-mesh infrastructure, from Titus to EKS, from conventional content delivery toward a deeply distributed Open Connect network, and from collections of specialized ML systems toward increasingly shared AI infrastructure.&lt;/p&gt;

&lt;p&gt;The individual technologies will keep changing.&lt;/p&gt;

&lt;p&gt;The engineering constraints won't:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;scale, failure, latency, organizational ownership, and cost.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's the part worth copying.&lt;/p&gt;




&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://netflixtechblog.com/" rel="noopener noreferrer"&gt;Netflix Technology Blog&lt;/a&gt; — the primary source for Netflix's engineering work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://about.netflix.com/en/news/completing-the-netflix-cloud-migration" rel="noopener noreferrer"&gt;Completing the Netflix Cloud Migration&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://netflixtechblog.com/zero-configuration-service-mesh-with-on-demand-cluster-discovery-49fbdb211edd" rel="noopener noreferrer"&gt;Zero Configuration Service Mesh with On-Demand Cluster Discovery&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://netflixtechblog.com/how-netflix-scales-its-api-with-graphql-federation-part-1-ae3557c187e2" rel="noopener noreferrer"&gt;How Netflix Scales Its API with GraphQL Federation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://netflixtechblog.medium.com/how-and-why-netflix-built-a-real-time-distributed-graph-part-2-building-a-scalable-storage-layer-ff4a8dbd3d1f" rel="noopener noreferrer"&gt;Real-Time Distributed Graph&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://netflixtechblog.com/av1-now-powering-30-of-netflix-streaming-02f592242d80" rel="noopener noreferrer"&gt;AV1 — Now Powering 30% of Netflix Streaming&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://netflixtechblog.com/in-house-llm-serving-at-netflix-a5a8e799ea2c" rel="noopener noreferrer"&gt;In-House LLM Serving at Netflix&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://netflixtechblog.com/netflix-live-origin-41f1b0ad5371" rel="noopener noreferrer"&gt;Netflix Live Origin&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://repost.aws/articles/ARpqKdaLinSJqT4dTbRn7WUg/aws-re-invent-2025-the-future-of-kubernetes-on-aws" rel="noopener noreferrer"&gt;AWS re:Invent 2025 — The Future of Kubernetes on AWS&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This post draws on Netflix's public engineering blog, company publications, AWS material, and reporting that covers those sources. It is not an official Netflix publication. Infrastructure figures are snapshots of publicly reported systems and can change over time.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://zyvop.com/how-netflix-s-architecture-works-in-2026-a-developer-s-guide-jluo9" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡 For more articles like this, &lt;a href="https://zyvop.com/newsletter" rel="noopener noreferrer"&gt;subscribe to the ZyVOP newsletter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>distributedsystems</category>
      <category>microservices</category>
      <category>kubernetes</category>
      <category>cloudarchitecture</category>
    </item>
    <item>
      <title>AirLLM: Running Giant AI Models on Everyday Hardware</title>
      <dc:creator>Bhavya Arora</dc:creator>
      <pubDate>Thu, 27 Aug 2026 12:49:40 +0000</pubDate>
      <link>https://dev.to/bhavya_arora/airllm-running-giant-ai-models-on-everyday-hardware-2dkf</link>
      <guid>https://dev.to/bhavya_arora/airllm-running-giant-ai-models-on-everyday-hardware-2dkf</guid>
      <description>&lt;h2&gt;
  
  
  The Problem Nobody Wanted to Talk About
&lt;/h2&gt;

&lt;p&gt;For most of the past few years, the conversation around large language models has been dominated by capability benchmarks and API releases. What got less attention was a growing divide: the gap between what the models could do and who could actually run them.&lt;/p&gt;

&lt;p&gt;Models like LLaMA 3 70B or DeepSeek-V3 demand enormous amounts of GPU memory — often 140GB or more of VRAM at full precision. The most powerful consumer GPU on the market, NVIDIA's RTX 4090, ships with just 24GB. Most developers have 4GB, 8GB, or 16GB setups. For anyone outside a well-funded research lab or a cloud-compute budget, experimenting with frontier open-source models was simply off the table.&lt;/p&gt;

&lt;p&gt;AirLLM changes that.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is AirLLM?
&lt;/h2&gt;

&lt;p&gt;AirLLM is an open-source Python library — built by developer Gavin Li (lyogavin) — that lets you run extremely large language models on consumer-grade hardware with very limited GPU memory. We're talking 70B parameter models on a single 4GB GPU. 405B parameter models on 8GB VRAM. And as of mid-2026, even Kimi K3 (a 2.8 trillion parameter sparse MoE model, the largest open-source model released to date) on under 4GB of VRAM.&lt;/p&gt;

&lt;p&gt;No quantization tricks required (though optional compression is available). No accuracy loss from model distillation. No need for a multi-GPU server.&lt;/p&gt;

&lt;p&gt;First released in November 2023, AirLLM has rapidly gathered community momentum, crossing 21,000+ GitHub stars and expanding support to include some of the most widely used open model families.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Idea: Layer-by-Layer Inference
&lt;/h2&gt;

&lt;p&gt;The innovation at AirLLM's heart is elegantly simple: instead of loading an entire model into GPU memory at once, it processes the model &lt;strong&gt;one transformer layer at a time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's what that looks like under the hood:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;AirLLM loads the first transformer layer from disk (or system RAM) into VRAM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It runs the forward computation for that layer on the input tensor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It offloads that layer from VRAM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It loads the next layer and repeats until the full forward pass is complete.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The final output — a probability distribution over the vocabulary — yields the next token.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From the user's perspective, the output is &lt;strong&gt;identical&lt;/strong&gt; to what you'd get from a fully loaded model. The model's weights are never modified, so there's no accuracy compromise baked into the architecture itself.&lt;/p&gt;

&lt;p&gt;The technique isn't brand new — sequential layer offloading has appeared in academic research before — but AirLLM made it practical, packaged it cleanly, and put it in the hands of everyday developers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Layer-Wise Streaming Execution&lt;/strong&gt; — The foundational innovation. Only one layer occupies VRAM at any given moment, making enormous models accessible on minimal hardware.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optional Block-Wise Quantization&lt;/strong&gt; — AirLLM v2.0 introduced compression based on block-wise quantization of weights (not activations, which is an important distinction). This can deliver up to a 3x inference speedup with minimal accuracy loss. A 70B model's layer shards drop from ~140GB to ~18GB with 4-bit compression. You can enable it with a single parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta-llama/Llama-3-70B-Instruct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;compression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;4bit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;  &lt;span class="c1"&gt;# or '8bit'
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prefetching&lt;/strong&gt; — Added in v2.5, this overlaps model loading and computation, squeezing out an additional ~10% speed improvement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AutoModel API&lt;/strong&gt; — Since v2.6, AirLLM can automatically detect the model type without you specifying a class manually. It integrates directly with Hugging Face Hub — &lt;code&gt;AutoModel.from_pretrained()&lt;/code&gt; handles weight downloading, layer partitioning, and memory orchestration automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Apple Silicon Support&lt;/strong&gt; — AirLLM supports Apple's M-series chips via the MLX framework. Because M-series chips use unified memory shared between CPU and GPU, MacBook Pro and Mac Studio users can potentially run very large models without hitting the traditional VRAM ceiling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CPU Inference&lt;/strong&gt; — Since August 2024, any x86_64 CPU is a valid inference target. Slower, yes — but useful for environments without a GPU.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FP8 Support (v3.0)&lt;/strong&gt; — June 2026 brought v3.0 with FP8 model precision support, enabling even more efficient inference alongside expanded support for the latest generation of models.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MoE Expert-Level Streaming&lt;/strong&gt; — For sparse mixture-of-experts models like DeepSeek-V3 and Kimi K3, AirLLM streams individual experts rather than whole layers, meaning only the experts a given token actually routes to are ever loaded.&lt;/p&gt;




&lt;h2&gt;
  
  
  Supported Models
&lt;/h2&gt;

&lt;p&gt;AirLLM supports a broad range of decoder-only models via Hugging Face compatibility. The current list includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;LLaMA family&lt;/strong&gt; (LLaMA 2, 3, 3.1, 3.3, and 4 — including the 405B variant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mistral&lt;/strong&gt; and &lt;strong&gt;Mixtral&lt;/strong&gt; (via AirLLMMixtral)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Qwen&lt;/strong&gt;, &lt;strong&gt;Qwen 2.5&lt;/strong&gt;, and &lt;strong&gt;Qwen3&lt;/strong&gt; (including Qwen3-235B, runnable on ~3GB VRAM)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DeepSeek&lt;/strong&gt; (V2, V3 at 671B on ~12GB VRAM, and R1)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Kimi K3&lt;/strong&gt; (2.8T sparse MoE, on ~3.72GB VRAM)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Phi&lt;/strong&gt; (including Phi-4)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gemma&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ChatGLM&lt;/strong&gt;, &lt;strong&gt;Baichuan&lt;/strong&gt;, &lt;strong&gt;InternLM&lt;/strong&gt;, &lt;strong&gt;Yi&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Support has expanded significantly since launch. As of v3.1.0, the library is generally compatible with virtually any popular model on Hugging Face — just pass the repo ID to &lt;code&gt;AutoModel.from_pretrained()&lt;/code&gt;. Here's a rough guide to VRAM requirements:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;VRAM needed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3 / Mistral / Phi (~8B)&lt;/td&gt;
&lt;td&gt;8B&lt;/td&gt;
&lt;td&gt;~1–2 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3-30B / Mixtral (MoE)&lt;/td&gt;
&lt;td&gt;30–47B&lt;/td&gt;
&lt;td&gt;~1–3 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3-235B (MoE)&lt;/td&gt;
&lt;td&gt;235B&lt;/td&gt;
&lt;td&gt;~3 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLaMA 3.x 70B (full precision)&lt;/td&gt;
&lt;td&gt;70B&lt;/td&gt;
&lt;td&gt;~4 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLaMA 3.1 405B&lt;/td&gt;
&lt;td&gt;405B&lt;/td&gt;
&lt;td&gt;~8 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek-V3&lt;/td&gt;
&lt;td&gt;671B&lt;/td&gt;
&lt;td&gt;~12 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kimi K3 (MoE)&lt;/td&gt;
&lt;td&gt;2.8T&lt;/td&gt;
&lt;td&gt;~3.72 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Installation is a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;airllm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A minimal working example looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;airllm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AutoModel&lt;/span&gt;

&lt;span class="c1"&gt;# Load a 70B model — AirLLM handles everything else
&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta-llama/Meta-Llama-3-70B-Instruct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Use the standard Hugging Face tokenizer
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AutoTokenizer&lt;/span&gt;
&lt;span class="n"&gt;tokenizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoTokenizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta-llama/Meta-Llama-3-70B-Instruct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Tokenize and generate
&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Explain quantum entanglement simply:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;return_tensors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_new_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No custom CUDA kernels. No manual memory management. If the model is on Hugging Face, AirLLM downloads and partitions it automatically.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: Gated models require a Hugging Face token via the&lt;/em&gt; &lt;code&gt;hf_token&lt;/code&gt; &lt;em&gt;parameter.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Trade-Off: Speed
&lt;/h2&gt;

&lt;p&gt;It wouldn't be honest to write about AirLLM without being direct about this: &lt;strong&gt;token generation is slow&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Each layer transfer from disk to VRAM introduces I/O overhead. The speed depends heavily on your storage medium — an NVMe SSD will dramatically outperform a mechanical hard drive — but even under ideal conditions, AirLLM is not competing with optimized inference servers on throughput. It is not the right tool if you need a low-latency chatbot serving many users, or a high-frequency production API.&lt;/p&gt;

&lt;p&gt;This is a deliberate trade-off: accessibility over speed. If that trade-off works for your use case, AirLLM is genuinely powerful.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who Should Use AirLLM?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Researchers on a hardware budget&lt;/strong&gt; — If you want to probe the internals of a 65B-parameter model on a single consumer GPU without buying enterprise hardware, this is probably the most practical path available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy-conscious teams&lt;/strong&gt; — Document analysis pipelines where sending text to a third-party API is off the table due to compliance or data sensitivity. Running locally means your data stays local.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learners and hobbyists&lt;/strong&gt; — If you're trying to understand how large transformer architectures behave, AirLLM lets you run and experiment with models you'd otherwise never touch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Offline evaluation and benchmarking&lt;/strong&gt; — Comparing model outputs across architectures without spinning up cloud infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who probably shouldn't use it&lt;/strong&gt; — If you're building a real-time user-facing application, or a service that needs to handle concurrent requests with low latency, tools like vLLM, TensorRT-LLM, or llama.cpp are better choices. AirLLM doesn't compete with them on throughput.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why It Matters Beyond the Technical Details
&lt;/h2&gt;

&lt;p&gt;There's a broader point here worth sitting with.&lt;/p&gt;

&lt;p&gt;The AI landscape has increasingly consolidated around a small number of organizations with enormous GPU clusters. Access to frontier models — even open-weight ones — has often been gated by the hardware required to run them. That reality shapes who gets to experiment, who gets to learn, and ultimately who gets to build.&lt;/p&gt;

&lt;p&gt;AirLLM doesn't close that gap entirely. But it meaningfully shifts the boundary. A developer with a mid-range laptop can now load and query a 70B parameter model locally. A small research team without a cloud budget can benchmark model behavior on hardware they already own. A company with strict data residency requirements can run local inference without a six-figure GPU investment.&lt;/p&gt;

&lt;p&gt;That kind of democratization is quiet, unglamorous, and genuinely important.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Road So Far (A Brief Timeline)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Milestone&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;November 2023&lt;/td&gt;
&lt;td&gt;Initial release — 70B inference on a 4GB GPU via layer streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;December 2, 2023&lt;/td&gt;
&lt;td&gt;v2.0 — Block-wise quantization, 3x speedup; ChatGLM, Qwen, Baichuan, Mistral, InternLM support added&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;December 2023&lt;/td&gt;
&lt;td&gt;v2.5 — Prefetching for 10% additional speed; v2.6 — AutoModel API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;December 25, 2023&lt;/td&gt;
&lt;td&gt;v2.8.2 — MacOS support for Apple Silicon (M1/M2/M3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;April 2024&lt;/td&gt;
&lt;td&gt;LLaMA 3 support — run LLaMA 3 70B on a single 4GB GPU&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;July 2024&lt;/td&gt;
&lt;td&gt;LLaMA 3.1 405B support; optional 4-bit/8-bit quantization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;August 18, 2024&lt;/td&gt;
&lt;td&gt;v2.10.1 — CPU inference support (any x86_64 CPU)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;September 21, 2024&lt;/td&gt;
&lt;td&gt;v2.11.0 — Qwen 2.5 support added&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;June 30, 2026&lt;/td&gt;
&lt;td&gt;v3.0 — FP8 model support; DeepSeek-V3 (671B) on ~12GB, Qwen3-235B on ~3GB; Llama 3.3/4, Phi-4, DeepSeek R1/V2/V3 added&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;July 29, 2026&lt;/td&gt;
&lt;td&gt;v3.1.0 — Kimi K3 (2.8T) support; runs on 3.72GB VRAM — largest open-source model to date&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;AirLLM is not magic. It doesn't make a 70B model run as fast as a dedicated inference server. What it does do is remove the barrier that said "you need $50,000 of hardware before you can even start."&lt;/p&gt;

&lt;p&gt;For researchers, learners, privacy-first teams, and curious developers, that removal is significant. In a field where the hardware gap often determines who gets to participate, tools like AirLLM represent a small but meaningful push toward a more accessible AI ecosystem.&lt;/p&gt;

&lt;p&gt;If you've been waiting for the right moment to run a large open-source model locally — this might be it.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GitHub: &lt;a href="https://github.com/lyogavin/airllm" rel="noopener noreferrer"&gt;https://github.com/lyogavin/airllm&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PyPI: &lt;a href="https://pypi.org/project/airllm/" rel="noopener noreferrer"&gt;https://pypi.org/project/airllm/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hugging Face: search for models compatible with AirLLM directly on the Hub&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://zyvop.com/airllm-running-giant-ai-models-on-everyday-hardware-uhfo3" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡 For more articles like this, &lt;a href="https://zyvop.com/newsletter" rel="noopener noreferrer"&gt;subscribe to the ZyVOP newsletter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>localai</category>
      <category>opensource</category>
      <category>llm</category>
      <category>airllm</category>
    </item>
    <item>
      <title>Stop Using useEffect for Data Fetching: A Modern React Architecture Guide</title>
      <dc:creator>Bhavya Arora</dc:creator>
      <pubDate>Wed, 26 Aug 2026 10:19:58 +0000</pubDate>
      <link>https://dev.to/bhavya_arora/stop-using-useeffect-for-data-fetching-a-modern-react-architecture-guide-n50</link>
      <guid>https://dev.to/bhavya_arora/stop-using-useeffect-for-data-fetching-a-modern-react-architecture-guide-n50</guid>
      <description>&lt;p&gt;If you review a React codebase written a few years ago, you will inevitably find components littered with code that looks exactly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isMounted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isMounted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isMounted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isMounted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Spinner&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorMessage&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how we were all taught to write React. It feels intuitive. You mount a component, trigger a side-effect to get data, and save it to state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In 2024, this is universally considered an anti-pattern.&lt;/strong&gt; The React core team actively advises against doing this.&lt;/p&gt;

&lt;p&gt;Let's dissect exactly why this approach is fundamentally flawed, and how modern query libraries solve these problems elegantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Four Fatal Flaws of &lt;code&gt;useEffect&lt;/code&gt; Fetching
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The Race Condition Nightmare
&lt;/h3&gt;

&lt;p&gt;Imagine the user clicks "Profile A", and your &lt;code&gt;useEffect&lt;/code&gt; fires a network request. It's taking a while. Impatient, the user clicks "Profile B". A second request fires.&lt;/p&gt;

&lt;p&gt;If the server processes Profile B quickly, it returns first. The UI updates to Profile B. Then, the slow request for Profile A finally returns. The &lt;code&gt;setState&lt;/code&gt; triggers, and the UI visually reverts to Profile A, even though the user is currently "looking" at Profile B!&lt;/p&gt;

&lt;p&gt;You can fix this with &lt;code&gt;isMounted&lt;/code&gt; boolean tracking flags or &lt;code&gt;AbortController&lt;/code&gt;, but you are now writing complex async state machines manually.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Strict Mode "Double Fetch"
&lt;/h3&gt;

&lt;p&gt;If you upgrade to React 18, React's Strict Mode aggressively mounts, unmounts, and remounts your components in development to expose bugs. This means your &lt;code&gt;useEffect&lt;/code&gt; fires &lt;em&gt;twice&lt;/em&gt;, hammering your API backend and flooding your network tab.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Cache Misses and Waterfall Loading
&lt;/h3&gt;

&lt;p&gt;When a user navigates from the Dashboard to the Settings page, the Dashboard unmounts. The &lt;code&gt;data&lt;/code&gt; state is destroyed. When they navigate back 3 seconds later, the &lt;code&gt;useEffect&lt;/code&gt; runs again. The user stares at a loading spinner for data they literally just saw.&lt;/p&gt;

&lt;p&gt;Worse, if &lt;code&gt;ParentComponent&lt;/code&gt; fetches a User, and &lt;code&gt;ChildComponent&lt;/code&gt; fetches the User's Posts, they execute sequentially. The Child waits for the Parent to finish before it even &lt;em&gt;starts&lt;/em&gt; fetching. This is the dreaded "Network Waterfall."&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Boilerplate Hell
&lt;/h3&gt;

&lt;p&gt;Tracking &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;isLoading&lt;/code&gt;, and &lt;code&gt;error&lt;/code&gt; variables requires dozens of lines of code. Multiply that across 50 components, and your codebase is drowning in repetitive state management.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: Specialized Query Libraries
&lt;/h2&gt;

&lt;p&gt;Data fetching is a complex engineering problem involving caching, background revalidation, stale-time policies, and retry logic. You should not write this yourself.&lt;/p&gt;

&lt;p&gt;The industry standard is to use a specialized library: &lt;strong&gt;TanStack Query (React Query)&lt;/strong&gt; for REST APIs, or &lt;strong&gt;Apollo Client&lt;/strong&gt; for GraphQL.&lt;/p&gt;

&lt;p&gt;Here is the exact same component rewritten with Apollo Client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@apollo/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GET_USER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  query GetUser($userId: ID!) {
    user(id: $userId) {
      id
      name
    }
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GET_USER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Spinner&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorMessage&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is beautiful, concise, and eliminates 90% of the boilerplate. But the real power is under the hood.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why this architecture is vastly superior:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Instant Cache Retrieval
&lt;/h4&gt;

&lt;p&gt;Apollo Client and TanStack Query maintain a normalized, global memory cache. If you navigate away from the Dashboard and return, the library instantly serves the data from memory. There is &lt;strong&gt;zero loading spinner&lt;/strong&gt;. It then silently triggers a background network request (stale-while-revalidate) and updates the UI if the data changed.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Automatic Race Condition Resolution
&lt;/h4&gt;

&lt;p&gt;If &lt;code&gt;userId&lt;/code&gt; changes rapidly, the library tracks the request IDs. It mathematically guarantees that only the data belonging to the &lt;em&gt;latest&lt;/em&gt; request will ever be passed to the component, completely eliminating async race conditions.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Global State Synchronization
&lt;/h4&gt;

&lt;p&gt;Because the cache is centralized, you don't need Redux or Context to share data.&lt;/p&gt;

&lt;p&gt;If your &lt;code&gt;Navbar&lt;/code&gt; component queries the user's name, and your &lt;code&gt;ProfileSettings&lt;/code&gt; component executes a mutation to change that name, the cache updates instantly. The &lt;code&gt;Navbar&lt;/code&gt; automatically re-renders with the new name without you writing a single line of state synchronization code.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Automatic Retries and Deduplication
&lt;/h4&gt;

&lt;p&gt;If the user's internet drops while on a train, the query will automatically retry 3 times with exponential backoff before throwing an error. Furthermore, if three different components on the screen all call &lt;code&gt;useQuery(GET_USER)&lt;/code&gt;, the library deduplicates them and only sends &lt;strong&gt;one&lt;/strong&gt; network request to your server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; was designed to synchronize React components with external systems (like attaching a DOM event listener or connecting to a WebSocket). It is a low-level primitive, not a data-fetching solution.&lt;/p&gt;

&lt;p&gt;By adopting a robust Query library, you delete hundreds of lines of boilerplate, vastly improve the user experience with instant caching, and permanently eliminate the most common async bugs in React development.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://zyvop.com/stop-using-useeffect-for-data-fetching-a-modern-react-architecture-guide-h5x7u" rel="noopener noreferrer"&gt;ZyVOP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡 For more articles like this, &lt;a href="https://zyvop.com/newsletter" rel="noopener noreferrer"&gt;subscribe to the ZyVOP newsletter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>tanstackquery</category>
    </item>
  </channel>
</rss>
