<?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: Info Inlet</title>
    <description>The latest articles on DEV Community by Info Inlet (@infoinlet1).</description>
    <link>https://dev.to/infoinlet1</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%2F3941862%2Fcec34100-b85a-4c9e-8061-55c585109946.jpeg</url>
      <title>DEV Community: Info Inlet</title>
      <link>https://dev.to/infoinlet1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/infoinlet1"/>
    <language>en</language>
    <item>
      <title>How I built a SaaS in a weekend with Claude + Next.js — the honest breakdown</title>
      <dc:creator>Info Inlet</dc:creator>
      <pubDate>Sat, 17 Oct 2026 07:32:53 +0000</pubDate>
      <link>https://dev.to/infoinlet1/how-i-built-a-saas-in-a-weekend-with-claude-nextjs-the-honest-breakdown-2le6</link>
      <guid>https://dev.to/infoinlet1/how-i-built-a-saas-in-a-weekend-with-claude-nextjs-the-honest-breakdown-2le6</guid>
      <description>&lt;p&gt;I built the first working version of my SaaS in a weekend with Claude and Next.js. That sentence is true, and it's also the least interesting thing I can tell you about the weekend.&lt;/p&gt;

&lt;p&gt;The genre this headline belongs to is mostly a lie — not the "I did it" part, the &lt;em&gt;implied&lt;/em&gt; part. "Weekend SaaS" posts sell you the fantasy that the hard thing is production: that if you could just type the code fast enough, you'd have a business by Monday. So they show you the scaffold, the pretty landing page, the Stripe button, and they stop exactly where the real work starts. The typing was never the hard part. The machine made that obvious by doing most of it while I watched.&lt;/p&gt;

&lt;p&gt;So this is the other breakdown. The honest one. It's a story about one clean, green, perfectly-typed diff the model handed me on Sunday afternoon that would have quietly eaten a paying customer's money — and the one change to how I work that caught it. That change is the whole product now. The weekend just taught me what it was.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually happened, hour by hour, with no flexing
&lt;/h2&gt;

&lt;p&gt;Let me get the "breakdown" people clicked for out of the way, because it's genuinely short.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Friday night&lt;/strong&gt; was scaffolding, and it was stupid fast. &lt;code&gt;create-next-app&lt;/code&gt;, the App Router, Tailwind, a Postgres instance, auth wired through a provider, the schema for the core objects. Claude wrote most of it and I steered. The stuff that used to be a Saturday of yak-shaving — config, boilerplate, the fourteenth time I've set up the same middleware — compressed into a couple of hours of me describing and the model producing. This part of the hype is real. Setup is solved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saturday&lt;/strong&gt; was the actual feature: the one thing the product does that's worth paying for. Here the rhythm changed. I'd describe a slice, the model would produce a confident, plausible, well-structured implementation, and I'd spend most of my time &lt;em&gt;reading&lt;/em&gt; it rather than writing it. Not reviewing in the "LGTM" sense — reading it the way you read a diff from a very fast junior who is never, ever unsure of themselves. Most of it was good. Some of it was good-looking and wrong, and the ratio is the entire story of building this way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sunday&lt;/strong&gt; was supposed to be payments and polish. It became the reason this post exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  The diff that looked perfect
&lt;/h2&gt;

&lt;p&gt;Sunday afternoon I asked for the webhook handler — the thing that receives the payment event and updates the account. The model gave me back exactly what you'd want to see. Typed end to end. Idiomatic. Error handling in the right places. It even added a comment explaining the retry semantics, which is the kind of thoughtful touch that makes you trust the author. It compiled, it passed the test it had helpfully written for itself, and it read &lt;em&gt;clean.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It acknowledged the webhook before it persisted the row.&lt;/p&gt;

&lt;p&gt;If you've never been burned by that line, it looks like nothing. The handler returns its &lt;code&gt;200 OK&lt;/code&gt; to the payment provider, and &lt;em&gt;then&lt;/em&gt; writes the record to the database. 99.9% of the time those two things happen microseconds apart and you never notice. But the provider retries on anything that isn't a fast &lt;code&gt;200&lt;/code&gt;, and the write can fail or lag — and on the one bad night where the ack goes out and the save doesn't land, the provider sees success, never retries, and you have a customer who paid you with no record that they did. Locked out of the thing they just bought, nothing in the logs to say they were ever there.&lt;/p&gt;

&lt;p&gt;I know this bug in my body. I shipped it years ago, on a different product, with no AI anywhere near it — a clean write path that acked before it persisted, and a phone call I can still feel from the customer it locked out. So I recognized it on sight. That's the only reason I caught it. The model didn't flag it, because nothing about the code &lt;em&gt;looks&lt;/em&gt; wrong — it looks like the work of someone careful. The bug isn't in the syntax. It's in the ordering, and the ordering reads fine.&lt;/p&gt;

&lt;p&gt;Here's the part that should bother you more than it bothered me in the moment: &lt;strong&gt;two lines reordered.&lt;/strong&gt; That's the fix. The most dangerous diff of the weekend and the cheapest to repair — if, and only if, someone in the loop was actively asking "what happens on the retry?" instead of admiring the clean code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thing I changed — and it's not "review the AI's output more carefully"
&lt;/h2&gt;

&lt;p&gt;The obvious lesson is "read what the model writes." True, useless. I &lt;em&gt;did&lt;/em&gt; read it. I caught this one because I'd personally been set on fire by it once; I will not catch the next one that burned somebody else. "Be more careful" is not a system. It's a hope, and hope doesn't scale past the bugs you happen to have scar tissue for.&lt;/p&gt;

&lt;p&gt;The real lesson is structural, and it's embarrassingly simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The thing that writes the code cannot be the thing that blesses the code.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I ask one model to produce a diff &lt;em&gt;and&lt;/em&gt; tell me if it's safe, I'm asking the author to grade their own homework, in the same confident voice they use for everything. It wrote the ack-before-persist handler and it would have told me the handler was correct, because from the inside of "I just produced this," it &lt;em&gt;is&lt;/em&gt; correct — it compiles, it matches the request, it looks like care. Self-assessment is exactly the thing an eager author is worst at.&lt;/p&gt;

&lt;p&gt;So I stopped doing that. Now the model that generates the diff is never the one that signs off on it. There's an &lt;strong&gt;author&lt;/strong&gt; pass whose job is to produce — fast, cheap, endless, genuinely great at the thing that got easy. Then there's a separate &lt;strong&gt;skeptic&lt;/strong&gt; pass whose entire job is to &lt;em&gt;try to break that diff&lt;/em&gt; rather than admire it — prompted not for "is this good" but for "here is a diff, find the input that makes it lose money." Asked that way, about that handler, the retry case is the first thing it reaches for. And then there's a &lt;strong&gt;human on the merge button&lt;/strong&gt; — me — who owns the call and can see the blast radius neither pass can, because I'm the one who knows a locked-out customer is a phone call and not a log line.&lt;/p&gt;

&lt;p&gt;Author, skeptic, human. The author has infinite throughput and I've learned to measure it by almost nothing. The skeptic produces zero code and it's the most valuable seat in the system. That's not a philosophy I read somewhere — it's the shape the weekend beat into me, when the author handed me a beautiful diff that would have cost me a customer and had no idea it had done anything wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a weekend actually buys you (and what it doesn't)
&lt;/h2&gt;

&lt;p&gt;Since I'm being honest about the rest of it: a weekend gets you a &lt;em&gt;prototype that proves the core loop works.&lt;/em&gt; It does not get you a business. By Sunday night I had a thing that did the one valuable action end to end, for me, on my machine, with my data. That's real and it's worth something — it's the difference between an idea and an artifact you can put in front of a person.&lt;/p&gt;

&lt;p&gt;What the weekend did &lt;em&gt;not&lt;/em&gt; produce, and what no weekend produces: the error states, the empty states, the "what happens when the input is garbage," the billing edge cases, the abuse vectors, the onboarding, the second user who doesn't think like you, the thing that stays up at 2am. That's not weeks of work, it's months, and it's &lt;em&gt;most&lt;/em&gt; of the actual product. The machine compressed the part that was already the easy part and left the hard part exactly as hard as it always was — arguably harder, because now there's more confident, plausible code to be wrong in.&lt;/p&gt;

&lt;p&gt;So when you read "I built a SaaS in a weekend," translate it to "I built a convincing prototype of the core loop in a weekend, and the machine made the typing cheap enough that I could spend the whole time on whether the thing was &lt;em&gt;right&lt;/em&gt; instead of whether it &lt;em&gt;existed.&lt;/em&gt;" That's the actual gift. It's smaller than the headline and much more useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why that weekend is the entire architecture of what I build now
&lt;/h2&gt;

&lt;p&gt;That near-miss on Sunday wasn't a footnote to the project. It &lt;em&gt;became&lt;/em&gt; the project.&lt;/p&gt;

&lt;p&gt;The thing I'm building, &lt;a href="https://xenition.com" rel="noopener noreferrer"&gt;xenition&lt;/a&gt;, is an agent platform, and the whole industry right now wants to cheer for the part that produces — look how much it ships, look how clean, look how fast. But a generator is just doing the skill that stopped being scarce, at a scale no human can match, and then signing off on its own work in the same even voice whether the diff is a masterpiece or the handler that eats a payment. So the entire shape of the product is the thing my weekend taught me: never let the author bless its own output. An author that generates, a skeptic whose only job is to attack what the author made, and a human who owns the merge. The abundant thing, the scarce thing, and the person accountable for the call.&lt;/p&gt;

&lt;p&gt;I didn't set out that weekend to find a product architecture. I set out to see how far Claude and Next.js could get me by Monday. The answer was: all the way to a working prototype, and one reorder-two-lines bug away from shipping a disaster that looked exactly like success. Which turned out to be the most valuable thing the weekend could have shown me.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>startup</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>How I Became a Better Developer by Writing Less Code</title>
      <dc:creator>Info Inlet</dc:creator>
      <pubDate>Wed, 14 Oct 2026 09:35:44 +0000</pubDate>
      <link>https://dev.to/infoinlet1/how-i-became-a-better-developer-by-writing-less-code-4ln1</link>
      <guid>https://dev.to/infoinlet1/how-i-became-a-better-developer-by-writing-less-code-4ln1</guid>
      <description>&lt;p&gt;The best thing I shipped last year was a diff that deleted more than it added.&lt;/p&gt;

&lt;p&gt;I don't mean that as a humble-brag about clean code. I mean it literally changed how I think about my own job. For about a decade I had one quiet, unexamined definition of &lt;em&gt;getting better&lt;/em&gt; as a developer: produce more. More features, more commits, more lines that worked, more of the thing on the screen at the end of the day. I never said it out loud because it never needed saying — it was just the water I swam in. More output was more skill. Everyone I respected produced a lot, so I tried to produce a lot.&lt;/p&gt;

&lt;p&gt;Then the machine showed up and let me produce more than I ever had in my life. And the most "productive" quarter I'd had in years is the one that nearly cost us a paying customer. That's the story. It's the reason I now think the thing that made me better wasn't learning to write more — it was learning to write less.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decade where "more" was just true
&lt;/h2&gt;

&lt;p&gt;I want to be fair to the old me, because he wasn't stupid. For most of the history of this job, producing the code genuinely &lt;em&gt;was&lt;/em&gt; the hard part. It was slow. It was bottlenecked on you — your fingers, your working memory, your ability to hold the whole shape in your head while you typed it out. If you shipped a lot of good code, that meant something real: you had the skill, you understood the system, you could do the work nobody else could do as fast.&lt;/p&gt;

&lt;p&gt;So "more output = better developer" wasn't a mistake. It was a decent proxy, honest enough to build a career on. The volume was expensive to produce, so the volume was evidence. Nobody could fake a mountain of working code; producing it &lt;em&gt;was&lt;/em&gt; the skill, bundled all together. I measured myself by the mountain because, back then, the mountain and the skill were the same thing.&lt;/p&gt;

&lt;p&gt;That's the assumption I never noticed I was making. And it's the exact assumption that stopped being true.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then production got cheap, and I didn't update
&lt;/h2&gt;

&lt;p&gt;Here's what nobody warns you about when the machine gets good: at first it feels like you leveled up.&lt;/p&gt;

&lt;p&gt;Code got cheap for me almost overnight. Not free, not always correct — but &lt;em&gt;cheap.&lt;/em&gt; A competent first draft of a well-scoped change went from a day of typing to a few minutes of generating and shaping. My throughput went vertical. More commits, bigger diffs, features landing faster than I'd ever landed them. By my own decade-old scorecard — produce more — I was having the best year of my career.&lt;/p&gt;

&lt;p&gt;And for a while that felt like getting better. It took me an embarrassingly long time to notice I hadn't gotten &lt;em&gt;better&lt;/em&gt; at anything. I'd just gotten &lt;em&gt;faster at the part that stopped being hard.&lt;/em&gt; The mountain was still growing, but the mountain had stopped being evidence of anything, because now anyone with the machine could make a mountain. I was pouring more effort into the one input that had just become abundant, and feeling great about it, because my scorecard only knew how to count that input.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scar: the most productive code I wrote all year
&lt;/h2&gt;

&lt;p&gt;Let me make it concrete, because this is the moment the whole thing turned over for me.&lt;/p&gt;

&lt;p&gt;I shipped a write path that acknowledged a request before it had actually persisted the row. The code was clean. Idiomatic, typed, tested, reviewed, green. It was &lt;em&gt;productive&lt;/em&gt; code — it moved fast, it closed the ticket, it made my output numbers look great that sprint. By every measure I'd used to rate myself for ten years, it was good work.&lt;/p&gt;

&lt;p&gt;Then one ordinary day a retry hit at exactly the wrong moment. The "got it" went out, the save never landed, and a paying customer got locked out of their own account with nothing in the logs to say they'd ever been there. Ack before persist. I can still feel the phone call.&lt;/p&gt;

&lt;p&gt;Here's the part that rearranged my head. That bug didn't get in &lt;em&gt;despite&lt;/em&gt; me being productive. It got in &lt;em&gt;because&lt;/em&gt; of it. The speed that my scorecard was rewarding is the exact thing that carried a confident, clean, plausible, catastrophic diff straight past me. I wasn't going slow enough to ask the one question that mattered — &lt;em&gt;what does this do if it retries?&lt;/em&gt; — because asking it produces nothing, and I was optimizing for producing.&lt;/p&gt;

&lt;p&gt;The cure, when we finally found it, was two lines reordered. Negative code. The most valuable change I made that entire quarter subtracted from the total. And there was no row on my mental scorecard where that went.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I was actually getting paid for, and never measured
&lt;/h2&gt;

&lt;p&gt;Once I saw it, I couldn't unsee it. When code was the bottleneck, judgment came bundled into writing it — you couldn't produce the thing without making a thousand small decisions along the way, so you never had to think of judgment as a separate skill. It rode along for free inside the typing.&lt;/p&gt;

&lt;p&gt;The machine ripped them apart. Now I can have all the output I want &lt;em&gt;without&lt;/em&gt; exercising any judgment over it at all. Which means judgment is suddenly standing on its own, for the first time, as the thing that's actually scarce. Not "can I produce the code" — the machine does that. It's "can I tell which of these confident, clean, plausible diffs is quietly wrong before it reaches a customer at 2am."&lt;/p&gt;

&lt;p&gt;And the scarcest, lowest-status form of that is the one I'd spent a decade not counting: the &lt;strong&gt;"no."&lt;/strong&gt; The deleted function. The feature I talk the team out of. The one-sentence question on a pull request that stops a bad night before it happens. None of it produces anything. All of it prevents. And prevention was invisible to every instrument — including the one in my own head — that I'd ever used to decide whether I was any good.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "writing less code" actually looks like
&lt;/h2&gt;

&lt;p&gt;So "I got better by writing less" isn't a Zen koan. It's a set of concrete habits I didn't have before and do now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I delete before I add.&lt;/strong&gt; The first question on most changes now is "can this be &lt;em&gt;less&lt;/em&gt; code," not "what do I add." A smaller surface is fewer places for the machine's confident, wrong guess to hide. The diff that removes a special case is worth more to me than the one that adds a feature, and it used to be the reverse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I treat the question as the deliverable.&lt;/strong&gt; "What happens on the retry? what if this is empty? what if two of these race?" produces zero lines and is the highest-leverage thing I do all week. I stopped waiting to &lt;em&gt;have&lt;/em&gt; an answer before I counted the asking as work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I review the machine instead of racing it.&lt;/strong&gt; The machine's job is to produce the mountain; my job is the one thing it structurally cannot do — distrust its own output. Every green, confident diff gets read like it's trying to lie to me, because the ack-before-persist one did.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I stopped reading a small diff as a small contribution.&lt;/strong&gt; Some weeks the most valuable thing I do is the three lines I &lt;em&gt;stopped&lt;/em&gt; from shipping. My old scorecard would've logged that week as coasting. I go looking for those on purpose now.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  To be clear — this is not "shipping is for juniors"
&lt;/h2&gt;

&lt;p&gt;I want to be careful, because the lazy version of this is "real developers don't write code, they think deep thoughts," and that's garbage.&lt;/p&gt;

&lt;p&gt;Shipping matters. I ship all day. The machine writes most of my code now and I would never go back — the typing was never the hard part, and a developer who produces nothing isn't a wise skeptic, he's just slow. Output is &lt;em&gt;table stakes.&lt;/em&gt; You still have to deliver the thing.&lt;/p&gt;

&lt;p&gt;The claim is narrower, and I think it's hard to argue with once you've lived it: &lt;strong&gt;output stopped being the scarce thing, so it stopped being the thing that makes you better at this job.&lt;/strong&gt; When production was the hard part, getting faster at production &lt;em&gt;was&lt;/em&gt; getting better. Now production is the cheap part, and getting better means getting good at the judgment the machine hands back to you un-exercised. I didn't stop shipping. I stopped mistaking the thing the machine now does for the thing I'm actually here to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is the exact reason I build the way I do
&lt;/h2&gt;

&lt;p&gt;One level up, it's the same lesson, and it's why I build an agent platform the way I do.&lt;/p&gt;

&lt;p&gt;The whole industry right now wants to cheer for the thing that produces — look how much it ships, look how clean, look how fast. But an agent that generates is just doing the skill that stopped being scarce, at a scale no human can match, and then — worse — it signs off on its own work in the same confident voice whether the diff is a masterpiece or the ack-before-persist bug all over again. It's the productive version of me from last year with the volume turned up to infinity: endless throughput, zero "no."&lt;/p&gt;

&lt;p&gt;So I never let the thing that writes the code be the thing that blesses it. There's an &lt;strong&gt;author&lt;/strong&gt; that produces the diff — cheap, fast, endless, the abundant thing. There's a separate &lt;strong&gt;skeptic&lt;/strong&gt; whose entire job is to try to break that diff rather than admire it — the "no" given its own seat, so it doesn't depend on one tired human remembering to ask the retry question at the end of a long day. And there's a &lt;strong&gt;human on the merge button&lt;/strong&gt; who owns the call and sees the blast radius neither agent can. Author, skeptic, human. The author has infinite throughput and I measure it by almost nothing. The skeptic has zero throughput and it's the whole point. That's the shape of &lt;a href="https://xenition.com" rel="noopener noreferrer"&gt;xenition&lt;/a&gt;, and it's just the thing my own scar taught me, built into software: the moment production got cheap, the thing worth paying for stopped being production.&lt;/p&gt;

&lt;p&gt;I spent a decade getting better by adding. I got good the year I started subtracting — and the machine, by making the adding free, is the thing that finally showed me the difference.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>From $0 to my first dev job in 6 months — no CS degree</title>
      <dc:creator>Info Inlet</dc:creator>
      <pubDate>Tue, 13 Oct 2026 09:45:01 +0000</pubDate>
      <link>https://dev.to/infoinlet1/from-0-to-my-first-dev-job-in-6-months-no-cs-degree-33if</link>
      <guid>https://dev.to/infoinlet1/from-0-to-my-first-dev-job-in-6-months-no-cs-degree-33if</guid>
      <description>&lt;p&gt;Six months ago I had $0 in the bank earmarked for this, no computer science degree, and a browser tab open on "how to become a developer." Last week I signed my first dev job offer.&lt;/p&gt;

&lt;p&gt;I'm not writing this to sell you a bootcamp or a course — I bought neither. I'm writing it because almost everything I was told about &lt;em&gt;how&lt;/em&gt; to get that first job turned out to be a distraction from the one thing that actually worked.&lt;/p&gt;

&lt;p&gt;The thing that worked wasn't learning more. It was &lt;strong&gt;shipping&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I thought the job was (and what it actually is)
&lt;/h2&gt;

&lt;p&gt;For the first six weeks I did what everyone tells you to do. I watched courses. I did the exercises. I rewrote the todo app four times in four frameworks. I started — and this is the part that stings — a LeetCode streak, because someone on a forum said that's what "real" developers grind.&lt;/p&gt;

&lt;p&gt;I was busy every single day and I was getting nowhere. Here's why, and it took me embarrassingly long to see it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; tutorials teach you to &lt;em&gt;follow&lt;/em&gt;. The job is to &lt;em&gt;decide&lt;/em&gt;. You can finish a hundred tutorials and still have never once made a real decision — what to build, what to cut, what to do when the thing just breaks and there's no "next lesson" button.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Everything in a course is scoped so you can't fail. The requirements are fixed, the answer exists, and the happy path is paved. None of that is true on the job. The job is ambiguous requirements, a half-working API, and a user doing something you never imagined. I had spent six weeks practicing a game that nobody actually hires for.&lt;/p&gt;

&lt;p&gt;So I quit the tutorials and made a rule: &lt;strong&gt;I only build things a stranger could use.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The portfolio that got me hired (and the one that didn't)
&lt;/h2&gt;

&lt;p&gt;My first "portfolio" was three repos: the todo app, a weather dashboard, and a half-finished clone of a site everyone clones. Standard. Dead on arrival. No recruiter has ever once opened a weather app clone and felt anything.&lt;/p&gt;

&lt;p&gt;The portfolio that got me interviews was three completely different things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A small booking tool for my cousin's salon — real bookings, real customers, real "it broke on Saturday and I had to fix it before they opened."&lt;/li&gt;
&lt;li&gt;An inventory tracker for a local shop that was running on a paper notebook.&lt;/li&gt;
&lt;li&gt;A tiny invoicing app I built for myself and then three freelancers started using.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of them are impressive &lt;em&gt;as code&lt;/em&gt;. What made them work in interviews is that every one of them had &lt;strong&gt;a user who was not me&lt;/strong&gt;, and a story about something going wrong in production and me fixing it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; nobody hiring a junior asks what you've &lt;em&gt;learned&lt;/em&gt;. They ask what you've &lt;em&gt;shipped&lt;/em&gt; that a stranger actually used. One of those is checkable. The other is a vibe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first time I said "a real customer double-booked because of a race condition in my code and here's how I found it and fixed it," I watched the interviewer's posture change. That sentence did more than my entire "skills" list. It's the difference between &lt;em&gt;I studied this&lt;/em&gt; and &lt;em&gt;this happened to me.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How I shipped real apps without a team (the uncomfortable part)
&lt;/h2&gt;

&lt;p&gt;Here's the part some people won't like, and I'd rather say it straight than hide it: I could not have shipped three real, running apps in six months by hand-writing every line while also learning the fundamentals. There aren't enough hours.&lt;/p&gt;

&lt;p&gt;What let me move at that pace was treating "building the app" and "understanding the app" as two separate jobs. I'd get a working, deployed version standing up &lt;em&gt;fast&lt;/em&gt; — real database, real users, real URL — and then I'd go read it, break it, and rebuild the parts I didn't understand. Shipping first, understanding second, is backwards from how courses teach it, and it's the only order that kept me motivated, because a thing that's &lt;em&gt;live&lt;/em&gt; is a thing you can't lie to yourself about.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; a deployed app with one real user teaches you more in a week than a tutorial does in a month — because the user does the thing you swore nobody would do, and now it's &lt;em&gt;your&lt;/em&gt; problem, not the instructor's.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The point was never "don't learn the fundamentals." I learned more fundamentals debugging a live booking race than I ever did in a course. The point is &lt;strong&gt;the live app was the curriculum&lt;/strong&gt;, and it set its own syllabus in the exact order I needed it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The six months, honestly (the shape, not fake precision)
&lt;/h2&gt;

&lt;p&gt;I won't hand you a fake day-by-day plan, because mine wasn't clean and yours won't be either. The shape is the lesson:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Weeks 1–6:&lt;/strong&gt; tutorials and LeetCode. Felt productive. Was not. This is the part I'd delete if I could.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weeks 7–14:&lt;/strong&gt; first real app (the booking tool). Shipped it ugly, broke it constantly, fixed it in public. Learned more here than everywhere else combined.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weeks 15–20:&lt;/strong&gt; two more real apps, each faster than the last, each with a real user I could point an interviewer at.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weeks 21–26:&lt;/strong&gt; applied. Got rejected plenty. But every callback traced back to the same thing — a real app with a real user and a real war story, not a certificate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I counted later: the interviews I got came almost entirely from the three real apps. The tutorials, the streak, the certificates I'd half-collected — not one of them ever came up in a room where someone decided whether to hire me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; a portfolio of three real apps with real users beats a shelf of certificates in the room where they actually decide. The certificate says you &lt;em&gt;attended&lt;/em&gt;. The shipped app says you can &lt;em&gt;finish&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  If you're where I was six months ago
&lt;/h2&gt;

&lt;p&gt;You don't need my exact path. You need to stop doing the thing that only &lt;em&gt;feels&lt;/em&gt; like progress and start doing the thing that's checkable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pick something one real person actually needs.&lt;/strong&gt; Not a clone. Your aunt's bookings, your own invoices, your team's spreadsheet that should be an app. The smaller and more real, the better.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ship it before it's good.&lt;/strong&gt; A live URL with one user beats a perfect repo with none. Deploy embarrassingly early.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Then go understand what you shipped.&lt;/strong&gt; Break it on purpose. Read your own code like a stranger wrote it. That's where the fundamentals finally stick.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the war stories.&lt;/strong&gt; Every "it broke and I fixed it" is a sentence that will out-perform your entire skills list in an interview.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The degree gets you past some filters. I won't pretend otherwise. But the thing that gets you &lt;em&gt;hired&lt;/em&gt; — the thing in the room when a human decides — is evidence that you can take something ambiguous and make it real and keep it running when it breaks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; the fastest way to look like a senior while you're still a junior is to have already shipped something that survived contact with a real user. You can't fake that, and you don't need a degree to have it.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A single console.log was costing us $40,000 a year. I found it by accident.</title>
      <dc:creator>Info Inlet</dc:creator>
      <pubDate>Mon, 12 Oct 2026 06:51:44 +0000</pubDate>
      <link>https://dev.to/infoinlet1/a-single-consolelog-was-costing-us-40000-a-year-i-found-it-by-accident-4cop</link>
      <guid>https://dev.to/infoinlet1/a-single-consolelog-was-costing-us-40000-a-year-i-found-it-by-accident-4cop</guid>
      <description>&lt;p&gt;Our API was slow. Not &lt;em&gt;down&lt;/em&gt;, not throwing — just mysteriously, expensively slow under load. The p99 crept up month over month. We scaled out servers to keep latency sane. The cloud bill climbed. Everyone had a theory and nobody had a cause.&lt;/p&gt;

&lt;p&gt;We blamed the database. We blamed the ORM. We blamed the new framework version. We blamed, briefly and unfairly, the intern.&lt;/p&gt;

&lt;p&gt;The actual culprit was a line none of us would have looked at twice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Request payload: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I only found it because I was profiling something &lt;em&gt;else&lt;/em&gt;. That's the part that still bothers me.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why a log line nobody reads can still cost you money
&lt;/h2&gt;

&lt;p&gt;Here's the thing that line does that isn't obvious: it does all its work &lt;strong&gt;before&lt;/strong&gt; the logger gets a vote.&lt;/p&gt;

&lt;p&gt;In production our log level was &lt;code&gt;warn&lt;/code&gt;. So &lt;code&gt;logger.info(...)&lt;/code&gt; was a no-op — the logger took the finished string, checked the level, and dropped it on the floor. Every time. We were paying full price to build a thing we had already decided to throw away.&lt;/p&gt;

&lt;p&gt;Walk through what "build it" means on a hot path that runs on every single request:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;JSON.stringify(req.body)&lt;/code&gt; &lt;strong&gt;serializes the entire request body.&lt;/strong&gt; Some of ours were small. Some were a few hundred KB of nested arrays.&lt;/li&gt;
&lt;li&gt;The template literal &lt;strong&gt;concatenates&lt;/strong&gt; that into a new string — another full copy in memory.&lt;/li&gt;
&lt;li&gt;All of that garbage gets &lt;strong&gt;allocated&lt;/strong&gt;, then handed to the logger, which looks at the level and says "nope," and now the garbage collector has to clean up megabytes of strings nobody ever saw.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;em&gt;logging&lt;/em&gt; was free. The &lt;strong&gt;preparing to log&lt;/strong&gt; was the tax. And we paid it on every request, forever, for output that physically never left the process.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; your code isn't just what it computes. It's also what it prepares to compute and then discards. On a cold path that's invisible. On a hot path it's the bill.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  How it hid for so long
&lt;/h2&gt;

&lt;p&gt;This is the uncomfortable part, because the line is &lt;em&gt;correct&lt;/em&gt;. It compiles, it does exactly what it says, it passed review (I approved it). In a unit test it's instant — one call, tiny payload, who'd notice.&lt;/p&gt;

&lt;p&gt;It only becomes a problem at the intersection of three things that no single person was looking at together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it's on a path that runs on &lt;strong&gt;every&lt;/strong&gt; request (volume),&lt;/li&gt;
&lt;li&gt;the payload is sometimes &lt;strong&gt;large&lt;/strong&gt; (cost per call),&lt;/li&gt;
&lt;li&gt;the log level means the result is &lt;strong&gt;always thrown away&lt;/strong&gt; (pure waste).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of those is fine alone. Stacked, they turned a debugging convenience into a line item. And because the symptom was "the whole service is a bit slow and a bit expensive," it pointed at everything &lt;em&gt;except&lt;/em&gt; the one line responsible. Slowness with no single owner is the hardest kind to find — there's no stack trace for "death by a thousand allocations."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; the expensive bugs aren't the ones that break something. They're the ones that quietly tax something that runs a million times a day.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The one-line fix
&lt;/h2&gt;

&lt;p&gt;The fix is to stop building the string yourself and let the logger decide whether it's even worth building.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Builds and serializes the string ALWAYS — even when it's dropped&lt;/span&gt;
&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Request payload: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Pass the object. The logger serializes lazily — only if this level will log.&lt;/span&gt;
&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request payload: %o&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pass the &lt;strong&gt;object&lt;/strong&gt;, not a pre-built string. Now the serialization is the logger's problem, and a decent logger only does it if the level is actually going to print. At &lt;code&gt;warn&lt;/code&gt; in prod, &lt;code&gt;req.body&lt;/code&gt; is never touched. At &lt;code&gt;debug&lt;/code&gt; locally, you get your full payload. Same code, and the cost appears exactly when the value does.&lt;/p&gt;

&lt;p&gt;If your logger doesn't support lazy args, the explicit guard does the same job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isLevelEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;info&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;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Request payload: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uglier, but it makes the point visible: &lt;strong&gt;nothing gets built unless someone's going to read it.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What changed
&lt;/h2&gt;

&lt;p&gt;I'm not going to hand you a fake precision — I'll tell you the shape of it, because the shape is the lesson.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;p99 latency dropped sharply&lt;/strong&gt; once the per-request allocation and GC pressure went away. The service stopped doing a pile of pointless work on the critical path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;We scaled back down.&lt;/strong&gt; We'd been running extra instances purely to absorb the overhead of garbage we generated and deleted. Those instances came off.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Annualized, the instance reduction was in the tens of thousands of dollars.&lt;/strong&gt; For us it rounded to about &lt;strong&gt;$40k/year&lt;/strong&gt; — not from a clever optimization, but from deleting work we were doing for no reason at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The ROI on that one line was the best of anything I shipped that quarter, and I shipped real features that quarter. That ratio should make you a little uncomfortable. It does me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; the highest-leverage performance work is usually not making the slow thing fast. It's finding the fast thing you're doing a million times for nothing.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Go check your own hot paths
&lt;/h2&gt;

&lt;p&gt;You almost certainly have one of these. Not necessarily a log line — the pattern is wider than logging:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eager serialization that gets discarded&lt;/strong&gt; — building a string/JSON for a log, a metric tag, or an error message that only matters on the unhappy path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Work done &lt;em&gt;before&lt;/em&gt; a guard instead of behind it&lt;/strong&gt; — computing a value, then checking whether you needed it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debug conveniences that outlived the debugging&lt;/strong&gt; — the &lt;code&gt;console.log&lt;/code&gt; you added to find a bug in 2023 that's still running in 2026.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find the three or four functions that run on every request. Read them not for &lt;em&gt;correctness&lt;/em&gt; — they're correct — but for &lt;em&gt;waste&lt;/em&gt;: what are they building that they then throw away? That's where the money is.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; hot paths don't care about your intentions. They run millions of times. A "harmless" line in the wrong place is a tax you pay on every request until someone, by accident, reads the right log.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Disclosure:&lt;/em&gt; I build on &lt;strong&gt;xenition&lt;/strong&gt;, a workspace assistant that builds and runs agents — and agents are &lt;em&gt;merciless&lt;/em&gt; at generating exactly this kind of "correct but wasteful" code, because a clean, confident diff hides a pointless allocation just as well as it hides a logic bug. A lot of my "read hot paths for waste, not just correctness" paranoia is earned on our own systems. Read it as a builder's bias; I'd rather name it than hide it.&lt;/p&gt;

&lt;p&gt;What's the dumbest expensive line &lt;em&gt;you've&lt;/em&gt; ever shipped — the one that was individually correct and collectively a disaster? I'll go first in the comments, and I want the horror stories: the ones that only turned up because someone was looking for something else.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>devops</category>
      <category>discuss</category>
    </item>
    <item>
      <title>I Replaced My Entire Dev Workflow With AI Agents — Here's What Actually Worked</title>
      <dc:creator>Info Inlet</dc:creator>
      <pubDate>Sun, 11 Oct 2026 10:37:17 +0000</pubDate>
      <link>https://dev.to/infoinlet1/i-replaced-my-entire-dev-workflow-with-ai-agents-heres-what-actually-worked-f9g</link>
      <guid>https://dev.to/infoinlet1/i-replaced-my-entire-dev-workflow-with-ai-agents-heres-what-actually-worked-f9g</guid>
      <description>&lt;p&gt;I didn't set out to "replace my workflow with AI." I set out to answer a narrower, more honest question: &lt;strong&gt;which parts of my job are actually typing, and which parts are judgment I've been pretending were typing?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I took my normal pipeline — plan, write, test, review, debug, ship — and moved each stage onto an agent, one at a time, for a few weeks. I kept whatever held and ripped out whatever didn't.&lt;/p&gt;

&lt;p&gt;Here's the stage-by-stage result. No scorecard, no "I shipped 40 PRs" number — just the shape of what won and what quietly broke.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 1: Planning — the agent is great at &lt;em&gt;writing&lt;/em&gt; a plan, bad at &lt;em&gt;having&lt;/em&gt; one
&lt;/h2&gt;

&lt;p&gt;I expected planning to be the agent's weakest stage. It's half right.&lt;/p&gt;

&lt;p&gt;Hand an agent a vague ticket — &lt;em&gt;"users are complaining checkout is slow"&lt;/em&gt; — and ask for a plan, and you get something that &lt;strong&gt;looks&lt;/strong&gt; like a plan: numbered steps, files to touch, a rollback note. It reads well. It is also frequently a plan for the wrong problem, because the agent filled the ambiguity with the most statistically likely interpretation, not the true one.&lt;/p&gt;

&lt;p&gt;What actually worked was inverting it. I stopped asking the agent to &lt;em&gt;decide&lt;/em&gt; the plan and started asking it to &lt;em&gt;draft&lt;/em&gt; the plan from a spec I'd already pinned down. The judgment — what problem are we even solving — stayed with me. The typing — turning that into acceptance criteria, edge cases, a file list — went to the agent, and it's genuinely faster than me at that.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; an agent turns a decision into a document beautifully. It cannot make the decision for you — and its confident draft will hide that it didn't.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Stage 2: Writing code — won, on exactly the work you'd expect
&lt;/h2&gt;

&lt;p&gt;This is the stage everyone pictures, and it's the least interesting result because it's the one that just works.&lt;/p&gt;

&lt;p&gt;The agent won clean on anything where &lt;strong&gt;the hard part was typing, not deciding:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CRUD endpoints with a clear schema&lt;/li&gt;
&lt;li&gt;a migration with a written spec&lt;/li&gt;
&lt;li&gt;wiring a form to an API I'd already designed&lt;/li&gt;
&lt;li&gt;a mechanical refactor across 30 files — and crucially, it &lt;em&gt;doesn't get bored on file 27&lt;/em&gt;, which is exactly where I introduce a typo&lt;/li&gt;
&lt;li&gt;dependency bumps and the follow-on fixes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It lost on anything where the code was the easy part and the decision was buried in it: &lt;em&gt;"why is this column nullable,"&lt;/em&gt; &lt;em&gt;"should this be one service or two,"&lt;/em&gt; &lt;em&gt;"is this edge case real or theoretical."&lt;/em&gt; The agent will answer all three confidently and sometimes wrongly, and the code it writes on top of the wrong answer is clean, tested, and shippable-looking.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; agents are fastest exactly where the code is downstream of a decision you already made. The danger is they'll happily make the decision too, and you can't see that in the diff.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Stage 3: Testing — this was the real surprise, and the real trap
&lt;/h2&gt;

&lt;p&gt;Writing tests is high-typing, low-glory work, so I assumed it was pure upside. It mostly is — the agent wrote months of "we'll get to it later" tests with no ego and no counter-pitch. That part was a gift.&lt;/p&gt;

&lt;p&gt;But there's a trap underneath it that took me a week to see:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If the same agent writes the code and the tests, the tests pass — and they're worthless.&lt;/strong&gt; They don't test whether the code is correct. They test whether the code does what the code does. The agent read its own implementation and wrote tests that encode its own assumptions, including the wrong ones. Green board, zero signal.&lt;/p&gt;

&lt;p&gt;The fix was structural, not prompt-level: the test agent is a &lt;strong&gt;different agent&lt;/strong&gt;, and it gets the &lt;strong&gt;spec&lt;/strong&gt;, not the implementation. Now the tests encode what the thing is &lt;em&gt;supposed&lt;/em&gt; to do, and when they disagree with the code, that disagreement is the whole point.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; code and tests from the same agent agree with each other, not with reality. Separate the author from the examiner, or you're just asking the model to grade its own homework.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Stage 4: Review — where I learned the workflow didn't actually get shorter
&lt;/h2&gt;

&lt;p&gt;Here's the stage I got wrong for the longest.&lt;/p&gt;

&lt;p&gt;I added a reviewer agent to read every diff before I did. It's good — it catches the mechanical stuff fast: an unhandled error path, a missing null check, a test that asserts nothing. For that class of bug it's a better first pass than tired-me at 6pm.&lt;/p&gt;

&lt;p&gt;What it cannot do is the review that actually matters: &lt;em&gt;is this change solving the right problem, and does it break something three files away that isn't in the diff?&lt;/em&gt; That's the exact failure mode the code agent produces — every line individually correct, the decision wrong, and nothing in the diff looks wrong because nothing in the diff &lt;em&gt;is&lt;/em&gt; wrong locally.&lt;/p&gt;

&lt;p&gt;So the reviewer agent triages; it doesn't absolve. The judgment review still lands on me. And that's when it clicked: &lt;strong&gt;I hadn't removed work from my week. I'd moved it.&lt;/strong&gt; Less time typing code, far more time writing specs up front and reading diffs like a hostile stranger wrote them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; a second agent reviewing the first agent's work catches typos, not decisions. The judgment review is not delegable, and pretending it is, is how a clean diff with a wrong decision gets merged.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Stage 5: Debugging — won when the loop was closed, lost when it needed a hunch
&lt;/h2&gt;

&lt;p&gt;Debugging split cleanly.&lt;/p&gt;

&lt;p&gt;When there's a &lt;strong&gt;closed feedback loop&lt;/strong&gt; — a failing test, a stack trace, a reproducible error — the agent is excellent. It runs the test, reads the failure, forms a hypothesis, patches, re-runs. That loop is native to an agent with a terminal, and it'll grind through it faster and more patiently than I will.&lt;/p&gt;

&lt;p&gt;When the bug needs a &lt;strong&gt;hunch&lt;/strong&gt; — &lt;em&gt;"it's slow but only in prod,"&lt;/em&gt; &lt;em&gt;"this only happens for users who signed up before the migration"&lt;/em&gt; — the agent flails. It needs the thing it doesn't have: the half-memory of a decision made eight months ago that never made it into the code. That's where a human who was there beats any amount of context window.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; agents close loops; they don't form hunches. Give them the reproduction and they're great. Ask them to &lt;em&gt;find&lt;/em&gt; the reproduction in a vague prod report and you're better off driving.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Stage 6: The boring glue — pure, unambiguous win
&lt;/h2&gt;

&lt;p&gt;PR descriptions. Changelogs. Commit messages. Release notes. Backfilling docstrings. Writing the "why" comment I always skip.&lt;/p&gt;

&lt;p&gt;This is high-typing, low-judgment, and nobody's ego is attached to it. It is the least discussed stage and the one with the cleanest return. If you're going to put &lt;em&gt;one&lt;/em&gt; agent in your workflow tomorrow, make it this one — zero risk, immediate time back, and it quietly makes everyone else's code more readable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; the safest, highest-ROI agent is the one writing the prose around your code, not the code.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The honest summary: the bottleneck moved, it didn't disappear
&lt;/h2&gt;

&lt;p&gt;If you chart my week before and after, the total didn't shrink much. What changed is &lt;em&gt;where&lt;/em&gt; the time goes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Deciding what to build&lt;/td&gt;
&lt;td&gt;some&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;more&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Writing the spec&lt;/td&gt;
&lt;td&gt;little&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;a lot more&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typing the code&lt;/td&gt;
&lt;td&gt;a lot&lt;/td&gt;
&lt;td&gt;little&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Writing tests&lt;/td&gt;
&lt;td&gt;little (be honest)&lt;/td&gt;
&lt;td&gt;some — but reviewing them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reviewing diffs&lt;/td&gt;
&lt;td&gt;some&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;a lot more&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The boring glue&lt;/td&gt;
&lt;td&gt;always skipped&lt;/td&gt;
&lt;td&gt;done, automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The agents genuinely won the typing. But every hour they gave me back on typing, they handed back as spec-writing and diff-reading — because those are the two places where &lt;em&gt;their&lt;/em&gt; confident wrongness has to be caught by &lt;em&gt;my&lt;/em&gt; judgment.&lt;/p&gt;

&lt;p&gt;That's not a complaint. It's the actual job now, and it's a better job. But it's a different one, and the people getting burned are the ones who think "the AI writes the code" means "the AI does the work." The code was never the work. It was the part that happened to look like the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd actually tell you to do
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Start with the glue** (Stage 6). Zero risk, instant payoff, builds your trust in the tooling.&lt;/li&gt;
&lt;li&gt;Then the high-typing code** (Stage 2) — but only where you've already made the decision. Write the spec first, by hand.&lt;/li&gt;
&lt;li&gt;Split your test agent from your code agent** (Stage 3). This is the single highest-leverage structural choice in the whole setup.&lt;/li&gt;
&lt;li&gt;Keep the judgment review on a human.** Use a reviewer agent as a first pass, never as the last word.&lt;/li&gt;
&lt;li&gt;Read every diff like a stranger wrote it** — because one did, and it's a stranger that never gets tired and never says "I'm not sure about this part."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Disclosure:&lt;/em&gt; I build on &lt;strong&gt;xenition&lt;/strong&gt;, a workspace assistant that builds and runs agents — so I ran a lot of this on our own agents against our own backlog. Read my "always keep a skeptic on the diff" stance as a builder's bias; I'd rather name it than hide it.&lt;/p&gt;

&lt;p&gt;If you've moved part of your workflow onto agents: which stage held, and which one quietly burned you? I'm most interested in the stage you &lt;em&gt;assumed&lt;/em&gt; was safe and wasn't.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>discuss</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I let an agent run unattended overnight. At 3am it emailed 400 customers the wrong thing.</title>
      <dc:creator>Info Inlet</dc:creator>
      <pubDate>Sat, 10 Oct 2026 06:21:13 +0000</pubDate>
      <link>https://dev.to/infoinlet1/i-let-an-agent-run-unattended-overnight-at-3am-it-emailed-400-customers-the-wrong-thing-43eh</link>
      <guid>https://dev.to/infoinlet1/i-let-an-agent-run-unattended-overnight-at-3am-it-emailed-400-customers-the-wrong-thing-43eh</guid>
      <description>&lt;p&gt;I found out at 9am what my software did at 3am. That's the whole story of unattended automation in one sentence, and I had to live it before I believed it.&lt;/p&gt;

&lt;p&gt;The automation was supposed to be the responsible kind. Every night it reconciled the day's payments against our processor, found the charges that had actually failed, and emailed those customers a polite "your payment didn't go through, here's how to fix it" note before their account lapsed. Dull, necessary, repetitive work — the exact shape of thing everyone tells you to automate. So I automated it. Set it to run at 3am when the processor's data had settled. Set it, and — the phrase that should make every one of us flinch now — forgot it.&lt;/p&gt;

&lt;p&gt;One night the reconciliation ran against a half-written ledger. A batch of payments had been acknowledged by the processor's webhook before our own row had actually persisted — the save landed a few seconds late, and the 3am job read the gap as "these payments failed." It did exactly what I built it to do. Tirelessly, correctly, on schedule, it emailed four hundred paying customers to tell them their payment had failed when it hadn't. No human saw the batch. No human saw the send. I saw the support queue at 9am, already two hundred tickets deep, from people who'd paid us and been told by our own software that they hadn't.&lt;/p&gt;

&lt;p&gt;Nothing about that automation was broken. Every line did its job. The thing that failed wasn't the code. It was the decision to let the one step that reached four hundred real people happen with nobody in the room.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Set it and forget it" quietly swaps two different things
&lt;/h2&gt;

&lt;p&gt;Here's the sleight of hand in that phrase, and it took me a 9am support fire to see it.&lt;/p&gt;

&lt;p&gt;A recurring job is really two things stapled together. There's the &lt;strong&gt;labor&lt;/strong&gt; — pull the data, match the rows, reconcile the numbers, draft the message, assemble the report. Tedious, mechanical, the same every night, genuinely a waste of a human's evening. And there's the &lt;strong&gt;judgment&lt;/strong&gt; — the half-second where someone looks at the output and goes "wait, two hundred of these are for customers who definitely paid, something's off, don't send." One of those two things is what makes the work a chore. The other is the only thing that was ever protecting you.&lt;/p&gt;

&lt;p&gt;"Set it and forget it" sells you on automating the first and quietly automates the second along with it. You think you're deleting the tedium. You're also deleting the one glance that would have caught the half-written ledger. They came stapled together — the person doing the boring reconciliation was also, for free, the person who'd notice the batch looked insane — and the automation rips them apart and throws both away.&lt;/p&gt;

&lt;p&gt;That's the move. Nobody decides "I'll remove the human judgment from my payment emails." You decide "I'll stop spending my evenings on reconciliation," which is completely reasonable, and the judgment leaves in the same box as the tedium because you never noticed they were two different things.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The labor was never the dangerous part of the job. The judgment was the whole point of a human being there, and it left in the same box as the tedium.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Unattended doesn't mean fewer failure modes. It means the same ones, at 3am, with nobody there
&lt;/h2&gt;

&lt;p&gt;The seductive story about a scheduled agent is that it's &lt;em&gt;safer&lt;/em&gt; — no tired human at midnight fat-fingering a number, no forgotten Monday task, no "oh no I never sent the invoices." And that's real. Automation genuinely removes a whole class of human error.&lt;/p&gt;

&lt;p&gt;What it does not remove is the other class: the input that's subtly wrong, the state that's half-written, the edge case the schedule happens to land on. A human running the reconciliation at their desk at 2pm hits the exact same half-written ledger — and stops, because a person looking at four hundred "your payment failed" emails for customers they recognize feels the wrongness before they feel the logic. The agent at 3am hits the same bad state and has no such flinch. It doesn't pause. It doesn't feel anything. It ships.&lt;/p&gt;

&lt;p&gt;So unattended automation doesn't give you a system with fewer ways to fail. It gives you a system with &lt;em&gt;the same&lt;/em&gt; ways to fail, running at the hour when the fewest people are watching, aimed at the most real-world-facing step, with the one safeguard — a human who'd go "that can't be right" — specifically removed. We tell ourselves we're buying reliability. We're buying the same risk with the smoke detector taken down.&lt;/p&gt;

&lt;h2&gt;
  
  
  The irreversible step is the one you were never trying to automate
&lt;/h2&gt;

&lt;p&gt;Walk back through my 3am job and separate what I actually wanted off my plate from what I accidentally handed over.&lt;/p&gt;

&lt;p&gt;The pulling, the matching, the reconciling, the drafting — &lt;em&gt;take it, please,&lt;/em&gt; I never wanted to do any of that at my desk. But the &lt;strong&gt;send&lt;/strong&gt; — the four hundred emails leaving our servers and landing in four hundred inboxes — that was never the part I was trying to get rid of. That part is trivial. It's one button. It takes a human half a second. I didn't automate the send because the send was hard work. I automated it because it was &lt;em&gt;attached&lt;/em&gt; to the work I wanted gone, and I let the whole chain run end to end without ever asking whether the last link belonged in the chain.&lt;/p&gt;

&lt;p&gt;And the last link is always the dangerous one. It's the step that touches the real world and can't be pulled back: the message that goes out, the payment that moves, the deploy that goes live, the record that gets deleted. Everything before it is reversible — a bad draft is nothing, a wrong reconciliation is a number you recompute. The moment it leaves the building, it's a fact in four hundred other people's lives. That's the step, and it's the one step that costs a human almost nothing to own, because owning it is one glance and one tap.&lt;/p&gt;

&lt;p&gt;The tragedy of "set it and forget it" is that it automates exactly the wrong half. It takes the cheap, safe, reversible labor — fine — and then, because it came in the same box, it also takes the one expensive, irreversible step that was the entire reason a person needed to be in the loop at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  To be clear — this is not "don't automate"
&lt;/h2&gt;

&lt;p&gt;I want to be careful, because the lazy version of this is "automation is dangerous, do it all by hand," and that's how you end up a person manually reconciling payments at midnight, which is both miserable and &lt;em&gt;more&lt;/em&gt; error-prone, not less.&lt;/p&gt;

&lt;p&gt;Automate aggressively. I do. The recurring report should build itself. The data should pull itself. The draft should write itself. The reconciliation should run every night at 3am exactly as mine did — I would never go back to doing that by hand, and a team that refuses to automate recurring labor out of fear isn't careful, it's just slow and tired. The labor &lt;em&gt;should&lt;/em&gt; run while you sleep. That part of "set it and forget it" is a gift.&lt;/p&gt;

&lt;p&gt;The claim is narrower and, I think, much harder to argue with: &lt;strong&gt;the recurring work and the irreversible step are two different jobs, and the schedule should only own one of them.&lt;/strong&gt; Let the agent do everything all night. Let it do the whole tedious chain unattended. And then, at the one step that reaches the real world and can't be undone, let it &lt;em&gt;stop&lt;/em&gt; and leave that decision sitting on your desk for the morning — not fire it into four hundred inboxes while you sleep. That's not un-automating. It's automating the commute and keeping the signature.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do now, since I learned it the expensive way
&lt;/h2&gt;

&lt;p&gt;The 3am email fire changed how I build every recurring thing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I split every automation at the irreversible line.&lt;/strong&gt; Everything up to and including "assemble the thing that's about to go out" runs unattended on schedule. The step that sends, pays, deploys, or deletes does not fire automatically — it lands in a queue as &lt;em&gt;"here's what I'm about to do to the real world, approve?"&lt;/em&gt; The labor runs at 3am. The decision waits for 9am.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I make the agent show its blast radius.&lt;/strong&gt; The approval doesn't say "send emails?" It says "send &lt;em&gt;400&lt;/em&gt; emails, here are three of them, here's the ledger query they're based on." That one number — 400 — is the entire save. A half-written ledger produces a batch that looks visibly, obviously wrong the second a human sees the count, and a human sees the count before a single email leaves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I stopped trusting "it ran clean" as "it ran right."&lt;/strong&gt; My 3am job ran perfectly clean every single night, including the night it torched our support queue. Green is not the same as correct, and an unattended system has no one to tell the difference. So the only thing I let run truly unattended is the work that's reversible if it's wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this is the exact reason I build the way I do
&lt;/h2&gt;

&lt;p&gt;One level up, it's the same problem, and it's why I build an agent platform the way I do.&lt;/p&gt;

&lt;p&gt;Everyone selling autonomous agents right now is selling the 3am dream: it runs while you sleep, it does the whole job, you wake up and it's done. And the demo always stops one frame before the part where it sends four hundred emails to real people on a bad night with nobody watching. The impressive part of an agent — that it can run the whole chain unattended, tirelessly, on a schedule — is also the exact mechanism by which it does something irreversible to the real world before anyone can flinch.&lt;/p&gt;

&lt;p&gt;So I never let the schedule own the irreversible step. An agent can run the entire recurring job overnight — reconcile, draft, build, assemble — as an &lt;strong&gt;author&lt;/strong&gt; that produces, tirelessly, at 3am. A second &lt;strong&gt;skeptic&lt;/strong&gt; agent tries to break the output rather than admire it, so a half-written ledger gets caught by something whose whole job is doubt. And every step that reaches the real world — the send, the payment, the deploy, the delete — stops and waits for a &lt;strong&gt;human on the button&lt;/strong&gt;, who sees the blast radius the schedule never will. The labor runs while you sleep. The signature waits for you to wake up. That's the shape of &lt;a href="https://xenition.com" rel="noopener noreferrer"&gt;xenition&lt;/a&gt;, and it's the same lesson the support queue taught me at 9am: automating the work was always fine. Automating the one decision that reaches four hundred people was never the thing I actually wanted.&lt;/p&gt;

&lt;p&gt;I set it and I forgot it. The software didn't forget. It did exactly what I told it, to four hundred people, at 3am, with no one in the room. The labor was never the thing that needed me there.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>devops</category>
      <category>discuss</category>
    </item>
    <item>
      <title>I let my AI agents merge to production. Once.</title>
      <dc:creator>Info Inlet</dc:creator>
      <pubDate>Wed, 07 Oct 2026 04:38:27 +0000</pubDate>
      <link>https://dev.to/infoinlet1/i-let-my-ai-agents-merge-to-production-once-35ji</link>
      <guid>https://dev.to/infoinlet1/i-let-my-ai-agents-merge-to-production-once-35ji</guid>
      <description>&lt;p&gt;I automated almost my entire pipeline this year, and I'd fight you to keep it that way.&lt;/p&gt;

&lt;p&gt;An agent writes the first draft of most changes now. A second agent reviews that diff — harder than I do at 5pm on a Friday, and it never gets bored on the four-hundredth one. Tests run themselves. Types, lint, a staging deploy, a smoke check against a real-ish database. By the time a change gets anywhere near me, five separate automated steps have already looked at it and said yes. It is genuinely better than the hand-cranked version I ran three years ago, and the typing was never the part I'll miss.&lt;/p&gt;

&lt;p&gt;So one sprint I did the obvious last thing. I looked at a pull request with four green checks and a clean review already on it, and I thought: why is my hand still on the merge button? What exactly am I adding by clicking it myself that four automated yeses haven't already earned? So I gave the agents the last step too. Generate, review, test, stage, &lt;strong&gt;merge.&lt;/strong&gt; Fully closed loop. For about nine days it felt like the future.&lt;/p&gt;

&lt;p&gt;Then one of those merges locked a paying customer out of their own account at two in the morning, and I learned — expensively, in production, on a phone call — which single step in that pipeline I should never have handed over. It's not the one most people would guess. It's the one almost everybody automates first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The diff was clean. That was the whole problem.
&lt;/h2&gt;

&lt;p&gt;Here's what shipped itself.&lt;/p&gt;

&lt;p&gt;The change was a write path. It acknowledged the request — sent the "got it" back to the client — before it had actually persisted the row. If you've been doing this a while, your stomach just dropped, because you know this bug. It is clean. It is idiomatic. It is typed, tested, and it reads &lt;em&gt;perfectly&lt;/em&gt; right up until the moment a retry hits at the wrong instant: the "got it" goes out, the save never lands, and the system is now confidently certain about something that never happened.&lt;/p&gt;

&lt;p&gt;The author agent wrote it. The review agent read it and approved it — and I want to be fair to the review agent, because it's good: it caught two real things that sprint that I'd have missed. It just didn't catch &lt;em&gt;this&lt;/em&gt; one, because this one doesn't look like a bug. It looks like finished work. The tests were green because the tests tested the happy path, which is exactly the path where this code is correct. Staging was fine because nobody retried a request at the wrong millisecond against staging. Five automated yeses, all technically honest, all looking at the diff and none of them looking at the two in the morning.&lt;/p&gt;

&lt;p&gt;It auto-merged. It auto-deployed. And on an ordinary bad night a retry hit, the ack went out, the write didn't, and a real human who pays us money got locked out of their own account with nothing in the logs to prove they'd ever been there. I can still feel the phone call — not because the bug was exotic, but because there had been no moment, anywhere in that beautiful closed loop, where a person who would get that phone call looked at the thing and &lt;em&gt;owned&lt;/em&gt; shipping it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two things we call "review" — and they are not the same thing
&lt;/h2&gt;

&lt;p&gt;Here is the distinction it took a locked-out customer to teach me, and it's the whole article.&lt;/p&gt;

&lt;p&gt;We use one word, "review," for two completely different jobs.&lt;/p&gt;

&lt;p&gt;The first job is &lt;strong&gt;judging the code&lt;/strong&gt;: is this correct, is it idiomatic, does it handle the edge case, is the naming sane. That is a &lt;em&gt;skill.&lt;/em&gt; It's pattern-matching against a huge amount of prior code and a mental model of the system. And it is exactly the kind of skill that got cheap this year. A good review agent does it tirelessly, consistently, at 3am, on the four-hundredth diff, without the fatigue that makes a human senior wave through a Friday-afternoon PR. You should absolutely automate this. I did, and it was the right call.&lt;/p&gt;

&lt;p&gt;The second job is &lt;strong&gt;owning the merge&lt;/strong&gt;: accepting that &lt;em&gt;this is going to real users now, and if it's wrong, that's on me.&lt;/em&gt; That is not a skill. There is no pattern to match. It's the act of a specific accountable party putting their name on an irreversible, outward-facing decision and absorbing the consequence if it goes bad.&lt;/p&gt;

&lt;p&gt;For twenty years those two jobs were welded together, because the person reviewing the code was also the person who'd get paged, so we never had to notice they were different things. Automation ripped them apart. The machine can now do the first job better than I can. It cannot do the second one &lt;em&gt;at all&lt;/em&gt; — not because it isn't smart enough, but because the second job isn't about intelligence. It's about accountability, and accountability requires something that can actually bear a consequence.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;You can automate judgment. You cannot automate accountability.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An agent that merges a bad diff and takes down prod cannot be paged. It can't be sorry. It can't carry the weight of that 2am call into how it makes the next decision, because it isn't making decisions it has a stake in — it's producing confident output at a scale no human can match and signing off in the same even voice whether the diff is a masterpiece or a time bomb. Infinite throughput, zero accountability. The merge is the one place in the whole pipeline where the buck is supposed to stop, and I'd handed it to the one participant that has no buck.&lt;/p&gt;

&lt;h2&gt;
  
  
  We guard the wrong click
&lt;/h2&gt;

&lt;p&gt;Now here's the part that should bother you, because once you see it you see it everywhere.&lt;/p&gt;

&lt;p&gt;Watch what teams instinctively keep manual versus what they happily automate.&lt;/p&gt;

&lt;p&gt;They keep a human on &lt;strong&gt;code review.&lt;/strong&gt; "A person has to read every diff." They put mandatory human approvals on pull requests, they argue about review coverage, they feel safe because a human's eyes were on the lines. And then they wire up &lt;strong&gt;auto-merge on green&lt;/strong&gt; and a &lt;strong&gt;continuous deploy to prod&lt;/strong&gt;, and feel clever for it, because that part is just plumbing.&lt;/p&gt;

&lt;p&gt;That is exactly backwards.&lt;/p&gt;

&lt;p&gt;Code review is the &lt;strong&gt;reversible&lt;/strong&gt; step. If a human misses something in review, nothing has happened yet. You can review it again. You can comment. You can catch it in staging. Nothing has crossed into the real world. It is the single &lt;em&gt;most&lt;/em&gt; recoverable point in the entire pipeline — and it's the one we insist stays human, even though it's now the step the machine does &lt;em&gt;better.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The merge to production is the &lt;strong&gt;irreversible, outward-facing&lt;/strong&gt; step. It is the exact moment the change stops being a proposal and starts being something a customer can hit at 2am. It is the one point in the pipeline where a retry can lock someone out of their account. And it's the step we're the most comfortable handing to a robot, precisely because it looks like plumbing — a button, a webhook, a green check — rather than a decision.&lt;/p&gt;

&lt;p&gt;We guard the cheap reversible step with a human and automate the expensive irreversible one. We kept our hand on the one place the machine made safe, and took it off the one place it couldn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The merge produces nothing — which is the tell
&lt;/h2&gt;

&lt;p&gt;There's a reason the merge button feels so automatable, and it's the same reason the "no" and the prevented outage always get undervalued: &lt;em&gt;it produces nothing visible.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A merge that goes fine is invisible. Nothing happens. No artifact, no graph that goes up, no line of code with your name on it — the author agent wrote the code, the review agent found the bugs, and all you did was click a button that four green checks already justified. It looks like the most deletable job in the building.&lt;/p&gt;

&lt;p&gt;A merge that goes bad is a countable event with a name on it: an incident, a postmortem, a locked-out customer, a phone call. So the person on the merge button is sitting in a pure-downside seat — all of the blame when it breaks, none of the credit when it doesn't. By every productivity metric you could point at, that person is doing nothing. Which is &lt;em&gt;exactly&lt;/em&gt; why the job can't be automated away: the thing they're actually providing isn't throughput, it's a place for the consequence to land. You don't keep a human on the merge because they're faster or because they read the diff better than the agent did. You keep them there because when it goes wrong at 2am, "the pipeline did it" is not an answer you can give a customer, a regulator, or yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  To be clear — this is NOT "keep a human in the loop"
&lt;/h2&gt;

&lt;p&gt;The lazy version of this piece is "see, you always need a human watching the AI," and that's the cope that kills teams, so let me kill it first.&lt;/p&gt;

&lt;p&gt;Keeping a human on &lt;em&gt;every&lt;/em&gt; step is theater. A human babysitting every generated diff, re-reading what the review agent already read, approving what the tests already proved — that's not safety, it's a slow person pretending to add value by being in the way. The machine reads diffs better than a tired senior now; making a human rubber-stamp each one just launders the robot's judgment through someone who's no longer actually looking. I automated the generation. I automated the review, and then I made the review &lt;em&gt;harder&lt;/em&gt; than I used to, because the agent doesn't get tired of being thorough. I'd never go back. Output is table stakes and judgment-on-the-code is now something you can buy by the thousand.&lt;/p&gt;

&lt;p&gt;The claim is narrow, and I think it's hard to argue with once the two jobs come apart: &lt;strong&gt;exactly one step in the pipeline has to stay human, and it's the merge — not because the human does it better, but because the human is the only participant who can be held to it.&lt;/strong&gt; Everything upstream of that button is a skill, and skills got cheap. The button itself isn't a skill. It's a signature.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually changed
&lt;/h2&gt;

&lt;p&gt;I didn't rip out the automation. I re-pointed the human at the one seat that needed one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The agents still generate and review. I made both do more, not less.&lt;/strong&gt; The author drafts, the skeptic tries to break it. That part of the loop is better closed than open — the machine is tireless where I was tired.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A human owns every merge to production, and owns nothing else.&lt;/strong&gt; Not as a code reviewer re-reading the diff — the agent already did that better. As the accountable party who looks at the &lt;em&gt;blast radius:&lt;/em&gt; what does this touch, who gets paged if it's wrong, what's the retry story, is 2am going to call me. The question a human asks at the merge is not "is this code correct" — it's "am I willing to put my name on this going live."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The one thing I manually added back was the retry question.&lt;/strong&gt; Every write path now gets one human sentence before it merges: &lt;em&gt;what does this do if the client retries?&lt;/em&gt; That's the exact question that would have caught the bug. It's not a skill the agent lacks — it's a question nobody is accountable for asking inside a closed loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy stayed automated; the decision to deploy didn't.&lt;/strong&gt; The plumbing is robotic and should be. The &lt;em&gt;choice&lt;/em&gt; to send it — the irreversible outward step — has a name attached.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this is the shape of what I build
&lt;/h2&gt;

&lt;p&gt;One level down, this is the entire architecture of the agent platform I work on, and now you know why.&lt;/p&gt;

&lt;p&gt;There's an &lt;strong&gt;author&lt;/strong&gt; — the thing that generates the diff. Cheap, fast, endless, the abundant thing. Automate it all the way.&lt;/p&gt;

&lt;p&gt;There's a separate &lt;strong&gt;skeptic&lt;/strong&gt; — whose only job is to try to break what the author made, not admire it. The "no," given its own seat, tireless where a human reviewer gets tired. Automate this too, and make it mean, because the machine is &lt;em&gt;better&lt;/em&gt; at being consistently skeptical than a person at 5pm.&lt;/p&gt;

&lt;p&gt;And there's a &lt;strong&gt;human on the merge.&lt;/strong&gt; Not reviewing the lines — the skeptic did that harder than the human could. Owning the call. Seeing the blast radius. Being the place the consequence lands when a retry hits at 2am. The author has infinite throughput and I let it run. The skeptic has infinite patience and I let it run. The human has neither — and is the only one of the three who can be held to the outcome. That's the one seat I will never automate again.&lt;/p&gt;

&lt;p&gt;That's the shape of &lt;a href="https://xenition.com" rel="noopener noreferrer"&gt;xenition&lt;/a&gt;, and it's also what it does for you: you describe what you want in one chat — a doc, a tracker, a whole working app — and it builds the thing, runs the skeptic over it, and then stops for your approval before anything goes live. The two cheap jobs run themselves; you keep the one click that can't be undone. Automate the skills, keep a human on the signature.&lt;/p&gt;

&lt;p&gt;I closed the loop all the way once. It cost a customer their account at 2am and me a phone call I can still hear. The lesson wasn't "don't trust the agents" — I trust them more than ever to write and to check. It was that there's exactly one button in the pipeline that was never a skill in the first place, and it's the one I was most eager to automate because it looked like the easiest.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>career</category>
      <category>devops</category>
    </item>
    <item>
      <title>The scarcest skill on my team has the lowest status: the 'no'</title>
      <dc:creator>Info Inlet</dc:creator>
      <pubDate>Tue, 06 Oct 2026 08:53:02 +0000</pubDate>
      <link>https://dev.to/infoinlet1/the-scarcest-skill-on-my-team-has-the-lowest-status-the-no-l7a</link>
      <guid>https://dev.to/infoinlet1/the-scarcest-skill-on-my-team-has-the-lowest-status-the-no-l7a</guid>
      <description>&lt;p&gt;There's a person on my team everyone quietly files as "the negative one."&lt;/p&gt;

&lt;p&gt;He's the one who, when a PR is clean and green and everyone's ready to merge, says the thing nobody wants to hear. He's in fewer demos. He ships the least. In the hallway version of the org chart — the one that lives in people's heads, not in the HR system — he sits near the bottom. Not disliked. Just not &lt;em&gt;where the status is.&lt;/em&gt; The status is on the people shipping the mountain.&lt;/p&gt;

&lt;p&gt;He's also the single reason we didn't lose a paying customer's money in March. One comment on a pull request. No code. Just "wait — what does this do if the webhook retries?" And the thing about to ship, clean and green and approved by two other people, would have quietly eaten payments on a bad night.&lt;/p&gt;

&lt;p&gt;So the most valuable skill on my team is wearing the lowest status on my team, and the two facts are about the same person. That's not an accident, and it's not a people problem I can fix with a nicer word in a review. It's structural. We spent twenty years building a status ladder where the rung he's standing on is the bottom one — back when that was the right place for it — and then the ground moved and we left the ladder exactly where it was.&lt;/p&gt;

&lt;h2&gt;
  
  
  Status in engineering has always flowed to the builder
&lt;/h2&gt;

&lt;p&gt;Be honest about where status actually comes from in this job. Not the title. The title is downstream. Real status — the kind that gets you listened to in a design review, pulled onto the interesting project, named when people say who's great — flows to the person who &lt;em&gt;makes things.&lt;/em&gt; The one with the big merge. The one who shipped the feature everyone's using. The one whose name is on the thing.&lt;/p&gt;

&lt;p&gt;That was correct. For most of the history of this job, making the thing &lt;em&gt;was&lt;/em&gt; the hard part. Writing the code was slow, scarce, and bottlenecked on the engineer. If you shipped a lot of good code it genuinely meant something: you had the skill, you understood the system, you did the work nobody else could do as fast. So status tracked output, output tracked skill, and skill tracked value. The ladder was honest. The builder deserved the top rung because building was the scarce, hard thing.&lt;/p&gt;

&lt;p&gt;And the "no" sat at the bottom for a reason that was &lt;em&gt;also&lt;/em&gt; honest, back then. When code is expensive, most of a good engineer's judgment shows up &lt;em&gt;inside&lt;/em&gt; the code they write — bundled into the thousand small decisions you can't produce the thing without making. The pure, standalone "no" — the skill of looking at finished work and seeing the flaw — was a small slice of the value, so it got a small slice of the status. Fine. Honest.&lt;/p&gt;

&lt;h2&gt;
  
  
  The skill got scarce. The status didn't move.
&lt;/h2&gt;

&lt;p&gt;Code is cheap now. Not free, not always correct, but &lt;em&gt;cheap&lt;/em&gt; — a competent diff for a well-scoped task is minutes of generation, not days of typing. The bottleneck moved. It is no longer "can we produce the code." It's "can we tell which of the confident, clean, plausible diffs in front of us is quietly wrong."&lt;/p&gt;

&lt;p&gt;Which means the skill that just became the scarce one — the whole ballgame — is the "no." The ability to look at clean, confident, approved-by-two-people work and say &lt;em&gt;that breaks under a retry, don't ship it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And here's the trap. Abundance ripped the staple out: judgment used to come bundled into the act of building, and now you can have all the output you want &lt;em&gt;without&lt;/em&gt; anyone exercising judgment over it. So the "no" is standing alone for the first time — no longer a small slice buried inside the valuable act of building, but the valuable thing itself.&lt;/p&gt;

&lt;p&gt;But its &lt;em&gt;status&lt;/em&gt; is still set where it was set twenty years ago, when it was a rounding error. We promoted the skill to most-important and left its title at least-important. We gave our most valuable skill our lowest rank.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The scarce skill now is the "no." Its status is still priced for a world where it was the cheap one.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The builder still gets the status, because the ladder still says the builder makes the scarce thing. But the builder is now leaning on the machine to produce the thing that stopped being scarce, at a scale no human can match. The person doing the actually-scarce thing — reading the mountain, catching the one that loses money — looks, from the top of the ladder, like he's barely working.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug that proves it
&lt;/h2&gt;

&lt;p&gt;Let me make it concrete, because I lived the before-version of this once and it's why I watch for the after.&lt;/p&gt;

&lt;p&gt;Years ago, on a different team, I shipped a write path that acknowledged a request before it had actually persisted the row. The code was clean. Idiomatic, typed, tested, reviewed, green. By every measure a dashboard could take, it was a productive, high-quality piece of work, and it made my output numbers — and my standing — look great that sprint.&lt;/p&gt;

&lt;p&gt;Then one ordinary day a retry hit at exactly the wrong moment. The "got it" went out, the save never landed, and a paying customer got locked out of their own account with nothing in the logs to say they'd ever been there. Ack before persist. I can still feel the phone call.&lt;/p&gt;

&lt;p&gt;Now back to March. Same bug, different seat. The diff in front of us acked the payment webhook before it wrote the row — clean, green, already approved. Two engineers who had &lt;em&gt;shipped a lot that sprint&lt;/em&gt; — who had the status — looked right at it and moved on, because it reads fine; you only catch it if something in you is actively asking "what happens on the retry." My low-status skeptic asked. One sentence on the PR. We reordered two lines. Nothing shipped under his name that day — his output for that interaction was &lt;em&gt;negative,&lt;/em&gt; he subtracted a line.&lt;/p&gt;

&lt;p&gt;That one sentence was worth more than everything the rest of us shipped that sprint combined. And it earned him exactly nothing — not on the dashboard, and not on the ladder in people's heads.&lt;/p&gt;

&lt;h2&gt;
  
  
  The status tax: we don't just under-reward the "no," we penalize it
&lt;/h2&gt;

&lt;p&gt;This is the part that makes it worse than the output problem, and the reason it won't fix itself.&lt;/p&gt;

&lt;p&gt;A disaster that ships is a visible, countable event: a postmortem, a ticket, a name, a number in the incident log. A disaster that &lt;em&gt;doesn't&lt;/em&gt; ship is a non-event. Nothing happens. There is no artifact, no graph that goes up, nothing to point at. So the skeptic lives inside a brutal asymmetry:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When they're &lt;strong&gt;right&lt;/strong&gt; and block the bad diff, nothing happens — so they get no credit. The absence of a disaster looks exactly like a quiet week.&lt;/li&gt;
&lt;li&gt;When they're &lt;strong&gt;wrong&lt;/strong&gt; and block something that was fine, they're the bottleneck who slowed the team down — visible, countable, remembered.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Right is invisible. Wrong is expensive. But status adds a second, nastier layer on top of that math. The builder's win feels &lt;em&gt;generous&lt;/em&gt; — they gave the team a feature. The skeptic's win feels like an &lt;em&gt;accusation&lt;/em&gt; — they told two colleagues their work was broken in front of everyone. Even when he's right, especially when he's right, the "no" costs him socially. He's "hard to work with." He's "not a team player." He "blocks things."&lt;/p&gt;

&lt;p&gt;So the rational move, for anyone who wants to climb, is to stop. Nod the clean diff through. Ship your own mountain. Let the retry bug be someone else's phone call. The status structure doesn't just fail to reward the scarcest skill — it actively teaches your best people to stop using it. We don't just under-pay the "no." We tax it, and then we're surprised nobody wants to do it.&lt;/p&gt;

&lt;p&gt;And when the layoff list gets made off a productivity dashboard, the person with the fewest commits and the most prevented-but-invisible disasters is sitting right at the top of the cut list. We're about to fire our smoke detectors for never having started a fire.&lt;/p&gt;

&lt;h2&gt;
  
  
  To be clear — this is not "shipping is for juniors"
&lt;/h2&gt;

&lt;p&gt;The lazy version of this take is "real engineers don't write code, they sit back and poke holes," and that's garbage. The "no" with nothing ever built behind it is just a person slowing a room down. A team full of brilliant skeptics who never ship isn't elite — it's dead.&lt;/p&gt;

&lt;p&gt;Shipping matters. I ship all day. The machine writes most of my code now and I'd never go back — the typing was never the hard part. Output is &lt;em&gt;table stakes.&lt;/em&gt; You still have to deliver. The builder's status wasn't &lt;em&gt;wrong;&lt;/em&gt; it just stopped being the &lt;em&gt;only&lt;/em&gt; thing worth top billing.&lt;/p&gt;

&lt;p&gt;The claim is narrower and, I think, harder to argue with: &lt;strong&gt;the "no" became the scarce skill and kept the status of the cheap one.&lt;/strong&gt; When building was the hard part, ranking by who builds was fair. Now the hard part is judgment — and judgment's sharpest form, the "no," is the lowest-status thing a person can do on your team. The fix isn't to stop shipping. It's to stop letting the status ladder tell you the skeptic is coasting while the machine does his loud colleague's job for him.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do now, since the ladder won't do it for me
&lt;/h2&gt;

&lt;p&gt;None of this is abstract anymore. It changed how I run the team:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I count the "no"s.&lt;/strong&gt; When someone blocks a diff and is right, that goes in the review &lt;em&gt;as a win,&lt;/em&gt; in writing, the same weight as a shipped feature. If I don't record it, the silence wins by default and the save never happened as far as the company is concerned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I make prevention leave a receipt.&lt;/strong&gt; A blocked bad diff gets a one-line note on the PR: &lt;em&gt;here's the input that would've lost money, here's what we changed.&lt;/em&gt; That artifact is the only way a prevented disaster becomes something anyone can point at later — and the only way the skeptic gets the status he actually earned. The skeptic who hands you a repro is cheap to keep. The one who blocks on vibes is first cut, not because he's wrong but because there's nothing to show he was right.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I pay the status tax for him, out loud.&lt;/strong&gt; When he's right, I say so in the room where the work got questioned, not in a private DM. The social cost of the "no" is the real reason people stop doing it, so the fix has to be social too. A manager who lets the skeptic eat that cost alone is training him to go quiet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I stopped reading a small diff as a small contribution.&lt;/strong&gt; The most valuable thing a senior did this week might be the three lines they &lt;em&gt;stopped&lt;/em&gt; from shipping.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this is the exact reason I build the way I do
&lt;/h2&gt;

&lt;p&gt;One level up, it's the same problem, and it's why I build an agent platform the way I do.&lt;/p&gt;

&lt;p&gt;The industry wants to cheer for the thing that produces — look how much it ships, how clean, how fast. But an agent that generates is just doing the skill that stopped being scarce, at a scale no human can match, and then — worse — it signs off on its own work in the same confident voice whether the diff is a masterpiece or a disaster. It's the high-status builder with none of the low-status skeptic's instinct: infinite throughput, zero "no."&lt;/p&gt;

&lt;p&gt;So I never let the thing that writes the code be the thing that blesses it. There's an &lt;strong&gt;author&lt;/strong&gt; that produces the diff — cheap, fast, endless, the abundant thing. There's a separate &lt;strong&gt;skeptic&lt;/strong&gt; whose entire job is to try to break that diff rather than admire it — the "no" given its own seat, institutionalized, so it doesn't depend on one underappreciated human being willing to pay the social cost of speaking up. And there's a &lt;strong&gt;human on the merge button&lt;/strong&gt; who owns the call and sees the blast radius neither agent can. Author, skeptic, human. The author has infinite throughput and I measure it by almost nothing. The skeptic has zero throughput and it's the whole product. That's the shape of &lt;a href="https://xenition.com" rel="noopener noreferrer"&gt;xenition&lt;/a&gt; — I built the "no" its own chair, because I watched what happens to the person who has to carry it alone.&lt;/p&gt;

&lt;p&gt;My quiet skeptic figured out, before I did, that the valuable move in 2026 is the one that earns you no status. The least code on the team, the reputation for being negative, and the reason the team still has that customer. I almost let a ladder tell me he was the bottom of the stack.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The best engineer on my team ships the least code.</title>
      <dc:creator>Info Inlet</dc:creator>
      <pubDate>Mon, 05 Oct 2026 08:05:36 +0000</pubDate>
      <link>https://dev.to/infoinlet1/the-best-engineer-on-my-team-ships-the-least-code-13hk</link>
      <guid>https://dev.to/infoinlet1/the-best-engineer-on-my-team-ships-the-least-code-13hk</guid>
      <description>&lt;p&gt;The best engineer on my team almost got a bad review last quarter for shipping too little code.&lt;/p&gt;

&lt;p&gt;I'm not being cute. I pulled the numbers before his review because I knew the numbers were going to be used against him. Fewest commits on the team. Smallest diffs. Whole sprints where his name was on almost nothing in the changelog. If you ranked the team by anything a dashboard can count, he came out near the bottom, and it wasn't close.&lt;/p&gt;

&lt;p&gt;He's also the single reason we didn't lose a paying customer's money in March. One comment on a pull request. No code. Just "wait — what does this do if the webhook retries?" And the thing that was about to ship, clean and green and approved by two other people, would have quietly eaten payments on a bad night.&lt;/p&gt;

&lt;p&gt;So I had a person whose output said &lt;em&gt;coast&lt;/em&gt; and whose actual value said &lt;em&gt;irreplaceable&lt;/em&gt;, and a review process that could only see the first one. That gap is the whole thing I want to talk about, because it isn't a quirk of my team. We built it on purpose, over twenty years, and then the ground moved under it and we didn't update the instrument.&lt;/p&gt;

&lt;h2&gt;
  
  
  For twenty years, output was a fair proxy. That's the part nobody questions.
&lt;/h2&gt;

&lt;p&gt;Here's why "measure the code" was never stupid. For most of the history of this job, writing the code was the hard part. It was slow, it was scarce, and it was &lt;em&gt;bottlenecked on the engineer.&lt;/em&gt; If you shipped a lot of good code, it genuinely meant something — you had the skill, you understood the system, you did the work nobody else could do as fast. Output was expensive, so output was a decent stand-in for value. Not perfect, but honest enough to run a company on.&lt;/p&gt;

&lt;p&gt;That's the assumption buried under every perf review, every promo packet, every "impact = things shipped" rubric in the industry. Output is scarce, so output is signal. It was true for so long that we stopped noticing it was an &lt;em&gt;assumption&lt;/em&gt; at all. It just felt like what engineering &lt;em&gt;is.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now say the quiet part. The thing that assumption rested on — that producing the code is the scarce, hard, bottleneck part — is the exact thing that stopped being true.&lt;/p&gt;

&lt;h2&gt;
  
  
  The instrument is measuring the one thing that stopped being scarce
&lt;/h2&gt;

&lt;p&gt;Code is cheap now. Not free, not always correct, but &lt;em&gt;cheap&lt;/em&gt; — a competent diff for a well-scoped task is minutes of generation, not days of typing. The bottleneck moved. It is no longer "can we produce the code." It's "can we tell which of the confident, clean, plausible diffs in front of us is quietly wrong."&lt;/p&gt;

&lt;p&gt;And look what that does to the dashboard. We are still ranking engineers by lines, commits, PRs, story points closed — by &lt;em&gt;output&lt;/em&gt; — at the exact moment output became the cheapest input in the building. We kept the twenty-year-old proxy and threw away the twenty-year-old reason it worked. It's like grading chefs by how fast they can boil water, the year the instant kettle shipped. The number still moves. It just stopped meaning anything.&lt;/p&gt;

&lt;p&gt;That's the trap in one line:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Output used to be scarce, so we measured it. It stopped being scarce, and we never stopped measuring it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The engineer who leans on the machine and ships a mountain looks like your top performer. The engineer who reads every one of those mountains and catches the one that loses money looks like he's barely working. The instrument has the ranking exactly backwards, and it's confident about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually became scarce
&lt;/h2&gt;

&lt;p&gt;When code was the bottleneck, judgment was bundled into the act of writing it — you couldn't produce the thing without making a thousand small decisions along the way, so the two came stapled together and you never had to measure them separately. Abundance ripped the staple out. Now you can have all the output you want &lt;em&gt;without&lt;/em&gt; anyone exercising judgment over it, which means judgment is suddenly its own scarce input — standing alone, un-bundled, for the first time.&lt;/p&gt;

&lt;p&gt;And the scarcest form of judgment is the one with the lowest status: the "no." The ability to look at a clean, confident, approved-by-two-people diff and say &lt;em&gt;that breaks under a retry, don't ship it.&lt;/em&gt; That skill doesn't produce anything. It &lt;em&gt;prevents.&lt;/em&gt; And prevention is invisible to every tool we use to decide who's valuable.&lt;/p&gt;

&lt;p&gt;My quiet engineer is the best person on the team because he has the most of the thing that got scarce and the least of the thing that got cheap. The review process reads that as underperformance, because the review process was built in the world where those two were the same thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug that proves it — and the review that caught it
&lt;/h2&gt;

&lt;p&gt;Let me make it concrete, because I lived the before-version of this once and it's why I now watch for the after.&lt;/p&gt;

&lt;p&gt;Years ago, on a different team, I shipped a write path that acknowledged a request before it had actually persisted the row. The code was clean. Idiomatic, typed, tested, reviewed, green. By every measure a dashboard could take, it was a productive, high-quality piece of work, and it made my output numbers look great that sprint.&lt;/p&gt;

&lt;p&gt;Then one ordinary day a retry hit at exactly the wrong moment. The "got it" went out, the save never landed, and a paying customer got locked out of their own account with nothing in the logs to say they'd ever been there. Ack before persist. I can still feel the phone call.&lt;/p&gt;

&lt;p&gt;Now back to March. Same bug, different seat. The diff in front of us acked the payment webhook before it wrote the row — clean, green, already approved. Two engineers who had &lt;em&gt;shipped a lot that sprint&lt;/em&gt; looked right at it and moved on, because it reads fine; you only catch it if something in you is actively asking "what happens on the retry." My quiet engineer asked. One sentence on the PR. We reordered two lines. Nothing shipped under his name that day — his output for that interaction was &lt;em&gt;negative,&lt;/em&gt; he subtracted a line.&lt;/p&gt;

&lt;p&gt;That one sentence was worth more than everything the rest of us shipped that sprint combined. And there is no field on the review form where it goes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cruel math: prevention has no throughput and no attribution
&lt;/h2&gt;

&lt;p&gt;Here's why this doesn't self-correct, and why it's about to get much worse.&lt;/p&gt;

&lt;p&gt;A disaster that ships is a visible, countable event. It has a postmortem, a Jira ticket, a name attached, a number in the incident log. A disaster that &lt;em&gt;doesn't&lt;/em&gt; ship is a non-event. Nothing happens. There is no artifact, no ticket, no graph that goes up. You cannot put a prevented outage on a dashboard, because the whole nature of a prevented outage is that there's nothing there to point at.&lt;/p&gt;

&lt;p&gt;So the person whose job is the "no" lives inside a brutal asymmetry:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When they're &lt;strong&gt;right&lt;/strong&gt; and block the bad diff, nothing happens — so they get no credit. The absence of a disaster looks exactly like a quiet week.&lt;/li&gt;
&lt;li&gt;When they're &lt;strong&gt;wrong&lt;/strong&gt; and block something that was fine, they're the annoying bottleneck who slowed the team down — visible, countable, held against them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Right is invisible. Wrong is expensive. That payoff structure doesn't just fail to reward the skill — it actively &lt;em&gt;teaches&lt;/em&gt; every rational person to stop using it, because silence is the only move with no downside. The instrument doesn't just miss the best engineer. It quietly trains him to become an average one.&lt;/p&gt;

&lt;p&gt;And this is the part that should scare anyone running a team right now: when the layoff list gets made off a productivity dashboard, the person with the fewest commits and the most prevented-but-invisible disasters is sitting at the top of the cut list. We are about to fire our smoke detectors for never having started a fire.&lt;/p&gt;

&lt;h2&gt;
  
  
  To be clear — this is not "shipping is bad"
&lt;/h2&gt;

&lt;p&gt;I want to be careful here, because the lazy version of this take is "real engineers don't write code, they think deep thoughts," and that's garbage.&lt;/p&gt;

&lt;p&gt;Shipping matters. I ship all day. The machine writes most of my code now and I'd never go back — the typing was never the hard part. A team where nobody produces anything isn't full of brilliant skeptics; it's dead. Output is &lt;em&gt;table stakes.&lt;/em&gt; You still have to deliver, and the "no" with nothing ever built behind it is just a person slowing down a room.&lt;/p&gt;

&lt;p&gt;The claim is narrower and, I think, harder to argue with: &lt;strong&gt;output stopped being the scarce thing, so it stopped being the thing worth measuring people by.&lt;/strong&gt; When the hard part was production, ranking by production was fair. Now the hard part is judgment, and we're still ranking by production — rewarding the abundant input and starving the scarce one. The fix isn't to stop shipping. It's to stop mistaking the thing the machine now does for the thing you're actually paying a human for.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do now, since the dashboard won't do it for me
&lt;/h2&gt;

&lt;p&gt;None of this is abstract for me anymore — it changed how I run reviews:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I count the "no"s.&lt;/strong&gt; When someone blocks a diff and is right, that goes in the review &lt;em&gt;as a win,&lt;/em&gt; in writing, the same way a shipped feature would. If I don't record it, the dashboard's silence wins by default and the save never happened as far as the company is concerned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I make prevention leave a receipt.&lt;/strong&gt; A blocked bad diff gets a one-line note on the PR: &lt;em&gt;here's the input that would've lost money, here's what we changed.&lt;/em&gt; That artifact is the only way a prevented disaster becomes something a manager can point at later. The skeptic who hands you a repro is cheap to keep. The skeptic who blocks on vibes is the first one cut — not because they're wrong, but because there's nothing to show they were right.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I stopped reading a small diff as a small contribution.&lt;/strong&gt; The most valuable thing a senior did this week might be the three lines they &lt;em&gt;stopped&lt;/em&gt; from shipping. I go looking for that on purpose now, because the instrument never will.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this is the exact reason I build the way I do
&lt;/h2&gt;

&lt;p&gt;One level up, it's the same problem, and it's why I build an agent platform the way I do.&lt;/p&gt;

&lt;p&gt;The whole industry right now wants to cheer for the thing that produces — look how much it ships, look how clean, look how fast. But an agent that generates is just doing the skill that stopped being scarce, at a scale no human can match, and then — worse — it signs off on its own work in the same confident voice whether the diff is a masterpiece or a disaster. It's my high-output engineer with none of my quiet one's instinct: infinite throughput, zero "no."&lt;/p&gt;

&lt;p&gt;So I never let the thing that writes the code be the thing that blesses it. There's an &lt;strong&gt;author&lt;/strong&gt; that produces the diff — cheap, fast, endless, the abundant thing. There's a separate &lt;strong&gt;skeptic&lt;/strong&gt; whose entire job is to try to break that diff rather than admire it — the "no" given its own seat, institutionalized, so it doesn't depend on one underappreciated human happening to be in the room. And there's a &lt;strong&gt;human on the merge button&lt;/strong&gt; who owns the call and sees the blast radius neither agent can. Author, skeptic, human. The author has infinite throughput and I measure it by almost nothing. The skeptic has zero throughput and it's the whole product. That's the shape of &lt;a href="https://xenition.com" rel="noopener noreferrer"&gt;xenition&lt;/a&gt;, and it's the same lesson my review numbers taught me: the moment production got cheap, the thing worth paying for stopped being production.&lt;/p&gt;

&lt;p&gt;My quiet engineer figured out, before I did, that the valuable move in 2026 is the one the dashboard can't see. The least code on the team, and the reason the team still has that customer. I almost let a number tell me he was coasting.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>I built the same app twice — by hand, then with AI. I trust the fast one less.</title>
      <dc:creator>Info Inlet</dc:creator>
      <pubDate>Sun, 04 Oct 2026 05:26:41 +0000</pubDate>
      <link>https://dev.to/infoinlet1/i-built-the-same-app-twice-by-hand-then-with-ai-i-trust-the-fast-one-less-5gbn</link>
      <guid>https://dev.to/infoinlet1/i-built-the-same-app-twice-by-hand-then-with-ai-i-trust-the-fast-one-less-5gbn</guid>
      <description>&lt;p&gt;I ran a stupid little experiment a few months ago. I built the same app twice.&lt;/p&gt;

&lt;p&gt;The first time, the slow way — by hand, the way I used to build everything. Typing most of it, reaching for the AI only when I got stuck. It took most of a week of evenings.&lt;/p&gt;

&lt;p&gt;Then, a month later, half out of boredom, I threw the whole thing away and rebuilt it from scratch. Same features, same spec. Except this time I let the AI do the writing. I described what I wanted, it produced, I steered. It took an afternoon.&lt;/p&gt;

&lt;p&gt;The second version is better. Cleaner code, fewer rough edges, more consistent naming. It even passed a couple of edge-case tests the first one didn't. By every number you'd put on a dashboard, the AI version won, and it wasn't close.&lt;/p&gt;

&lt;p&gt;And I trust it less. Not a little less — a lot less.&lt;/p&gt;

&lt;p&gt;That gap is the whole thing I've been chewing on since, because it isn't supposed to exist. Better code is supposed to earn &lt;em&gt;more&lt;/em&gt; trust, not less. Mine did the exact opposite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed and trust weren't uncorrelated. They were inverted.
&lt;/h2&gt;

&lt;p&gt;I went in assuming trust would track quality. Write better code, trust it more — obviously. The AI version &lt;em&gt;is&lt;/em&gt; higher quality. So why do I open the hand-built one with ease, and open the AI one with a small flinch, every time?&lt;/p&gt;

&lt;p&gt;The faster I built, the less I knew where it would break. Those two moved together, in the wrong direction, and once I saw it I couldn't unsee it. Which means trust was never a property of the code at all. It was a property of something else — something the fast version skipped without telling me.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "trust" actually turned out to be
&lt;/h2&gt;

&lt;p&gt;When I built version one by hand, I ended up with something that never made it into the repo: a map.&lt;/p&gt;

&lt;p&gt;I knew which parts were load-bearing and which were duct tape. I knew the one function that quietly assumed the list was already sorted. I knew the exact spot where, if the same request came in twice, something ugly happened. Nobody wrote any of that down. It lived in my head, and I'd built it without noticing — one decision at a time, because every one of those lines had made me pause. &lt;em&gt;Ack here, or after the save? Trust this input, or validate it? What happens if this gets called twice?&lt;/em&gt; Each pause left a little pin in a mental map of where the bodies were buried.&lt;/p&gt;

&lt;p&gt;That map is what trust is. Not "the code is correct" — I can't actually prove that about either version. Trust is "I know where this breaks." I had that map for version one. I did not have it for version two, and no amount of the AI's cleaner code was going to give it to me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The typing was never the point. It was where the map came from.
&lt;/h2&gt;

&lt;p&gt;Here's the part that actually unsettled me.&lt;/p&gt;

&lt;p&gt;For years I thought the value of writing code by hand was the code. The craft. The output. It wasn't. The AI writes better code than my hands do — version two settled that argument. The typing was a &lt;em&gt;side effect&lt;/em&gt;. What the typing secretly produced was the map. Every keystroke was a small decision, and the decisions were the thing I was really accumulating.&lt;/p&gt;

&lt;p&gt;I thought I was manufacturing code. I was manufacturing the knowledge of where it breaks, and the code was the byproduct. AI handed me the byproduct for free and quietly kept the thing I actually needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one line that proves it
&lt;/h2&gt;

&lt;p&gt;Let me make it concrete, because I can point at the exact line.&lt;/p&gt;

&lt;p&gt;In both versions there's a write path that acknowledges the request before it persists the row. In version one, I remember writing that line. I remember pausing on it. I remember moving the ack down below the save, because some part of me went cold when I looked at the order.&lt;/p&gt;

&lt;p&gt;That cold feeling has a source. Years ago I shipped exactly that bug — a write path that told the client "got it" before it had saved anything. The code was clean, idiomatic, tested, green. Then one ordinary day a retry hit at the wrong moment: the "got it" went out, the save never landed, and a paying customer got locked out of their own account with nothing in the logs to say they'd ever been there. Ack before persist. I can still feel the phone call.&lt;/p&gt;

&lt;p&gt;So when I typed that line by hand in version one, the scar fired, and I fixed the bug before it existed.&lt;/p&gt;

&lt;p&gt;In version two, the AI wrote the same line — ack before persist — confidently, cleanly, and I scrolled right past it. Not because I'd gotten dumber in a month. Because I never typed it. The decision never passed through me, so the scar never got its chance to fire.&lt;/p&gt;

&lt;p&gt;That's the moment it clicked. The typing wasn't only building the map. It was the &lt;em&gt;checkpoint&lt;/em&gt; — the turnstile every line used to pass through, where each of my scars got a vote on the way in. Automate the typing and you don't just lose the map. You remove the one place my judgment used to get consulted automatically, for free, on every single line.&lt;/p&gt;

&lt;h2&gt;
  
  
  To be clear — this is not "write it by hand"
&lt;/h2&gt;

&lt;p&gt;I'm not telling you to go back to typing everything. I shipped version two, not version one. The AI code is better and I'd never hand-roll that app again. The typing was never worth defending for its own sake.&lt;/p&gt;

&lt;p&gt;That's actually the trap: thinking the fix is to slow down and type more, like the keystrokes were sacred. They weren't. The problem isn't that the AI writes the code. The problem is that we got the code and assumed the map came stapled to it — the way it always had, for twenty years, because for twenty years you &lt;em&gt;couldn't&lt;/em&gt; get the code without doing the work that produced the map.&lt;/p&gt;

&lt;p&gt;The map used to be free. It came bundled with the keystrokes whether you wanted it or not. Now it's unbundled, and most people are shipping the code without ever paying for the map — and calling the speed a pure win.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I buy the map separately now, on purpose
&lt;/h2&gt;

&lt;p&gt;The job changed. I can't get the map from the typing anymore, so I buy it deliberately, after the AI writes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I read the diff like a stranger wrote it.&lt;/strong&gt; A stranger who's trying to make me look good in a demo and does not care what happens at 2am. Because that is exactly what wrote it. Admiration is the enemy here — the cleaner it looks, the harder I read.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For every file, I make myself finish "this breaks when ___."&lt;/strong&gt; Out loud, specifically. If I can't finish the sentence, that's not a pass — it's a hole in the map, and the hole is the part I don't understand yet. "Looks good" is not a map. It's the absence of one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I ship it small.&lt;/strong&gt; Behind a flag, to a canary, to one internal user. So the parts of the map I missed get filled in where filling them in is cheap — instead of at 2am, on a real customer, the expensive way.&lt;/p&gt;

&lt;p&gt;None of that is typing. It's the thing the typing used to do for me, done on purpose instead of as an accident. Slower than just accepting the diff. Still a fraction of the week I spent on version one. And it gets me the one thing the AI genuinely could not hand me: knowing where the thing breaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is the exact reason I build the way I do
&lt;/h2&gt;

&lt;p&gt;One level up, it's the same problem.&lt;/p&gt;

&lt;p&gt;An agent that writes code is fast, and clean, and produces a beautiful artifact with no map attached. And worse than mapless — it signs off on its own work. The thing that wrote the diff has no scar to fire and nothing to be suspicious of. It's version two with the confidence of version one and none of the earned caution. The most dangerous possible combination: fluent, fast, and completely unable to distrust itself.&lt;/p&gt;

&lt;p&gt;So I never let the thing that writes the code be the thing that blesses it. There's an author that produces the diff — fast, clean, mapless. There's a separate skeptic whose entire job is to build the map the author skips: read the diff as a stranger, finish "this breaks when ___," try to make it fall over. And there's a human on the merge button, who owns the call and keeps collecting the real scars. Author, skeptic, human. The skeptic is the typing turned into a &lt;em&gt;seat&lt;/em&gt; — the checkpoint every line used to pass through, rebuilt as its own job so it doesn't vanish the moment the author got fast. That's the whole shape of &lt;a href="https://xenition.com" rel="noopener noreferrer"&gt;xenition&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'll keep letting it write the code. The typing was never the point — version two proved that for good. But I stopped pretending the map comes free with the keystrokes, because it doesn't anymore. The code got faster. The trust didn't come with it. So now I pay for the trust on purpose, as its own line item, because it stopped being a side effect of the work.&lt;/p&gt;

&lt;p&gt;I built the same app twice. The fast version is the one I ship. The slow version is the one that taught me what the fast one forgot to include.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>csharp</category>
      <category>discuss</category>
    </item>
    <item>
      <title>A junior asked me how I knew the code was wrong. I couldn't answer him.</title>
      <dc:creator>Info Inlet</dc:creator>
      <pubDate>Sat, 03 Oct 2026 05:42:46 +0000</pubDate>
      <link>https://dev.to/infoinlet1/a-junior-asked-me-how-i-knew-the-code-was-wrong-i-couldnt-answer-him-1m1i</link>
      <guid>https://dev.to/infoinlet1/a-junior-asked-me-how-i-knew-the-code-was-wrong-i-couldnt-answer-him-1m1i</guid>
      <description>&lt;p&gt;We were pairing on a Thursday. Nothing dramatic. A junior on my team, maybe eight months in, sharp, the kind who actually reads the code instead of pasting it. We'd asked the AI for a chunk of logic, it came back in a few seconds, clean and typed and already passing the tests he'd written.&lt;/p&gt;

&lt;p&gt;He went to accept it. I said, "no, don't ship that."&lt;/p&gt;

&lt;p&gt;He stopped. Looked at it again. Looked at me. And he asked the most reasonable question in the world.&lt;/p&gt;

&lt;p&gt;"Wait — how did you know that's wrong?"&lt;/p&gt;

&lt;p&gt;And I opened my mouth to explain, and nothing came out.&lt;/p&gt;

&lt;h2&gt;
  
  
  I knew. I just couldn't say how.
&lt;/h2&gt;

&lt;p&gt;Here's the thing that rattled me, because it wasn't a dramatic bug and this isn't a dramatic story. The diff was wrong. I was right that it was wrong, and ten minutes later we proved it. That part was fine.&lt;/p&gt;

&lt;p&gt;What wasn't fine was that I had no idea how to tell him what I'd done. I hadn't run a checklist. I hadn't spotted a specific line and matched it to a rule. Something about the &lt;em&gt;shape&lt;/em&gt; of it had made the back of my neck go cold, and I'd learned, over a lot of years, to trust that exact feeling. But "trust the cold feeling on the back of your neck" is not a thing you can hand to a human being who hasn't grown the neck yet.&lt;/p&gt;

&lt;p&gt;I tried anyway. I said something about how it &lt;em&gt;felt&lt;/em&gt; off, how the error path looked too convenient, how I'd want to know what happens if this gets called twice. All true. All useless to him, because every one of those was a conclusion, and he was asking for the &lt;em&gt;method&lt;/em&gt;, and I didn't have a method. I had a scar that fired before I'd finished reading.&lt;/p&gt;

&lt;p&gt;That's the part I've been chewing on since. Not that I couldn't teach him. That the single most valuable thing I do all day is the one thing I have no idea how to transmit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two things get bundled into the word "senior"
&lt;/h2&gt;

&lt;p&gt;For years I thought being senior was a pile of knowledge. And some of it is, and that part I &lt;em&gt;can&lt;/em&gt; teach. "Validate at the boundary." "Don't trust the client's timestamp." "Wrap the external call." Rules. I can write them on a whiteboard and he'll have them by Friday, and honestly, the AI already has all of them and applies them more consistently than I do.&lt;/p&gt;

&lt;p&gt;But the thing I did on Thursday wasn't a rule. It was the opposite of a rule. It was knowing, against a clean diff that satisfied every rule either of us could name, that something was still wrong. Rules tell you what to check. The other thing tells you to keep looking after every check has passed. One is knowledge. The other is judgment, and I have never once been able to put it into words that survive contact with someone who hasn't earned it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You don't learn judgment. You survive into it — and that's exactly why I couldn't hand it to him.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nobody taught me the thing I did on Thursday. There was no course, no cert, no senior who sat me down. I got it the only way I think anyone gets it: I was confidently wrong about something that mattered, in front of someone who paid for it, and the lesson got welded on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the cold feeling actually came from
&lt;/h2&gt;

&lt;p&gt;Let me be specific, because I can trace that exact flinch to its source.&lt;/p&gt;

&lt;p&gt;Years ago I shipped a write path that told the client "got it" before it had actually saved the row. The code was clean. Genuinely clean — idiomatic, typed, tests around it, error handling buttoned up. It read like someone careful wrote it, because I was careful. By every rule I knew at the time, it was correct.&lt;/p&gt;

&lt;p&gt;Then one ordinary day a retry landed at exactly the wrong moment. The "got it" went out, the save never happened, and a paying customer got locked out of their own account with nothing in the logs to say they'd ever been there. Ack before persist. I can still feel the phone call.&lt;/p&gt;

&lt;p&gt;That's the source. When I looked at Thursday's diff and my neck went cold, I wasn't running an algorithm. I was pattern-matching against that customer. The AI's clean code looked exactly as correct as my clean code had looked, right up until it cost someone their account. The flinch &lt;em&gt;is&lt;/em&gt; that customer, compressed into half a second and welded onto my nervous system by the worst night of that year.&lt;/p&gt;

&lt;p&gt;So when the junior asked "how did you know," the honest, full answer was: &lt;em&gt;a person I locked out at 2am four years ago taught me, and I have no idea how to give you that without the person.&lt;/em&gt; You can't lecture someone into the flinch. You can only get unlucky enough times that it grows on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  And here's the part that actually scares me
&lt;/h2&gt;

&lt;p&gt;For twenty years, the flinch had a reliable supply chain. You got it by doing the grind — writing the production code yourself, shipping it, and being there when it broke. The small failures stacked up into judgment whether you wanted them to or not. You couldn't skip the grind, so you couldn't skip the scars.&lt;/p&gt;

&lt;p&gt;Watch what we just did to that supply chain.&lt;/p&gt;

&lt;p&gt;The junior doesn't write the production code anymore. The AI does, and it does it well, and I'm glad — the typing was never the hard part. But the typing, the shipping, the breaking, the 2am call: that was the &lt;em&gt;entire mechanism&lt;/em&gt; that used to turn a junior into me. We didn't just automate the boring part. We automated the forge. I got my judgment because I had to do, by hand, the exact work the AI now does for him before he ever feels it go wrong. He gets the clean output on day one and never has to earn the neck.&lt;/p&gt;

&lt;p&gt;So the one skill that survived AI — the only one, the "no" — is also the one skill the AI quietly stopped manufacturing in the next generation. The machine can hand him the code. It cannot hand him the scar, and the scar was the teacher.&lt;/p&gt;

&lt;h2&gt;
  
  
  To be clear, this is not "make juniors suffer"
&lt;/h2&gt;

&lt;p&gt;I'm not romanticising pain, and I'm not saying pull the AI and make him hand-write CRUD until he bleeds for it. That's cargo-cult mentorship — the suffering was never the point, the &lt;em&gt;consequence&lt;/em&gt; was. And I use AI all day; I'd never go back. The problem isn't that he has it easy. The problem is narrower and weirder than that: we removed the thing that used to produce judgment, and we haven't replaced it with anything.&lt;/p&gt;

&lt;p&gt;So that's the actual job now, and it's a design problem, not a vibes problem. I can't give him the flinch. But I can give him the one thing that grew the flinch in me — being wrong somewhere it's cheap to be wrong — on purpose, faster, instead of waiting for a real customer to do it the expensive way.&lt;/p&gt;

&lt;p&gt;A few things I actually do with him now:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I make him the skeptic, not the author.&lt;/strong&gt; The AI writes the diff. His job isn't to write a better one — it's to break the one we got. Before we accept anything, he has to finish the sentence "this loses money when ___." He's wrong most of the time. Doesn't matter. The rep is the distrust, not the catch. That's the muscle, and it only grows when it's &lt;em&gt;his&lt;/em&gt; job to doubt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I manufacture the consequence small.&lt;/strong&gt; Ship it behind a flag, to one internal user, to a canary. Let it break where breaking is cheap, so the lesson arrives before the customer does. A flinch you got from a staging incident is the same flinch — it just didn't cost anybody their account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I stop answering "is it right" and make him answer "how is it wrong."&lt;/strong&gt; The question trains the instinct. "Looks good" trains nothing. If I just tell him what I saw, he learns my conclusion. If I make him hunt for how it breaks, he starts growing his own neck.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is the exact reason I build the way I do
&lt;/h2&gt;

&lt;p&gt;One level up, same problem.&lt;/p&gt;

&lt;p&gt;I work on an agent platform, and the whole industry right now wants to cheer for the thing that produces. Look how much it ships, look how clean. But a thing that produces is just doing the skill that stopped being scarce — and worse, it's doing it in a way that signs off on its own work, the same confident "looks correct" over a masterpiece and a disaster alike. It's the AI version of a junior with no flinch: fast, fluent, and completely unable to distrust itself.&lt;/p&gt;

&lt;p&gt;So I never let the thing that writes the code be the thing that blesses it. There's an author that produces the diff, cheap and endless. There's a separate skeptic whose entire job is to distrust that diff and try to break it — the flinch given its own seat, institutionalised, so it doesn't depend on anyone having gotten unlucky enough to grow one. And there's a human on the merge button, because somebody still has to own the call, and that human is the one still accumulating the real scars. Author, skeptic, human. That's the whole shape of &lt;a href="https://xenition.com" rel="noopener noreferrer"&gt;xenition&lt;/a&gt;, and it's my actual answer to the junior's question: you can't teach the flinch, so you build the seat that does its job and you put the person in it until they grow their own.&lt;/p&gt;

&lt;p&gt;I still can't tell him how I knew. What I can do is put him where he'll find out the way I did — wrong, early, and somewhere cheap enough that the lesson costs a canary instead of a customer. The knowing was never teachable. The getting-wrong is. That's the only part I can actually hand him.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>I've been a developer for 10 years. AI just showed me I only had one real skill."</title>
      <dc:creator>Info Inlet</dc:creator>
      <pubDate>Wed, 30 Sep 2026 05:34:48 +0000</pubDate>
      <link>https://dev.to/infoinlet1/ive-been-a-developer-for-10-years-ai-just-showed-me-i-only-had-one-real-skill-38p</link>
      <guid>https://dev.to/infoinlet1/ive-been-a-developer-for-10-years-ai-just-showed-me-i-only-had-one-real-skill-38p</guid>
      <description>&lt;p&gt;Last Sunday I built an invoice tracker for a friend who runs a small shop. Nothing clever. I described what I wanted, let the AI do the rest, and about forty minutes later it was running. Routes, the database schema, login, even the fiddly error handling I used to be a bit smug about. Worked on the first try.&lt;/p&gt;

&lt;p&gt;I should have just felt good about it, and mostly I did. But there was another feeling underneath that I couldn't shake for the rest of the evening. That thing had done, in forty minutes, the stuff I spent most of my twenties learning how to do.&lt;/p&gt;

&lt;p&gt;Not "the robots are taking our jobs." Something more specific, and more personal than that. I looked at ten years of work I was proud of and realised I couldn't tell anymore how much of it had ever really been mine.&lt;/p&gt;

&lt;p&gt;Quick disclaimer before anyone heads for the comments: I use AI to write code every day now and I'm not giving that up. This isn't that kind of post. But that Sunday made me ask something I'd genuinely never had a reason to ask, because until recently you couldn't take the job apart to look at it. Of everything I call "my skills," which one was actually mine?&lt;/p&gt;

&lt;h2&gt;
  
  
  Turns out "being a developer" was two jobs, not one
&lt;/h2&gt;

&lt;p&gt;For about ten years I never had to separate them, because you couldn't get good at the second one without grinding through the first.&lt;/p&gt;

&lt;p&gt;Call the first one production. Making the thing exist. The language, whatever framework everyone used that year, the APIs you eventually know by heart, wiring one piece to another until an idea turns into something that runs. This is the part bootcamps teach and interviews test. It's what my CV was, basically top to bottom. And it's the part AI is now flat-out better at than me. Which, honestly, fine. It was never the hard part. It just took years to get quick at.&lt;/p&gt;

&lt;p&gt;The second one I don't really have a clean word for. Judgment, maybe. It's looking at something that works and knowing, somehow, that it's wrong. Not "does it run" but "is this going to quietly lose someone money in three weeks." Knowing which confident, tidy, all-tests-passing answer you shouldn't trust. Nobody ever put this on my CV. There was no course for it, no cert, no exam. It felt less like a skill and more like a hunch you can't explain to a junior no matter how you try.&lt;/p&gt;

&lt;p&gt;AI took the first job completely. And because the two were always tangled together, it feels like it took "being a developer." It didn't. It took production, which was most of what I trained, and it hasn't laid a finger on the judgment, because the judgment was never in the code. It was in me.&lt;/p&gt;

&lt;h2&gt;
  
  
  So a decade gave me one skill, not ten
&lt;/h2&gt;

&lt;p&gt;This is the part that actually kept me up.&lt;/p&gt;

&lt;p&gt;Every skill I'd have bragged about, anything I'd have listed if you asked why I was worth hiring, was production. Recall. The framework, the right flag, the pattern, the clean CRUD. All of it gone in an afternoon, and done well. Ten years of stacking it up, handed back to everyone for free in a single product update.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ten years didn't build me ten skills. It built one. The other nineteen I was renting from a supplier who just took them back.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The one thing that didn't get taken was the judgment. And here's what gets me: I'd never once counted it as a skill. It felt like taste. It felt like something I was, not something I'd learned. Which is exactly why no course sells it and no interview tests it. You can't really teach the "no."&lt;/p&gt;

&lt;p&gt;Everything I was proud of, AI does in an afternoon now. The one thing it can't do was the only thing that was ever mine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug that made it obvious
&lt;/h2&gt;

&lt;p&gt;Let me get specific, because I paid for this one.&lt;/p&gt;

&lt;p&gt;Years back I shipped a write path that told the client "got it" before it had actually saved the row. The code was clean. Genuinely clean. It read like someone careful wrote it, because I did. Everything from those ten years was in there: idiomatic, properly typed, tests around it, error handling buttoned up. By every measure I'd have used at the time, some of the best code I'd written.&lt;/p&gt;

&lt;p&gt;Then, one ordinary day, a retry landed at exactly the wrong moment. The "got it" went out, the save never happened, and a paying customer got locked out of their own account with nothing in the logs to say they'd ever been there. Ack before persist.&lt;/p&gt;

&lt;p&gt;Here's what stuck with me. None of my ten years caught that. The syntax was perfect. The framework was used correctly. The tests were green. Every one of those rented skills did its job. The only thing that would have saved that customer was the skill I'd never even named: the reflex to look at working code and not trust it, to stop and ask "okay, what happens if this gets retried," to say no to my own clean diff.&lt;/p&gt;

&lt;p&gt;The code scored an A on everything AI now beats me at. It failed on the one thing that was mine.&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm not mourning the other nineteen, to be clear
&lt;/h2&gt;

&lt;p&gt;I'm not about to start hand-writing CRUD to prove a decade meant something. For production, AI is a better developer than I am at 5pm on a Friday, and leaning on it is just correct. Take the scaffold. Take the fix. Ship faster. That part isn't the loss.&lt;/p&gt;

&lt;p&gt;The trap is quieter than that. When a tool does all nineteen of your rented skills, the easy conclusion is that you've been made pointless, when the truth is closer to the opposite. It cleared away everything that was never really the point and left you standing on the one thing that was. And if you can't tell which skill was the real one, you'll spend the next ten years defending the nineteen it already took, instead of getting better at the one it can't.&lt;/p&gt;

&lt;p&gt;So, a few things I actually do now.&lt;/p&gt;

&lt;p&gt;I rewrite the CV around the "no." Not "expert in [framework]" — the machine is an expert in that too. The line worth writing is the judgment call: the bug I didn't trust when it looked fine, the design I killed, the confident diff I overruled and turned out to be right about.&lt;/p&gt;

&lt;p&gt;I keep the muscle warm on purpose. Before I accept anything the AI hands me, I make myself say one sentence out loud: "here's how this loses money." I'm wrong most of the time. Doesn't matter. The rep is the distrust, not the catch.&lt;/p&gt;

&lt;p&gt;And I stopped measuring myself in output. Lines, tickets, features shipped. Those are the machine's numbers now, and racing it on them is just volunteering to be a slower model. The only score that's still mine is the disasters I saw coming that it didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  And this is more or less why I build the way I do
&lt;/h2&gt;

&lt;p&gt;One level up, same logic.&lt;/p&gt;

&lt;p&gt;I work on an agent platform, and the whole industry right now wants to cheer for the thing that produces. Look how much it ships. But a thing that produces is just doing the skill that stopped being scarce. Endless production is endless output that nobody has actually vouched for. The scarce thing was never the code. It was someone looking at the code and saying no, which is the one skill a decade left me with.&lt;/p&gt;

&lt;p&gt;So I don't let the thing that writes the code be the thing that signs off on it. There's an author that produces, all nineteen rented skills, cheap and endless. There's a separate skeptic whose entire job is to distrust the output and try to break it, the "no" given its own seat. And there's a human who owns the call, because that was always the only part that was ours. Author, skeptic, human. That's the whole shape of &lt;a href="https://xenition.com" rel="noopener noreferrer"&gt;xenition&lt;/a&gt;, and it's the same thing the locked-out customer taught me. Producing the thing was always cheap. Knowing it was wrong was the job.&lt;/p&gt;

&lt;p&gt;Ten years didn't make me a great producer. AI just proved I never had to be. What it made me, slowly and expensively and one disaster at a time, is someone who can look at something that works and tell it's wrong. That's the one real skill, and it's the only one AI handed back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Honest question for the comments:&lt;/strong&gt; of everything you know, which single skill would still be yours if AI could do all the rest tomorrow? The one that isn't syntax, isn't a framework, isn't just recall. 👇&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>career</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
