<?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: Tyson Cung</title>
    <description>The latest articles on DEV Community by Tyson Cung (@tyson_cung).</description>
    <link>https://dev.to/tyson_cung</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2787666%2Fdd365f5a-f7fd-4e3f-9d3f-404eeb4ca1a2.jpg</url>
      <title>DEV Community: Tyson Cung</title>
      <link>https://dev.to/tyson_cung</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tyson_cung"/>
    <language>en</language>
    <item>
      <title>Claude Opus 4.8: Effort Control Changes How You Work With AI</title>
      <dc:creator>Tyson Cung</dc:creator>
      <pubDate>Fri, 29 May 2026 06:07:28 +0000</pubDate>
      <link>https://dev.to/tyson_cung/claude-opus-48-effort-control-changes-how-you-work-with-ai-1e68</link>
      <guid>https://dev.to/tyson_cung/claude-opus-48-effort-control-changes-how-you-work-with-ai-1e68</guid>
      <description>&lt;p&gt;Anthropic released Claude Opus 4.8 yesterday, and it ships with something developers have wanted since GPT-3: a knob that controls how hard the model thinks. Not a prompt engineering trick. Not "think step by step." An actual slider that dials compute up or down depending on what the task needs.&lt;/p&gt;

&lt;p&gt;Alongside this, they announced a $65 billion Series H at a $965 billion valuation. Big numbers, but the interesting part is what the model can actually do.&lt;/p&gt;

&lt;p&gt;Let me walk through the three features that change how you work with AI, and why they matter for everyday development.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Effort Slider Is Bigger Than It Sounds
&lt;/h2&gt;

&lt;p&gt;Every developer has been here: you ask an LLM to review a PR, and it spots a missing semicolon but misses the race condition three lines up. Or you ask it to rename a variable, and it spends 30 seconds "thinking" about it.&lt;/p&gt;

&lt;p&gt;The problem is that current models apply roughly the same compute to every request. Claude Opus 4.8 lets you decide.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Low effort     → Quick reviews, refactoring, boilerplate
Medium effort  → Architecture decisions, debugging, data analysis
High effort    → Complex multi-file changes, security audits, system design
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdlm5cdi4shsj93kr1x45.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdlm5cdi4shsj93kr1x45.png" alt="Claude Opus 4.8 Effort Control - three levels of compute allocation" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This isn't just a UI gimmick. It changes the economics of using AI for development. Instead of paying for maximum compute on trivial tasks, you match compute to complexity and save money on the 80% of requests that don't need deep reasoning.&lt;/p&gt;

&lt;p&gt;Cursor's CEO Michael Truell said Opus 4.8 "exceeds prior Opus models across every effort level" and that "tool calling is meaningfully more efficient, using fewer steps for the same intelligence."&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Code Gets "Dynamic Workflows"
&lt;/h2&gt;

&lt;p&gt;If you use Claude Code (or any AI coding agent), you know the pattern: it works great on a single file or small feature, but falls apart on large-scale changes that span dozens of files and services.&lt;/p&gt;

&lt;p&gt;Dynamic workflows are Anthropic's answer to this. Instead of a single linear chain of reasoning, Claude can now decompose large problems, work on sub-tasks independently, and synthesize results.&lt;/p&gt;

&lt;p&gt;Here is what that looks like in practice:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (Opus 4.7):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Refactor the authentication system" → model attempts it as one giant task&lt;/li&gt;
&lt;li&gt;Loses context mid-way, misses edge cases, produces inconsistent code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;After (Opus 4.8 with dynamic workflows):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same request → model breaks it into: audit current auth flow, design new interface, migrate each service, update tests&lt;/li&gt;
&lt;li&gt;Maintains consistency across sub-tasks&lt;/li&gt;
&lt;li&gt;Catches its own mistakes and pushes back on unsound plans&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A staff engineer at Anthropic described it perfectly: "In Claude Code, it asks the right questions, catches its own mistakes, pushes back when a plan isn't sound, and builds up confidence around complex, multi-service explorations before making big changes."&lt;/p&gt;

&lt;p&gt;For teams building with AI agents, this is the difference between a tool that handles PR comments and one that can genuinely own a feature.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuouwptrdupf7cihhhoo2.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuouwptrdupf7cihhhoo2.png" alt="Claude Code Dynamic Workflows - Before vs After Opus 4.8" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Fast Mode Got 3× Cheaper
&lt;/h2&gt;

&lt;p&gt;Speed and cost are usually a tradeoff. Opus 4.8's fast mode runs at 2.5× the speed of standard mode, and it is now three times cheaper than fast mode was on previous models.&lt;/p&gt;

&lt;p&gt;The practical impact: you can use Opus 4.8 in fast mode for real-time coding assistance without burning through credits. Think Copilot-level latency with Opus-level intelligence.&lt;/p&gt;

&lt;p&gt;Here is a rough cost comparison for a typical development session:&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;Speed&lt;/th&gt;
&lt;th&gt;Relative Cost&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;2.5× baseline&lt;/td&gt;
&lt;td&gt;1×&lt;/td&gt;
&lt;td&gt;Real-time pair programming, autocomplete, quick fixes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;1× baseline&lt;/td&gt;
&lt;td&gt;1× (same price as Opus 4.7)&lt;/td&gt;
&lt;td&gt;Code review, debugging, architecture discussions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High Effort&lt;/td&gt;
&lt;td&gt;Slower (more compute)&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;td&gt;Complex system design, security audits&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo53zqatokw46s9w7l4t2.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo53zqatokw46s9w7l4t2.png" alt="Claude Opus 4.8 Mode Comparison - Fast, Standard, and High Effort modes" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The headline: Opus 4.8 costs the same as 4.7 at standard mode, but you get more control over where your compute budget goes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmarks and Real-World Performance
&lt;/h2&gt;

&lt;p&gt;The benchmark tables tell one story. What early testers say tells another:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On coding benchmarks&lt;/strong&gt;, Opus 4.8 outperforms Opus 4.7 across SWE-bench, HumanEval, and agentic coding tasks. TR Labs' Super-Agent benchmark is particularly notable: Opus 4.8 is the only model to complete every case end-to-end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On computer use&lt;/strong&gt;, it scores 84% on Online-Mind2Web, a meaningful jump over both Opus 4.7 and GPT-5.5. If you are building browser automation or web agents, this is the strongest model available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On enterprise workflows&lt;/strong&gt;, Databricks reported that Opus 4.8 "unlocks a step change in agentic reasoning, tackling deeper, multistep questions faster than any prior Opus" at 61% cheaper token cost than Opus 4.7.&lt;/p&gt;

&lt;p&gt;One pattern that keeps coming up in tester feedback: Opus 4.8 proactively flags issues in inputs and outputs that other models miss. A senior investment analyst noted that "the biggest differentiator was Opus 4.8's tendency to proactively flag issues with the inputs and outputs of an analysis, something other models routinely missed and left to the users to catch."&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Developers
&lt;/h2&gt;

&lt;p&gt;Three practical takeaways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Stop prompting for effort. Use the slider.&lt;/strong&gt;&lt;br&gt;
"Think carefully" and "take your time" prompts are guesswork. The effort control gives you deterministic control over compute allocation. Use low effort for mechanical tasks, high effort for reasoning-heavy work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. AI agents just got production-ready.&lt;/strong&gt;&lt;br&gt;
Dynamic workflows solve the biggest barrier to autonomous coding agents: handling tasks that are too large for a single context window. If you have been on the fence about agentic coding tools, this release changes the calculus.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The pricing model is evolving in your favor.&lt;/strong&gt;&lt;br&gt;
Same base price as the previous generation, with cheaper fast mode and controllable compute. The trend across all frontier models is toward more granular cost control. Build your tooling to take advantage of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;The $65 billion raise is eye-catching, but the product direction is more interesting. Anthropic is betting that the next phase of AI adoption isn't about bigger models, it's about more useful ones. Effort control, dynamic workflows, and tiered pricing are features for people who use AI to ship software every day, not just for benchmark leaderboards.&lt;/p&gt;

&lt;p&gt;If you are using Claude Code, Cursor, or any AI coding tool built on Claude, these features are available now. The fast mode alone makes it worth switching from the default settings.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Claude Opus 4.8 is available today on claude.ai, the Anthropic API, Amazon Bedrock, and Google Cloud's Vertex AI. Claude Code users get dynamic workflows automatically.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>python</category>
    </item>
    <item>
      <title>The AI Free Ride Is Over: Why Your Token Bill Is About to Skyrocket</title>
      <dc:creator>Tyson Cung</dc:creator>
      <pubDate>Thu, 28 May 2026 06:04:33 +0000</pubDate>
      <link>https://dev.to/tyson_cung/the-ai-free-ride-is-over-why-your-token-bill-is-about-to-skyrocket-1586</link>
      <guid>https://dev.to/tyson_cung/the-ai-free-ride-is-over-why-your-token-bill-is-about-to-skyrocket-1586</guid>
      <description>&lt;p&gt;Simon Willison ran a tool to check his actual token usage last week. The result: $2,180 worth of API calls in 30 days. His subscription cost? $200. That's an 11x gap, and it tells you exactly where the AI industry is going.&lt;/p&gt;

&lt;p&gt;Over the past two months, both Anthropic and OpenAI have quietly executed the same playbook: shift enterprise customers from flat-rate pricing to per-token billing. The free ride is over, and developers who depend on AI coding agents are about to feel it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pricing Shift Nobody Noticed
&lt;/h2&gt;

&lt;p&gt;Here's what changed and when:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Anthropic (Claude Code, Enterprise plans):&lt;/strong&gt; Originally sold as "Claude seats include enough usage for a typical workday" at a flat rate. Sometime in the last six months, new enterprise contracts switched to $20 per seat per month &lt;em&gt;plus&lt;/em&gt; API token pricing. Existing customers are discovering this change as their contracts come up for renewal. The Information reported on the shift on April 14, but an Anthropic spokesperson claimed the change actually happened in November 2025.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenAI (Codex, April 2026):&lt;/strong&gt; On April 2, OpenAI switched Codex pricing from per-message to per-token billing for Plus, Pro, and ChatGPT Business plans. By April 23, this applied to all Enterprise plans, including Edu, Health, Gov, and ChatGPT for Teachers. The credits system maps directly to API token costs.&lt;/p&gt;

&lt;p&gt;In both cases, the flat-rate era is dead. You now pay for every token your developers consume.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Much Are Developers Actually Using?
&lt;/h2&gt;

&lt;p&gt;Willison's &lt;code&gt;ccusage&lt;/code&gt; tool breakdown is revealing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ccusage
Anthropic Claude Code (30 days): $1,199.79
OpenAI Codex (30 days):         $980.37
Total:                          $2,180.16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;He describes himself as a "moderately heavy user, certainly not running agents every hour." If a single power user hits $2k per month, imagine a 50-person engineering team.&lt;/p&gt;

&lt;p&gt;Let's do the math:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Monthly AI tooling cost for a 50-dev team:
------------------------------------------
Light users (40 devs, ~$200/month):    $8,000
Heavy users (8 devs, ~$800/month):     $6,400
Power users (2 devs, ~$2,000/month):   $4,000
                                       -------
Monthly total:                         $18,400
Annual:                                $220,800
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For context, that's roughly the cost of two additional senior engineers. Is the productivity gain worth it? For many teams, absolutely. But the bill still stings when you weren't budgeting for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hacker News Reaction
&lt;/h2&gt;

&lt;p&gt;Simon Willison's piece hit 765 points and 400+ comments on Hacker News within hours. The top threads reveal three camps of developers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Camp 1: "This is fine, still worth it"&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I would gladly pay $1k/month for Claude Code. It's replaced 2-3 hours of tedious work every single day." ,  top-voted comment&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Camp 2: "I'm cutting back"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Multiple developers reported setting hard daily token budgets, switching to local models for boilerplate code, and being more selective about when they invoke agents. One developer built a wrapper that routes simple queries to Ollama and only escalates to Claude for complex refactors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Camp 3: "We're building alternatives"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Several HN commenters shared projects to build cost-aware coding agents that track token usage in real time, display a running tally in the terminal, and cut off requests when they exceed a budget. These tools didn't exist three months ago because nobody needed them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for the AI Industry
&lt;/h2&gt;

&lt;p&gt;The pricing shift isn't just about revenue. It signals something bigger: product-market fit.&lt;/p&gt;

&lt;p&gt;Simon Willison's title says it plainly: "I think Anthropic and OpenAI have found product-market fit." When customers complain about prices instead of switching off entirely, that's a strong signal. Enterprise users aren't leaving. They're paying.&lt;/p&gt;

&lt;p&gt;But there's a second signal: the labs are under immense pressure to become profitable. The Verge's Hayden Field captured it perfectly in April with the headline "You're about to feel the AI money squeeze." The billions in venture funding and compute costs don't pay for themselves.&lt;/p&gt;

&lt;p&gt;Anthropic is rumored to be approaching its first profitable quarter. OpenAI, with its massive infrastructure spend, is likely further away. But both are now acting like real businesses, not research labs with infinite runway.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Steps for Developers
&lt;/h2&gt;

&lt;p&gt;If your team relies on AI coding agents, here's what you should do now:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Audit your actual usage
&lt;/h3&gt;

&lt;p&gt;Neither Anthropic nor OpenAI makes this easy. Willison built &lt;code&gt;ccusage&lt;/code&gt; himself because the platforms don't surface per-user token costs. Until first-party tools arrive, here's a quick audit approach:&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;# For Claude Code users: check the usage log&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.claude/usage.json | python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"
import json, sys
data = json.load(sys.stdin)
total_tokens = sum(session.get('tokens', 0) for session in data)
# Rough estimate: &lt;/span&gt;&lt;span class="nv"&gt;$15&lt;/span&gt;&lt;span class="s2"&gt; per million input tokens, &lt;/span&gt;&lt;span class="nv"&gt;$75&lt;/span&gt;&lt;span class="s2"&gt; per million output tokens
print(f'Total tokens: {total_tokens:,}')
print(f'Estimated cost: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;total_tokens&lt;/span&gt;&lt;span class="p"&gt; / 1_000_000 * 45&lt;/span&gt;:.2f&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;')
"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Set budgets before you need them
&lt;/h3&gt;

&lt;p&gt;Most teams discover they have a problem when the CFO forwards a $50,000 invoice. Set per-developer or per-team monthly budgets now. If your platform doesn't support hard limits, implement soft limits with monitoring:&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="c1"&gt;# Simple cost tracker for team AI usage
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AICostTracker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;budget_per_dev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;budget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;budget_per_dev&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;record_usage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Approximate pricing (varies by model/provider)
&lt;/span&gt;        &lt;span class="n"&gt;rates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;# per million tokens
&lt;/span&gt;            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;claude-opus-4&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gpt-4.1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;budget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.8&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WARNING: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; of budget&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; / $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;budget&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; budget&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Route intelligently
&lt;/h3&gt;

&lt;p&gt;Not every task needs Claude Opus or GPT-4.1. Build a triage system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Task complexity        Recommended model       Cost per million tokens
------------------     -------------------     -----------------------
Boilerplate, types     Local (Ollama/Llama)    $0
Simple refactors       Claude Haiku / GPT-4o   $1-3
Complex debugging      Claude Sonnet           $15
Architecture design    Claude Opus / GPT-4.1   $45-75
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Cache aggressively
&lt;/h3&gt;

&lt;p&gt;If five developers ask Claude Code essentially the same question about your codebase, you're paying for that answer five times. A shared context cache or team-level prompt library can cut repeat costs dramatically.&lt;/p&gt;

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

&lt;p&gt;The AI industry has crossed a threshold. Two years ago, AI coding tools were a novelty. Six months ago, they were a productivity boost. Today, they're essential infrastructure that costs real money.&lt;/p&gt;

&lt;p&gt;The good news: if you're paying $1,000 per month for AI tools that save you 40+ hours of work, your ROI is absurdly positive. A developer's time is worth far more than $25 per hour.&lt;/p&gt;

&lt;p&gt;The bad news: nobody told you the meter was running. And if you're not tracking it, you'll find out from accounting.&lt;/p&gt;

&lt;p&gt;Simon Willison ended his piece with a telling observation: "I think they've found product-market fit. And they're ramping up." Developer tools that people complain about but keep paying for? That's exactly what product-market fit looks like.&lt;/p&gt;

&lt;p&gt;Now go check your token usage. It's probably higher than you think.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>MySQL's 20-Year Bug #11472 Is Finally Fixed: Here's Why It Mattered</title>
      <dc:creator>Tyson Cung</dc:creator>
      <pubDate>Wed, 27 May 2026 06:06:22 +0000</pubDate>
      <link>https://dev.to/tyson_cung/mysqls-20-year-bug-11472-is-finally-fixed-heres-why-it-mattered-590h</link>
      <guid>https://dev.to/tyson_cung/mysqls-20-year-bug-11472-is-finally-fixed-heres-why-it-mattered-590h</guid>
      <description>&lt;p&gt;After 20 years, 1,600+ Reddit upvotes, birthday celebration threads, and at least one postponed marriage proposal, MySQL Bug #11472 has been fixed.&lt;/p&gt;

&lt;p&gt;This isn't just another bug fix story. It's a case study in how one design decision, buried deep in a database engine, can silently corrupt data integrity for two decades. And it's a reminder that the quietest bugs are often the most dangerous.&lt;/p&gt;

&lt;p&gt;Let's break down what the bug was, why it survived 20 years, and what the fix means for your applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bug: When CASCADE Goes Silent
&lt;/h2&gt;

&lt;p&gt;Here's a scenario that looks completely innocent:&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="c1"&gt;-- Parent table: users&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;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;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;status&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;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Child table: orders, with a CASCADE&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Audit trigger: log every deletion&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TRIGGER&lt;/span&gt; &lt;span class="n"&gt;audit_order_delete&lt;/span&gt;
    &lt;span class="k"&gt;AFTER&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;
    &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;EACH&lt;/span&gt; &lt;span class="k"&gt;ROW&lt;/span&gt;
    &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;audit_log&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'orders'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;OLD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'DELETE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run this:&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="c1"&gt;-- Delete a user; CASCADE should delete their orders&lt;/span&gt;
&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&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;What you expect:&lt;/strong&gt; The user is deleted. Their orders are cascade-deleted. The &lt;code&gt;audit_order_delete&lt;/code&gt; trigger fires for each deleted order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What actually happened (for 20 years):&lt;/strong&gt; The orders were deleted. The trigger &lt;strong&gt;never fired&lt;/strong&gt;. No audit log entries. Silent data loss.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture: Why This Happened
&lt;/h2&gt;

&lt;p&gt;MySQL processes foreign key cascades &lt;em&gt;before&lt;/em&gt; trigger execution. The execution flow looked like this:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9en483a19nxzwpj5ejj.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9en483a19nxzwpj5ejj.png" alt="MySQL CASCADE execution flow showing the bypass" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The FK cascade system bypassed the trigger infrastructure entirely. It used an internal row-deletion path that didn't go through the standard &lt;code&gt;DELETE&lt;/code&gt; handler, so triggers, which hook into the standard handler, were never invoked.&lt;/p&gt;

&lt;p&gt;This is the kind of architecture decision that makes sense in a vacuum (FK cascades are internal operations, right?) but creates a deep violation of the principle of least surprise in practice.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Broke in Production
&lt;/h2&gt;

&lt;p&gt;The cascade-trigger gap wasn't theoretical. It silently corrupted three critical patterns:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Audit Trails
&lt;/h3&gt;

&lt;p&gt;Every system that relied on triggers for audit logging had invisible holes. When a parent record was deleted, the cascade-deleted children left no audit trail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Expected audit log:
  [2026-05-27 14:02:01] orders | #8823 | DELETE
  [2026-05-27 14:02:01] orders | #8824 | DELETE
  [2026-05-27 14:02:01] orders | #8825 | DELETE

Actual audit log (pre-fix):
  (empty; triggers never fired)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Business Logic in Triggers
&lt;/h3&gt;

&lt;p&gt;Teams that encoded validation or side effects in child-table triggers had them silently skipped:&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="c1"&gt;-- This trigger NEVER fired on cascade deletes&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TRIGGER&lt;/span&gt; &lt;span class="n"&gt;refund_order&lt;/span&gt;
    &lt;span class="k"&gt;AFTER&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;
    &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;EACH&lt;/span&gt; &lt;span class="k"&gt;ROW&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
    &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;OLD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'paid'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
        &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;refunds&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;OLD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;OLD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'user_deleted'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users who deleted their accounts would cascade-delete orders, but refunds would never be issued because the trigger never ran.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Denormalization and Caching
&lt;/h3&gt;

&lt;p&gt;Triggers used to maintain denormalized fields or cache tables silently fell out of sync:&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="c1"&gt;-- Keeps a running total, silently falls out of sync&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TRIGGER&lt;/span&gt; &lt;span class="n"&gt;update_user_total&lt;/span&gt;
    &lt;span class="k"&gt;AFTER&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;
    &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;EACH&lt;/span&gt; &lt;span class="k"&gt;ROW&lt;/span&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;total_spent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total_spent&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;OLD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;OLD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a cascade delete, &lt;code&gt;users.total_spent&lt;/code&gt; would remain unchanged, even though the orders were gone.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why It Took 20 Years to Fix
&lt;/h2&gt;

&lt;p&gt;Not because MySQL engineers didn't care. Because fixing it correctly required touching the most sensitive part of the engine:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsg8blp95zeug42lwvx4s.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsg8blp95zeug42lwvx4s.png" alt="Three subsystems the fix had to coordinate across" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each subsystem represented a risk. A careless fix could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Break existing applications&lt;/strong&gt; relying on triggers &lt;em&gt;not&lt;/em&gt; firing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cause deadlocks&lt;/strong&gt; in high-concurrency workloads (FK cascades + triggers = complex locking)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create infinite loops&lt;/strong&gt; (trigger fires → FK cascade → trigger fires → ...)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The MySQL team's solution in 9.7 is elegant: a new system variable &lt;code&gt;foreign_key_checks_trigger&lt;/code&gt; (default: OFF) that explicitly opt-ins to the new behavior. This means existing applications with workarounds won't break, but new applications can get correct behavior:&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="c1"&gt;-- Enable trigger execution on FK cascades (MySQL 9.7+)&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;foreign_key_checks_trigger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Now triggers fire correctly&lt;/span&gt;
&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- audit_order_delete trigger fires for each cascaded order ✓&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Human Side: Internet Folklore
&lt;/h2&gt;

&lt;p&gt;Bug #11472 became more than a bug. It became a piece of developer culture. Here's the timeline:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrvpr4ffxymn0n5gbfeu.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrvpr4ffxymn0n5gbfeu.png" alt="Bug #11472 timeline: 2005-2026" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The original reporter, who filed the bug in 2005, is still active and commented on the fix in 2026. Two decades of waiting.&lt;/p&gt;

&lt;p&gt;The most upvoted Reddit comment on the fix thread?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"WTF? I was relying on this feature! Change it back please."&lt;/em&gt;  &lt;strong&gt;987 upvotes&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Developer humor at its finest.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Means for Your Applications
&lt;/h2&gt;

&lt;h3&gt;
  
  
  If You're Running MySQL &amp;lt; 9.7
&lt;/h3&gt;

&lt;p&gt;You still have the bug. Your triggers on child tables are silently skipped during FK cascade operations. Check your applications:&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="c1"&gt;-- Find tables with BOTH triggers AND foreign key relationships&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; 
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;TABLE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;TRIGGER_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVENT_MANIPULATION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;REFERENCED_TABLE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;COLUMN_NAME&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TRIGGERS&lt;/span&gt; &lt;span class="n"&gt;tr&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TABLES&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVENT_OBJECT_TABLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;TABLE_NAME&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KEY_COLUMN_USAGE&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; 
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;TABLE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;TABLE_NAME&lt;/span&gt; 
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;REFERENCED_TABLE_NAME&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TABLE_SCHEMA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'your_database'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  If You're Migrating to MySQL 9.7
&lt;/h3&gt;

&lt;p&gt;The fix is opt-in. Your existing code won't break, but you should:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Audit your triggers:&lt;/strong&gt; Identify which ones depend on FK cascade behavior&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test with &lt;code&gt;foreign_key_checks_trigger = ON&lt;/code&gt;:&lt;/strong&gt; Make sure your triggers handle cascade events correctly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch for performance:&lt;/strong&gt; FK cascade + triggers can increase locking overhead in high-write workloads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update your workarounds:&lt;/strong&gt; If you wrote application-level code to compensate for the bug, you can now remove it&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Migration Path
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Phase 1: Enable in a staging environment&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;foreign_key_checks_trigger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Phase 2: Monitor for issues&lt;/span&gt;
&lt;span class="c1"&gt;-- Check slow query log for new trigger-related queries&lt;/span&gt;
&lt;span class="c1"&gt;-- Watch for deadlocks in FK-heavy workloads&lt;/span&gt;

&lt;span class="c1"&gt;-- Phase 3: Enable in production (gradual rollout)&lt;/span&gt;
&lt;span class="c1"&gt;-- Start with read replicas, then primary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Bigger Lesson
&lt;/h2&gt;

&lt;p&gt;Bug #11472 teaches something important about software architecture: &lt;strong&gt;silent failures are worse than loud ones.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If MySQL had thrown an error when triggers couldn't fire on cascade operations, every DBA would have noticed immediately. The bug would have been fixed in 2005. But because it failed silently (rows were deleted, triggers were skipped, everything looked normal on the surface), it survived two decades.&lt;/p&gt;

&lt;p&gt;This is the same pattern we see in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Distributed systems&lt;/strong&gt; that silently drop messages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API clients&lt;/strong&gt; that retry without logging failures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database ORMs&lt;/strong&gt; that swallow constraint violations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Silence is not a feature. It's a time bomb.&lt;/p&gt;




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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bug #11472 caused MySQL triggers to silently skip execution during FK CASCADE operations.&lt;/strong&gt; Rows were deleted but triggers never fired.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The fix in MySQL 9.7 is opt-in&lt;/strong&gt; via &lt;code&gt;foreign_key_checks_trigger&lt;/code&gt;. Existing applications won't break, but you should audit your trigger dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The architecture problem was a bypass:&lt;/strong&gt; FK cascades used an internal deletion path that didn't route through the standard trigger dispatcher.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;20 years of survival&lt;/strong&gt; shows how deeply buried design decisions can create persistent, invisible bugs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Audit your audit trails.&lt;/strong&gt; If you use triggers for logging, make sure they're actually firing for all delete paths, not just direct DELETEs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;The MySQL 9.7 release notes include the full details of this fix. If you're running production MySQL with triggers + foreign keys, this is the upgrade you've been waiting two decades for.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow for more deep dives on database internals, software architecture, and the bugs that shaped our industry.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How Video-Native AI Actually Works — The Architecture Behind Gemini Omni</title>
      <dc:creator>Tyson Cung</dc:creator>
      <pubDate>Tue, 26 May 2026 06:05:23 +0000</pubDate>
      <link>https://dev.to/tyson_cung/how-video-native-ai-actually-works-the-architecture-behind-gemini-omni-3bh7</link>
      <guid>https://dev.to/tyson_cung/how-video-native-ai-actually-works-the-architecture-behind-gemini-omni-3bh7</guid>
      <description>&lt;h1&gt;
  
  
  How Video-Native AI Actually Works — The Architecture Behind Gemini Omni
&lt;/h1&gt;

&lt;p&gt;Google just dropped Gemini Omni, and the AI world is losing its mind. Not because it's another chatbot — because it's the first model that truly &lt;em&gt;understands&lt;/em&gt; video.&lt;/p&gt;

&lt;p&gt;Not "watches 3 frames per second and tries to guess what's happening." Not "transcribes the audio and ignores the visuals." Native. Every frame. Every pixel. Every timestamp.&lt;/p&gt;

&lt;p&gt;Let's break down how video-native AI actually works — and why the architecture is fundamentally different from every model you've used before.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: Current AI is Legally Blind to Video
&lt;/h2&gt;

&lt;p&gt;When you upload a video to ChatGPT or Claude today, here's what actually happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────┐     ┌───────────────┐     ┌──────────────┐
│  30-second   │────▶│ Extract 1 fps  │────▶│ 30 still     │
│   video      │     │ (30 frames)   │     │ images       │
└──────────────┘     └───────────────┘     └──────┬───────┘
                                                  │
                    ┌───────────────┐              │
                    │  "The person  │◀─────────────┘
                    │   is walking" │
                    └───────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model never actually &lt;em&gt;sees&lt;/em&gt; motion. It sees a slideshow of still images and uses language reasoning to &lt;em&gt;infer&lt;/em&gt; what's happening between frames.&lt;/p&gt;

&lt;p&gt;This is why current AI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Misses fast actions.&lt;/strong&gt; A tennis serve at 30fps becomes 1 frame. That serve is invisible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can't track objects across frames.&lt;/strong&gt; Every frame is a fresh analysis — no memory of the previous one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fails at temporal reasoning.&lt;/strong&gt; "Did the person pick up the cup before or after they sat down?" requires tracking state across time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's like trying to understand a movie by reading the script one random page at a time.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture Shift: From Frame Sampler to Video Streamer
&lt;/h2&gt;

&lt;p&gt;Gemini Omni processes video as a &lt;strong&gt;continuous stream&lt;/strong&gt;, not a collection of snapshots. Here's the architectural difference:&lt;/p&gt;

&lt;h3&gt;
  
  
  Old Way: Frame-By-Frame
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Video → Frame Extractor → Image Encoder → LLM → Text Output
         (1-2 fps)         (ViT/CLIP)    (text tokens)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  New Way: Native Video Streaming
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Video → Space-Time Tokenizer → Video Transformer → Multimodal Output
        (all frames)           (3D attention)      (text + video + audio)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key difference is the &lt;strong&gt;space-time tokenizer&lt;/strong&gt;. Instead of treating a video as a sequence of independent images, it creates tokens that span both space AND time:&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="c1"&gt;# Traditional approach: each frame is independent
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extract_frames&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;image_encoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# [256 tokens] × 30 frames = 7,680 tokens
&lt;/span&gt;    &lt;span class="c1"&gt;# No relationship between frame tokens
&lt;/span&gt;
&lt;span class="c1"&gt;# Video-native approach: tokens represent spatiotemporal patches
&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;video_encoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# [16×16×4] patches across space-time
# Each token covers: 16px×16px spatial region × 4 consecutive frames
# Tokens inherently carry motion information
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the same leap that CNNs made over MLPs for images — moving from "process each pixel independently" to "understand spatial relationships through convolutions." Except now it's in the time dimension.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three-Layer Architecture
&lt;/h2&gt;

&lt;p&gt;Here's what the full pipeline looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│                    VIDEO-NATIVE AI ARCHITECTURE              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌──────────┐    ┌──────────────┐    ┌──────────────────┐  │
│  │  INPUT   │    │ SPACE-TIME   │    │   MULTIMODAL     │  │
│  │  STREAM  │───▶│ TOKENIZER    │───▶│   TRANSFORMER    │  │
│  │          │    │              │    │                  │  │
│  │ Video    │    │ 16×16×4      │    │ 3D Self-Attention│  │
│  │ + Audio  │    │ Patches      │    │ over all tokens  │  │
│  │ + Text   │    │              │    │                  │  │
│  └──────────┘    └──────────────┘    └────────┬─────────┘  │
│                                               │            │
│                    ┌──────────────────────────┘            │
│                    ▼                                       │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              MULTIMODAL DECODER                      │   │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐          │   │
│  │  │  TEXT    │  │  VIDEO   │  │  AUDIO   │          │   │
│  │  │  OUTPUT  │  │  OUTPUT  │  │  OUTPUT  │          │   │
│  │  └──────────┘  └──────────┘  └──────────┘          │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layer 1: Space-Time Tokenizer
&lt;/h3&gt;

&lt;p&gt;This is where the magic happens. Instead of the standard ViT patch embedding (16×16 pixels), video-native models use &lt;strong&gt;3D patch embeddings&lt;/strong&gt;:&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="c1"&gt;# Conceptual code — how space-time tokenization works
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SpaceTimeTokenizer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Divides video into 3D patches: (time, height, width)
    Each patch spans multiple frames, so it naturally
    captures local motion within the patch.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;temporal_patch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;patch_size&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;span class="c1"&gt;# 4 frames
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spatial_patch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;  &lt;span class="c1"&gt;# 16×16 pixels
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tokenize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# video shape: (T, H, W, C) — e.g., (120, 720, 1280, 3)
&lt;/span&gt;        &lt;span class="c1"&gt;# Extract overlapping 3D cubes
&lt;/span&gt;        &lt;span class="n"&gt;patches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unfold&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;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;temporal_patch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# stride=2
&lt;/span&gt;                     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unfold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spatial_patch&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;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unfold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spatial_patch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Each patch: (4 frames × 16×16 pixels × 3 channels) = 3072 values
&lt;/span&gt;        &lt;span class="c1"&gt;# Project to model dimension (e.g., 4096)
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;projection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;patches&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# (N_patches, d_model)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The crucial insight: by making the tokenizer operate on &lt;strong&gt;space-time cubes&lt;/strong&gt; instead of space-only patches, motion becomes a first-class citizen of the token representation. A patch containing a tennis racket moving left-to-right has a fundamentally different embedding than a static racket — even if the pixel values at the center frame are identical.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 2: 3D Self-Attention
&lt;/h3&gt;

&lt;p&gt;Once you have spatiotemporal tokens, the transformer needs to attend across both space AND time simultaneously. This is the expensive part:&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="c1"&gt;# Standard 2D attention (image models)
# Each token attends to all other tokens in the same FRAME
&lt;/span&gt;&lt;span class="n"&gt;attention_scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;  &lt;span class="c1"&gt;# (N_spatial, N_spatial)
&lt;/span&gt;
&lt;span class="c1"&gt;# 3D attention (video models)  
# Each token attends to ALL tokens across ALL frames
&lt;/span&gt;&lt;span class="n"&gt;attention_scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;  &lt;span class="c1"&gt;# (N_spatiotemporal, N_spatiotemporal)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a 30-second video at 30fps with 16×16×4 patches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Standard approach:&lt;/strong&gt; 30 separate attention computations, each over ~3,600 tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3D attention:&lt;/strong&gt; One massive attention computation over ~108,000 tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's 30× more tokens in the attention matrix — and attention scales O(n²). This is why video-native models need clever optimizations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ring Attention&lt;/strong&gt; distributes the attention computation across devices in a ring topology. Each device computes attention for its chunk and passes intermediate results to the next:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Device 1 (tokens 0-27K)  →  Device 2 (tokens 27K-54K)  →  Device 3 (54K-81K)  →  Device 4 (81K-108K)
        ↑                                                                                     │
        └───────────────────────── Ring topology ──────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layer 3: Multimodal Decoder
&lt;/h3&gt;

&lt;p&gt;The decoder can produce multiple output modalities — not just text:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Text:&lt;/strong&gt; Standard autoregressive decoding (predict next token)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video:&lt;/strong&gt; Diffusion-based generation or autoregressive frame prediction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audio:&lt;/strong&gt; Waveform or spectrogram generation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mixed:&lt;/strong&gt; The model can interleave text with generated video clips&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why Gemini Omni can &lt;em&gt;edit&lt;/em&gt; video natively — it's not calling an external video processing library. The same model that understands "remove the background noise" can generate the cleaned audio.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Means for Developers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Video Understanding APIs Will Change
&lt;/h3&gt;

&lt;p&gt;Instead of the current pattern:&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="c1"&gt;# Today's approach: extract frames, describe each, stitch together
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;VideoCapture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meeting.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;frames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="n"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Describe every 30th frame
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&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="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)}},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Describe what&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s happening&lt;/span&gt;&lt;span class="sh"&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;You'll be able to do 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="c1"&gt;# Tomorrow's approach: stream video directly
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;VideoAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Upload and analyze in one call
&lt;/span&gt;&lt;span class="n"&gt;analysis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meeting.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Who spoke longest, and what was their key point?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;temporal_resolution&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;full&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Every frame, not sampled
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Or stream in real-time
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webcam&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action_detected&lt;/span&gt;&lt;span class="sh"&gt;"&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Action: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Confidence: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;confidence&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. New Use Cases Become Possible
&lt;/h3&gt;

&lt;p&gt;Applications that were science fiction 6 months ago:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Old Limitation&lt;/th&gt;
&lt;th&gt;Video-Native Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sports coaching&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Misses fast movements&lt;/td&gt;
&lt;td&gt;Full-motion analysis at native FPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Can't track objects across frames&lt;/td&gt;
&lt;td&gt;Persistent object tracking with temporal reasoning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Medical imaging&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ultrasound/endoscopy treated as stills&lt;/td&gt;
&lt;td&gt;Full procedure analysis with temporal context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Manufacturing QA&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Frame sampling misses defects&lt;/td&gt;
&lt;td&gt;Continuous monitoring catches transient anomalies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Video editing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Separate AI for understanding + external tools for editing&lt;/td&gt;
&lt;td&gt;Single model understands AND edits&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  3. Compute Requirements Are Massive — But Dropping Fast
&lt;/h3&gt;

&lt;p&gt;Running 3D attention over 100K+ tokens is expensive. Current estimates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;30-second video analysis:&lt;/strong&gt; ~10-50× more compute than text-only&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time streaming:&lt;/strong&gt; Requires distillation or specialized hardware&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge deployment:&lt;/strong&gt; Not feasible yet for full models&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the pattern is familiar. GPT-3 took a datacenter in 2020. Today it runs on a phone. Video-native AI will follow the same curve.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bigger Picture: AI That Lives in Time
&lt;/h2&gt;

&lt;p&gt;The shift from frame-sampling to native video processing isn't just an engineering optimization. It's a philosophical shift in how AI experiences the world.&lt;/p&gt;

&lt;p&gt;Current AI models live in a world of static snapshots. They're like someone reading a photo album — they can describe each picture, but they can't feel the rhythm of the dance, the tension of a conversation, or the flow of a basketball game.&lt;/p&gt;

&lt;p&gt;Video-native models live in time. They understand &lt;em&gt;before&lt;/em&gt; and &lt;em&gt;after&lt;/em&gt;. They can track a coffee cup as it moves across a desk and reason about &lt;em&gt;when&lt;/em&gt; it was picked up, not just &lt;em&gt;that&lt;/em&gt; it was picked up. This is a fundamental leap toward AI that interacts with the real, dynamic, moving world — not just the static, curated web.&lt;/p&gt;




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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Video-native ≠ frame-sampling.&lt;/strong&gt; Native models process continuous streams with spatiotemporal tokens that inherently capture motion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The space-time tokenizer is the breakthrough.&lt;/strong&gt; By encoding patches that span both space and time, motion becomes embedded in the token representation itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;3D attention is the bottleneck.&lt;/strong&gt; Ring attention and other distributed strategies make it feasible, but we're still early in the optimization curve.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Developer APIs will transform.&lt;/strong&gt; The video → extract frames → describe → stitch pipeline will be replaced by single-call video analysis and real-time streaming.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;This is just the beginning.&lt;/strong&gt; As compute costs drop (and they will), video-native AI will become the default — just like image-native CNNs replaced hand-crafted feature extractors a decade ago.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;This article analyzes publicly available architectural patterns in video-native AI models. Code examples are conceptual illustrations of the underlying principles, not production implementations.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow for more deep dives on AI architecture and practical engineering insights.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>python</category>
    </item>
    <item>
      <title>How APIs Actually Work — The Simplest Explanation You'll Find</title>
      <dc:creator>Tyson Cung</dc:creator>
      <pubDate>Sat, 11 Apr 2026 23:49:36 +0000</pubDate>
      <link>https://dev.to/tyson_cung/how-apis-actually-work-the-simplest-explanation-youll-find-1n4f</link>
      <guid>https://dev.to/tyson_cung/how-apis-actually-work-the-simplest-explanation-youll-find-1n4f</guid>
      <description>&lt;p&gt;APIs are everywhere. Every app you use talks to other services through APIs. And yet most explanations make it more complicated than it needs to be.&lt;/p&gt;

&lt;p&gt;Let me give you the clearest version I know.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/K33ovRaS6ok"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The One Analogy That Works
&lt;/h2&gt;

&lt;p&gt;An API is a waiter.&lt;/p&gt;

&lt;p&gt;You're at a restaurant. You don't go into the kitchen. You don't cook the food yourself. You tell the waiter what you want, the waiter goes to the kitchen, the kitchen prepares it, and the waiter brings it back to you.&lt;/p&gt;

&lt;p&gt;You never interact with the kitchen directly. The waiter is the interface.&lt;/p&gt;

&lt;p&gt;In software:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're the app (or the developer making the request)&lt;/li&gt;
&lt;li&gt;The waiter is the API&lt;/li&gt;
&lt;li&gt;The kitchen is the server/database with the data&lt;/li&gt;
&lt;li&gt;The food is the response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it. That's what an API is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Happens When You Use One
&lt;/h2&gt;

&lt;p&gt;Say you're using a weather app. You type in your city and see the current temperature.&lt;/p&gt;

&lt;p&gt;Behind the scenes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The app sends a &lt;strong&gt;request&lt;/strong&gt; to a weather API: "Give me the current temperature for Melbourne"&lt;/li&gt;
&lt;li&gt;The API server receives that request&lt;/li&gt;
&lt;li&gt;The server looks up the data (from weather sensors, satellites, whatever)&lt;/li&gt;
&lt;li&gt;The server sends back a &lt;strong&gt;response&lt;/strong&gt;: &lt;code&gt;{"city": "Melbourne", "temperature": 22, "unit": "celsius"}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Your app reads that response and shows you "22°C"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole thing happens in milliseconds. You see a number. The app made an API call.&lt;/p&gt;

&lt;h2&gt;
  
  
  REST — The Standard
&lt;/h2&gt;

&lt;p&gt;Most APIs you'll encounter are REST APIs (REpresentational State Transfer). REST isn't a technology — it's a set of conventions about how requests and responses should work.&lt;/p&gt;

&lt;p&gt;The key ideas:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt; — Everything is a resource with a URL. A user is &lt;code&gt;/users/123&lt;/code&gt;. A list of products is &lt;code&gt;/products&lt;/code&gt;. A specific order is &lt;code&gt;/orders/456&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP Methods&lt;/strong&gt; — Different operations use different methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET&lt;/code&gt; — Read data&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST&lt;/code&gt; — Create something new&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PUT/PATCH&lt;/code&gt; — Update something&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DELETE&lt;/code&gt; — Remove something&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Status Codes&lt;/strong&gt; — Responses include a number telling you what happened:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;200&lt;/code&gt; — Success&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;201&lt;/code&gt; — Created&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;400&lt;/code&gt; — Your request is wrong&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;401&lt;/code&gt; — Not authenticated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;404&lt;/code&gt; — Not found&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;500&lt;/code&gt; — Server error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;JSON&lt;/strong&gt; — Data travels in JSON format (key-value pairs, like a dictionary). Easy for both humans and machines to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Real Example
&lt;/h2&gt;

&lt;p&gt;Say you're building an app that shows GitHub repos. You'd call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET https://api.github.com/users/tysoncung/repos
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub's API receives that request, finds the repos for that user, and sends back a JSON array with all the details. Your app loops through that array and displays them.&lt;/p&gt;

&lt;p&gt;You didn't need access to GitHub's database. You didn't need to know how their servers work. You just followed their API documentation and made a request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why APIs Matter
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;For developers:&lt;/strong&gt; APIs let you build on top of existing services instead of reinventing everything. Need payments? Stripe API. Need maps? Google Maps API. Need user authentication? Auth0 API. Your app becomes a composition of specialized services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For companies:&lt;/strong&gt; APIs are how products become platforms. Twitter opened their API and an entire ecosystem of clients and tools emerged. Stripe's API is why developers love them — it's clean, well-documented, and predictable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For you as a learner:&lt;/strong&gt; Once you understand APIs, a massive part of modern software development clicks. Every mobile app, most web apps, and increasingly even desktop apps are built around API calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Should Learn Next
&lt;/h2&gt;

&lt;p&gt;If you want to go deeper:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Authentication&lt;/strong&gt; — How do APIs know you're allowed to make requests? (API keys, OAuth, JWT)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limiting&lt;/strong&gt; — Why APIs restrict how many calls you can make&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhooks&lt;/strong&gt; — The reverse of an API call: the server pushes data to you instead of you pulling it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API documentation&lt;/strong&gt; — How to read and use API docs (Swagger/OpenAPI)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But for 80% of what you'll do as a developer, the waiter analogy is all you need to hold in your head. Request, response, JSON, HTTP methods. The rest is details.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What was the first API you integrated? What made it click for you?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Claude Code vs Codex CLI — Two Terminal Coding Agents, One Honest Comparison</title>
      <dc:creator>Tyson Cung</dc:creator>
      <pubDate>Sat, 11 Apr 2026 23:48:30 +0000</pubDate>
      <link>https://dev.to/tyson_cung/claude-code-vs-codex-cli-two-terminal-coding-agents-one-honest-comparison-1l37</link>
      <guid>https://dev.to/tyson_cung/claude-code-vs-codex-cli-two-terminal-coding-agents-one-honest-comparison-1l37</guid>
      <description>&lt;p&gt;The terminal got interesting. AI coding started in IDEs with Copilot autocomplete, moved to chat interfaces, and now we've got full agents that run inside your terminal and can edit code, run tests, and loop until they get it right.&lt;/p&gt;

&lt;p&gt;Claude Code (from Anthropic) and Codex CLI (from OpenAI) are the two most talked-about examples of this. I've used both. Here's what actually matters.&lt;/p&gt;


&lt;div&gt;
    &lt;iframe src="https://www.youtube.com/embed/AO9lAuPxHSw"&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;


&lt;h2&gt;
  
  
  What They Are
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt; is Anthropic's CLI that brings Claude Sonnet/Opus directly into your terminal. You run &lt;code&gt;claude&lt;/code&gt; from inside a git repo, give it a task, and it reads files, writes code, runs commands, and iterates. It operates with explicit permission prompts before making changes, which is either reassuring or slow depending on your mood.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codex CLI&lt;/strong&gt; is OpenAI's terminal agent, using GPT-4 (and now GPT-4.1 class models). Similar concept: runs in your repo, takes tasks, makes changes. OpenAI's approach gives it a bit more autonomy by default — it'll chain commands without as many interruptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Experience
&lt;/h2&gt;

&lt;p&gt;Both are surprisingly capable at well-scoped tasks. "Add error handling to this function," "write tests for this module," "refactor this to use the strategy pattern" — these work well in both. You describe what you want in natural language, the agent reads your code, and it produces a reasonable implementation.&lt;/p&gt;

&lt;p&gt;The difference shows up at the edges.&lt;/p&gt;

&lt;p&gt;Claude Code is better at understanding context in large codebases. Anthropic has invested heavily in Claude's ability to hold large amounts of code in context and reason about the relationships between files. When I give it a task that touches five different modules, it tends to understand the architecture and make changes that are consistent with existing patterns.&lt;/p&gt;

&lt;p&gt;Codex CLI is faster for single-file tasks. It's snappier, iterates quickly, and feels more aggressive (in a good way) about just getting things done. For focused tasks — fix this function, implement this endpoint — it's often the quicker path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic Behavior
&lt;/h2&gt;

&lt;p&gt;Codex CLI is more autonomous. It'll chain tool calls, run tests, see failures, and try fixes without stopping to ask you. Sometimes this is great. Sometimes it goes down a rabbit hole. You can set safety levels (&lt;code&gt;--approval-mode&lt;/code&gt; flags) to control how much it acts without permission.&lt;/p&gt;

&lt;p&gt;Claude Code is more collaborative. It shows you what it's planning to do and waits for confirmation before executing. This feels slower but means you're always aware of what's happening. For production code, I actually prefer this — I want to review changes before they hit the filesystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model Quality
&lt;/h2&gt;

&lt;p&gt;This is the hard part to compare because it changes with every model update. Both agents are essentially wrappers around powerful LLMs, and the model quality matters more than the agent shell.&lt;/p&gt;

&lt;p&gt;Right now: Claude's reasoning on complex architectural questions tends to be better. GPT-4 class models have slightly better code style consistency in my experience, particularly for Python and TypeScript.&lt;/p&gt;

&lt;p&gt;Both will make mistakes. Neither replaces code review. The agent loop (write → run → fail → fix) helps catch some errors automatically, but you still need to read what it produces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Both are pay-per-use via API tokens. For intensive coding sessions, costs add up quickly — I've spent $5-10 in a session doing heavy refactoring. Neither is "free" at serious usage volumes.&lt;/p&gt;

&lt;p&gt;Claude Code has a subscription tier through Anthropic's API. Codex CLI uses OpenAI API credits.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Honest Take
&lt;/h2&gt;

&lt;p&gt;If you're doing large codebase work, complex architectural changes, or tasks that require understanding how many parts of a system interact: Claude Code.&lt;/p&gt;

&lt;p&gt;If you want a fast, aggressive agent for focused tasks and you're comfortable with more autonomous behavior: Codex CLI.&lt;/p&gt;

&lt;p&gt;Both are worth trying. Neither is the magic wand that writes your code for you. They're tools that handle the tedious parts better than they used to, and they're getting better fast.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Are you using AI terminal agents yet? What's been your experience?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>tools</category>
      <category>terminal</category>
    </item>
    <item>
      <title>Your Dashboard Numbers Are Wrong — And Your Team Is Making Decisions Based on Them</title>
      <dc:creator>Tyson Cung</dc:creator>
      <pubDate>Sat, 11 Apr 2026 23:47:58 +0000</pubDate>
      <link>https://dev.to/tyson_cung/your-dashboard-numbers-are-wrong-and-your-team-is-making-decisions-based-on-them-3h8b</link>
      <guid>https://dev.to/tyson_cung/your-dashboard-numbers-are-wrong-and-your-team-is-making-decisions-based-on-them-3h8b</guid>
      <description>&lt;p&gt;I've sat in too many meetings where someone points at a number on a dashboard and says "look, it's working" or "look, it's broken" — and the number is measuring the wrong thing, or measuring the right thing wrong, or both.&lt;/p&gt;

&lt;p&gt;This isn't a data engineering problem. It's a measurement problem. And it's more common than anyone wants to admit.&lt;/p&gt;


&lt;div&gt;
    &lt;iframe src="https://www.youtube.com/embed/LE4YNgRqdr0"&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;


&lt;h2&gt;
  
  
  Why Dashboard Numbers Lie
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem 1: The metric was defined in a meeting, not in code
&lt;/h3&gt;

&lt;p&gt;Someone says "we need to track active users." Everyone nods. Nobody asks what "active" means. Is it users who logged in today? Users who performed any action? Users who performed a meaningful action (not a bot ping)? Users who paid?&lt;/p&gt;

&lt;p&gt;The engineer implements something. The product manager had something different in mind. The exec reading the dashboard has a third interpretation. The number exists, it changes over time, and everyone is confidently wrong about what it means.&lt;/p&gt;

&lt;p&gt;Fix: Define metrics in writing before building. "Active user: a user account that submitted at least one form in the last 30 days, excluding accounts marked as test or internal." That's a spec, not a vibe.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 2: The data pipeline has bugs
&lt;/h3&gt;

&lt;p&gt;Metrics pipelines are production code. They fail, they drift, they have edge cases. But unlike application bugs that show up as broken features, data bugs show up as slightly wrong numbers. Slightly wrong numbers are the most dangerous kind because they feel believable.&lt;/p&gt;

&lt;p&gt;A query that's double-counting events because someone joins the wrong way. A timezone issue that moves events between days. A column that changed meaning when the schema evolved but the query didn't update.&lt;/p&gt;

&lt;p&gt;Nobody knows these exist. The dashboard looks fine. Decisions get made.&lt;/p&gt;

&lt;p&gt;Fix: Treat your data pipeline like you treat application code. Tests, code review, alerts when outputs go outside expected ranges. "This metric dropped 40% overnight" should be an automated alert, not something someone notices in a quarterly review.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 3: The metric is easy to measure, not important to measure
&lt;/h3&gt;

&lt;p&gt;Page views. Email opens. Time on site. These are easy to measure and frequently wrong proxies for what you actually care about.&lt;/p&gt;

&lt;p&gt;Page views go up if your site is slow and people reload. Email opens are inflated by Apple's Mail Privacy Protection. Time on site goes up if your UX is confusing.&lt;/p&gt;

&lt;p&gt;You optimize for what you measure. If you measure the wrong thing, you optimize in the wrong direction.&lt;/p&gt;

&lt;p&gt;Fix: Work backward from business outcomes. What does success actually look like? Revenue, retention, task completion rate, NPS. Then find metrics that lead to those outcomes. Resist the urge to track what's easy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 4: Survivorship bias in the sample
&lt;/h3&gt;

&lt;p&gt;Your dashboard probably shows data about the users you have. It probably doesn't show you much about the users you lost.&lt;/p&gt;

&lt;p&gt;Churn dashboards that only track reasons given by departing customers miss the 60% who leave without clicking the feedback button. Conversion funnels show where people drop off but not why. Satisfaction scores track satisfied users more than dissatisfied ones who've already moved on.&lt;/p&gt;

&lt;p&gt;Fix: Design for the data you don't have. Exit surveys. Cohort analysis that follows users from signup through churn. Win/loss interviews. The data you're missing is often more important than the data you have.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Uncomfortable Conclusion
&lt;/h2&gt;

&lt;p&gt;Most dashboards tell you what happened. The useful question is why it happened and whether it matters.&lt;/p&gt;

&lt;p&gt;A metric without context is just a number. "DAUs up 12%" is not useful without knowing whether that's a trend or a spike, whether it's driven by the user segment you care about, and whether it maps to outcomes that actually matter for the business.&lt;/p&gt;

&lt;p&gt;The best data teams I've seen spend more time on measurement strategy — defining what to track and why — than they do on building pipelines. The pipeline is the easy part. Getting the right number is hard.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's the most misleading metric you've ever seen a team optimize for? I want to hear the stories.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>datascience</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>AWS vs Azure vs GCP — Which Cloud Should You Learn in 2026?</title>
      <dc:creator>Tyson Cung</dc:creator>
      <pubDate>Sat, 11 Apr 2026 23:47:27 +0000</pubDate>
      <link>https://dev.to/tyson_cung/aws-vs-azure-vs-gcp-which-cloud-should-you-learn-in-2026-576l</link>
      <guid>https://dev.to/tyson_cung/aws-vs-azure-vs-gcp-which-cloud-should-you-learn-in-2026-576l</guid>
      <description>&lt;p&gt;This is the cloud question that comes up in every bootcamp, every career change conversation, and every "where should I focus" thread on Reddit. The answer isn't as complicated as the cloud vendors want you to think.&lt;/p&gt;


&lt;div&gt;
    &lt;iframe src="https://www.youtube.com/embed/OQplZcd1tmY"&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;


&lt;h2&gt;
  
  
  The Market Reality
&lt;/h2&gt;

&lt;p&gt;AWS holds roughly 30% of the cloud market. Azure is around 22%. GCP sits at about 12%. The rest is distributed across other providers.&lt;/p&gt;

&lt;p&gt;This matters because it tells you where the jobs are. AWS has the most adoption across the broadest range of companies — startups, enterprises, government, everything. Azure dominates in enterprises that are already deep in the Microsoft ecosystem (Office 365, Active Directory, .NET). GCP is strong in companies doing heavy data/ML work and startups that want to run Kubernetes on managed infrastructure.&lt;/p&gt;

&lt;p&gt;If you're optimizing for job market breadth, AWS first.&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS — The Default Choice
&lt;/h2&gt;

&lt;p&gt;AWS has the widest service catalog (200+ services), the deepest documentation, and the largest community. There are more Stack Overflow answers, more YouTube tutorials, more blog posts, and more job postings for AWS than the other two combined.&lt;/p&gt;

&lt;p&gt;The certification path is mature — Solutions Architect Associate is recognized across the industry and genuinely tests useful knowledge. The downside is complexity: AWS grew organically and the UI is notoriously confusing. Some services exist for historical reasons that no longer make sense. The pricing is opaque.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn AWS if:&lt;/strong&gt; You want the widest job options, you're going into a startup or general tech company, or you're targeting cloud engineering as a career.&lt;/p&gt;

&lt;h2&gt;
  
  
  Azure — The Enterprise Path
&lt;/h2&gt;

&lt;p&gt;If you're already working at a company in Microsoft's orbit (Windows, Office, SQL Server, Active Directory), you're probably already touching Azure or about to. Azure's integration with Microsoft's identity systems and developer tooling is genuinely better than the alternatives for Windows-heavy shops.&lt;/p&gt;

&lt;p&gt;Azure DevOps is a legitimate competitor to GitHub Actions for enterprise CI/CD. Azure Active Directory (now Entra ID) is how most large enterprises handle identity. If you want to work in enterprise IT and cloud, Azure knowledge is often more valuable than AWS knowledge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn Azure if:&lt;/strong&gt; You're targeting enterprise clients, your company is Microsoft-heavy, or you're coming from a traditional IT background.&lt;/p&gt;

&lt;h2&gt;
  
  
  GCP — The Data/ML Play
&lt;/h2&gt;

&lt;p&gt;Google's cloud has historically punched below its weight in enterprise adoption but has genuine technical advantages in certain areas. BigQuery for data warehousing is legitimately best-in-class. Vertex AI for ML workloads is excellent. GKE (Google Kubernetes Engine) is arguably the easiest managed Kubernetes to operate.&lt;/p&gt;

&lt;p&gt;If you're going into data engineering, ML engineering, or you want to understand Kubernetes deeply, GCP is worth learning. The job market is smaller but the roles tend to be more specialized and often pay well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn GCP if:&lt;/strong&gt; You're going into data engineering, ML, or you want to work at companies that run large-scale data infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Answer
&lt;/h2&gt;

&lt;p&gt;Learn one deeply, understand the others at a conceptual level.&lt;/p&gt;

&lt;p&gt;The fundamentals transfer: VMs, storage, networking, databases, serverless functions, IAM — every cloud does these things. Once you understand how AWS does it, Azure and GCP are variations on the same theme. The vendor-specific details matter for day-to-day work but the concepts are portable.&lt;/p&gt;

&lt;p&gt;Most companies that ask for "cloud experience" in a job posting are happy with any cloud background. They'll train you on their specific vendor. What they actually want to know is whether you understand how cloud infrastructure works.&lt;/p&gt;

&lt;p&gt;So: pick the one most relevant to the jobs you want, get certified (it signals commitment and tests real knowledge), and don't overthink the choice. In 12 months you'll have enough experience that the original pick matters less than you think.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Which cloud are you using? Did you deliberately choose it or just end up there? Tell me below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>aws</category>
      <category>azure</category>
      <category>devops</category>
    </item>
    <item>
      <title>Windsurf vs Cursor — Two AI IDEs Walk Into a Bar</title>
      <dc:creator>Tyson Cung</dc:creator>
      <pubDate>Sat, 11 Apr 2026 23:46:57 +0000</pubDate>
      <link>https://dev.to/tyson_cung/windsurf-vs-cursor-two-ai-ides-walk-into-a-bar-2mje</link>
      <guid>https://dev.to/tyson_cung/windsurf-vs-cursor-two-ai-ides-walk-into-a-bar-2mje</guid>
      <description>&lt;p&gt;The AI-native IDE wars are heating up. For a while, Cursor was the obvious choice if you wanted an editor built around AI coding. Then Codeium shipped Windsurf and claimed the throne for a minute. Now we've got two serious contenders and developers trying to figure out which one to actually use.&lt;/p&gt;

&lt;p&gt;I've been switching between both. Here's my take.&lt;/p&gt;


&lt;div&gt;
    &lt;iframe src="https://www.youtube.com/embed/oB4uIXOhYsA"&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;


&lt;h2&gt;
  
  
  What Are We Actually Comparing?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cursor&lt;/strong&gt; is a VS Code fork with AI deeply integrated — not as an extension, but as first-class functionality. Tab completions, Cmd+K inline edits, the Composer (now called Agent) for multi-file edits. It uses a mix of frontier models and caches aggressively to keep latency low.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windsurf&lt;/strong&gt; is Codeium's full IDE, also VS Code-based, with their "Cascade" agent as the centerpiece. Cascade can take on multi-step tasks autonomously, browse the web, run terminal commands, and edit across multiple files. It's marketed as the more "agentic" of the two.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day-to-Day Editing
&lt;/h2&gt;

&lt;p&gt;Cursor wins here for most developers. The Tab completion is genuinely magical — it predicts multi-line edits with high accuracy, and the Cmd+K inline edit mode is fast and reliable. The UX has been refined over years of iteration.&lt;/p&gt;

&lt;p&gt;Windsurf's editing experience is good but plays second fiddle to Cascade. If you're not using Cascade, you're leaving most of Windsurf's value on the table. The basic completions are solid (it's Codeium under the hood) but don't feel as polished as Cursor's Tab.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Agentic Story
&lt;/h2&gt;

&lt;p&gt;This is where Windsurf pulls ahead — or at least, where it's making its bet. Cascade is more autonomous than Cursor's Agent. It'll plan a task, execute steps, check its work, and loop back when something fails. For big refactors or implementing features from scratch, Cascade can handle more without needing you to guide it.&lt;/p&gt;

&lt;p&gt;Cursor's Agent has caught up significantly in recent updates. It's also now capable of multi-file edits, running tests, and iterating. But in my experience, Cascade still takes on messier tasks with less hand-holding required.&lt;/p&gt;

&lt;p&gt;That said, agentic AI is still unreliable enough that I don't trust either to run unsupervised on important code. Both are tools that require oversight.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance and Stability
&lt;/h2&gt;

&lt;p&gt;Cursor is more stable. It's older, more battle-tested, and the VS Code base it's built on is rock solid.&lt;/p&gt;

&lt;p&gt;Windsurf has had more rough edges in my testing — occasional slowdowns, Cascade sometimes losing track of what it was doing, and the occasional crash. It's improving quickly, but if stability matters to you (and it should), Cursor is the safer choice right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Cursor: $20/month Pro, includes fast requests to frontier models and unlimited slower requests.&lt;/p&gt;

&lt;p&gt;Windsurf: $15/month Pro. Codeium's free tier works in Windsurf for basic completions. Cascade is usage-limited on free.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who Should Use Which
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cursor&lt;/strong&gt; is the better default choice. It's more polished, more stable, and the Tab completion is class-leading. If you're a developer who wants AI that enhances how you already work, Cursor nails it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windsurf&lt;/strong&gt; is worth trying if you're excited about agentic workflows and willing to tolerate some rough edges for the payoff of a more autonomous AI. If Cascade's roadmap keeps improving, this could flip.&lt;/p&gt;

&lt;p&gt;Both are far better than using Copilot in a regular VS Code window. The fully integrated experience — completions, chat, and agents in one tool — changes how you code in a way that extensions just don't.&lt;/p&gt;

&lt;p&gt;The honest answer: try both. They both have free tiers. Your preference will probably come down to whether Tab completion or Cascade resonates more with how you think about writing code.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Cursor or Windsurf person? Or are you still on vanilla VS Code? Let me know.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>tools</category>
      <category>webdev</category>
    </item>
    <item>
      <title>GitHub Copilot vs Codeium — I Used Both for a Month. Here's What I Actually Think.</title>
      <dc:creator>Tyson Cung</dc:creator>
      <pubDate>Sat, 11 Apr 2026 23:46:28 +0000</pubDate>
      <link>https://dev.to/tyson_cung/github-copilot-vs-codeium-i-used-both-for-a-month-heres-what-i-actually-think-2ff1</link>
      <guid>https://dev.to/tyson_cung/github-copilot-vs-codeium-i-used-both-for-a-month-heres-what-i-actually-think-2ff1</guid>
      <description>&lt;p&gt;The AI coding assistant market split somewhere between "pay for quality" and "free is good enough." GitHub Copilot sits squarely in the first camp. Codeium decided to be the second.&lt;/p&gt;

&lt;p&gt;I've spent the last few months switching between them on real projects — not demos, not tutorials, just actual work. Here's what I found.&lt;/p&gt;


&lt;div&gt;
    &lt;iframe src="https://www.youtube.com/embed/CXUntcxbnNY"&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;


&lt;h2&gt;
  
  
  What Each Is Trying to Do
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt; is built on OpenAI's Codex (and increasingly GPT-4 class models) with GitHub's training data advantage. It's deeply integrated into VS Code, JetBrains, and a growing list of editors. At $10/month individually or $19 for Business, it's not cheap for a single developer but is reasonable for a team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codeium&lt;/strong&gt; is free for individuals and positions itself as the "Copilot but without the paywall." It covers 70+ languages, supports VS Code, JetBrains, Neovim, and a bunch of others. Enterprise tier exists for teams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Completion Quality
&lt;/h2&gt;

&lt;p&gt;Copilot has better context over larger files. When I'm in a module with 300+ lines, Copilot tends to understand the patterns I've established and suggests completions consistent with my code style. Codeium's suggestions are good but occasionally feel disconnected — like it's completing based on the local context without understanding the broader patterns.&lt;/p&gt;

&lt;p&gt;For boilerplate (CRUD operations, tests, simple transformations), Codeium is nearly as good. The gap shows most on complex logic or when you're building on top of patterns you've established in the same file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed
&lt;/h2&gt;

&lt;p&gt;Codeium is faster. Noticeably so. I think this is partly infrastructure (they've clearly invested in latency) and partly model architecture choices. When I'm in a flow state and just want completions quickly, Codeium's responsiveness beats Copilot.&lt;/p&gt;

&lt;p&gt;Copilot's latency is acceptable — maybe 300-500ms for suggestions — but Codeium regularly comes in under 200ms in my experience. That's a real difference when you're completing several lines per minute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chat / Explain Features
&lt;/h2&gt;

&lt;p&gt;Copilot Chat (requires the separate chat extension or VS Code's built-in integration) is genuinely useful for explaining code, generating tests, and refactoring suggestions. The conversation quality is good.&lt;/p&gt;

&lt;p&gt;Codeium also has a chat feature and it's solid, but Copilot Chat has the edge on nuanced requests. When I ask "what's wrong with this function" and there are three issues, Copilot is more likely to catch all three.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy Tradeoffs
&lt;/h2&gt;

&lt;p&gt;This is where many teams make their decision. Copilot Business offers code snippet exclusion (your code doesn't get used to train the model), dedicated enterprise options, and clearer compliance documentation.&lt;/p&gt;

&lt;p&gt;Codeium's free tier privacy policy is... less detailed. For hobby projects and personal learning, this doesn't matter. For work on proprietary codebases, read the fine print before installing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Actual Verdict
&lt;/h2&gt;

&lt;p&gt;If you're a student, learning to code, working on open source, or just can't justify $10/month — Codeium is excellent for free. Don't let "free" make you assume it's bad. It genuinely accelerates your workflow.&lt;/p&gt;

&lt;p&gt;If you're working on commercial software, especially in a team environment, Copilot's quality edge and clearer enterprise policies make the $10-19/month worth it. The suggestions are better on complex code, and the peace of mind on data handling is real.&lt;/p&gt;

&lt;p&gt;The competition between them is good for developers either way. A year ago there was no credible free alternative to Copilot. Now there is. That's kept Copilot honest and improved both products.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Which AI coding tool are you using? Have you switched recently? Tell me in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>tools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why Most APIs Fail — 3 Mistakes That Kill Developer Experience</title>
      <dc:creator>Tyson Cung</dc:creator>
      <pubDate>Sat, 11 Apr 2026 23:45:56 +0000</pubDate>
      <link>https://dev.to/tyson_cung/why-most-apis-fail-3-mistakes-that-kill-developer-experience-3a5i</link>
      <guid>https://dev.to/tyson_cung/why-most-apis-fail-3-mistakes-that-kill-developer-experience-3a5i</guid>
      <description>&lt;p&gt;I've integrated hundreds of APIs over the years. Some were a pleasure. Most were a chore. A handful were genuinely painful experiences that made me question the life choices that led me to this career.&lt;/p&gt;

&lt;p&gt;The frustrating part: the same three mistakes show up over and over. They're not exotic bugs. They're design decisions that seemed fine at the time and became load-bearing walls of confusion later.&lt;/p&gt;


&lt;div&gt;
    &lt;iframe src="https://www.youtube.com/embed/xaegVsBuVzc"&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;


&lt;h2&gt;
  
  
  Mistake 1: Inconsistent Naming
&lt;/h2&gt;

&lt;p&gt;This sounds trivial. It isn't.&lt;/p&gt;

&lt;p&gt;I once integrated with an API where the user ID was called &lt;code&gt;userId&lt;/code&gt; in the auth endpoints, &lt;code&gt;user_id&lt;/code&gt; in the profile endpoints, and &lt;code&gt;uid&lt;/code&gt; in the events endpoints. Same field. Three names. Zero documentation explaining why.&lt;/p&gt;

&lt;p&gt;Inconsistent naming forces developers to check the docs for every single call. It breaks the intuition that good APIs build — the feeling that you can &lt;em&gt;guess&lt;/em&gt; what a field is called because everything follows the same pattern.&lt;/p&gt;

&lt;p&gt;The fix is boring: pick a convention (camelCase, snake_case, kebab-case — doesn't matter which) and use it everywhere. Make a linter rule if you have to. Never let "we just called it something different here" ship to production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bonus failure mode:&lt;/strong&gt; Naming things what they are today, not what they'll need to be. &lt;code&gt;isAdmin&lt;/code&gt; becomes a lie the moment you add a second role type. &lt;code&gt;premiumUser&lt;/code&gt; breaks when you launch three tiers. Use abstract names that survive your roadmap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake 2: No Versioning
&lt;/h2&gt;

&lt;p&gt;Every API will change. If you're not versioning, you're setting up for one of two bad outcomes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You never change anything because you're afraid of breaking integrations (stagnation)&lt;/li&gt;
&lt;li&gt;You change things and break integrations (chaos)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Versioning buys you the ability to evolve without punishing your existing users. &lt;code&gt;/v1/users&lt;/code&gt; stays stable. &lt;code&gt;/v2/users&lt;/code&gt; adds the new fields. Clients migrate on their schedule, not yours.&lt;/p&gt;

&lt;p&gt;The most common excuse for not versioning: "We'll add it when we need it." By the time you need it, you have production clients that assume the unversioned endpoint is permanent. Adding a version prefix to existing routes is a breaking change. You've trapped yourself.&lt;/p&gt;

&lt;p&gt;Start with versioning. Even if v1 never changes, having the habit in place means v2 doesn't cause a crisis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;URL vs Header versioning:&lt;/strong&gt; Both work. URL (&lt;code&gt;/v1/endpoint&lt;/code&gt;) is more visible and easier to debug. Header versioning (&lt;code&gt;Accept: application/vnd.api+json;version=2&lt;/code&gt;) is cleaner architecturally but harder to test in a browser. Pick one and document it clearly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake 3: Poor Error Responses
&lt;/h2&gt;

&lt;p&gt;This is the one that makes me lose my mind most often.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Something went wrong"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's not an error response. That's an apology. It tells me nothing I can act on.&lt;/p&gt;

&lt;p&gt;A good error response tells me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What&lt;/strong&gt; went wrong (specific, not generic)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why&lt;/strong&gt; it went wrong (validation failure? rate limit? bad auth?)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What I can do about it&lt;/strong&gt; (retry? fix the request? check my credentials?)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The gold standard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VALIDATION_ERROR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The 'email' field must be a valid email address"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"field"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"docs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.example.com/docs/errors#VALIDATION_ERROR"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can read that, understand it, and fix my request without a support ticket.&lt;/p&gt;

&lt;p&gt;Also: use the right HTTP status codes. &lt;code&gt;200 OK&lt;/code&gt; with an error body is a crime against HTTP. &lt;code&gt;401&lt;/code&gt; vs &lt;code&gt;403&lt;/code&gt; is not interchangeable. &lt;code&gt;404&lt;/code&gt; vs &lt;code&gt;410&lt;/code&gt; (gone vs not found) matters for caching behavior. These distinctions exist for a reason — use them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Cost of Getting This Wrong
&lt;/h2&gt;

&lt;p&gt;Bad API design doesn't just frustrate developers. It costs you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Support time&lt;/strong&gt; — most support tickets are "what does this error mean" or "where is this field"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration time&lt;/strong&gt; — slow, painful integrations mean fewer third-party developers bother&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Churn&lt;/strong&gt; — if your API is harder than a competitor's, the technical buyer notices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best APIs are the ones where developers get to the first successful call in under 10 minutes. That's the goal. Consistent naming, versioning from day one, and real error responses get you most of the way there.&lt;/p&gt;

&lt;p&gt;The boring stuff is usually the most important.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Which API gave you the worst integration experience? I want to hear the horror stories.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>webdev</category>
      <category>programming</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Tech Debt Compounds Like Interest — And Most Teams Are Already Bankrupt</title>
      <dc:creator>Tyson Cung</dc:creator>
      <pubDate>Sat, 11 Apr 2026 23:45:22 +0000</pubDate>
      <link>https://dev.to/tyson_cung/tech-debt-compounds-like-interest-and-most-teams-are-already-bankrupt-2l9i</link>
      <guid>https://dev.to/tyson_cung/tech-debt-compounds-like-interest-and-most-teams-are-already-bankrupt-2l9i</guid>
      <description>&lt;p&gt;Tech debt is the one thing every dev knows is a problem and almost nobody actually deals with it until it's too late.&lt;/p&gt;

&lt;p&gt;I've watched teams go from "we'll clean this up later" to "we can't ship anything without breaking three other things" in under a year. The compounding isn't a metaphor — it's mechanical.&lt;/p&gt;


&lt;div&gt;
    &lt;iframe src="https://www.youtube.com/embed/zkQ5qYkp3qg"&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;


&lt;h2&gt;
  
  
  What Actually Happens
&lt;/h2&gt;

&lt;p&gt;Every shortcut you take today creates friction for every engineer who touches that code afterward. That friction slows decisions, causes bugs, and makes refactoring scarier than it needs to be.&lt;/p&gt;

&lt;p&gt;Here's the thing about compound interest: small rates don't feel dangerous until you do the math. 10% compounding annually turns $1,000 into $6,727 in 20 years. Tech debt works the same way — a "quick hack" that saves 3 hours this sprint could cost 30 hours across the next six months as it calculates wrong, misleads other devs, and generates bug reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Phases Teams Go Through
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Phase 1 — Ignorance is bliss.&lt;/strong&gt; The codebase is young, features ship fast, nobody talks about tech debt because there isn't much of it. This is the honeymoon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 2 — Accumulation.&lt;/strong&gt; Deadlines get tight, shortcuts get taken. "We'll refactor this after launch" becomes a running joke. Each sprint adds more interest to the principal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 3 — The wall.&lt;/strong&gt; New features take three times as long. Bugs reproduce only in production. Onboarding new engineers becomes a multi-week affair because nobody can explain how anything actually works. This is the phase teams call "rewrite" — and that's almost always the wrong answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where It Actually Comes From
&lt;/h2&gt;

&lt;p&gt;Not just "bad developers" cutting corners. More often:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deadline-driven decisions&lt;/strong&gt; — someone above the team decided the date, and engineering bore the cost&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evolving requirements&lt;/strong&gt; — code written for spec A doesn't gracefully handle spec B three iterations later&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context loss&lt;/strong&gt; — the original author left, the code lives on, nobody knows why it works the way it does&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tooling drift&lt;/strong&gt; — the ecosystem moved on but the codebase didn't&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last one is underrated. Code written with React 16 patterns in a React 18 codebase isn't "wrong" exactly, but it's drag.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Actually Manage It
&lt;/h2&gt;

&lt;p&gt;You can't eliminate tech debt. Trying to is its own form of inefficiency. What you can do:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Track it explicitly.&lt;/strong&gt; Create tickets for known debt. Not a shame list — a backlog item with an actual cost estimate. "This authentication module has three known race conditions, estimated 2 days to fix properly." When it gets expensive enough, it gets prioritized.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Budget for it.&lt;/strong&gt; Some teams do 20% of sprint capacity on debt reduction. Others do one full "hardening sprint" per quarter. Either works. Nothing earmarked means nothing happens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pay debt at the point of touch.&lt;/strong&gt; Before adding a feature to a module, spend 30 minutes cleaning it up first. Boy Scout Rule: leave the codebase better than you found it. Marginal cost is low when you're already there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't let it block you.&lt;/strong&gt; Some debt is fine to live with. A poorly-named variable in a stable module nobody touches isn't worth a dedicated sprint. Save the effort for the high-traffic, high-churn areas.&lt;/p&gt;

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

&lt;p&gt;Here's what nobody says in the business meetings: tech debt is a transfer of cost from now to future-you. Your team isn't saving time by taking shortcuts. They're borrowing it. And the interest rate isn't fixed — it tends to go up as the codebase grows and the shortcut touches more things.&lt;/p&gt;

&lt;p&gt;The teams that consistently ship fast, year over year, are usually the ones treating their codebase like infrastructure worth maintaining. Not perfect — just maintained.&lt;/p&gt;

&lt;p&gt;If you're in Phase 2 right now, the best time to start was six months ago. The second best time is this sprint.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's the most expensive piece of tech debt you've ever had to deal with? Drop it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>techdebt</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
