<?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: Adam - The Developer ✨</title>
    <description>The latest articles on DEV Community by Adam - The Developer ✨ (@adamthedeveloper).</description>
    <link>https://dev.to/adamthedeveloper</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%2F1002243%2F2c616028-c3f5-4013-87d5-2815b28aa1f3.jpeg</url>
      <title>DEV Community: Adam - The Developer ✨</title>
      <link>https://dev.to/adamthedeveloper</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adamthedeveloper"/>
    <language>en</language>
    <item>
      <title>Greatness Is Forged by Limitation</title>
      <dc:creator>Adam - The Developer ✨</dc:creator>
      <pubDate>Wed, 19 Aug 2026 13:04:47 +0000</pubDate>
      <link>https://dev.to/adamthedeveloper/greatness-is-forged-by-limitation-e20</link>
      <guid>https://dev.to/adamthedeveloper/greatness-is-forged-by-limitation-e20</guid>
      <description>&lt;p&gt;Can't believe I spent 2 weeks writing this.&lt;/p&gt;

&lt;p&gt;Last week, I gave a talk at a Cursor community event about AI and how it's changing the way we build software. The event went great, and after the talk, quite a few people came up to me for 1:1 conversations.&lt;/p&gt;

&lt;p&gt;One particular guy caught my attention. He wasn't a technical person, but he asked me something interesting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"With so many tools and technologies available today, how do you even navigate all of this and pick the right ones?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;He thought it must be overwhelming. Then he smiled and said that with so many options available, he hopes many great things be built.&lt;/p&gt;

&lt;p&gt;I thought about it for a second and smiled too, and before I could answer, he had to leave... but his question stuck with mi.&lt;/p&gt;

&lt;p&gt;A few days later, sitting in a library looking for something to read, I ran into an answer: &lt;em&gt;&lt;a href="https://www.amazon.com/UNIX-Network-Programming-Networking-Sockets/dp/013490012X" rel="noopener noreferrer"&gt;UNIX Network Programming&lt;/a&gt;&lt;/em&gt; by W. Richard Stevens. (Great book btw, give it a read!)&lt;/p&gt;

&lt;p&gt;90s tech, limited memory, limited processing power, limited bandwidth and limited tooling... etc.&lt;/p&gt;

&lt;p&gt;Yet somehow, we got things like UNIX, TCP/IP, early operating systems, incredible mathematical breakthroughs, massive engineering projects, and some of the most elegant pieces of technology ever built.&lt;/p&gt;

&lt;p&gt;It made me wonder:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if the things that limited us were also the things that forced us to become better?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What if greatness isn't always created by having more, but by being forced to do more with less?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The guy assumed more tools meant a better shot at greatness, but the book in my hands was proof of the opposite.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Paradox of Limitation
&lt;/h2&gt;

&lt;p&gt;I believe there's a reason having less can sometimes make us better.&lt;/p&gt;

&lt;p&gt;We usually think of limitations as something to overcome: less money, less time, fewer resources, less knowledge. All of it standing between us and what we want to achieve.&lt;/p&gt;

&lt;p&gt;But there's another side to limitation we don't talk about enough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A limitation doesn't just take something away. It also takes away what could have been.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And maybe that's exactly what we need. Because when everything is available, when every direction is possible, every tool is at hand, every approach is open to us, it sounds like freedom.&lt;/p&gt;

&lt;p&gt;But freedom without boundaries can be surprisingly hard to live inside.&lt;/p&gt;

&lt;p&gt;You give someone unlimited resources and they can spend a lifetime deciding what to do with them. Give them nothing and the question suddenly gets simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How much can I achieve with what I have?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That question changes how you think. You stop searching for the perfect tool, because it doesn't exist, and start building with what's in front of you. You notice details that would otherwise stay invisible, not because you're more observant by nature, but because you no longer have the luxury of not noticing.&lt;/p&gt;

&lt;p&gt;Maybe that's the real gift of limitation. Narrowing down your options but also sharpening your attention.&lt;/p&gt;

&lt;p&gt;Perhaps that's the paradox: the fewer doors we have, the more clearly we see the one we're standing in front of.&lt;/p&gt;

&lt;p&gt;And btw, this isn't a new idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Constraints Force Creativity
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The book
&lt;/h3&gt;

&lt;p&gt;Let's take a look at Stevens' book for a moment. The book is essentially a walkthrough of the sockets API: &lt;code&gt;socket()&lt;/code&gt;, &lt;code&gt;bind()&lt;/code&gt;, &lt;code&gt;listen()&lt;/code&gt;, &lt;code&gt;accept()&lt;/code&gt;, &lt;code&gt;connect()&lt;/code&gt;, &lt;code&gt;read()&lt;/code&gt;, &lt;code&gt;write()&lt;/code&gt;, and &lt;code&gt;close()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's the whole vocabulary for making two machines on opposite sides of the planet talk to each other reliably.&lt;/p&gt;

&lt;p&gt;But Stevens didn't invent those calls. The Berkeley sockets came out of UC Berkeley's CSRG in 4.2BSD, around 1983. Stevens wrote the book that taught a generation of programmers how they actually worked.&lt;/p&gt;

&lt;p&gt;He wasn't designing for a world of infinite compute. He was documenting an API built in an era of expensive memory, slow CPUs, and unreliable, low-bandwidth links and there was no room for mistakes, sprawling do-everything interfaces, or generic, accept-all contracts.&lt;/p&gt;

&lt;p&gt;Every function had to earn its place.&lt;/p&gt;

&lt;p&gt;And with those constraints forced upon the people who designed it, the result is an API so minimal and well-composed that, four decades later, in a world where none of those original constraints exist anymore, it's still the interface nearly every programming language wraps for networking.&lt;/p&gt;

&lt;p&gt;Take Python's &lt;code&gt;socket&lt;/code&gt; module, Node's &lt;code&gt;net&lt;/code&gt; module, or Go's &lt;code&gt;net&lt;/code&gt; package, they all trace their shape back to those same eight or so primitives.&lt;/p&gt;

&lt;p&gt;The paradox in miniature: by not having the luxury of building something bloated, they had no choice but to build something timeless instead. BSD built it under scarcity. Stevens documented why it was that tight.&lt;/p&gt;

&lt;p&gt;And of course, this is also what surprised &lt;em&gt;mi&lt;/em&gt; when I decided to pick up a book from the 90s. I expected it to feel dated but instead, I ended up learning a great deal from it, much of which I can still apply to the software I'm building today.&lt;/p&gt;

&lt;h3&gt;
  
  
  C
&lt;/h3&gt;

&lt;p&gt;The language that started it all, laying the foundation for everything we have today.&lt;/p&gt;

&lt;p&gt;C is a good example here, a language so elegant yet it gives you remarkably little. no GC, no elaborate standard abstractions, no safety net between you and memory. want something? you often have to understand what's happening underneath.&lt;/p&gt;

&lt;p&gt;By today's standards, we'd call it unsafe or labeling it a weakness but that limitation also forces a certain kind of thinking, you have to pay more attention to details, you become more conscious of memory, data layout, ownership and what the machine's actually doing.&lt;/p&gt;

&lt;p&gt;The language doesn't give you many options or answers but it makes you ask better questions and make better, timeless decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go
&lt;/h3&gt;

&lt;p&gt;Let's come back to the future, let's look at Go. Go takes a different direction, Its constraints weren't imposed by hardware, they were largely chosen by its designers.&lt;/p&gt;

&lt;p&gt;With all the things available by its time, the language was designed with its featured kept deliberately minimal &amp;amp; simple. syntax wise, type system wise, fewer ways to express the same idea.&lt;/p&gt;

&lt;p&gt;When a language gives you fewer ways to solve a problem, you spend less time debating which clever abstraction to use and more time solving the problem itself.&lt;/p&gt;

&lt;p&gt;Go's restraint is the feature, What it leaves out is just as intentional as what it includes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Music
&lt;/h3&gt;

&lt;p&gt;I play the piano, so this one isn't theoretical.&lt;/p&gt;

&lt;p&gt;Today you can put a DAW, a thousand plugins, and an AI vocal fixer on a laptop and make a record anywhere. In the 70s and 80s, a lot of that work was physical. Cut the wrong stretch of tape and it was gone. Limited tracks, limited studio time, expensive gear. The band had to know the part. Screw up a take and sometimes everyone started over.&lt;/p&gt;

&lt;p&gt;When recording time costs real money, you don't spend six hours on a snare. When you have eight tracks, you decide what deserves one. You can hear that in the records: the performances, the imperfections, the decisions.&lt;/p&gt;

&lt;p&gt;I'm not arguing we go back to splicing tape. I'm saying the constraint did work that infinite undo doesn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem With Having Everything
&lt;/h2&gt;

&lt;p&gt;Abundance can create complacency, endless choices... which creates the temptation to solve every problem by simply throwing more at it.&lt;/p&gt;

&lt;p&gt;Let's come back to our topic regarding AI. Like a modern DAW, I believe AI is a wonderful partner in our work. But next to that, it is also removing a great deal of constraints faster than almost anything we've seen before.&lt;/p&gt;

&lt;p&gt;Just a few years ago, a requested feature would take around 1-2 months. Trying a different architecture meant actually building it. Rewriting a block of code took time, and if it wasn't mine, I had to understand the context first.&lt;/p&gt;

&lt;p&gt;Now I can ask AI to do all of that in seconds. The thing that used to stop you was effort. When that cost drops, it's easy to stop asking whether you should do it at all. You generate five versions instead of picking one. You add another library because the model already knows it. You rewrite working code because the new draft looks cleaner.&lt;/p&gt;

&lt;p&gt;The shift isn't "can I build this?" anymore. it's &lt;strong&gt;"Should I?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you have nothing, the limits are imposed on you. When you have everything, &lt;strong&gt;you have to impose some on yourself.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So What Do You Do With That
&lt;/h2&gt;

&lt;p&gt;I never got to answer that guy at the event. If I could now, I wouldn't give him a list of tools.&lt;/p&gt;

&lt;p&gt;I'd tell him more options don't guarantee better work and they just make it easier to never decide. The 90s didn't produce UNIX because people had more. They produced it because they had less, and less forced the work to get honest.&lt;/p&gt;

&lt;p&gt;That doesn't mean throw AI away, or go back to cutting tape, or write everything in C. It means the environment won't hand you a limit for free anymore. If you want the sharpening, you have to pick one. Ship one use case. Let the model generate the boring parts and keep the core decision yours. Give yourself a deadline ugly enough that you can't keep adding.&lt;/p&gt;

&lt;p&gt;Cap the stack this week.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>webdev</category>
      <category>career</category>
    </item>
    <item>
      <title>Understanding Over Origin: The Missing Friction</title>
      <dc:creator>Adam - The Developer ✨</dc:creator>
      <pubDate>Tue, 04 Aug 2026 04:36:13 +0000</pubDate>
      <link>https://dev.to/adamthedeveloper/understanding-over-origin-the-missing-friction-55ag</link>
      <guid>https://dev.to/adamthedeveloper/understanding-over-origin-the-missing-friction-55ag</guid>
      <description>&lt;p&gt;A few days ago, I wrote &lt;a href="https://dev.to/adamthedeveloper/understanding-over-origin-4685"&gt;"Understanding Over Origin"&lt;/a&gt; and it got alot of engagement and I'm really happy that it did because it means people took the time to read, understand my perspective and I get to engage with every one of them in the comments as well. Of course, not everyone agrees but that's irrevelant, the point is a healthy discussion between various perspective from different developers around the world.&lt;/p&gt;

&lt;p&gt;But what I haven't told anyone is this: the more I engage, the more I realized something that I still do. I still write a lot of my code by hand and those are the parts I'm more proud of "&lt;/p&gt;

&lt;p&gt;Not gatekeeping, not me being nostalgic or identity-defensive ( well, a little nostalgic ), that's me admitting the article I published was &lt;em&gt;incomplete&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Some conversations don't end when the replies stop. My discussion with &lt;a class="mentioned-user" href="https://dev.to/darkwiiplayer"&gt;@darkwiiplayer&lt;/a&gt;  was probably my favorite of all because more we talked, the more I found myself wrestling with an incomplete idea that refused to stay unfinished and this essay is the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Discussion Clarified
&lt;/h2&gt;

&lt;p&gt;First, I need to thank the people who actually engaged with the core argument.&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/unitbuilds"&gt;@unitbuilds&lt;/a&gt; gave his take that seams everything together and concludes the core idea of modern software enigeering: " &lt;em&gt;If it can run a standardized benchmarking suite against competition, it's provable and reproducible. If that's good enough for a scientific discovery, it's good enough for programming."&lt;/em&gt;, they're not defending AI, they're saying with better standards available, we shouldn't choose to ignore them. He also pointed out something I'd missed, the burden of correctness has always been on the developer who signs off on the PR. &lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/madsendev"&gt;@madsendev&lt;/a&gt; who wrote the original article that sparked this whole discussion, showed genuine class. He came back, said the argument had "gone further," and proposed an idea that's stuck with me: what if AI-assisted projects included a standard where you quiz yourself on your own repository? Not to prove you didn't use AI, but to prove you actually understand what you built.&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/reidmarlow"&gt;@reidmarlow&lt;/a&gt;  hit on something important and i think it's my favorite takeaway from the discussion: &lt;strong&gt;"Maintenance receipts are much harder to fake."&lt;/strong&gt; That single sentence reframes the entire debate. Tests. Bug fixes. Production incidents. Responding to issues. Refactoring. Every one of those leaves a trail of evidence that someone not only built the project but continues to understand, improve, and take responsibility for it. That's the kind of ownership that matters. It's earned over time, and it's far harder to fake than explaining code in an interview or claiming you wrote every line by hand.&lt;/p&gt;

&lt;p&gt;I'm absolutely grateful that people gave in their thoughts but you can never have a good discussion without a pushback ⚔️&lt;/p&gt;

&lt;p&gt;the pushback's always my favorite part of any technical discussion.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge That Made Me Think
&lt;/h2&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/darkwiiplayer"&gt;@darkwiiplayer&lt;/a&gt; showed up and said something like: "Training AI on stolen code without consent is theft. Everything built with AI carries that theft in its DNA. You're overlooking this."&lt;/p&gt;

&lt;p&gt;She wasn't being rhetorical, she was actually making a philosophical point about training data, consent, and what "learning" means when it's done at scale without permission.&lt;/p&gt;

&lt;p&gt;We went back and forth. I argued that training data and generated output aren't automatically equivalent to copying and she countered that if you removed all stolen code from training data, the models wouldn't exist as they do. Which is... probably true? And that matters.&lt;/p&gt;

&lt;p&gt;I don't think it invalidates the &lt;em&gt;engineering&lt;/em&gt; argument. But it does mean the conversation has two layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The technical layer&lt;/strong&gt;: is the work maintained, understood, and good?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The ethical layer&lt;/strong&gt;: how should we feel about tools built on potentially non-consensual training data?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most people in that thread were debating layer 1 and she dragged me down to layer 2 into the conversation. Both are real. Neither invalidates the other.&lt;/p&gt;

&lt;p&gt;But it also made me realize my original article &lt;em&gt;didn't address&lt;/em&gt; why handwritten code felt different to me because honestly? it does.&lt;/p&gt;

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

&lt;p&gt;The argument I made: origin doesn't determine quality. Understanding, testing, maintainability, accountability, that's what matters.&lt;/p&gt;

&lt;p&gt;My own experience reflects that. I started writing code around 2018, and back then the only AI most of us could name was Sophia, the humanoid robot from Hong Kong. I learned the traditional way: by writing everything myself. Even today, when I write code by hand, I understand it differently. More deeply. I notice edge cases I might have overlooked if I'd generated the first draft with AI. And when I'm done, I'm genuinely more proud of what I've built.&lt;/p&gt;

&lt;p&gt;These aren't compatible statements if you think about them too hard.&lt;/p&gt;

&lt;p&gt;Either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;My pride is just ego (origin bias)&lt;/li&gt;
&lt;li&gt;Handwritten code actually &lt;em&gt;is&lt;/em&gt; better (proving the gatekeepers right)&lt;/li&gt;
&lt;li&gt;Both are true, but for reasons I didn't examine&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/fromzerotoship"&gt;@fromzerotoship&lt;/a&gt; helped me see option 3 clearly. They're not a developer but they've shipped 20+ working internal tools using AI. A hospital runs them. By my standards, they'd "fail" the understanding test, there are parts of their system they couldn't explain line-by-line.&lt;/p&gt;

&lt;p&gt;But then they said something that shifted everything: &lt;em&gt;"Demonstrable behavior under deliberate failure is another form of earning trust, and it's the only one available to me. It's also harder to fake."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Plant defects, watch the guards catch them, restore the guards and watch them go green and then deploy and check the URLs a few seconds later.&lt;/p&gt;

&lt;p&gt;they demonstrate that they can keep it alive.&lt;/p&gt;

&lt;p&gt;And that made me realize the real distinction wasn't about who typed the code. It was about &lt;strong&gt;&lt;em&gt;friction&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Friction Actually Matters
&lt;/h2&gt;

&lt;p&gt;In my earlier &lt;a href="https://dev.to/adamthedeveloper/i-could-review-it-i-couldnt-write-it-3gfj"&gt;piece&lt;/a&gt; I wrote a few weeks ago, I described not being able to write some logic from scratch despite reviewing it perfectly, that wasn't just skill loss. It was proof that I'd skipped the friction that builds actual understanding.&lt;/p&gt;

&lt;p&gt;When I write code by hand, &lt;strong&gt;I encounter problems in real-time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I hit a wall. My approach doesn't work. I refactor. I discover the problem space through constraint and failure. I make decisions &lt;em&gt;about decisions&lt;/em&gt;, not just typing, but choosing between paths I've actually explored. this is the learning path that I unknowingly go through whenever I write code by hand and Wii reminded me of this.&lt;/p&gt;

&lt;p&gt;When I use AI, I describe what I want. I get options. I pick the one that looks right. &lt;strong&gt;I'm curating, not exploring.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both can produce good code. But the &lt;em&gt;path to understanding&lt;/em&gt; is fundamentally different.&lt;/p&gt;

&lt;p&gt;With handwritten code: friction, insight, better next decisions&lt;br&gt;&lt;br&gt;
With AI-assisted: selection, implementation, validation&lt;/p&gt;

&lt;p&gt;The friction is the learning mechanism.&lt;/p&gt;

&lt;p&gt;So when I say I'm more proud of handwritten code? I'm not being romantic about suffering. I'm noting that &lt;strong&gt;the code I'm proudest of is the code I fought for&lt;/strong&gt;, and handwriting forces the fight.&lt;/p&gt;

&lt;h2&gt;
  
  
  But Here's the Problem With That Logic
&lt;/h2&gt;

&lt;p&gt;If friction is the mechanism, then the &lt;em&gt;type&lt;/em&gt; of friction matters more than &lt;em&gt;who did the typing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You could write AI-assisted code where you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fight with the prompt&lt;/li&gt;
&lt;li&gt;Critique every generated option&lt;/li&gt;
&lt;li&gt;Refactor aggressively&lt;/li&gt;
&lt;li&gt;Hit walls and redesign&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That has friction and it also builds understanding.&lt;/p&gt;

&lt;p&gt;Conversely, you could hand-write code where you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Autopilot through a familiar pattern&lt;/li&gt;
&lt;li&gt;Never question assumptions&lt;/li&gt;
&lt;li&gt;Copy-paste from Stack Overflow&lt;/li&gt;
&lt;li&gt;Never understand &lt;em&gt;why&lt;/em&gt; it works&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That has no friction and it builds nothing.&lt;/p&gt;

&lt;p&gt;So the honest version of my position isn't "handwritten code is better." It's: &lt;strong&gt;"friction builds understanding, and handwriting &lt;em&gt;tends to create friction&lt;/em&gt; because you're forced to think through every line."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But that's a contingent truth, not an absolute one.&lt;/p&gt;

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

&lt;p&gt;The critics ( gatekeepers, but we'll stick with this from now on ) were partially right and I was too generous in my original position.&lt;/p&gt;

&lt;p&gt;Not about the gatekeeping itself, no, that's still wrong. But about the &lt;em&gt;tendency&lt;/em&gt;: AI &lt;em&gt;does&lt;/em&gt; make it easier to produce low-understanding code. Not because AI is bad, but because &lt;strong&gt;removing friction is literally what AI does, and friction is what builds understanding.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer isn't "use less AI" or "never use AI." It's "if you use AI to skip engagement with the problem, whether that's the code, the failure modes, or the maintenance, you build worse systems.&lt;/p&gt;

&lt;p&gt;That applies to humans too but humans have an inherent friction cost, we get bored, we hate typing, we make mistakes. That friction is annoying, but it forces us to stay engaged.&lt;/p&gt;

&lt;h2&gt;
  
  
  So What Changed?
&lt;/h2&gt;

&lt;p&gt;Nothing about the original argument was &lt;em&gt;wrong&lt;/em&gt;. But I was treating "understanding + accountability" as if they were just checkboxes you could verify at the end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;They're not.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Understanding isn't a property you can inspect, it's a &lt;em&gt;process&lt;/em&gt; and that process requires friction. Real engagement with the problem. Mistakes you learn from.&lt;/p&gt;

&lt;p&gt;The reason I'm prouder of handwritten code is because I &lt;em&gt;earned&lt;/em&gt; the understanding in a way that's harder to fake.&lt;/p&gt;

&lt;p&gt;Does that mean every line should be handwritten? No. Boilerplate is boilerplate. Some friction is just noise.&lt;/p&gt;

&lt;p&gt;But the core logic? The architecture decisions? The places where "understanding this code" actually matters? &lt;strong&gt;Yeah, I want to have fought for that.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And I want the same from anyone shipping code that matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Uncomfortable Middle Ground
&lt;/h2&gt;

&lt;p&gt;Here's where I land:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To the critics:&lt;/strong&gt; You're using the wrong filter. "AI or no AI" doesn't tell you anything but you're accidentally right that there's something real to be concerned about, it's the &lt;em&gt;laziness&lt;/em&gt; that AI enables, not the tool itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To AI enthusiasts:&lt;/strong&gt; Yeah, your tooling is amazing. But it's worth asking whether you're using it to think better or think less. Those feel the same until you try to maintain the code six months later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To myself:&lt;/strong&gt; The pride I feel in handwritten code isn't ego, It's legitimate. every line that I typed out isn't some sort of magical unicorn mythological Godly line but it's the friction that comes with it, the learning I build that comes with it.&lt;/p&gt;

&lt;p&gt;Sometimes the answer requires admitting you skipped and sometimes that's fine for routine work. But if you're building something that matters, you should want to have fought for it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Choose Where You Fight
&lt;/h2&gt;

&lt;p&gt;I still write a lot of code by hand. I still use AI every day. Those aren't contradictions anymore.&lt;/p&gt;

&lt;p&gt;The original article was right: origin doesn't determine quality. What it missed is that understanding isn't a checkbox you tick at the end. It's something you earn through friction. Handwriting tends to create that friction. AI tends to remove it. Neither is inherently good or bad. Both are choices about how you engage with the problem.&lt;/p&gt;

&lt;p&gt;So I'm not asking "Did you use AI?" anymore.&lt;/p&gt;

&lt;p&gt;I'm asking: Did you fight for the parts that matter?&lt;/p&gt;

&lt;p&gt;And if the tool answered that for you, you'll find out the next time something breaks.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>learning</category>
    </item>
    <item>
      <title>My favorite article of the week. for someone who's where he is today by breaking things, painfully manually writing CRUD apps and having no choice but to learn how to read people's code, this hits too close to home.</title>
      <dc:creator>Adam - The Developer ✨</dc:creator>
      <pubDate>Wed, 29 Jul 2026 16:12:45 +0000</pubDate>
      <link>https://dev.to/adamthedeveloper/my-favorite-article-of-the-week-for-someone-whos-where-he-is-today-by-breaking-things-painfully-18gg</link>
      <guid>https://dev.to/adamthedeveloper/my-favorite-article-of-the-week-for-someone-whos-where-he-is-today-by-breaking-things-painfully-18gg</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/nazar-boyko/the-junior-developer-pipeline-is-broken-and-ai-broke-it-1aai" class="crayons-story__hidden-navigation-link"&gt;The Junior Developer Pipeline Is Broken... And AI Broke It&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/nazar-boyko/the-junior-developer-pipeline-is-broken-and-ai-broke-it-1aai" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Deletes the career ladder&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/nazar-boyko" class="crayons-avatar  crayons-avatar--l  "&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1875383%2F1b3f5dc9-df1c-4551-9f6e-e3b6234b3d6c.gif" alt="nazar-boyko profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/nazar-boyko" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Nazar Boyko
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Nazar Boyko
                
                
              
              &lt;div id="story-author-preview-content-4240237" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/nazar-boyko" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1875383%2F1b3f5dc9-df1c-4551-9f6e-e3b6234b3d6c.gif" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Nazar Boyko&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/nazar-boyko/the-junior-developer-pipeline-is-broken-and-ai-broke-it-1aai" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 27&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/nazar-boyko/the-junior-developer-pipeline-is-broken-and-ai-broke-it-1aai" id="article-link-4240237"&gt;
          The Junior Developer Pipeline Is Broken... And AI Broke It
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/discuss"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;discuss&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/career"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;career&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/nazar-boyko/the-junior-developer-pipeline-is-broken-and-ai-broke-it-1aai" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;267&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/nazar-boyko/the-junior-developer-pipeline-is-broken-and-ai-broke-it-1aai#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              216&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            9 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Understanding Over Origin</title>
      <dc:creator>Adam - The Developer ✨</dc:creator>
      <pubDate>Tue, 28 Jul 2026 09:36:21 +0000</pubDate>
      <link>https://dev.to/adamthedeveloper/understanding-over-origin-4685</link>
      <guid>https://dev.to/adamthedeveloper/understanding-over-origin-4685</guid>
      <description>&lt;p&gt;Many of developers communities are asking the wrong question.&lt;/p&gt;

&lt;p&gt;Not because they're wrong to worry about low-effort work, no, but the filter they're using doesn't actually separate maintained engineering from generated slop. It just separates projects based on which tools were involved in their creation.&lt;/p&gt;

&lt;p&gt;Imagine trying to share a work that you're really proud of, with the help of AI assisting it, the idea's yours but your work gets flagged, rejected, or buried under comments like &lt;em&gt;"no you didn't"&lt;/em&gt; and &lt;em&gt;"I hate how there's so many AI projects these days."&lt;/em&gt; Someone definitely felt righteous after saying this, believing they're protecting themselves from low-effort slop. &lt;/p&gt;

&lt;p&gt;Except that's not actually what they're protecting against. They're protecting against &lt;em&gt;a label&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Distinction
&lt;/h2&gt;

&lt;p&gt;I read &lt;a class="mentioned-user" href="https://dev.to/madsendev"&gt;@madsendev&lt;/a&gt; 's article regarding &lt;a href="https://dev.to/madsendev/i-built-something-good-with-ai-now-some-developer-communities-dont-want-to-see-it-20mo"&gt;Open Vectorizer&lt;/a&gt; and Madsen wants to share the project with other people and in hope that someone would like to contribute as well.&lt;/p&gt;

&lt;p&gt;Apparently, difference between "AI-generated" and "maintained engineering" has become invisible to gatekeepers who've simplified the filter down to a single binary question.&lt;/p&gt;

&lt;p&gt;the wrong question.&lt;/p&gt;

&lt;p&gt;" AI or no AI "? ( they didn't literally ask this but that's the filter in practice )&lt;/p&gt;

&lt;p&gt;Here's why: imagine two projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project A:&lt;/strong&gt; Someone spends two years redesigning a vectorization algorithm, investigates whether machine learning could improve it, decides against it, implements a deterministic approach, discovers their own benchmark was inflated (and fixes it anyway), publishes reproducible results, and actively maintains the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project B:&lt;/strong&gt; Someone types "make me a music streaming app" into an AI prompt, publishes whatever emerges without testing it, and disappears.&lt;/p&gt;

&lt;p&gt;Both used AI. Both are labeled "AI-generated." One belongs in a developer community. The other is exactly what communities should be filtering out.&lt;/p&gt;

&lt;p&gt;Guess which one gets rejected? yah, both get rejected. The luckiest you can get is being rejected later because the gatekeeper was busy arguing with you and changing their community name to: " i miss what was it like to program on punch cards and a ciggy in my mouth " ahhh yes, the identity crisis.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem With Using "AI-Generated" as a Quality Filter
&lt;/h2&gt;

&lt;p&gt;The gatekeeping argument seems reasonable at first glance. But it has real problems:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The dismissal:&lt;/strong&gt; &lt;em&gt;"no you didn't&lt;/em&gt; (via &lt;a class="mentioned-user" href="https://dev.to/deammer"&gt;@deammer&lt;/a&gt;). This response requires ignoring the actual technical work, but Madsen rewrote an entire algorithm pipeline, tested it against established tools, and caught a bug that made his own benchmarks look better, then published the worse numbers anyway. That's not  someone slapping a prompt onto Claude and calling it a day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The broader concern:&lt;/strong&gt; &lt;a class="mentioned-user" href="https://dev.to/blakebeckcoding"&gt;@blakebeckcoding&lt;/a&gt; points out something real, unvetted AI-generated code has introduced security vulnerabilities. That's a legitimate worry about maintainability and accountability. Where the argument breaks down is treating that as sufficient reason to reject &lt;em&gt;every&lt;/em&gt; AI-assisted project before evaluating its technical merits. The concern about low-quality code is valid. The heuristic of "reject based on tool choice" doesn't actually address it. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think of it differently:&lt;/strong&gt; we don't reject all Rust packages because Rust makes memory safety easier, nor do we assume all C projects are insecure because C makes memory errors possible. Language choice affects probabilities, but it doesn't determine quality. The same applies to AI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The nostalgia play:&lt;/strong&gt; &lt;em&gt;"Dev.to used to be good"&lt;/em&gt; (same dude, you know who, bro's just nostalgic). There's an assumption that developer communities were higher-quality before AI tooling arrived. But humans have been publishing terrible code since the 1980s, spamming them has always been a problem and it isn't new, AI just makes it easier and cheaper to spam.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Problem (And Why It Requires Actual Work)
&lt;/h2&gt;

&lt;p&gt;Developer communities &lt;em&gt;are&lt;/em&gt; being flooded and it's not the AI-generated projects specifically but &lt;em&gt;low-effort projects&lt;/em&gt;, period. and like I said up there, the flood's rising fast at an overwhelming rate because AI made it cheaper to produce them.&lt;/p&gt;

&lt;p&gt;The solution, though? It's not "ban the AI ones."&lt;/p&gt;

&lt;p&gt;It's understanding what actually separates signal from noise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can the maintainer explain the architecture, or does it sound like they're reading stack overflow?&lt;/li&gt;
&lt;li&gt;Are there meaningful tests?&lt;/li&gt;
&lt;li&gt;Can claims be independently reproduced?&lt;/li&gt;
&lt;li&gt;Are benchmarks transparent?&lt;/li&gt;
&lt;li&gt;Are weaknesses disclosed?&lt;/li&gt;
&lt;li&gt;Does the maintainer actually review changes and take responsibility?&lt;/li&gt;
&lt;li&gt;Will this be maintained in six months, or is it a one-off lab experiment?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions work equally well for human-written code. And they're &lt;em&gt;expensive to verify&lt;/em&gt;, they require actual reading, thinking, and judgment.&lt;/p&gt;

&lt;p&gt;"Was AI used?" is cheap. One checkbox. Feels principled. Lets moderators move on.&lt;/p&gt;

&lt;p&gt;"Is this maintained engineering?" requires actually engaging with the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pointed Out Irony
&lt;/h2&gt;

&lt;p&gt;In the comment thread, &lt;a class="mentioned-user" href="https://dev.to/unitbuilds"&gt;@unitbuilds&lt;/a&gt; delivered the most sensible take on all of this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Software development is an orchestration process where the ultimate value is the working, audited, and tested software—not just human typing time."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And then:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If that's the kind of comments you leave, go to X and join the cesspool, or Reddit, they'll love you there. Please keep Dev.to a safe space for all developers."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;hits good, doesn't it? it's not defending AI in the abstract. It's defending &lt;em&gt;communities staying communities&lt;/em&gt;, places where people can share work and get feedback, not face purity tests based on which tools they used.&lt;/p&gt;

&lt;p&gt;The person who said they used 99% AI to ship a 3000-line game while working full-time deserves to share that. So does someone who used GitHub Copilot for routine completions. So does the Open Vectorizer author who made architectural decisions with AI assistance but wouldn't ship something they couldn't explain.&lt;/p&gt;

&lt;p&gt;What none of them deserve is dismissal based on a label that tells you nothing about the quality of the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Historical Perspective
&lt;/h2&gt;

&lt;p&gt;This is something that might seem beside the point but isn't: software development has &lt;em&gt;always&lt;/em&gt; worked this way.&lt;/p&gt;

&lt;p&gt;We moved from assembly to C and nobody said &lt;em&gt;"You didn't really code because you're using a compiler."&lt;/em&gt; We moved from manual memory management to garbage collection. From raw SQL to ORMs. From writing Dockerfiles by hand to templates. From Stack Overflow copy-paste to IDE refactoring to GitHub Copilot autocomplete.&lt;/p&gt;

&lt;p&gt;Each step increased abstraction. Each step generated concern that developers were getting lazy, that standards were dropping, that the craft was being diluted.&lt;/p&gt;

&lt;p&gt;Each time, the question that actually mattered wasn't &lt;em&gt;"What abstraction level did you use?"&lt;/em&gt; It was &lt;em&gt;"Do you understand what was generated? Can you defend it? Will you maintain it?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's been the real standard all along.&lt;/p&gt;

&lt;p&gt;AI is just the next step on that continuum. It's more aggressive, more visible, and it generates more mediocre output faster. But it's not fundamentally different from any other tool that lets developers offload rote work to focus on decisions that matter.&lt;/p&gt;

&lt;p&gt;The question isn't whether AI should be accepted.&lt;/p&gt;

&lt;p&gt;In short, people have been saying software development is dead since the first high level programming language was invented... just, circling around the same anxiety cycle over and over.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Good Moderation Requirements
&lt;/h2&gt;

&lt;p&gt;no, it's not "open the floodgates." it's about what you're really filtering&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good moderation would:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Require disclosure of substantial AI involvement (transparency matters)&lt;/li&gt;
&lt;li&gt;Judge projects on reproducibility, test coverage, and maintainer accountability&lt;/li&gt;
&lt;li&gt;Fast-track projects with public benchmarks or active bug resolution&lt;/li&gt;
&lt;li&gt;Catch obvious slop &lt;em&gt;by its lack of depth&lt;/em&gt;, not its origin story&lt;/li&gt;
&lt;li&gt;Create space for people who are learning while filtering out low-effort republishing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bad moderation does what's happening now:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blanket bans that assume all AI-assisted work is equivalent to prompt-and-publish&lt;/li&gt;
&lt;li&gt;Dismissive comments that never engage with technical substance&lt;/li&gt;
&lt;li&gt;Rejection based on the presence of a tool, not the absence of rigor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DEV's shift toward requiring disclosure rather than banning AI-assisted content is great. It puts the burden on the creator to be honest, then lets the community decide based on the actual work.&lt;/p&gt;

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

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/unitbuilds"&gt;@unitbuilds&lt;/a&gt; had it right: a developer community's job is to share work and get substantive feedback, not police the method.&lt;/p&gt;

&lt;p&gt;The questions that separate good engineering from slop are straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can you explain the architectural decisions?&lt;/li&gt;
&lt;li&gt;What broke, and how did you fix it?&lt;/li&gt;
&lt;li&gt;Are benchmarks reproducible?&lt;/li&gt;
&lt;li&gt;Will you maintain this?&lt;/li&gt;
&lt;li&gt;Are you willing to be corrected?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They work regardless of whether code was typed by a human, generated by Claude, or mixed. Because they're about understanding and accountability - what has always determined quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Engineering should be evaluated on understanding, correctness, maintainability, testing, and accountability. Not keystrokes.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The World's Oldest Communication Protocol Is Music</title>
      <dc:creator>Adam - The Developer ✨</dc:creator>
      <pubDate>Fri, 24 Jul 2026 03:52:53 +0000</pubDate>
      <link>https://dev.to/adamthedeveloper/the-worlds-oldest-communication-protocol-is-music-3njg</link>
      <guid>https://dev.to/adamthedeveloper/the-worlds-oldest-communication-protocol-is-music-3njg</guid>
      <description>&lt;p&gt;This is going to be a very different article from what I usually write. No technical discussions, architecture deep dives, or engineering practices today. Instead, we're talking about something much older than software itself: music.&lt;/p&gt;

&lt;p&gt;We treat language like it's the default mode of human communication, like it's the &lt;em&gt;real&lt;/em&gt; and only thing used to communicate, everything else is secondary, emotional, aesthetic, nice to have.&lt;/p&gt;

&lt;p&gt;But language is actually the outlier. It's the new protocol layered on top of something much older.&lt;/p&gt;

&lt;p&gt;Music is the original standard and we've basically forgotten how to read it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Protocol Stack
&lt;/h2&gt;

&lt;p&gt;Think of communication like a network stack. Language is high-level. It's TCP/IP. Built on assumptions, needs learning, breaks the second you cross a boundary. You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A shared vocabulary&lt;/li&gt;
&lt;li&gt;Syntactic understanding&lt;/li&gt;
&lt;li&gt;Cultural context&lt;/li&gt;
&lt;li&gt;Years of study if you actually want fluency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's powerful but It's also fragile. And it's &lt;em&gt;recent&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Written language is a few thousand years old. Spoken language is older, sure, but both are late abstractions compared to the hundreds of thousands of years humans have been syncing bodies to shared sound. Relative to that timeline? Language is yesterday's patch.&lt;/p&gt;

&lt;p&gt;Music? That's the lower-level protocol. The physical layer everything else runs on.&lt;/p&gt;

&lt;p&gt;A Japanese teenager at a Michael Jackson concert doesn't need to speak English. She doesn't need to understand what "Man in the Mirror" means as a concept. She also doesn't need a music degree.  &lt;/p&gt;

&lt;p&gt;Music isn't &lt;em&gt;zero&lt;/em&gt;-cost. Genre, culture, convention still shape how we hear it. But the entry barrier for emotional communication is way lower. A rhythm can hit urgency, celebration, sadness, or tension long before anyone understands the formal structure behind it.&lt;/p&gt;

&lt;p&gt;Her nervous system speaks that fluently. And so does everyone else in that stadium.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the Protocol Works
&lt;/h2&gt;

&lt;p&gt;Here's what happens when the song starts: 70,000 people stop being individuals and start being a distributed system synchronizing to the same signal.&lt;/p&gt;

&lt;p&gt;The bass hits. Her heartbeat starts matching it. Involuntarily. Her neurons fire in sync with the guy three rows over. The girl next to her moves when the rhythm says move — not because she decided to, but because the protocol sits lower than conscious decision-making.&lt;/p&gt;

&lt;p&gt;This isn't mystical. This isn't the "universal language of music" in the poetic sense. This is just biology.&lt;/p&gt;

&lt;p&gt;Babies respond to rhythm before they understand words. Crowds clap together without a conductor. Soldiers march to drums. Rituals across cultures use singing and percussion to pull a group into the same tempo. The pattern shows up everywhere because the hardware is shared.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The protocol specs, if we're being nerdy about it:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses mostly rhythm, tempo, and frequency&lt;/li&gt;
&lt;li&gt;Hits the nervous system, not the cognitive layer&lt;/li&gt;
&lt;li&gt;Needs way less shared context than language&lt;/li&gt;
&lt;li&gt;Backward compatible across human brains for 300,000+ years&lt;/li&gt;
&lt;li&gt;Works at scale (70,000 synchronizations at once)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Language, meanwhile:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preprocessing (learning)&lt;/li&gt;
&lt;li&gt;Translation (if you're cross-language)&lt;/li&gt;
&lt;li&gt;Cognitive overhead (your brain has to &lt;em&gt;think&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;High latency (meaning takes time)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Music? Low preprocessing. No translation step. Near-zero latency. Your body gets the signal before your mind finishes negotiating what it means.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why We Don't See This
&lt;/h2&gt;

&lt;p&gt;We're obsessed with meaning. We assume communication = transfer of semantic content. You encode an idea into words, I decode it, boom: we've connected.&lt;/p&gt;

&lt;p&gt;So when we see that girl screaming English lyrics she doesn't understand, we quietly reframe it. "Oh, the &lt;em&gt;message&lt;/em&gt; transcends language. She understands on a &lt;em&gt;deeper level&lt;/em&gt;."&lt;/p&gt;

&lt;p&gt;Nah. She's not understanding the message at all. She's on a different protocol entirely. Language is offline. The lower-level stuff is handling it.&lt;/p&gt;

&lt;p&gt;We miss this because we've built an entire civilization on top of language. We think the higher-level protocol is the "real" one. Which is like saying TCP/IP is more real than the electrical signals it runs on.&lt;/p&gt;

&lt;p&gt;Music isn't poetry. It isn't transcendence. It's infrastructure. It's what everything else runs on.&lt;/p&gt;

&lt;p&gt;And no, it's not &lt;em&gt;better&lt;/em&gt; than language. It solves a different problem. Music synchronizes systems. Language coordinates them.&lt;/p&gt;

&lt;p&gt;A drumbeat can make people march together. It won't tell them why they're marching, what they believe, or what to do when the song ends. Language is powerful because it encodes abstractions. Music is powerful because it doesn't need to.&lt;/p&gt;




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

&lt;p&gt;Here's the part that gets weird: you can sync humans at massive scale without them sharing &lt;em&gt;any&lt;/em&gt; values, beliefs, or understanding.&lt;/p&gt;

&lt;p&gt;That stadium full of people moving together? They don't agree on anything. They might hate each other politically. They might speak no common language. They might have zero common ground.&lt;/p&gt;

&lt;p&gt;But for three minutes, their nervous systems are linked. That's a connection. Just not the kind we like to talk about.&lt;/p&gt;

&lt;p&gt;We want connection to require understanding. We want it to mean something. We want it to prove that underneath all our differences, we're fundamentally united in shared meaning.&lt;/p&gt;

&lt;p&gt;What music actually shows us is simpler and weirder: humans are pattern-matching machines wired to sync with other humans. You don't need shared values for that. You don't need agreement. You don't need understanding.&lt;/p&gt;

&lt;p&gt;You just need a rhythm everyone can feel.&lt;/p&gt;




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

&lt;p&gt;Language will always need translation and will always be high-friction, high-latency, high-failure-rate across boundaries and... that's not a bug, it's what gives it power, precision requires friction.&lt;/p&gt;

&lt;p&gt;But for raw synchronization, getting lots of humans moving together, feeling together, breathing together, language is overkill. Also unreliable.&lt;/p&gt;

&lt;p&gt;Music is the protocol that works when nothing else does.&lt;/p&gt;

&lt;p&gt;An orchestra where nobody shares a language. A protest with thousands of strangers chanting. A stadium of people from different countries, different beliefs, different everything, all moving as one.&lt;/p&gt;

&lt;p&gt;These aren't examples of music "transcending barriers." They're examples of a lower-level protocol just... working, while the higher-level ones fail.&lt;/p&gt;

&lt;p&gt;We've built everything on top of language. We've made it the primary. And we've kind of forgotten what it's sitting on.&lt;/p&gt;

&lt;p&gt;Language lets us share thoughts. Music lets us share states.&lt;/p&gt;

&lt;p&gt;And every time a girl who doesn't speak English screams an English song in perfect sync with 70,000 other people, she's reminding us: the infrastructure was always there. We just stopped noticing it.&lt;/p&gt;

&lt;p&gt;The oldest communication protocol is still the most reliable one. We just got distracted by the newer layers.&lt;/p&gt;




&lt;h2&gt;
  
  
  And sooooo, Here's my favorite song of the week
&lt;/h2&gt;

&lt;p&gt;✨🎶 &lt;strong&gt;Love Hurts&lt;/strong&gt; — Nazareth&lt;/p&gt;

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

&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Drop your favorite music down below, let's hear what gets your system in sync!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>music</category>
      <category>distributedsystems</category>
      <category>productivity</category>
      <category>learning</category>
    </item>
    <item>
      <title>Stop Saying You Want Ownership Mindset</title>
      <dc:creator>Adam - The Developer ✨</dc:creator>
      <pubDate>Tue, 14 Jul 2026 05:59:52 +0000</pubDate>
      <link>https://dev.to/adamthedeveloper/stop-saying-you-want-ownership-mindset-34nf</link>
      <guid>https://dev.to/adamthedeveloper/stop-saying-you-want-ownership-mindset-34nf</guid>
      <description>&lt;p&gt;My 2nd article this week, I'm supposed to keep it to just once per week but whateverrr, I've had this in drafts for a while now, let's get straight into it.&lt;/p&gt;

&lt;p&gt;Here's the thing about "ownership mindset" that nobody on the management side wants to admit: you love the slogan. You hate the behavior.&lt;/p&gt;

&lt;p&gt;You want engineers who care. Who think about scale. Who ask "wait, will this melt in four months?" Who treat the product like it's theirs.&lt;/p&gt;

&lt;p&gt;Cool. Then someone &lt;em&gt;actually does that&lt;/em&gt; in a meeting, and suddenly they're "being difficult," "not a team player," "too negative," or my personal favorite — "can you just build what I asked for?"&lt;/p&gt;

&lt;p&gt;I've sat through this movie enough times that I can recite the script.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Script
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Manager / PM / whoever is currently wearing the "decider" hat:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We need someone with real ownership on this. Someone who cares whether the product actually works.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Someone raises a real concern about the architecture. Not vibes. Constraints. Data model. Failure modes. The stuff that will wake someone up at in the middle of the night later.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Same person, 90 seconds later:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why are you pushing back so hard? Why are you being so difficult? We're already behind. Just ship it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So which is it?&lt;/p&gt;

&lt;p&gt;You asked for ownership. They gave you ownership. Now you're mad that ownership came with opinions.&lt;/p&gt;




&lt;h2&gt;
  
  
  You're Not Confused. You're Convenient.
&lt;/h2&gt;

&lt;p&gt;I used to think this was a communication problem. It's not. It's incentives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You feel the delay today. You don't feel the outage later.&lt;/strong&gt; Design pushback slows the thing you want shipped &lt;em&gt;this sprint&lt;/em&gt;. The mess it prevents shows up next quarter, under someone else's KPI. Of course you optimize for the pain that's in the room.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hierarchy feels like efficiency when you're on top of it.&lt;/strong&gt; A senior decision getting questioned doesn't feel like engineering. It feels like disrespect. Even when the question is "this will corrupt data under concurrent writes." You wanted a yes. You got a reason. Those feel different to the ego.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance feels like progress.&lt;/strong&gt; An engineer saying "yeah, I'll build it" gives you a hit of motion. An engineer saying "we should rethink the data model" feels like friction. Your brain does lazy math: less friction = better leadership. No. Less friction = quieter failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And "ownership" means two different things depending on who's talking.&lt;/strong&gt; When you say it, you often mean "make sure it ships and don't bother me." When I hear it, I mean "make sure it doesn't screw us." Those conflict. You keep using the same word like that's my problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Quiet Engineer Is Not Owning Anything
&lt;/h2&gt;

&lt;p&gt;Here's the part that should piss you off more than it does: the engineer who just implements what you ask, every time, with a smile, is not demonstrating ownership.&lt;/p&gt;

&lt;p&gt;They're optimizing for approval.&lt;br&gt;
They're minimizing confrontation.&lt;br&gt;
They're following orders.&lt;/p&gt;

&lt;p&gt;None of that is ownership. That's liability transfer.&lt;/p&gt;

&lt;p&gt;When it breaks, they've got the perfect line: "I built exactly what was specified." Clean hands. Diffused responsibility. You got the compliant builder you rewarded.&lt;/p&gt;

&lt;p&gt;The person who says "this is going to bite us" is the one actually treating the outcome like theirs. They're spending social capital in a room that usually punishes that spend. If you punish them, don't act shocked when the next three people learn to shut up.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Ownership Actually Looks Like From Our Side
&lt;/h2&gt;

&lt;p&gt;It's not being a dick in design reviews. It's this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concerns come early.&lt;/strong&gt; During design. Not three weeks into implementation when changing direction costs a sprint and a relationship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reasoning, not vibes.&lt;/strong&gt; "This N+1 dies at 10k users on our current growth curve" beats "this feels off." If an engineer can't explain the failure mode, push back. If they can — listen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alternatives, not just no.&lt;/strong&gt; "What if we index on user_id?" is ownership. "This won't work, good luck" is theater.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Knowing when to escalate vs. when to build-and-learn.&lt;/strong&gt; Sometimes you need to ship something imperfect to learn. Sometimes you're walking into a known footgun. A good owner can tell you which meeting you're in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Staying for the outcome.&lt;/strong&gt; "I told you so" is not ownership. Owning it means if you were wrong, you help clean it up. If you were right and ignored, you still help clean it up — and you remember who ignored you.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You Get When You Train That Out of People
&lt;/h2&gt;

&lt;p&gt;I've watched this culture settle in. It's not subtle.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Engineers who optimize for "not getting blamed" instead of "building something that lasts"&lt;/li&gt;
&lt;li&gt;Debt that accumulates in silence because speaking up is career-limiting&lt;/li&gt;
&lt;li&gt;Smart people quietly updating their LinkedIn&lt;/li&gt;
&lt;li&gt;Meltdowns that somehow still surprise leadership&lt;/li&gt;
&lt;li&gt;"Team player" becoming code for "doesn't question bad decisions"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You buy short-term speed. You pay medium-term chaos. Then you schedule a retrospective where everyone agrees "we should have spoken up earlier," and nobody asks why they stopped.&lt;/p&gt;




&lt;h2&gt;
  
  
  If You Actually Want It
&lt;/h2&gt;

&lt;p&gt;Stop asking for ownership like it's a personality trait. Build the conditions where it's safe to exercise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separate design talk from implementation talk.&lt;/strong&gt; Let people think out loud about whether something will work before you've already committed the sprint. Thinking hard and shipping fast aren't enemies. Collapsing them into one meeting is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reward the pushback you say you want.&lt;/strong&gt; If someone raised a legitimate concern and you overrode them, make that a &lt;em&gt;visible decision&lt;/em&gt;. Don't pretend the conversation didn't happen. If they were right later, say so. Out loud. In front of people. If they were wrong, they learn the domain. Either way, the signal is: speaking up was the job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be specific.&lt;/strong&gt; "Take ownership" is useless. Do you mean "ship this by Friday even if it's dirty"? Then say that. Do you mean "this has to survive 10x traffic"? Say that. Vague slogans produce people guessing what will get them yelled at least.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Listen when we push back.&lt;/strong&gt; Not because we're always right — we're not. Because we live in the codebase you only see through tickets. That's not attitude. That's the job you hired us for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Normalize disagreement.&lt;/strong&gt; The best teams I've been on argue about design and still trust each other the next morning. Disagreement isn't personal. Making it personal is how you get yes-men and broken systems.&lt;/p&gt;




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

&lt;p&gt;You probably do want engineers with an ownership mindset.&lt;/p&gt;

&lt;p&gt;What you don't want, and keep accidentally selecting for, is engineers who smile, implement, and let you walk into the wall so they can stay popular.&lt;/p&gt;

&lt;p&gt;Ownership is annoying. It asks inconvenient questions. It slows the "just ship it" meeting. It makes seniors defend decisions they wanted to treat as settled.&lt;/p&gt;

&lt;p&gt;If that sounds exhausting, good. That's the cost of building something that doesn't fall apart the second real users touch it.&lt;/p&gt;

&lt;p&gt;You don't get "people who care" and "people who never push back." Pick one.&lt;/p&gt;

&lt;p&gt;And if you pick compliance, at least stop calling it ownership. That word still means something to the rest of us.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
      <category>architecture</category>
      <category>software</category>
    </item>
    <item>
      <title>I Could Review It. I Couldn’t Write It.</title>
      <dc:creator>Adam - The Developer ✨</dc:creator>
      <pubDate>Mon, 13 Jul 2026 07:52:12 +0000</pubDate>
      <link>https://dev.to/adamthedeveloper/i-could-review-it-i-couldnt-write-it-3gfj</link>
      <guid>https://dev.to/adamthedeveloper/i-could-review-it-i-couldnt-write-it-3gfj</guid>
      <description>&lt;p&gt;...now, I pride myself on being good at my job, I'm fast at catching mistakes, I'm efficient at reviewing code and I'm quick to spot patterns across systems. But ever since I knew how to use AI ( maybe around mid 2024, I was still doing the old trad way when i started in 2018 ), I've been letting AI write ALOT of my code.&lt;/p&gt;

&lt;p&gt;And I thought I was still learning.&lt;/p&gt;

&lt;p&gt;Then one day I sat down to write an HTTP handler in Go from scratch, and I froze... and I can't describe how scary this was.&lt;/p&gt;

&lt;p&gt;Not because I don't understand HTTP or because I don't know Go because I recognize these patterns instantly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;handleJobNext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can review it, spot mistakes, discuss the design. But build it from scratch? I found myself thinking: "Wait... is it &lt;code&gt;http.HandleFunc&lt;/code&gt;? &lt;code&gt;ServeMux&lt;/code&gt;? How do I start the server?"&lt;/p&gt;

&lt;p&gt;That's when I realized something was wrong, I realized the trap I'd fallen into and I had to do something about it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Recognition is not Production
&lt;/h2&gt;

&lt;p&gt;This biggest illusion that AI makes much easier to fall into is the thinking that goes:&lt;br&gt;&lt;br&gt;
"I understand this" and it feels &lt;em&gt;exactly&lt;/em&gt; like "I can produce this."&lt;/p&gt;

&lt;p&gt;I also wanna clarify that AI isn't the first one to inven this problem, Stack Overflow, copy-pasted frameworks and tutorials all created it first and AI's just accelarating the distance.&lt;/p&gt;

&lt;p&gt;Recognizing a solution is just one skill. Your brain does pattern matching beautifully and way effortlessly than you think once you get used to it, you see &lt;code&gt;http.HandleFunc&lt;/code&gt;, think "yep, that's how you register routes," and feel confident.But try retriving that knowledge from scratch, constructing it... that's a whole other level, those are completely different neural pathways because the ability to review code, design &amp;amp; architecture aren't the same as writing it from memory and it should never be mistaken.  &lt;/p&gt;

&lt;p&gt;I got really good at reviewing, too good I guess, I am fast &amp;amp; efficient, I could critique architecture, spot edge cases, ask the right questions and basically start a whole drunken bar vibe conversation with it but you know what scares me despite being able to do all of this? I couldn't write an HTTP handler from memory.&lt;/p&gt;

&lt;p&gt;I WAS practicing &lt;em&gt;some&lt;/em&gt; skills. just some. just not the ones I thought.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Gap and I Started A Series
&lt;/h2&gt;

&lt;p&gt;There's also a dangerous confidence trap here: convincing yourself you're still learning because you're the "architect" or "reviewer", you're making decisions, you understand the system.&lt;/p&gt;

&lt;p&gt;But how would you feel if knowing you can't write what the AI wrote, not without looking. that's the gap.&lt;/p&gt;

&lt;p&gt;Anyway, a few months ago, I started writing distributed systems algorithms in Go from scratch, each algorithm belonging to their own repo. No AI. I write entirely, then ask it to review and I tell you it's very rewarding!  &lt;/p&gt;

&lt;p&gt;I am doing the series for 2 reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This will help me strengthen my skill in Go, I love Go but it's also the least used language of mine too but a very important one.&lt;/li&gt;
&lt;li&gt;I hope to help others understand algorithms in distributed systems where it's written with as much as simplicity as I could but also not leaving out edge cases and failure modes. Many developers work with one unknowingly and wonder why their simple code causes data corruption as soon as someone adds another instance of the backend.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will be releasing the article one by one each after I'm done where I will document every hell and tasmanian devil I would've had gone through, no filters with the exception of bad languages.&lt;/p&gt;




&lt;h2&gt;
  
  
  You Can't Download Experience
&lt;/h2&gt;

&lt;p&gt;Great software doesn't come from perfect code, It comes from &lt;em&gt;surviving&lt;/em&gt; bad code.&lt;/p&gt;

&lt;p&gt;Engineering intuition is built from mistakes, failed designs, debugging at 2 AM, edge cases that shouldn't exist, trade-offs that haunt you for years. The final code is just the artifact. The scar tissue is the education.&lt;/p&gt;

&lt;p&gt;Take a system like PostgreSQL represents decades of accumulated engineering decisions.&lt;/p&gt;

&lt;p&gt;I'm picking on Postgres specifically because I saw someone tried to rewrite Postgres with Rust nearly entirely with agents. It's not a bad thing, in fact, it's improving Postgres tremendously: with Rust, it's moving from the historic &lt;em&gt;process-per-connection&lt;/em&gt; to &lt;em&gt;thread-per-connection,&lt;/em&gt; massive performance gain and some of the long-standing postgres pain points.&lt;/p&gt;

&lt;p&gt;You can rewrite it. You can reproduce the behavior. But you won't reproduce the journey that created that understanding—the bugs fixed, the performance lessons learned, the constraints that forced particular designs.&lt;/p&gt;

&lt;p&gt;Letting an agent write everything and you get the artifact without the scar tissue.&lt;/p&gt;

&lt;p&gt;And expertise lives in the scar tissue.&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;The skills you practice will grow. The skills you outsource will weaken.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I outsourced writing and my writing muscle atrophied. I got better at reviewing and architecture, but lost something important.&lt;/p&gt;

&lt;p&gt;Now I'm deliberate: distributed systems algorithms in Go, I write. from scratch.&lt;/p&gt;

&lt;p&gt;Not because I am better than AI but because I'm choosing which muscles to exercise and the choice matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'm Not Saying
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AI is not bad. I use it daily. Heck, I still use it for work because businesses' deadlines now are unrealistic standards compared to what they were a few years ago.&lt;/li&gt;
&lt;li&gt;Code review is still critical work.&lt;/li&gt;
&lt;li&gt;AI is still my thinking partner and my force multiplier, I still consult it from time to time when making decisions, it builds me up and makes me a better developer and I make decisions faster because I'm not the only one thinking when no one's around.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What I'm saying is: &lt;strong&gt;Be intentional about which parts of expertise you allow to change.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every tool reshapes what engineers need to know. The goal isn't to preserve manual typing forever. The goal is to ensure that the parts of engineering &lt;em&gt;you want to own&lt;/em&gt; are still exercised by you.&lt;/p&gt;

&lt;p&gt;If you want to stay sharp at writing, you have to pick code you're not going to outsource.&lt;/p&gt;

&lt;p&gt;Because expertise follows exercise. Always.&lt;/p&gt;

&lt;p&gt;The question isn't whether you can write without AI.&lt;/p&gt;

&lt;p&gt;The question is: &lt;em&gt;Will you?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>You Never Eliminate a Bottleneck — You Just Move It</title>
      <dc:creator>Adam - The Developer ✨</dc:creator>
      <pubDate>Mon, 06 Jul 2026 09:59:27 +0000</pubDate>
      <link>https://dev.to/adamthedeveloper/you-never-eliminate-a-bottleneck-you-just-move-it-41ia</link>
      <guid>https://dev.to/adamthedeveloper/you-never-eliminate-a-bottleneck-you-just-move-it-41ia</guid>
      <description>&lt;p&gt;I once spent quite some time optimizing a database query that was bringing our API to its knees. We shaved 200ms off response time with careful indexing and query rewriting. Success, right?&lt;/p&gt;

&lt;p&gt;Wrong.&lt;/p&gt;

&lt;p&gt;Within a week, a different bottleneck surfaced. The network became the constraint. We optimized that. Then client-side rendering became slow. Then memory usage spiked. Each "fix" just moved the problem downstream.&lt;/p&gt;

&lt;p&gt;Eventually, I learned something that changed how I approach performance work: &lt;strong&gt;bottlenecks aren't anomalies to eliminate, they're laws of nature baked into how systems work.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Bottlenecks Are Inevitable
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Theory of Constraints
&lt;/h3&gt;

&lt;p&gt;Every system has a weakest link. Think of water flowing through a pipeline, the narrowest section determines your throughput, no matter how wide the rest of the pipe is.&lt;/p&gt;

&lt;p&gt;Software systems work the same way. At any given moment, &lt;em&gt;something&lt;/em&gt; is the binding constraint:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is it the CPU?&lt;/li&gt;
&lt;li&gt;The database?&lt;/li&gt;
&lt;li&gt;Network latency?&lt;/li&gt;
&lt;li&gt;Disk I/O?&lt;/li&gt;
&lt;li&gt;Memory?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you optimize that constraint, you don't eliminate constraints altogether. &lt;strong&gt;The constraint simply moves to the next-slowest component.&lt;/strong&gt; The system's total throughput increases, but a new bottleneck emerges.&lt;/p&gt;

&lt;h3&gt;
  
  
  Amdahl's Law: The Math That Proves It
&lt;/h3&gt;

&lt;p&gt;Even with infinite parallelization, there's a mathematical ceiling. Amdahl's Law tells us:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9oe009j5ib6k2usdm1rl.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9oe009j5ib6k2usdm1rl.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If just &lt;strong&gt;10% of your code runs sequentially&lt;/strong&gt;, you can never speed up more than 10x—no matter if you have 1,000 CPUs. That sequential 10% becomes an eternal bottleneck.&lt;/p&gt;

&lt;p&gt;For our social media app, some processes &lt;em&gt;must&lt;/em&gt; happen in order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authenticate user&lt;/li&gt;
&lt;li&gt;Fetch permissions&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Then&lt;/em&gt; fetch feed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can't parallelize that without breaking safety. So authentication becomes a permanent bottleneck, though a small one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Great Trade-Off Game
&lt;/h2&gt;

&lt;p&gt;Here's the dirty secret: optimizing for one thing almost always hurts something else. You're not solving problems; you're &lt;strong&gt;choosing which constraint to live with.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Optimize For&lt;/th&gt;
&lt;th&gt;What Improves&lt;/th&gt;
&lt;th&gt;What Gets Worse&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fast responses&lt;/td&gt;
&lt;td&gt;CPU/memory usage spikes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Throughput&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;More requests/sec&lt;/td&gt;
&lt;td&gt;Resource exhaustion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cheaper infrastructure&lt;/td&gt;
&lt;td&gt;Performance degrades&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Consistency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Strong guarantees&lt;/td&gt;
&lt;td&gt;Write latency increases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Availability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Always online&lt;/td&gt;
&lt;td&gt;Coordination overhead explodes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Pick one. You're implicitly de-prioritizing others.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: The Classic API Scaling
&lt;/h3&gt;

&lt;p&gt;Let's say I worked on an API that handled 10 requests/second. Bottleneck? The database.&lt;/p&gt;

&lt;p&gt;We added caching.&lt;/p&gt;

&lt;p&gt;Now: 100 requests/second. Bottleneck? Memory, our cache grew too big.&lt;/p&gt;

&lt;p&gt;We sharded the cache.&lt;/p&gt;

&lt;p&gt;Now: 500 requests/second. Bottleneck? Network bandwidth between nodes.&lt;/p&gt;

&lt;p&gt;We optimized serialization.&lt;/p&gt;

&lt;p&gt;Now: 1,000 requests/second. Bottleneck? Client-side parsing of responses.&lt;/p&gt;

&lt;p&gt;We gzipped responses.&lt;/p&gt;

&lt;p&gt;Now: 2,000 requests/second. Bottleneck? The upstream service that feeds our API.&lt;/p&gt;

&lt;p&gt;At each step, we "solved" the problem. But we never eliminated bottlenecks—we choreographed a dance, moving them from place to place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distributed Systems Make It Worse
&lt;/h2&gt;

&lt;p&gt;In a distributed system, bottlenecks hide in shadows and move in unpredictable ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network RTT (round-trip time) is a physical law.&lt;/strong&gt; You can't send data faster than light travels. For a global system, that's roughly 50-150ms of minimum latency per hop. Every extra network call multiplies this cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leader election is expensive.&lt;/strong&gt; When a leader fails in your distributed system, electing a new one takes time. During that window, writes are blocked. The leader election itself becomes the bottleneck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quorum writes create coordination overhead.&lt;/strong&gt; To ensure consistency across replicas, you need a quorum (majority) to acknowledge a write. That coordination, waiting for responses from multiple nodes, is itself a bottleneck that throttles your write throughput.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hot partitions kill performance.&lt;/strong&gt; If all your traffic hits one partition (shard) of data, that partition becomes the bottleneck. You optimized everywhere else, but one hot partition brings the whole system down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cross-region latency compounds.&lt;/strong&gt; Replicate data to multiple regions for resilience? Now reads and writes must cross regions. A single cross-region call might be 100ms. Add three of them together? You've hit a bottleneck that optimization can't touch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fan-out requests multiply latency.&lt;/strong&gt; Your service calls 10 microservices in parallel. The slowest one determines your response time. You optimize 9 of them, but the 10th — now &lt;em&gt;that's&lt;/em&gt; your bottleneck.&lt;/p&gt;

&lt;p&gt;There is no way around these trade-offs. They're mathematical, physical. Bottlenecks in distributed systems aren't bugs, they're features of reality.&lt;/p&gt;

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

&lt;p&gt;The question shouldn't be: "How do I eliminate bottlenecks?"&lt;/p&gt;

&lt;p&gt;It should be: "Which bottleneck am I willing to live with, and how do I make sure it's the right one?"&lt;/p&gt;

&lt;h3&gt;
  
  
  Actionable practices:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Profile first, optimize later&lt;/strong&gt;&lt;br&gt;
Use a profiler. Find the actual bottleneck, not the one you &lt;em&gt;think&lt;/em&gt; exists. 90% of optimization effort goes to wrong places because developers guess.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Optimize strategically&lt;/strong&gt;&lt;br&gt;
Focus on the binding constraint. Optimizing something that's 5% of your runtime is pointless if the database is 80% of your runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Plan for the next bottleneck&lt;/strong&gt;&lt;br&gt;
When you fix something, ask: "What becomes slow now?" You can't prevent it, but you can prepare.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Make trade-offs consciously&lt;/strong&gt;&lt;br&gt;
Don't accidentally sacrifice something important. If you add aggressive caching, you're choosing performance over freshness. Make sure that's actually what you want.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Accept limits gracefully&lt;/strong&gt;&lt;br&gt;
Some bottlenecks are laws of physics (network latency, disk I/O). Design around them instead of fighting them. Use caching for latency. Use batching for throughput.&lt;/p&gt;

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

&lt;p&gt;Some of the best engineers I know aren't the ones who "eliminate" bottlenecks. They're the ones who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand where bottlenecks live&lt;/li&gt;
&lt;li&gt;Move them strategically&lt;/li&gt;
&lt;li&gt;Stay ahead of the game by anticipating the next constraint&lt;/li&gt;
&lt;li&gt;Optimize for what actually matters (user experience, cost, reliability)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your job isn't to break the laws of systems theory. It's to work within them intelligently.&lt;/p&gt;

&lt;p&gt;The bottleneck never disappears. You just get better at dancing around it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eliyahu Goldratt&lt;/strong&gt;: &lt;a href="https://www.leanproduction.com/theory-of-constraints/" rel="noopener noreferrer"&gt;The Theory of Constraints&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gene Amdahl&lt;/strong&gt;: &lt;a href="https://www.geeksforgeeks.org/computer-organization-architecture/computer-organization-amdahls-law-and-its-proof/" rel="noopener noreferrer"&gt;Amdahl's Law (1967)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brendan Gregg&lt;/strong&gt;: Systems Performance (book) + his incredible &lt;a href="https://www.brendangregg.com/" rel="noopener noreferrer"&gt;blog&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eric Brewer&lt;/strong&gt;: &lt;a href="https://www.geeksforgeeks.org/dbms/the-cap-theorem-in-dbms/" rel="noopener noreferrer"&gt;CAP Theorem&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>architecture</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Illusion of the Clean Slate</title>
      <dc:creator>Adam - The Developer ✨</dc:creator>
      <pubDate>Tue, 30 Jun 2026 06:28:20 +0000</pubDate>
      <link>https://dev.to/adamthedeveloper/the-illusion-of-the-clean-slate-2di0</link>
      <guid>https://dev.to/adamthedeveloper/the-illusion-of-the-clean-slate-2di0</guid>
      <description>&lt;p&gt;Every engineer has fantasized about it: starting over. Throwing out the old system and building something clean. No legacy constraints. No accumulated compromises. Just pure, intentional design.&lt;/p&gt;

&lt;p&gt;It never works that way.&lt;/p&gt;

&lt;p&gt;You can delete all the code. You can architect from scratch. You can make the best technical decisions possible. But you can't delete the organizational memory. You can't unlearn what the last system taught you. You can't escape the patterns that already run through the business, the workflows people have shaped themselves around, the problems you've already paid the cost of understanding.&lt;/p&gt;

&lt;p&gt;The new system will look clean. But it will be haunted.&lt;/p&gt;

&lt;h2&gt;
  
  
  What rewrites actually inherit
&lt;/h2&gt;

&lt;p&gt;A rewrite isn't a fresh start. It's archaeology pretending to be innovation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The constraints don't go away.&lt;/strong&gt; The old system wasn't overcomplicated because engineers were bad. It was overcomplicated because of customer requirements, regulatory expectations, performance demands, and edge cases that took years to discover. A fresh rewrite finds all those edge cases again. Slower this time, because you don't have documentation—you have broken customers and escalations. The system gets layers of protection again, but now it looks like paranoia instead of learned caution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The organizational memory becomes invisible.&lt;/strong&gt; Someone fought for that data model three years ago. There was a reason. A business rule that couldn't be violated. A data consistency requirement that cost a quarter to figure out. The new system doesn't have the battle scars that explain &lt;em&gt;why&lt;/em&gt; things are the way they are. So they get rebuilt differently, until they hit the same requirement at 2am on a Saturday.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The workflow is already baked in.&lt;/strong&gt; Users have shaped their behavior around the old system. Sales has built their pitch around certain capabilities. Support has written documentation and runbooks. Customers have automation that depends on specific behaviors. The new system is technically cleaner, but it forces change on everyone else first. The rewrite isn't done until the new system works like the old one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The code patterns stick around.&lt;/strong&gt; Teams find themselves solving the same problems the same ways. Not because the architecture forces it, but because it's familiar. Because there's institutional knowledge about how to do X in a way that doesn't break. Because someone senior knows the pitfalls. The "clean" codebase starts looking like the old one within six months, just with better error handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  The ghost of the old system
&lt;/h2&gt;

&lt;p&gt;sometimes the best decision in a rewrite is to do it exactly like the previous system.&lt;/p&gt;

&lt;p&gt;Not because the old code was good. But because a &lt;em&gt;lot of people understand it&lt;/em&gt;. The business logic is tested by production. The failure modes are known. The performance characteristics are predictable. Starting fresh means starting ignorant, and ignorance costs money.&lt;/p&gt;

&lt;p&gt;A truly clean slate would require starting ignorant &lt;em&gt;and&lt;/em&gt; willing to pay the cost of ignorance. Most organizations can't afford that. So the rewrite becomes "the old thing, but better implemented"—which is fine, maybe even better, but it's not what anyone was imagining when they said "let's start over."&lt;/p&gt;

&lt;p&gt;The ghost isn't a bad thing. It's just unavoidable. Organizations have memory whether they codify it or not. That memory shapes everything built inside them, even when you're trying to escape it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Understanding this changes how you approach a rewrite. You're not escaping the past. You're translating it.&lt;/p&gt;

&lt;p&gt;The best rewrites don't pretend to be clean slates. They acknowledge what they're inheriting. They talk to users about why the old system worked the way it did. They preserve the tacit knowledge that's been learned the hard way. They choose: what patterns do we keep because they're actually good, versus what patterns do we change because we have time to do it right.&lt;/p&gt;

&lt;p&gt;The worst rewrites assume they're smarter than everyone who came before. They rebuild against the patterns of the old system instead of with understanding of them. They rediscover the same edge cases as new bugs instead of as features. They become legacy before they're finished.&lt;/p&gt;

&lt;p&gt;A rewrite isn't a clean slate. It's a translation. And translation is hard because you have to understand both languages, the constraints of the old world and the possibilities of the new one. You have to honor what worked without being trapped by it.&lt;/p&gt;

&lt;p&gt;The fantasy of the clean slate is tempting because it promises escape. But the only way to actually learn something is to carry it forward, consciously, even when you're trying to leave it behind.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>architecture</category>
      <category>software</category>
    </item>
    <item>
      <title>Conduit: The Gateway I Built to Forget About</title>
      <dc:creator>Adam - The Developer ✨</dc:creator>
      <pubDate>Wed, 24 Jun 2026 07:37:59 +0000</pubDate>
      <link>https://dev.to/adamthedeveloper/conduit-the-gateway-i-built-to-forget-about-2ann</link>
      <guid>https://dev.to/adamthedeveloper/conduit-the-gateway-i-built-to-forget-about-2ann</guid>
      <description>&lt;p&gt;I've been trying to keep my publishing schedule to one article a week, but this one felt too special to wait so I had Claude helping me generate a portion of this so I can publish it quick.&lt;/p&gt;

&lt;p&gt;The article today might be a little boring depending on how much you're into systems and distributed architecture. And if you're already thinking, "Great, another API gateway," I can't really blame you.&lt;/p&gt;

&lt;p&gt;But bear with me for a bit: Conduit isn't just another request-forwarding proxy. Along the way, we'll dive into programmable gateways, sandboxed runtimes, Unix sockets, and some of the engineering decisions that made building it surprisingly fun.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Built a small Go API gateway in front of three services with two different auth schemes (custom HMAC sessions, and JWT).&lt;/li&gt;
&lt;li&gt;It worked. It also became unmaintainable: every routing exception meant editing Go and redeploying.&lt;/li&gt;
&lt;li&gt;Rewrote it as &lt;strong&gt;Conduit&lt;/strong&gt;: Go stays on the network path (routing, proxying, CORS, SSRF guards). A sandboxed &lt;strong&gt;Deno runtime&lt;/strong&gt; runs policy as plain TypeScript plugins, talking to Go over a Unix socket with a strict snapshot-and-patch protocol.&lt;/li&gt;
&lt;li&gt;Net result: auth, logging, and routing rules became files I could edit and save, no recompiling the gateway.&lt;/li&gt;
&lt;li&gt;Full FAQ/defense-of-design-decisions Q&amp;amp;A is &lt;a href="https://a-thedeveloper.vercel.app/blog/conduit" rel="noopener noreferrer"&gt;here&lt;/a&gt;, not in this post.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;Three services, one public API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;chat-service&lt;/strong&gt;: real-time messaging&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;user-service&lt;/strong&gt;: profiles, sessions, identity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;admin-service&lt;/strong&gt;: internal tooling, elevated operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;User and chat traffic ran a custom session + HMAC scheme: &lt;code&gt;Authorization: Session &amp;lt;id&amp;gt;&lt;/code&gt;, signed with &lt;code&gt;X-Signature&lt;/code&gt;, &lt;code&gt;X-Timestamp&lt;/code&gt;, &lt;code&gt;X-Nonce&lt;/code&gt;, backed by Redis for sessions and replay protection. Not JWT. Not OAuth. Something built and iterated on for months.&lt;/p&gt;

&lt;p&gt;Admin traffic was JWT, verified at the edge, then forwarded with trusted &lt;code&gt;X-Gateway-Admin-&lt;/code&gt;* headers so the admin service skipped re-validation.&lt;/p&gt;

&lt;p&gt;Different trust models. Different header shapes. Different public-path exceptions. All of it had to land on one hostname, because clients don't care how many services you run behind it.&lt;/p&gt;

&lt;p&gt;So I built the obvious thing: a small Go gateway. Service-prefixed paths picked the upstream. A &lt;code&gt;route.Select()&lt;/code&gt; function picked the auth mode. A growing stack of prefix conditionals decided which paths were public:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/admin-service/*  → admin upstream   + JWT (except login, refresh, external-api)
/user-service/*   → user upstream    + HMAC (except auth, device, internal, …)
/chat-service/*   → chat upstream    + HMAC for users, JWT for /api/v1/admin/*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It shipped. It worked. It was ugly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the ugliness actually lived
&lt;/h2&gt;

&lt;p&gt;Not in reliability. Requests hit the right upstream, JWT/HMAC validation worked, sessions slid TTL correctly. The ugliness was in &lt;strong&gt;extensibility&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;proxies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;applyAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sessionStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nonceStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServeHTTP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean on paper. But &lt;code&gt;adminAuth()&lt;/code&gt;, &lt;code&gt;userAuth()&lt;/code&gt;, and &lt;code&gt;chatAuth()&lt;/code&gt; were each a wall of &lt;code&gt;strings.HasPrefix&lt;/code&gt; branches, each one carrying tribal knowledge about which paths were exceptions. Every new public-path exception meant editing Go and redeploying the gateway. Figuring out &lt;em&gt;why&lt;/em&gt; a path behaved a certain way meant reading three functions and cross-referencing a README the size of a small service.&lt;/p&gt;

&lt;p&gt;I wasn't failing at microservices. I was failing at &lt;strong&gt;boundary discipline&lt;/strong&gt;: policy had nowhere clean to live except deeper inside the gateway's Go source.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every new exception made the gateway more specific instead of more general.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That gateway didn't get thrown away. It proved the routing model was right. It just proved the &lt;em&gt;implementation&lt;/em&gt; model needed to change. That became Conduit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design goals (the actual constraints, not aspirations)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Freedom of implementation.&lt;/strong&gt; If you can write TypeScript, you can extend the gateway. No DSL, no Lua config, no plugin marketplace format: drop a file in &lt;code&gt;./plugins&lt;/code&gt;, export an object with lifecycle hooks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GatewayContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../runtime/shared/types.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;beforeRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GatewayContext&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;missing token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Low operational overhead.&lt;/strong&gt; No control plane, no Kubernetes requirement, no sidecar ceremony. Default setup is one Go binary supervising a Deno runtime, reading a JSON config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run ./cmd/conduit &lt;span class="nt"&gt;-config&lt;/span&gt; conduit.config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Explicit separation of concerns.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Go gateway&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;HTTP ingress, routing, upstream proxying, CORS, body limits, timeouts, SSRF guards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deno runtime&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sandboxed plugin execution in a warm worker pool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Plugins&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Business policy: auth, logging, transforms, route control&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Go never gets to know about plugin internals. The runtime never owns routing. Plugins never touch the network boundary directly. These invariants are written down because violating them produces cross-language bugs that tests don't reliably catch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Predictable failure modes.&lt;/strong&gt; A misbehaving plugin shouldn't take down the gateway. Hook timeouts log and continue. Worker crashes replace the isolate, not the process. If the entire runtime is unreachable, &lt;code&gt;failPolicy&lt;/code&gt; decides: &lt;code&gt;closed&lt;/code&gt; (503, no proxy) or &lt;code&gt;open&lt;/code&gt; (skip plugins, proxy anyway), configurable per route.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Invisible in production.&lt;/strong&gt; The bar I actually cared about: deploy a plugin when policy changes, glance at structured logs when something's off, otherwise forget the thing exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture: two processes, one socket
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgdbudfy2h1yrsaee8yar.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgdbudfy2h1yrsaee8yar.png" alt=" " width="799" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Per request:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Client hits the Go gateway.&lt;/li&gt;
&lt;li&gt;CORS preflight (&lt;code&gt;OPTIONS&lt;/code&gt;) is answered in Go; plugins never see it.&lt;/li&gt;
&lt;li&gt;Go builds a serializable context snapshot from the request.&lt;/li&gt;
&lt;li&gt;Every plugin's &lt;code&gt;beforeRequest&lt;/code&gt; hook runs, in filename order.&lt;/li&gt;
&lt;li&gt;Go proxies once to the matched (or plugin-selected) upstream.&lt;/li&gt;
&lt;li&gt;The upstream response gets attached to context.&lt;/li&gt;
&lt;li&gt;Every plugin's &lt;code&gt;afterResponse&lt;/code&gt; hook runs, same order.&lt;/li&gt;
&lt;li&gt;Go writes the response to the client.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Upstream services have zero awareness Conduit exists: no SDK, no self-registration. Multi-service routing is config, not code:&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;"routes"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/user-service/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"upstream"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://user-service:2001"&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;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/admin-service/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"upstream"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://admin-service:2002"&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;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/chat-service/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"upstream"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://chat-service:2003"&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;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;One plugin chain, many backends, policy applied uniformly at the edge.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual hard part: getting context across the process boundary
&lt;/h2&gt;

&lt;p&gt;The real problem with the first gateway wasn't routing logic. It was &lt;em&gt;where state lived&lt;/em&gt;. Mutable request objects passed through middleware created hidden coupling, and that gets worse the moment you're crossing a process boundary: you cannot hand Deno a live &lt;code&gt;http.Request&lt;/code&gt; and hope for the best.&lt;/p&gt;

&lt;p&gt;Conduit's contract:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go &lt;strong&gt;snapshots&lt;/strong&gt; the request into serializable JSON.&lt;/li&gt;
&lt;li&gt;The snapshot crosses a length-prefixed frame over a Unix socket to Deno.&lt;/li&gt;
&lt;li&gt;The plugin operates on a cloned, hook-local context with a frozen inbound request.&lt;/li&gt;
&lt;li&gt;The plugin returns a &lt;strong&gt;patch&lt;/strong&gt;: a minimal delta, not a mutated object.&lt;/li&gt;
&lt;/ol&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftk257re0smggaasx6zxz.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftk257re0smggaasx6zxz.png" alt=" " width="800" height="791"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why patch instead of full context on return:&lt;/strong&gt; sending the complete context back from every hook means re-serializing headers, identity, and potentially large bodies, twice per request, per plugin. The patch engine instead sends only what changed: omitted fields are unchanged, present fields overwrite, &lt;code&gt;null&lt;/code&gt; tombstones a deletion. A logging plugin that sets one &lt;code&gt;state&lt;/code&gt; field ships a few dozen bytes back, not the whole request graph.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why bodies never fully cross the wire:&lt;/strong&gt; anything above 64 KiB stays in a per-request &lt;code&gt;BodyStore&lt;/code&gt; in Go. Plugins get a &lt;code&gt;stream://&lt;/code&gt; reference token, not raw bytes. Megabytes stay in Go; metadata crosses the socket.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Plugins don't own the request. They propose changes to it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sentence is the whole design. Reject/forward signals, the patch diffing rules, the frozen snapshot: all of it exists to make "propose, don't own" safe and cheap.&lt;/p&gt;

&lt;h2&gt;
  
  
  The plugin model
&lt;/h2&gt;

&lt;p&gt;Plugins stay deliberately small:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hook&lt;/th&gt;
&lt;th&gt;When&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;onLoad&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Once at startup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;beforeRequest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Before upstream proxying&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;afterResponse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;After upstream response is captured&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;onError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;When a hook in &lt;em&gt;this&lt;/em&gt; plugin throws unexpectedly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;ctx.reject()&lt;/code&gt; is intentional control flow, not an error; &lt;code&gt;onError&lt;/code&gt; is for actual surprises.&lt;/p&gt;

&lt;p&gt;Plugins load in filename order, full stop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins/
  001-auth.ts           ← runs first
  002-logging.ts        ← sees ctx.user from auth
  003-header-rewrite.ts
  004-route-control.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No dependency graph, no hidden priority system. &lt;code&gt;001-auth.ts&lt;/code&gt; runs before &lt;code&gt;002-logging.ts&lt;/code&gt; because of the filename, and that's grep-able at 3am.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ctx&lt;/code&gt; surface is narrow on purpose:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Member&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ctx.request&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read-only inbound snapshot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ctx.response&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Outbound builder (&lt;code&gt;setStatus&lt;/code&gt;, &lt;code&gt;setHeader&lt;/code&gt;, &lt;code&gt;setBody&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ctx.user&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Identity set by auth plugins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ctx.state&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Per-request key/value bag shared across hooks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ctx.log&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Structured logging with trace correlation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ctx.reject(status, msg)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stop pipeline, return HTTP error&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ctx.forward(url)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Proxy to an alternate upstream (validated by the gateway)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ctx.services&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Optional &lt;code&gt;http&lt;/code&gt; and &lt;code&gt;cache&lt;/code&gt; helpers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No global singletons, no ambient mutable request object. Auth sets &lt;code&gt;ctx.user&lt;/code&gt;; logging reads it. That's the entire coordination contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happened when I actually ran it
&lt;/h2&gt;

&lt;p&gt;The first deployment was personal: three services behind one port, HMAC checks in one plugin file, JWT checks in another, logging in a third. The prefix-matching spaghetti became three files I could read top to bottom.&lt;/p&gt;

&lt;p&gt;Then it spread quietly: internal tools needing a stable hostname, admin surfaces needing stricter gating, experimental routes I could add without redeploying backends.&lt;/p&gt;

&lt;p&gt;The moment I knew it worked wasn't a benchmark. It was forgetting it was running, then stopping the Docker container to debug something unrelated and watching everything break. That's the success criterion I actually cared about: not feature parity with Kong, invisibility under normal operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Failure modes, stated plainly
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Plugin hook exceeds timeout (default 100ms)&lt;/td&gt;
&lt;td&gt;Warning logged; request continues proxying&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plugin worker crashes&lt;/td&gt;
&lt;td&gt;Isolate replaced; gateway process survives&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entire Deno runtime unavailable&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;failPolicy: "closed"&lt;/code&gt; → 503; &lt;code&gt;"open"&lt;/code&gt; → proxy without plugins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ctx.reject(401)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pipeline stops; remaining hooks skipped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invalid &lt;code&gt;ctx.forward()&lt;/code&gt; target&lt;/td&gt;
&lt;td&gt;Logged, ignored; original route used&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upstream failure&lt;/td&gt;
&lt;td&gt;Standard &lt;code&gt;502&lt;/code&gt; propagated&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Hook timeout and runtime death are different failure classes on purpose. A slow logger shouldn't look like a dead security layer.&lt;/p&gt;

&lt;p&gt;The riskiest failure mode isn't a crash, though. It's &lt;strong&gt;silent semantic change&lt;/strong&gt;: a plugin that mis-sets &lt;code&gt;ctx.user&lt;/code&gt; or swallows a header keeps the system at &lt;code&gt;200 OK&lt;/code&gt; while behavior quietly drifts underneath it. That's why every log line carries &lt;code&gt;[trace:&amp;lt;id&amp;gt;]&lt;/code&gt;, and why &lt;code&gt;reject&lt;/code&gt; and thrown errors are treated as distinct signals.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it's not
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Not Envoy: no xDS, no WASM filter ecosystem at scale.&lt;/li&gt;
&lt;li&gt;Not Kong: no admin UI, no plugin marketplace.&lt;/li&gt;
&lt;li&gt;Not a service mesh.&lt;/li&gt;
&lt;li&gt;Not for multi-gigabyte streaming responses. &lt;code&gt;afterResponse&lt;/code&gt; buffers the body so plugins can inspect/rewrite it, which costs memory proportional to response size.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What it gains in exchange: a codebase readable in an afternoon, plugins you edit and save instead of recompile, no cloud dependency to define policy, and bounded IPC cost (one warm Unix socket, patches instead of full payloads, body references instead of raw bytes).&lt;/p&gt;

&lt;p&gt;It's lean, not free. Four plugins across two phases is up to eight round trips per request. Sub-millisecond on a local socket. Wrong tool if you need per-byte stream processing at scale; right tool if you've got a handful of services, evolving edge policy, and a team that already writes TypeScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  What stuck
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Abstraction is only good if it disappears in daily use.&lt;/strong&gt; The pieces that survived are the ones I stopped thinking about. The pieces that died were baked into Go: the &lt;code&gt;adminAuth()&lt;/code&gt;/&lt;code&gt;userAuth()&lt;/code&gt;/&lt;code&gt;chatAuth()&lt;/code&gt; prefix ladders that worked fine until they needed to change without a redeploy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-process plugin systems are viable if state transfer is strict.&lt;/strong&gt; Patches, body references, frozen snapshots. Not optimization trivia; the actual precondition for Go and Deno cooperating without shared-memory bugs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failure design shaped operability more than any plugin API did.&lt;/strong&gt; &lt;code&gt;failPolicy&lt;/code&gt;, hook timeouts, and the &lt;code&gt;reject&lt;/code&gt;/&lt;code&gt;onError&lt;/code&gt; split mattered more than feature count.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Simple" means boundary discipline, not low line count.&lt;/strong&gt; Go owns the network. Deno owns execution. Plugins own policy proposals. Upstream owns business logic. Nobody reaches across.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;This wasn't built to be a product. It was a response to a system that stopped fitting in my head: three services, two auth models, one endpoint, and a gateway that grew a new &lt;code&gt;strings.HasPrefix&lt;/code&gt; branch every time something shipped.&lt;/p&gt;

&lt;p&gt;The goal was never to out-build Envoy or Kong. It was to build something I could forget existed until the day I needed to reason about it. At that point, reasoning about it should be easy: read the plugin files, read the config, follow one request through Go → IPC → Deno → upstream → back.&lt;/p&gt;

&lt;p&gt;If you're standing where I was (auth diverging, routing logic leaking into every handler), you might not need another service. You might need a place where policy can live without infecting everything else.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run ./cmd/conduit &lt;span class="nt"&gt;-config&lt;/span&gt; conduit.config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;beforeRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* policy */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nf"&gt;afterResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* transforms */&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;Full design-decision Q&amp;amp;A (why Deno over Node/Lua/WASM, scaling, "when is this the wrong choice," etc.) is in my site, not &lt;a href="https://a-thedeveloper.vercel.app/blog/conduit" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to Claude for helping with my wording, grammars...etc and it also added its own intro at the very top. I was so excited to share Conduit that I forgot to review it added a very LLM-generic intro for me that just got me flagged by Sloan.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>architecture</category>
      <category>typescript</category>
      <category>go</category>
    </item>
    <item>
      <title>When Software Started Writing Software: A Developer’s History of AI</title>
      <dc:creator>Adam - The Developer ✨</dc:creator>
      <pubDate>Mon, 22 Jun 2026 08:06:29 +0000</pubDate>
      <link>https://dev.to/adamthedeveloper/when-software-started-writing-software-a-developers-history-of-ai-4p9n</link>
      <guid>https://dev.to/adamthedeveloper/when-software-started-writing-software-a-developers-history-of-ai-4p9n</guid>
      <description>&lt;p&gt;If you've shipped software in the last three years, you've probably watched your job description quietly rewrite itself. You went from writing code, to writing code &lt;em&gt;with&lt;/em&gt; an autocomplete, to writing code &lt;em&gt;with&lt;/em&gt; a collaborator, to increasingly writing a spec and watching an agent write, test, and ship the code for you.&lt;/p&gt;

&lt;p&gt;That didn't happen overnight. It's the latest chapter in a 70-year story that started with researchers trying to teach machines to play checkers. Let's walk through it, not as a dry timeline, but as the story of how "intelligence" kept getting redefined every time machines got good at the last definition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;1. The Symbolic Era: Intelligence as Logic (1950s–1980s)&lt;/li&gt;
&lt;li&gt;2. Statistics Quietly Eats Symbols (1990s–2000s)&lt;/li&gt;
&lt;li&gt;3. Deep Learning Breaks the Ceiling (2012–2017)&lt;/li&gt;
&lt;li&gt;4. The Transformer and the Birth of "General-ish" Intelligence (2017–2022)&lt;/li&gt;
&lt;li&gt;5. From Chatbot to Coworker: The Agentic Turn (2023–Today)&lt;/li&gt;
&lt;li&gt;So What Changed, Really?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. The Symbolic Era: Intelligence as Logic (1950s–1980s)
&lt;/h2&gt;

&lt;p&gt;The founding bet of AI, made official at the 1956 Dartmouth Workshop, was simple and audacious: thought is computation. If you could represent knowledge as symbols and rules, and manipulate those symbols correctly, you'd get intelligence.&lt;/p&gt;

&lt;p&gt;This gave us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Logic Theorist (1956)&lt;/strong&gt;: proved mathematical theorems by searching through logical statements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ELIZA (1966)&lt;/strong&gt;: pattern-matched your sentences back at you and convinced people it understood them. The first chatbot, and the first time humans projected understanding onto a system that had none.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expert systems (1970s–80s)&lt;/strong&gt;: programs like &lt;a href="https://en.wikipedia.org/wiki/MYCIN" rel="noopener noreferrer"&gt;MYCIN&lt;/a&gt; encoded a domain expert's rules as &lt;code&gt;IF-THEN&lt;/code&gt; statements. MYCIN could diagnose bacterial infections about as well as a human specialist, using a few hundred hand-written rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was &lt;strong&gt;weak, narrow intelligence&lt;/strong&gt; in the most literal sense: a system that was a genius in one box and knew nothing outside it. The fatal flaw was scale, every rule had to be written by hand by a human expert. Knowledge didn't generalize, and it didn't learn from data. When funding agencies realized these systems couldn't handle the messiness of the real world, the money dried up. This was the &lt;strong&gt;first AI winter&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Statistics Quietly Eats Symbols (1990s–2000s)
&lt;/h2&gt;

&lt;p&gt;While "AI" was a dirty word in grant applications, a different idea was gaining ground: instead of &lt;em&gt;telling&lt;/em&gt; a machine the rules, show it examples and let it find the rules itself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Neural networks&lt;/strong&gt; had existed since the 1950s (the perceptron) but were widely written off after Minsky and Papert detailed their mathematical limits in &lt;a href="https://en.wikipedia.org/wiki/Perceptrons_(book)" rel="noopener noreferrer"&gt;Perceptrons (1969)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backpropagation&lt;/strong&gt;, popularized in 1986, gave multi-layer networks a real way to learn and yet networks still mostly lost to simpler methods for another two decades. The algorithm existing wasn't enough; there wasn't enough labeled data or compute to let it show what it could do. It sat half-revived, a promising idea nobody could afford to run at scale.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support Vector Machines, decision trees, and Bayesian methods&lt;/strong&gt; dominated practical machine learning, spam filters, recommendation engines, fraud detection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IBM's Deep Blue beat Garry Kasparov in 1997&lt;/strong&gt;, but largely through brute-force search over chess positions, not learning. Still narrow, still impressive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This era's intelligence was &lt;em&gt;statistical&lt;/em&gt; rather than &lt;em&gt;logical&lt;/em&gt;: pattern recognition over labeled data. It worked well on narrow, well-defined tasks but needed mountains of hand-labeled examples and feature engineering done by humans. The "intelligence" was still mostly in the human designing the features the model was just fitting a curve.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Deep Learning Breaks the Ceiling (2012–2017)
&lt;/h2&gt;

&lt;p&gt;The ingredients for the next leap had been sitting around for a decade: more data (the internet), more compute (GPUs originally built for video games), and algorithmic tricks for training deeper networks without them collapsing into noise. None of this looked inevitable at the time. Most of the field had moved on from neural networks; deep nets were a fringe bet kept alive by a small number of labs who kept getting told they were wasting their careers.&lt;/p&gt;

&lt;p&gt;The spark was &lt;strong&gt;&lt;a href="https://papers.nips.cc/paper_files/paper/2012/hash/c399862d3b9d6b76c8436e924a68c45b-Abstract.html" rel="noopener noreferrer"&gt;AlexNet (2012)&lt;/a&gt;&lt;/strong&gt;, a deep convolutional neural network that crushed the ImageNet image-classification competition, slashing the error rate compared to the next-best approach. That one result told the field something important: stack enough layers, feed them enough data, and the network finds its own features, no human feature engineering required. It wasn't a smooth continuation of the field's direction; it was closer to a coup. Within a couple of years, techniques that had been a punchline became the default starting point for almost every computer vision paper.&lt;/p&gt;

&lt;p&gt;What followed was a five-year sprint:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://arxiv.org/abs/1301.3781" rel="noopener noreferrer"&gt;Word2Vec (2013)&lt;/a&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;a href="https://aclanthology.org/D14-1162/" rel="noopener noreferrer"&gt;GloVe (2014)&lt;/a&gt;&lt;/strong&gt;: words became vectors, and "meaning" became something you could do arithmetic on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://arxiv.org/abs/1406.2661" rel="noopener noreferrer"&gt;Generative Adversarial Networks (2014)&lt;/a&gt;&lt;/strong&gt;: two networks competing, one generating fakes, one detecting them, together learning to produce eerily convincing images.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.nature.com/articles/nature16961" rel="noopener noreferrer"&gt;AlphaGo (2016)&lt;/a&gt;&lt;/strong&gt;: beat the world's best Go player (the board game, not &lt;code&gt;go run main.go&lt;/code&gt; energy) using deep learning plus reinforcement learning plus tree search, on a game once thought too intuitive for machines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these was still task-bound, a vision model couldn't write a sentence, a Go-playing model couldn't recognize a cat — but the skill inside each one was no longer handed to it by a human; the model discovered its own representation of the problem. That shift in mechanism, more than any single result, is what made the next jump possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The Transformer and the Birth of "General-ish" Intelligence (2017–2022)
&lt;/h2&gt;

&lt;p&gt;In 2017, a Google paper titled &lt;a href="https://arxiv.org/abs/1706.03762" rel="noopener noreferrer"&gt;"Attention Is All You Need"&lt;/a&gt; introduced the &lt;strong&gt;transformer architecture&lt;/strong&gt;. Instead of processing text sequentially like older recurrent networks, transformers let every word attend to every other word at once. It was a better way to model sequences and it turned out to scale beautifully.&lt;/p&gt;

&lt;p&gt;That architectural choice, combined with the realization that you could pretrain a single giant model on a huge slice of the internet and then adapt it to almost any language task, produced the GPT lineage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GPT (2018) → GPT-2 (2019) → GPT-3 (2020)&lt;/strong&gt;: each generation showed that scaling up parameters and data kept producing qualitatively new abilities, not just marginal accuracy gains. GPT-3 could write code, translate, summarize, and hold a conversation, despite never being explicitly trained to do any of those things.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instruction tuning and RLHF (2021–2022)&lt;/strong&gt;: raw language models predict the next token; they don't inherently want to be &lt;em&gt;helpful&lt;/em&gt;. Techniques like reinforcement learning from human feedback turned raw next-token predictors into assistants that follow instructions and refuse harmful ones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://chat.openai.com/" rel="noopener noreferrer"&gt;ChatGPT (November 2022)&lt;/a&gt;&lt;/strong&gt;: &lt;a href="https://twitter.com/sama/status/1598038815599661056" rel="noopener noreferrer"&gt;Sam Altman announced it on X&lt;/a&gt; with the energy of a minor release: "today we launched ChatGPT. try talking with it here." Understated copy for the moment the old era ended and a new history began. Research left the lab; your non-technical relatives showed up. A hundred million users in two months. The Turing Test stopped being a thought experiment and became something people ran into accidentally over breakfast.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the point where AI stopped meaning "deep in one box, blank everywhere else" and started meaning &lt;em&gt;compositional&lt;/em&gt;: a single set of weights that could combine skills it was never explicitly trained to combine. One model could write a sonnet, debug Python, and explain the sonnet's meter not because it was three different systems, but because language turned out to be a surprisingly good universal interface to a huge range of human tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. From Chatbot to Coworker: The Agentic Turn (2023–Today)
&lt;/h2&gt;

&lt;p&gt;A language model that just answers questions is a powerful autocomplete. The next phase of the story is about giving that model &lt;strong&gt;hands&lt;/strong&gt;: the ability to call tools, write and execute code, browse the web, remember state across steps, and chain its own reasoning into multi-step plans.&lt;/p&gt;

&lt;p&gt;A few threads converged here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tool use / function calling&lt;/strong&gt; let models stop just describing actions and start taking them, querying a database, hitting an API, running a calculation, instead of guessing at the answer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval-augmented generation (RAG)&lt;/strong&gt; gave models access to information beyond their training data, grounding answers in real documents instead of frozen memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chain-of-thought and reasoning models&lt;/strong&gt; showed that letting a model "think out loud" before answering and eventually training it specifically to reason longer on hard problems, produced dramatically better results on math, logic, and multi-step planning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agentic frameworks&lt;/strong&gt; stitched these into loops: plan → act → observe → revise. Wrapped in orchestration code, retry logic, and well-designed tools, a model could chase a goal across many steps instead of answering once and stopping. Left alone long enough, it still drifts or takes wrong turns, the scaffolding exists to catch that. "Agent" describes a system, not a self-sufficient mind.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-agent orchestration&lt;/strong&gt;: models that spin up &lt;em&gt;other&lt;/em&gt; model instances to parallelize work, each with a narrower role, then combine results. The specialist of the symbolic era is back, except now it's a transformer playing a role inside a swarm coordinated by another transformer, instead of a human-written rule.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the world a developer in 2026 actually lives in. Code isn't just suggested line-by-line; it's planned, written across multiple files, tested, and debugged in a loop that needs less hands-on steering than it used to, though still real review, real guardrails, and real human judgment about when to trust the output. The same pattern shows up outside coding: research agents that browse, synthesize, and cite sources across dozens of pages; operations agents that read a ticket, check a calendar, and draft a response; design agents that take a brief and return a working prototype. None of this is autonomy in the strong sense yet. It's interactive capability, a model in a loop with tools and a feedback signal — and it's powerful precisely because of how tightly that loop is engineered, not in spite of it.&lt;/p&gt;

&lt;p&gt;Easy to miss when you're staring at capability charts: every jump here was also an economics story. Expert systems died because expert time didn't scale. Statistical ML rode cheap labeled data and storage. Deep learning rode gaming GPUs. LLMs rode internet-scale data and transformer parallelism. Agents are having their moment because inference got cheap enough to run a model in a loop hundreds of times per task without laughing. The recurring question isn't "can we build it?" but it's "can we afford to run it enough times to be useful?" That bottleneck moved; it didn't disappear.&lt;/p&gt;

&lt;h2&gt;
  
  
  So What Changed, Really?
&lt;/h2&gt;

&lt;p&gt;If you zoom out, the history of AI is a story about &lt;em&gt;where the intelligence lives&lt;/em&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Era&lt;/th&gt;
&lt;th&gt;Where the "smarts" lived&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Symbolic AI&lt;/td&gt;
&lt;td&gt;In rules a human expert wrote by hand&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Statistical ML&lt;/td&gt;
&lt;td&gt;In features a human engineer chose&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deep learning&lt;/td&gt;
&lt;td&gt;In representations the model learned itself&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large language models&lt;/td&gt;
&lt;td&gt;In patterns learned from most of the public internet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agentic systems&lt;/td&gt;
&lt;td&gt;In the model's own planning, tool use, and self-correction across time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each era didn't replace the last so much as absorb it. Today's agents still do statistical pattern matching under the hood; they still occasionally fail in the brittle, overconfident ways the old expert systems did, just less often and less predictably.&lt;/p&gt;

&lt;p&gt;If you compress the five eras above, there are really only three discontinuities that mattered:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hand-coded intelligence&lt;/strong&gt;: rules a human wrote (symbolic AI).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learned representations&lt;/strong&gt;: patterns a model found in data, with steadily less human-chosen structure (statistical ML → deep learning → LLMs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive systems&lt;/strong&gt;: models that act, observe consequences, and revise, instead of just outputting a single answer (agents).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The five-era version tells a better story; the three-version compression is what actually changed underneath.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shift one: who writes the rules — human or data. &lt;/li&gt;
&lt;li&gt;Shift two: passive answer vs. active loop. Most of "AI got so much better" traces to one of those.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't a straight march toward AGI. It's researchers repeatedly asking "what if the machine decided this part?" and finding that worked, once the economics finally allowed it.&lt;/p&gt;

&lt;p&gt;Whether the next chapter is "agents that reliably run entire businesses" or "another winter while the hype outpaces the engineering" is genuinely an open question and depending on who you ask, both are already happening at once.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>There Is No Perfect Solution in Software Development: Every Decision is a Tradeoff</title>
      <dc:creator>Adam - The Developer ✨</dc:creator>
      <pubDate>Mon, 15 Jun 2026 06:22:48 +0000</pubDate>
      <link>https://dev.to/adamthedeveloper/there-is-no-perfect-solution-in-software-development-every-decision-is-a-tradeoff-136l</link>
      <guid>https://dev.to/adamthedeveloper/there-is-no-perfect-solution-in-software-development-every-decision-is-a-tradeoff-136l</guid>
      <description>&lt;p&gt;Most bad decisions in software engineering aren't made because the engineer chose wrong between two clear options. They're made because the engineer didn't realize they were making a choice at all.&lt;/p&gt;

&lt;p&gt;You optimized for readability without noticing that particular loop runs a million times per second. You built for perfect flexibility without realizing you'd never actually need it. You shipped fast and acknowledged the technical debt—until the debt became someone else's problem, and by then it was too late to refactor.&lt;/p&gt;

&lt;p&gt;The pattern: teams usually aren't choosing between two good options. They're choosing between one safe default and one speculative optimization, and calling it a tradeoff to feel better about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What Every Engineer Needs to Know About Tradeoffs&lt;/li&gt;
&lt;li&gt;
Classic Tradeoffs You'll Face

&lt;ul&gt;
&lt;li&gt;Performance vs. Readability&lt;/li&gt;
&lt;li&gt;Flexibility vs. Simplicity&lt;/li&gt;
&lt;li&gt;Speed to Market vs. Technical Debt&lt;/li&gt;
&lt;li&gt;Scalability vs. Cost&lt;/li&gt;
&lt;li&gt;Security vs. Convenience&lt;/li&gt;
&lt;li&gt;The CAP Theorem: What It Actually Means&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The Pattern: How Good Decisions Actually Get Made&lt;/li&gt;
&lt;li&gt;How to Make Better Tradeoff Decisions&lt;/li&gt;
&lt;li&gt;The Mark of Experience&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Every Engineer Needs to Know About Tradeoffs
&lt;/h2&gt;

&lt;p&gt;There is no perfect solution. Every architecture, every algorithm, every design decision buys you something at the cost of something else. This isn't pessimism, it's the foundation of good engineering judgment.&lt;/p&gt;

&lt;p&gt;But here's the catch: not all tradeoffs are 50/50. In practice, experienced engineers often default heavily one way and only deviate with evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Classic Tradeoffs You'll Face
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Performance vs. Readability
&lt;/h3&gt;

&lt;p&gt;Here's what usually wins: readability. Unless you have a proven bottleneck backed by profiling data, optimize for clarity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Faster but harder to maintain&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Slower but immediately clear&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second version is probably fine. Premature optimization is still the root of all evil. The first example should only exist if: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;you've profiled&lt;/li&gt;
&lt;li&gt;you found this function is actually slow&lt;/li&gt;
&lt;li&gt;you've measured that the optimization makes a meaningful difference&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;All three conditions are rarer than you'd think.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Flexibility vs. Simplicity
&lt;/h3&gt;

&lt;p&gt;"Flexibility" often looks like smart future-proofing until you realize you'll never actually need it.&lt;/p&gt;

&lt;p&gt;You build a generic plugin system because "we might need it." You abstract everything into interfaces because "we'll probably want to swap implementations." You create configuration options for scenarios that never materialize. Meanwhile, your simple code that handles exactly one thing is getting buried under layers of generality.&lt;/p&gt;

&lt;p&gt;Ship the simple thing. If you actually need multiple use cases later, refactoring from concrete to generic is almost always easier than refactoring from over-engineered to usable. The exception: if you're building a library or platform that multiple teams depend on, flexibility becomes a real requirement, not speculation.&lt;/p&gt;

&lt;p&gt;Most over-engineering is just ego disguised as foresight.&lt;/p&gt;

&lt;h3&gt;
  
  
  Speed to Market vs. Technical Debt
&lt;/h3&gt;

&lt;p&gt;Ship in two weeks with known compromises? Or spend two months building something maintainable? &lt;/p&gt;

&lt;p&gt;Both answers are right in different contexts. A startup with three months of runway and a saturated market needs speed. A fintech system handling billions in transactions needs stability. There's no universal answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scalability vs. Cost
&lt;/h3&gt;

&lt;p&gt;Premature scalability is usually just waste unless you have strong signals of growth.&lt;/p&gt;

&lt;p&gt;You can architect for 100x your current traffic and be right. You can also architect for today's load and be right. The difference is that one cost money now, and the other might cost money later. Most teams choose wrong because they're optimizing for an imagined future instead of the constraints they actually face.&lt;/p&gt;

&lt;p&gt;The right call: scale when you have evidence that growth is coming, not because it &lt;em&gt;might&lt;/em&gt; happen. Growth that doesn't materialize? You've spent months and money on infrastructure that will never be used. Growth that does materialize and catches you off-guard? That's painful, but you'll fix it. The fix is usually cheaper than over-engineering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are unsure whether you need scalability, you don't.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Security vs. Convenience
&lt;/h3&gt;

&lt;p&gt;Require 2FA, complex passwords, and proof of identity? That's more secure. Users will also hate you.&lt;/p&gt;

&lt;p&gt;Frictionless auth is delightful for users and a security nightmare. You're balancing two legitimate concerns.&lt;/p&gt;

&lt;h3&gt;
  
  
  The CAP Theorem: What It Actually Means
&lt;/h3&gt;

&lt;p&gt;Everything above applies to a single application you control end to end. This one is different — it belongs to &lt;strong&gt;distributed systems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A distributed system is software spread across multiple machines that coordinate over a network. Your API talking to one database is distributed in the loose sense, but CAP really starts to matter when the same data lives in more than one place: a primary with read replicas, a Redis cluster, a multi-region deployment. The moment you have copies of data on separate nodes, connected by a network that can fail, you inherit tradeoffs you do not get on a single server.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;CAP theorem&lt;/strong&gt; names the central one. The textbook version says: "Pick any two of Consistency, Availability, and Partition Tolerance."&lt;/p&gt;

&lt;p&gt;Here's what actually happens: In any real distributed system, &lt;strong&gt;partition tolerance is not optional&lt;/strong&gt;. Network failures will happen. So the real choice is between &lt;strong&gt;Consistency and Availability when the network breaks&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CP systems&lt;/strong&gt; fail safely when they can't guarantee consistency. A banking app might do this, it's better to be down than serve wrong balances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AP systems&lt;/strong&gt; stay up and serve whatever data they have. A social feed might do this, slightly stale likes are better than a 503.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code doesn't need to be complicated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CP: fail rather than serve wrong data&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT balance FROM accounts WHERE id = $1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&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="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// If database is unreachable, the request fails. That's the design.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// AP: serve cached data with a staleness flag&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;stale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT balance FROM accounts WHERE id = $1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&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="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;stale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Partition: return whatever we have cached&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cache&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="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;stale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="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;Choose based on what breaks is worse: being wrong (CP) or being unavailable (AP).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pattern: How Good Decisions Actually Get Made
&lt;/h2&gt;

&lt;p&gt;Once you recognize that a tradeoff exists, you're already halfway to making a good decision. You can be intentional about what you're trading and why. You can explain it to your team. You can revisit it later if your constraints change.&lt;/p&gt;

&lt;p&gt;Without that awareness? You end up optimizing for readability on a loop that runs a million times per second. You build flexibility you'll never need. You ship fast and defer the cost to future-you.&lt;/p&gt;

&lt;p&gt;Here's what separates functional teams from dysfunctional ones: functional teams argue about &lt;em&gt;which&lt;/em&gt; tradeoff they're making. Dysfunctional teams don't realize there's a choice at all, and they compound the costs by pretending it was inevitable.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Make Better Tradeoff Decisions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Name the tradeoff explicitly&lt;/strong&gt;&lt;br&gt;
Don't say "should we use Redis?" Say "are we optimizing for speed or operational simplicity?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Understand your constraints&lt;/strong&gt;&lt;br&gt;
What actually matters in your context? A library used by millions needs different tradeoffs than an internal tool used by five people.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Make it reversible if possible (but know the real limits)&lt;/strong&gt;&lt;br&gt;
Refactoring from concrete to generic is usually easier than the reverse. Local code changes are easy to undo. But reversibility has hard boundaries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;True reversibility&lt;/strong&gt;: Internal implementation details, local code scope, nothing that touches user-facing behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;False reversibility&lt;/strong&gt;: Anything that becomes business-critical, anything customers build workflows around, anything that spreads to multiple teams. A quick hack that ships and immediately gets embedded in product behavior doesn't refactor cleanly six months later. The team has built processes around it. Customers depend on it. Other engineers have written code that relies on it. Reversibility was an illusion from the moment the code touched production.&lt;/p&gt;

&lt;p&gt;Know which category your decision falls into before you ship it as temporary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Document your reasoning&lt;/strong&gt;&lt;br&gt;
Future you (and your teammates) will thank you. "We chose simple over performant here because X" is gold.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Revisit your assumptions&lt;/strong&gt;&lt;br&gt;
Your constraints change. What was the right tradeoff six months ago might be wrong now. That's not failure—that's growth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mark of Experience
&lt;/h2&gt;

&lt;p&gt;Here's what changes as you get better at this:&lt;/p&gt;

&lt;p&gt;Seniors aren't less stressed, they're stressed about the right things. They don't waste energy trying to eliminate uncertainty. They can't. Uncertainty is part of the job. Instead, they focus on &lt;strong&gt;reducing risk and keeping decisions reversible where possible&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They ask good questions: "What happens if we're wrong about this?" "What would make us want to undo this decision?" "Do we have evidence this is actually a bottleneck?" They make explicit choices, document the tradeoffs, and move forward without second-guessing.&lt;/p&gt;

&lt;p&gt;The skill isn't knowing everything. It's &lt;strong&gt;making conscious tradeoffs and living with the consequences&lt;/strong&gt; without pretending there was ever a perfect choice.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>software</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
