<?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: Ravi Rohith Savaram</title>
    <description>The latest articles on DEV Community by Ravi Rohith Savaram (@ravirohith).</description>
    <link>https://dev.to/ravirohith</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4070791%2Fdcc12af0-a018-498b-81bd-b2bd8ba1e302.jpg</url>
      <title>DEV Community: Ravi Rohith Savaram</title>
      <link>https://dev.to/ravirohith</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ravirohith"/>
    <language>en</language>
    <item>
      <title>Architects, Not Code Writers: Why System Design Matters More in the Age of AI</title>
      <dc:creator>Ravi Rohith Savaram</dc:creator>
      <pubDate>Fri, 14 Aug 2026 05:24:16 +0000</pubDate>
      <link>https://dev.to/ravirohith/architects-not-code-writers-why-system-design-matters-more-in-the-age-of-ai-12di</link>
      <guid>https://dev.to/ravirohith/architects-not-code-writers-why-system-design-matters-more-in-the-age-of-ai-12di</guid>
      <description>&lt;p&gt;&lt;em&gt;How token economics make code structure a cost, speed, and correctness problem — not just a style one.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;If you're a software engineer working with AI coding agents, your job has fundamentally changed. You're no longer the person writing most of the diffs. You're the person designing systems that agents operate through — and how well you design those systems has measurable, compounding consequences.&lt;/p&gt;

&lt;p&gt;This isn't an abstract argument about clean code being "nice to have." Token economics turn code structure into a cost, speed, and correctness problem with real numbers attached to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shift
&lt;/h2&gt;

&lt;p&gt;Before AI agents, structure was a personal habit. Some teams enforced it, most let it slide. The code worked either way.&lt;/p&gt;

&lt;p&gt;Now, agents write, edit, and reason across your codebase continuously. Every time an agent touches your repo, it follows the same cycle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Read&lt;/strong&gt; — Pull in files, directory structure, dependencies, past context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reason&lt;/strong&gt; — Hold it all in the context window while planning the change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write&lt;/strong&gt; — Generate an edit or new code, often re-stating surrounding code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify&lt;/strong&gt; — Re-read to check the change, sometimes across several turns.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every one of these steps consumes tokens. A single coding task can loop through this cycle many times before it's done. And every token has a price — not just in dollars, but in real GPU compute, latency, and accuracy.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Token Actually Is
&lt;/h2&gt;

&lt;p&gt;A token is the chunk of text a model reads or writes at a time — roughly 4 characters of English prose.&lt;/p&gt;

&lt;p&gt;But here's the thing: &lt;strong&gt;code tokenizes worse than prose.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Symbols, punctuation, and indentation all cost tokens that carry little semantic meaning on their own. Long identifiers, boilerplate, and repeated imports inflate the count fast. &lt;code&gt;calculateShippingCostForOrder&lt;/code&gt; burns roughly 8 tokens just sitting there as a function name — before it does anything. Meanwhile, &lt;code&gt;fn&lt;/code&gt; is a single token but tells neither the agent nor the next human reader anything useful.&lt;/p&gt;

&lt;p&gt;Verbose or duplicated code is literally more expensive to read and write. Not metaphorically — literally.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Context Window Compounds
&lt;/h2&gt;

&lt;p&gt;This is where it gets expensive. In an agentic loop, most of the context from turn 1 gets re-sent on turn 2, turn 3, turn 4. The context doesn't just add linearly — it compounds.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Turn&lt;/th&gt;
&lt;th&gt;Approximate Context&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;~14K tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;~22K tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;~31K tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;~40K tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The same file gets paid for again and again. If that file is 2,400 lines when the agent only needs 90, you're paying for the other 2,310 lines on every single turn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Same Edit, Two Very Different Blast Radii
&lt;/h2&gt;

&lt;p&gt;Let's make this concrete. Task: "fix a rounding bug in checkout pricing."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The monolith approach&lt;/strong&gt; — a single &lt;code&gt;orders.py&lt;/code&gt; at 2,400 lines:&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;# orders.py — 2,400 lines
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_shipping&lt;/span&gt;&lt;span class="p"&gt;(...):&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_discount&lt;/span&gt;&lt;span class="p"&gt;(...):&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_inventory&lt;/span&gt;&lt;span class="p"&gt;(...):&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_email_receipt&lt;/span&gt;&lt;span class="p"&gt;(...):&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log_analytics&lt;/span&gt;&lt;span class="p"&gt;(...):&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.0725&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# &amp;lt;- bug here
&lt;/span&gt;    &lt;span class="c1"&gt;# … 40 more unrelated functions
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent reads ~9,600 tokens to make a one-line fix safely, because the whole file is one unit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The modular approach:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;checkout/
├── cart.py        (140 lines)
├── pricing.py      (90 lines)  ← bug lives here
└── checkout.py    (110 lines)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# pricing.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_tax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subtotal&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subtotal&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.0725&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# &amp;lt;- fix this
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bug lives in one 90-line file. Agent reads ~1,400 tokens. &lt;strong&gt;Nearly 7x cheaper&lt;/strong&gt; for the same fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caching Rewards Stability
&lt;/h2&gt;

&lt;p&gt;Modern model APIs offer prompt caching: reused context can be read back at roughly 90% off a fresh read. But caching only pays off when the same context is genuinely reusable turn to turn.&lt;/p&gt;

&lt;p&gt;A 90-line &lt;code&gt;pricing.py&lt;/code&gt; is stable and cacheable. The 2,400-line god-file that half-changes every turn? It invalidates its own cache constantly. Structure decides whether this discount is even available to you.&lt;/p&gt;

&lt;p&gt;In the modular case, that same 5-turn session on &lt;code&gt;pricing.py&lt;/code&gt; runs roughly &lt;strong&gt;3.5x cheaper&lt;/strong&gt; — for free, just by not re-explaining the file to the model every turn.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Compute Underneath
&lt;/h2&gt;

&lt;p&gt;The dollar figure is a proxy. Self-attention — the mechanism models use to relate every token to every other — gets more expensive faster than the token count grows.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1x context → ~1x compute&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2x context → ~4x compute&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;4x context → ~16x compute&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't linear. Doubling the context quadruples the compute. That means bigger context adds real latency to every turn — and real GPU-hours that somebody is paying for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bloated Context Doesn't Just Cost More — It Works Worse
&lt;/h2&gt;

&lt;p&gt;Research testing 18 frontier models found that accuracy degrades as input length grows, often well before the context window is even full. The pattern is consistent across every model tested:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Info at the start:&lt;/strong&gt; ~90% accuracy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Info in the middle:&lt;/strong&gt; ~58% accuracy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Info at the end:&lt;/strong&gt; ~87% accuracy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a coding agent, this is a third lever alongside cost and compute. A bloated file doesn't just cost more to read — the agent is measurably more likely to miss or misuse the one relevant function buried in the middle of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Duplicated Logic Multiplies Every Future Read
&lt;/h2&gt;

&lt;p&gt;Task: "tighten email validation rules." The same check exists in 5 files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Copy-pasted across the codebase:&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;# orders.py, billing.py, signup.py, support.py, admin.py — all contain:
&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fixing the rule means finding and editing 5 places — 5x the tokens, 5x the chance one gets missed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shared through a single module:&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;# validators.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix the rule once. Every call site is correct without being touched or re-read. This isn't new advice — DRY has been a principle for decades. What's new is that duplication now has a measurable per-invocation cost every time an agent traverses your codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Compounding Loop
&lt;/h2&gt;

&lt;p&gt;Here's the part that should make you uncomfortable: AI-written code builds on top of what's already there. Every change an agent makes becomes the context the next change is read against. Structure is self-reinforcing in both directions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Virtuous cycle:&lt;/strong&gt; Clean, modular code → agent reads only the relevant piece → small, well-scoped edit that fits the existing pattern → next task starts cheaper. The codebase keeps paying dividends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vicious cycle:&lt;/strong&gt; Tangled, sprawling code → agent pulls in far more than necessary to be safe → bolted-on edit that makes the pattern messier → next task starts more expensive and more error-prone than the last.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Good Signature Can Save an Entire File Read
&lt;/h2&gt;

&lt;p&gt;Task: "call this from the new refund flow." Can the agent trust the function signature, or does it have to read the entire body?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unclear:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# ~40 lines of logic
&lt;/span&gt;    &lt;span class="c1"&gt;# no types, no docstring
&lt;/span&gt;    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent must open and read the full body to know what this does. ~150 extra tokens just to trust one call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Self-describing:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_discount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;cart_total&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="n"&gt;discount_pct&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="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Applies a capped percentage discount.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Signature plus docstring is often enough. Body stays unread.&lt;/p&gt;

&lt;h2&gt;
  
  
  "But Repo Maps and Retrieval Fix This"
&lt;/h2&gt;

&lt;p&gt;Fair pushback. Modern coding agents increasingly use repo maps, embeddings-based search, and codebase indexing to fetch only what looks relevant — instead of reading a whole file blindly every time.&lt;/p&gt;

&lt;p&gt;But retrieval quality depends on structure too. Clear boundaries and names make it easy for a retrieval system to identify what's relevant. Tangled code with unclear boundaries confuses automated retrieval the same way it confuses a person skimming quickly.&lt;/p&gt;

&lt;p&gt;Better tooling raises the floor for everyone. But it performs best on exactly the codebases that are already well-structured. These tools shrink the gap. They don't erase it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Break the Vicious Cycle
&lt;/h2&gt;

&lt;p&gt;If a messy codebase makes every future agent task more expensive, the fix isn't to stop using AI on it. It's to point AI at the mess itself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Refactor as you go.&lt;/strong&gt; When a feature touches messy code, clean the touched area before extending it. Don't bolt on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Budget for it explicitly.&lt;/strong&gt; Treat structural cleanup as a normal line item in agent usage, not a "someday" project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Let agents propose the boundary.&lt;/strong&gt; Ask for a modularization plan before the feature, then implement against that plan.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Pays Off
&lt;/h2&gt;

&lt;p&gt;These aren't new principles. What's new is that each one now has a measurable impact on every agent interaction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modular boundaries&lt;/strong&gt; — clear seams limit how much an agent must read to change one thing safely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong naming and interfaces&lt;/strong&gt; — self-describing code reduces how much surrounding context is needed to reason correctly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs and READMEs as context&lt;/strong&gt; — written for humans, but now also the cheapest way to orient an agent fast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests as guardrails&lt;/strong&gt; — let an agent verify itself against tests instead of re-reading the whole surrounding system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No god-files&lt;/strong&gt; — a 5,000-line file forces an all-or-nothing read; small files let an agent scope precisely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit dependencies&lt;/strong&gt; — hidden coupling is invisible to an agent until it breaks something. Make it visible.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;"Architect" isn't a metaphor here. Your highest-leverage work is designing a system that stays cheap, fast, and correct for every agent that touches it next — human or otherwise.&lt;/p&gt;

&lt;p&gt;Every read and write is billed, in dollars and in real compute. Structure compounds: clean code keeps a task cheap for the next task, messy code makes every future one worse. And the choices that move the needle aren't grand architectural rewrites — they're small, measurable decisions. A file split. A clear signature. A shared module instead of a copy-paste.&lt;/p&gt;

&lt;p&gt;These are things you can estimate in tokens before you ship them. That's the new game.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>architecture</category>
      <category>programming</category>
    </item>
    <item>
      <title>Identity Infrastructure at Scale: The Hardest Problem Nobody Sees</title>
      <dc:creator>Ravi Rohith Savaram</dc:creator>
      <pubDate>Mon, 10 Aug 2026 08:49:46 +0000</pubDate>
      <link>https://dev.to/ravirohith/identity-infrastructure-at-scale-the-hardest-problem-nobody-sees-43fa</link>
      <guid>https://dev.to/ravirohith/identity-infrastructure-at-scale-the-hardest-problem-nobody-sees-43fa</guid>
      <description>&lt;p&gt;Every engineer has a mental model of what "hard problems" look like in large-scale systems. They think of recommendation engines, real-time video encoding, or distributed databases that span continents. Identity infrastructure rarely makes the list. And that's exactly why it's the hardest problem in the building — it's invisible until it breaks, and when it breaks, everything breaks.&lt;/p&gt;

&lt;p&gt;I've built identity systems that serve billions of users across multiple products. Along the way I've learned that identity isn't a service you bolt on. It's the connective tissue of your entire platform. Get it right and nobody notices. Get it wrong and you're looking at cascading auth failures, account takeovers at scale, and the kind of trust erosion that takes years to repair.&lt;/p&gt;

&lt;p&gt;This post is a practitioner's account of what actually works, what doesn't, and what I wish someone had told me when I started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Identity Is Structurally Different from Other Infrastructure
&lt;/h2&gt;

&lt;p&gt;Most backend systems can tolerate brief inconsistency. A social feed that's two seconds stale is fine. A search index that hasn't caught the last write is acceptable. Identity doesn't get that grace period.&lt;/p&gt;

&lt;p&gt;When a user changes their password, revokes a session, or enables two-factor authentication, that change must propagate instantly and universally. If there's a ten-second window where an old session token still works after a password reset, you've created a ten-second window for an attacker who already has that token. Identity is one of the few domains where &lt;strong&gt;consistency isn't a nice-to-have — it's a security boundary&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At the same time, identity sits in the critical path of every single request. Every API call, every page load, every real-time message begins with "who is this user, and are they allowed to do this?" If your identity layer goes down, your entire platform goes down. That means you also need extreme availability.&lt;/p&gt;

&lt;p&gt;This is the fundamental tension: you need strong consistency &lt;em&gt;and&lt;/em&gt; extreme availability, which anyone who's read the CAP theorem knows is a painful place to live. The real engineering isn't choosing one over the other. It's designing around the tension so that the tradeoffs are invisible to users and safe for the platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Design Challenges
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Federated Identity Across Products
&lt;/h3&gt;

&lt;p&gt;Single-product companies have it easy. One user table, one auth flow, one session model. But the moment you operate a family of products — each with its own history, its own user base, its own auth requirements — identity becomes a federation problem.&lt;/p&gt;

&lt;p&gt;The naive approach is to build a central identity service and migrate everyone onto it. I've watched this approach fail more than once. Products have different trust levels, different session lifetimes, different regulatory environments. A messaging product handles identity differently than an e-commerce platform or a streaming service.&lt;/p&gt;

&lt;p&gt;What works is a &lt;strong&gt;layered identity model&lt;/strong&gt;: a core identity graph that establishes who a person &lt;em&gt;is&lt;/em&gt;, with product-specific identity projections that handle how that person is represented and authenticated in each context. The core layer owns the canonical user record, credential storage, and cross-product linkage. The projection layer owns product-specific sessions, scopes, and consent surfaces.&lt;/p&gt;

&lt;p&gt;This separation sounds clean on a whiteboard. In practice, the hard part is the boundary. Where does the core layer end and the product layer begin? The answer shifts over time, and you need to design for that migration path, not just the current state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Token Lifecycle at Billions Scale
&lt;/h3&gt;

&lt;p&gt;A typical large-scale platform might have tens of billions of active tokens at any given moment — access tokens, refresh tokens, device tokens, API tokens, OAuth grants. Each has its own lifetime, revocation semantics, and blast radius if compromised.&lt;/p&gt;

&lt;p&gt;The mistakes I see most often:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Over-reliance on long-lived tokens.&lt;/strong&gt; Engineers default to long expiration times because short-lived tokens mean more refresh traffic. But long-lived tokens are long-lived attack surfaces. The right pattern is short-lived access tokens (minutes, not hours) backed by longer-lived refresh tokens with rotation on every use. If a refresh token is used twice, you know it's been stolen — kill the entire token family.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Revocation as an afterthought.&lt;/strong&gt; It's easy to issue tokens. It's incredibly hard to revoke them instantly across a globally distributed system. Maintaining a global revocation list that every service checks on every request doesn't scale. What does scale is a combination of short token lifetimes (so most revocations are "wait for expiry"), a lightweight real-time revocation channel for critical events (password changes, account compromises), and epoch-based invalidation where you can bump a user's "auth epoch" and instantly invalidate everything issued before it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treating all tokens as equal.&lt;/strong&gt; A token that lets you read your own profile and a token that lets you modify account security settings should not have the same architecture. Step-up authentication — requiring a fresh, stronger auth challenge before high-risk operations — is essential. But it needs to be baked into the token model, not layered on top.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zero Trust in a Multi-Service World
&lt;/h3&gt;

&lt;p&gt;The old model was simple: authenticate at the edge, then trust everything inside the network perimeter. That model is dead, and it should be. Any system with hundreds of internal services has too large an internal attack surface to trust implicitly.&lt;/p&gt;

&lt;p&gt;In practice, zero trust for identity means every service-to-service call carries user context and is independently verified. The user's identity and their authorization scopes travel with the request, and each service makes its own authorization decision based on that context.&lt;/p&gt;

&lt;p&gt;The engineering challenge is doing this without destroying latency. If every service makes a fresh call to your identity service on every request, you've built a system where your identity service's p99 latency &lt;em&gt;is&lt;/em&gt; your platform's p99 latency. The solution is cryptographic verification at the edge: signed, self-contained tokens (like JWTs, but carefully — see below) that services can verify locally without a network call, combined with an asynchronous revocation channel for the cases where you need to pull the rug out.&lt;/p&gt;

&lt;p&gt;A word of caution on JWTs specifically: they've become the default answer, but they're not a free lunch. They can't be revoked without infrastructure to support it. They bloat quickly when you stuff too many claims in. And the ecosystem of JWT libraries has a terrible security track record — algorithm confusion attacks, none-algorithm acceptance, key confusion between signing and encryption. If you use JWTs, treat the library choice and configuration as a security-critical decision, not a dependency you pull in and forget about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Patterns That Work (and Ones That Break)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Hierarchical identity models work.&lt;/strong&gt; Rather than a flat user → session mapping, model identity as a tree: person → accounts → sessions → tokens. This gives you natural revocation cascades (disable an account, all its sessions die; kill a session, all its tokens die) and clean multi-account support.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Progressive authentication works.&lt;/strong&gt; Not every action requires the same level of assurance. Let users browse with a session cookie, but require a fresh password or biometric before they change their email or download their data. This reduces friction for low-risk flows while maintaining security for high-risk ones. The key is building this into your identity model from the start — retrofitting progressive auth onto a system that treats all sessions as equal is painful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global session management works, eventually.&lt;/strong&gt; Letting a user see and revoke all their active sessions across all devices sounds simple. Building it at scale, across multiple products, with real-time accuracy, is a multi-year infrastructure project. But it's table stakes for user trust and regulatory compliance (GDPR's right to withdrawal of consent, for instance). Start early.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What breaks: monolithic auth services.&lt;/strong&gt; I've seen teams build a single auth service that handles registration, login, session management, OAuth, SAML, passwordless auth, and fraud detection. It becomes the most critical, most complex, and most feared service in the entire stack. No one wants to deploy to it. No one fully understands it. Break it up. Separate the credential verification path from the session management path from the token issuance path. They have different scaling characteristics, different failure modes, and different change velocities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What breaks: treating identity migration as a one-time project.&lt;/strong&gt; Identity infrastructure is never done. Credential standards change (passwords → OTP → push notifications → passkeys). Regulatory requirements shift. New products join the platform. Design for continuous migration, not a big bang cutover.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Most Engineers Get Wrong
&lt;/h2&gt;

&lt;p&gt;The biggest mistake is treating identity as an application feature rather than a platform primitive. When identity is owned by a product team, you get auth flows that are optimized for that product's onboarding funnel but impossible to extend to new products. When identity is a platform, you get consistent security properties everywhere, even in products that haven't been built yet.&lt;/p&gt;

&lt;p&gt;The second mistake is underinvesting in the unglamorous parts. Credential rotation, token hygiene, session cleanup, audit logging — these aren't exciting. They're also the things that determine whether you survive a security incident or end up in the news.&lt;/p&gt;

&lt;p&gt;The third is ignoring the human side. Identity systems are ultimately about people, and people do unpredictable things. They share accounts. They forget passwords on devices they no longer own. They pass away, and someone needs to access their account. They're minors who age into adulthood and need their data handling to change. Every identity system I've built has eventually needed to handle cases that no spec anticipated, and the systems that handled them gracefully were the ones designed with extensibility and human judgment baked in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Identity Infrastructure Is Heading
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Passkeys are the most significant shift in consumer authentication in a decade.&lt;/strong&gt; They eliminate passwords entirely, replacing them with device-bound cryptographic credentials that are phishing-resistant by design. The migration is messy — you need to support passwords and passkeys simultaneously for years — but the security improvement is step-function, not incremental. If you're building identity infrastructure today and you're not planning for passkeys, you're building for the past.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decentralized identity (DIDs, verifiable credentials) is interesting but not ready for mainstream consumer platforms.&lt;/strong&gt; The standards are maturing, but the user experience is still poor, and the trust model requires users to manage cryptographic material, which history says they won't do reliably. Watch this space, but don't bet your architecture on it yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI-driven adaptive authentication is already here in practice, even if it's not always labeled that way.&lt;/strong&gt; Risk-based authentication — adjusting the auth challenge based on device fingerprint, location, behavioral signals — has been standard at scale for years. What's changing is the sophistication of the signals and the models. Expect authentication to become increasingly invisible for legitimate users and increasingly hostile for attackers, with the identity system making real-time judgments about how much friction to introduce.&lt;/p&gt;

&lt;p&gt;The constant across all of these trends is that identity infrastructure keeps getting more complex, more critical, and more underappreciated. If you're an engineer working in this space, know that what you're building is the foundation everything else stands on. And if you're not in this space, the next time you log in seamlessly across three products on two devices without thinking about it — someone built that, and it was harder than it looked.&lt;/p&gt;

</description>
      <category>identity</category>
      <category>security</category>
      <category>systemdesign</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
