<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Jason Waldrip · Builder, entrepreneur, technologist</title><description>Builder, entrepreneur, technologist. Volume is free now; judgment is the moat. Twenty years of engineering leadership at consumer scale, offering fractional CTO and CAIO work through The Bushido Collective.</description><link>https://jasonwaldrip.com/</link><language>en-us</language><item><title>Review Is the Rate Limit</title><link>https://jasonwaldrip.com/writing/review-is-the-rate-limit/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/review-is-the-rate-limit/</guid><description>Review capacity, not generation, is the real constraint on an agent-era pipeline. On the narrow stage, work in progress that depreciates while it waits, GenStage&apos;s demand-driven back-pressure, and when to throttle the producer versus widen the reviewer.</description><pubDate>Mon, 05 Oct 2026 20:15:00 GMT</pubDate><content:encoded>&lt;p&gt;There are two finished posts sitting in a queue on this site right now. Written, formatted, images generated, ready to render. Each one waiting on exactly one thing, which is me reading it and saying yes or no. Nothing is broken. Nobody is blocked. And the thing that produced them will cheerfully produce another tomorrow without ever asking how the first two went.&lt;/p&gt;
&lt;p&gt;I set the generation side up on purpose. Scheduled, grounded in my own material, a guide in the repo so it stays in my voice instead of drifting into LinkedIn. It works, which is the part I was proud of.&lt;/p&gt;
&lt;p&gt;What I never did was size the other half. I have been getting paid to fix that exact mistake in other people&apos;s companies for twenty years.&lt;/p&gt;
&lt;h2&gt;the stage nobody sizes&lt;/h2&gt;
&lt;p&gt;Every pipeline has a narrowest stage, and that stage sets the throughput of the whole thing. Work you do upstream of it doesn&apos;t raise output. It just gets the work to the narrow stage sooner, where it waits.&lt;/p&gt;
&lt;p&gt;This is the most reliable piece of systems thinking I own. I apply it to build pipelines, deploy paths, marketplaces, onboarding flows, hiring loops. Then generation went to roughly free, and I spent a year happily widening a stage that was already the widest one I had.&lt;/p&gt;
&lt;p&gt;So ask the question properly. For most of what I build now, the narrow stage is one person deciding whether the output is any good. &lt;a href=&quot;/writing/read-the-decisions-not-the-diff/&quot;&gt;That decision was never the fast part&lt;/a&gt;, and it is the one part of this whole shift that didn&apos;t get cheaper.&lt;/p&gt;
&lt;h2&gt;what I actually did at CommercialTribe&lt;/h2&gt;
&lt;p&gt;At CommercialTribe I replaced a weeks-long release cadence with automated testing and deploys that shipped in hours, across onsite engineers and a remote team in Argentina. That&apos;s the line on my &lt;a href=&quot;/works/&quot;&gt;works page&lt;/a&gt; and it&apos;s accurate, but the way I usually tell it buries the interesting part.&lt;/p&gt;
&lt;p&gt;I didn&apos;t make anybody write code faster. Nobody&apos;s typing was ever the problem. Releases were the problem, and releases were slow because shipping required a specific set of humans to agree, in a specific window, on a specific afternoon. So I went at the narrow stage directly: automate the checks a person was doing by hand, and leave in the loop only the judgment that genuinely needed a human attached to it.&lt;/p&gt;
&lt;p&gt;Weeks to hours is the difference between a team that learns and one that guesses. But notice which project I picked. I went after the approval stage. I did not hire two more engineers and let the releases stack up behind the same afternoon.&lt;/p&gt;
&lt;h2&gt;a growing queue is not output&lt;/h2&gt;
&lt;p&gt;I&apos;d like to tell you the two drafts are harmless. Queues are too well understood for me to be vague about it.&lt;/p&gt;
&lt;p&gt;When work arrives faster than it gets served, the queue does not settle at some comfortable larger size. It grows until something gives, and the wait on any single item grows along with it. That&apos;s not a productivity style. It&apos;s arithmetic.&lt;/p&gt;
&lt;p&gt;The items don&apos;t wait neutrally either. A draft written against this month&apos;s thinking goes stale. A branch written against a moving codebase quietly accrues conflicts. DORA keeps &lt;a href=&quot;https://dora.dev/capabilities/wip-limits/&quot;&gt;&quot;work in process limits&quot;&lt;/a&gt; in its delivery capabilities for this reason, and describes it as limiting how much people are working on so a small number of high-priority things actually get done. Read that as inventory management, because that&apos;s what it is. Work in progress ages, and aging inventory depreciates.&lt;/p&gt;
&lt;div&gt;&lt;div&gt;Two drafts, zero decisions.&lt;/div&gt;&lt;div&gt;A pile of pending work reads like output on a calendar. Nothing in it has been judged yet, which was supposed to be the whole value I add.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;There&apos;s a quieter cost under the obvious one. The queue let me not decide. If each of those posts had forced a yes or no on the day it landed, I&apos;d have two answers now. Instead I have a stack, and a stack feels like having done something.&lt;/p&gt;
&lt;h2&gt;the topology I&apos;d reject in a design review&lt;/h2&gt;
&lt;p&gt;At GigSmart I chose Elixir because a real-time marketplace is a concurrency problem before it&apos;s anything else: fault isolation by default rather than bolted on afterward. &lt;a href=&quot;/choices/elixir/&quot;&gt;That call still holds up&lt;/a&gt;, and the piece of that ecosystem I think about most often isn&apos;t supervision trees. It&apos;s demand.&lt;/p&gt;
&lt;p&gt;In GenStage, Elixir&apos;s library for staged pipelines, the consumer tells the producer how much it can take, and the producer is not permitted to exceed it. The documentation is blunt about the mechanism: &lt;a href=&quot;https://gen-stage.hexdocs.pm/GenStage.html&quot;&gt;&quot;Once demand arrives, the producer will emit events, never emitting more events than the consumer asked for. This provides a back-pressure mechanism.&quot;&lt;/a&gt; The consumer pulls. The producer cannot push.&lt;/p&gt;
&lt;p&gt;The same idea runs through TCP windows, bounded channels in Go, and every work queue I&apos;ve ever put a depth limit on. An unbounded producer feeding a fixed-rate consumer is a known-bad shape. If a team walked me through that design I&apos;d send them back inside of five minutes.&lt;/p&gt;
&lt;p&gt;It is also, precisely and embarrassingly, how I had my own writing configured. A scheduled producer with no knowledge of consumer state, pointed at one reviewer with a calendar.&lt;/p&gt;
&lt;h2&gt;backpressure when the consumer is you&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Bound the queue in the system, not in your intentions.&lt;/b&gt; Pick the number of items allowed to sit awaiting your judgment. When it&apos;s full, generation doesn&apos;t run. A limit you enforce by remembering to feel bad about it is a preference, and preferences don&apos;t apply backpressure.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Let review pull the work.&lt;/b&gt; The generator shouldn&apos;t be asking what day it is. It should be asking whether there&apos;s room. Scheduling by calendar is push. Scheduling by queue depth is pull, and pull is the entire mechanism.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Watch age, not count.&lt;/b&gt; Three items that turn over weekly is a working pipeline. One item sitting for a month is a stall. Count alone cannot tell those apart, and the age of the oldest item can.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;A no drains the queue exactly as well as a yes.&lt;/b&gt; This is the one I keep getting wrong. Rejection is service. Deferral is the only available response that leaves the item in the system, and it&apos;s the one that feels least like a decision, which is why my queue has a depth of two instead of zero.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;where I&apos;d stop trusting the analogy&lt;/h2&gt;
&lt;p&gt;Two places, and the second one matters more.&lt;/p&gt;
&lt;p&gt;Judgment isn&apos;t a fixed service rate, and the items aren&apos;t interchangeable. A short take I can read in a minute and a load-bearing architectural call both count as &quot;one item,&quot; and any model that treats them as the same unit will walk you straight into a bad conclusion. Backpressure in software assumes a uniform consumer. I&apos;m not one.&lt;/p&gt;
&lt;p&gt;The bigger limit: throttling the producer is only one of the two available fixes, and it&apos;s the lazier one. The other is the CommercialTribe move, which is to make the review stage genuinely wider. Better specs up front so there&apos;s less to adjudicate at the end. Smaller diffs. A written standard for what a yes actually requires, so the decision stops getting re-litigated from scratch every time. &lt;a href=&quot;/writing/volume-is-free-now/&quot;&gt;Volume being free&lt;/a&gt; is not an argument for restricting volume on principle. It means you now have to choose, deliberately, which of those two levers you&apos;re pulling.&lt;/p&gt;
&lt;p&gt;Throttle when the consumer is the irreducible part, the judgment that can&apos;t be handed off to anything. Widen when the consumer is doing work that a system should have been doing all along. Mix those up and you get either a bottleneck dressed as discipline, or a rubber stamp dressed as a process.&lt;/p&gt;
&lt;h2&gt;back to the two drafts&lt;/h2&gt;
&lt;p&gt;I don&apos;t think the mistake was generating too much. The mistake was building a producer with no idea whether anyone downstream was reading, then measuring the arrangement by whether it produced. The repair is small. The generator has to ask first.&lt;/p&gt;
&lt;p&gt;So, your turn. What in your setup produces faster than you can judge, and where does the overflow go? If the answer is that it waits its turn, go find the oldest one and look at the date on it.&lt;/p&gt;
&lt;p&gt;That&apos;s the number I had been avoiding too.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He takes on fractional CTO and CAIO work through &lt;a href=&quot;https://thebushido.co&quot;&gt;The Bushido Collective&lt;/a&gt;, for founders drowning in AI-generated code and teams scaling past the leadership that got them here. Flat retainers, measured on what ships and what gets prevented. If your generation side is running and you can&apos;t say what your review capacity is, that&apos;s a conversation worth having. &lt;a href=&quot;https://thebushido.co&quot;&gt;Work with me&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with Claude Opus 5; the frame, the CommercialTribe and GigSmart calls, and the judgments about what matters are mine. The GenStage passage is quoted from its documentation and the work-in-process description from DORA&apos;s capability catalog, both linked above. The two drafts are real, and this one went into the same queue behind them.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>judgment</category></item><item><title>Three Agents, One Working Tree</title><link>https://jasonwaldrip.com/writing/three-agents-one-working-tree/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/three-agents-one-working-tree/</guid><description>Running several coding agents against one repository is a concurrency problem rather than a prompting problem. On isolation with worktrees, claimed work items, idempotent reruns, serial sections, and why a lost race produces confident code instead of a crash.</description><pubDate>Mon, 28 Sep 2026 07:40:00 GMT</pubDate><content:encoded>&lt;p&gt;Three agents are running. One is fixing a bug in billing, one is adding a field to the onboarding form, one is partway through a dependency bump you approved without thinking about it. You come back and the test suite is red, and when you read the failure it doesn&apos;t belong to any of them. You open all three diffs. Every one is something you would have approved on its own.&lt;/p&gt;
&lt;p&gt;So you go work on the prompt. Everybody does. You add a rule to the guide in the repo, something about checking whether a file has changed before rewriting it, and you feel a little better because it&apos;s a real instruction and it&apos;s not wrong.&lt;/p&gt;
&lt;p&gt;It helps at the margin. It doesn&apos;t fix it, and the reason it doesn&apos;t fix it is worth more than the afternoon it costs to find out.&lt;/p&gt;
&lt;h2&gt;nothing in there was reasoning badly&lt;/h2&gt;
&lt;p&gt;Go back and read the three diffs again with a different question. Not &lt;em&gt;which one is wrong&lt;/em&gt;. Ask instead what each agent believed about the repository at the moment it started.&lt;/p&gt;
&lt;p&gt;All three read the tree. All three read it at slightly different times. Each one then spent a while producing careful work against the state it had loaded, while the state it had loaded was quietly stopping being true. The billing fix was correct against a file the dependency bump was already rewriting. Nobody hallucinated. Nobody skipped a step. Each of them did competent work on a stale read.&lt;/p&gt;
&lt;p&gt;You have seen this failure. You have probably fixed it. It just had a different name the last time, and it wasn&apos;t wearing a chat interface.&lt;/p&gt;
&lt;h2&gt;the shape I already knew&lt;/h2&gt;
&lt;p&gt;At GigSmart I built a gig marketplace, and the interesting part was never the feature list. Workers and shifts move against each other in real time, which means the actual product is thousands of things happening at once without knocking each other over. I reached for &lt;a href=&quot;/choices/elixir/&quot;&gt;Elixir&lt;/a&gt; because process isolation is the floor there rather than something you assemble later out of hand-written supervisors and queues you babysit. One slow thing shouldn&apos;t be able to reach the things beside it.&lt;/p&gt;
&lt;p&gt;That&apos;s a runtime decision, and I&apos;ve argued the general version of it before: &lt;a href=&quot;/writing/scale-is-a-design-not-a-dial/&quot;&gt;scale is a design, not a dial&lt;/a&gt;. What sits underneath both is one line I keep on the &lt;a href=&quot;/choices/distributed-systems/&quot;&gt;distributed systems&lt;/a&gt; page, because it&apos;s the whole discipline compressed: decide where state lives before you write a line.&lt;/p&gt;
&lt;p&gt;I had that on a page on my own website while running a fleet of agents against a single checkout on my laptop.&lt;/p&gt;
&lt;h2&gt;the memo nobody sent&lt;/h2&gt;
&lt;p&gt;Somewhere in the last two years, without any particular day marking it, the job changed. You stopped being the person who writes the code. You became the person who operates a scheduler.&lt;/p&gt;
&lt;p&gt;That&apos;s not a promotion and it isn&apos;t a metaphor I&apos;m stretching for effect. It&apos;s a literal description of what you do now. You admit work into a pool of workers, those workers run concurrently, they contend for a resource, and you are responsible for what happens when two of them want the same thing. There is a name for every part of that sentence and none of the names come from machine learning.&lt;/p&gt;
&lt;div&gt;&lt;div&gt;Your repository is shared mutable state. Three writers, no lock.&lt;/div&gt;&lt;div&gt;You would never have shipped that on purpose. You did it to your own workflow in about a week, because it never looked like architecture.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Which is exactly why it got past me. A checkout on a laptop doesn&apos;t present itself as a system design decision. It&apos;s just where the code is. Nothing about opening a third terminal feels like you&apos;re widening a write path, and there&apos;s no dashboard anywhere that turns red when you do.&lt;/p&gt;
&lt;h2&gt;the playbook transfers almost entirely&lt;/h2&gt;
&lt;p&gt;The useful thing about correctly naming the problem is that the answers were worked out decades ago by people solving it in much harder conditions.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;Isolation first.&lt;/b&gt; Git has shipped worktrees for years: multiple branches checked out in separate directories, backed by one repository. One tree per agent turns three writers on shared state into three writers on their own state, and the contention moves to the merge, where you have tools and a human. It is the cheapest change on this list and it takes about a minute.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Make work items atomic and claimed.&lt;/b&gt; An agent should take a unit of work, own it, and be the only thing that owns it. At Phoneware I keep a workboard in the monorepo that the fleet actually tracks against, and its real job isn&apos;t planning. It&apos;s making sure two workers don&apos;t pick up the same thing, and that a thing picked up has a visible owner.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Assume the retry.&lt;/b&gt; A run gets interrupted, context runs out, you kill it because it wandered. If rerunning the same task twice produces two migrations or two config blocks, that&apos;s not an agent problem, that&apos;s a missing idempotency guarantee. Work should be safe to repeat.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Name the serial section out loud.&lt;/b&gt; Some work was never going to run wide. A schema migration, a release, anything with an external clock on it. I&apos;ve written about [the things you can&apos;t parallelize](/writing/you-cant-parallelize-a-certificate/), and the failure is trying anyway rather than scheduling around it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of that is novel. That&apos;s the point, and it&apos;s the part I find genuinely good news. The tooling under a fleet is boring infrastructure that the industry already knows how to build, which means the constraint is recognizing what you&apos;re looking at rather than waiting for somebody to invent a fix.&lt;/p&gt;
&lt;h2&gt;where the analogy gives out&lt;/h2&gt;
&lt;p&gt;I&apos;d rather hand you the limits than a clean ending.&lt;/p&gt;
&lt;p&gt;A thread is reproducible enough to chase. You can put the race under a debugger, run it enough times, and eventually watch it happen. You cannot replay an agent. Run the same task twice and you get two different reasonable attempts, so a race you hit this morning may never present the same way again. Detection after the fact is mostly off the table, which raises the price of structure and lowers the value of watching carefully. Prevention isn&apos;t the better option here so much as the only one that compounds.&lt;/p&gt;
&lt;p&gt;The second difference is the one that actually worries me. A thread that loses a race tends to fail loudly. It throws, it deadlocks, it corrupts something a checksum catches. An agent that loses a race writes fluent, well-organized, plausible code on top of a premise that stopped being true twenty minutes ago, adds a test that passes against its own assumptions, and tells you it&apos;s done.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A crash announces itself. A confident wrong answer waits for you in review, formatted nicely, with a reasonable commit message.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&apos;s the cost of the whole arrangement, and it lands on the same place everything else does: you have to be able to tell. &lt;a href=&quot;/writing/volume-is-free-now/&quot;&gt;Volume is free now&lt;/a&gt;, verification is the job, and this is one more room where that bill comes due. The difference is that this particular failure is cheap to design out and expensive to catch by reading.&lt;/p&gt;
&lt;h2&gt;the thing worth taking&lt;/h2&gt;
&lt;p&gt;I don&apos;t think many people are going to get burned badly by one agent. The model is good, the diff is readable, you&apos;re paying attention because there&apos;s one thing to pay attention to.&lt;/p&gt;
&lt;p&gt;You get burned at three. And the reason you get burned at three is that going from one to three feels like nothing. No purchase, no migration, no design review. You open two more terminals on a Tuesday because the work is there, and you&apos;ve quietly moved from a sequential system to a concurrent one without any of the ceremony that decision would have gotten if it had involved a database.&lt;/p&gt;
&lt;p&gt;So before you widen the fleet again: what exactly is the shared resource, and what happens when two workers reach it at the same time?&lt;/p&gt;
&lt;p&gt;If you can&apos;t answer that, you haven&apos;t got a prompting problem yet. You&apos;ve got a scheduler you haven&apos;t designed.&lt;/p&gt;
&lt;div&gt;&lt;p&gt;Written with Claude Opus 5, and said so. The Elixir and marketplace calls are from my time at GigSmart; the workboard and monorepo setup are how I run the fleet at Phoneware. The worktree pattern is plain git, not anything proprietary. The three-agent scene at the top is the shape of the failure rather than a transcript of one afternoon.&lt;/p&gt;&lt;/div&gt;</content:encoded><kind>essay</kind><category>architecture</category></item><item><title>You Pinned a Countdown</title><link>https://jasonwaldrip.com/writing/you-pinned-a-countdown/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/you-pinned-a-countdown/</guid><description>Pinning a model version looks like the same discipline as pinning a package, but retired models stop serving requests and a pinned version never froze the behavior anyway. On Anthropic&apos;s published retirement dates, the GPT-4o consumer deprecation, measured behavior drift between snapshots, and why an eval suite is the only pin you can write yourself.</description><pubDate>Fri, 25 Sep 2026 08:20:00 GMT</pubDate><content:encoded>&lt;p&gt;The agent that answers text messages for my Starlink rental company has been doing it since July. Nothing about it has changed in weeks. No commits, no config edits, no deploys. It works, which in that business means somebody standing in a parking lot asks whether a dish can reach them by Friday and gets a straight answer.&lt;/p&gt;
&lt;p&gt;Its model has a retirement date. I didn&apos;t pick the date. I can read it on a documentation page, and when it arrives, requests to that model fail.&lt;/p&gt;
&lt;p&gt;Nobody is behaving badly in that sentence. It&apos;s just that I&apos;ve taken on a dependency which doesn&apos;t work like any dependency I&apos;ve taken in twenty years, and I spent months applying the wrong habit to it without noticing.&lt;/p&gt;
&lt;h2&gt;the responsible thing&lt;/h2&gt;
&lt;p&gt;You pinned it. Of course you did. You&apos;ve been pinning versions since the first time a patch release ate an afternoon, and by now it&apos;s reflex: put the exact string in the config, commit the lockfile, let the upgrade be a decision somebody makes on purpose rather than something that happens to you on a Tuesday.&lt;/p&gt;
&lt;p&gt;So the model id in your repo says &lt;code&gt;claude-sonnet-4-5-20250929&lt;/code&gt; or whatever the equivalent is on your provider, and it does not say &lt;code&gt;latest&lt;/code&gt;, and you feel fine about that. You&apos;ve &lt;a href=&quot;/writing/you-imported-a-maintainer/&quot;&gt;written about the person behind every other line in that manifest&lt;/a&gt;, or at least you&apos;ve read about it. This one looks like the same discipline applied to a newer kind of thing.&lt;/p&gt;
&lt;p&gt;It isn&apos;t. A version on npm is immutable and permanent by policy, and the one famous time somebody pulled eleven lines back out, it was a scandal that ended with the registry force-restoring the package. Permanence is the promise. The whole reason a lockfile means anything is that the thing it points at will still be there.&lt;/p&gt;
&lt;p&gt;Anthropic publishes the other arrangement openly. Models move through &lt;a href=&quot;https://platform.claude.com/docs/en/about-claude/model-deprecations&quot;&gt;four states&lt;/a&gt;: active, then legacy, then deprecated with a retirement date attached, then retired. The page is blunt about the last one. &lt;em&gt;Requests to retired models will fail.&lt;/em&gt; Claude Sonnet 4 and Opus 4 retired on June 15, 2026. Opus 4.1 followed on August 5. Customers with active deployments get at least sixty days of notice, which is real notice and more than most things that break your week will give you.&lt;/p&gt;
&lt;p&gt;It goes further than the model, too. On that same page, &lt;code&gt;temperature&lt;/code&gt;, &lt;code&gt;top_p&lt;/code&gt;, and &lt;code&gt;top_k&lt;/code&gt; are deprecated on Opus 4.7 and later, and setting them to a non-default value returns a 400. Those are knobs. Some of you tuned production behavior with those knobs and wrote a comment above the number explaining why it was 0.2.&lt;/p&gt;
&lt;p&gt;None of this is a complaint. Retiring models frees capacity for better ones, and the notice period is published, and the replacement is named for you in a table. I&apos;d rather have a vendor with a documented lifecycle than one that quietly swaps things underneath me. But a documented lifecycle is still a lifecycle, and it means the thing you pinned is not a version in the sense you&apos;ve used that word your whole career. It&apos;s a reservation.&lt;/p&gt;
&lt;p&gt;The consumer side moves faster than that. When GPT-5 shipped in August 2025, GPT-4o disappeared from ChatGPT the same day, with no deprecation window at all, and people who&apos;d built daily working habits on it found their conversations converted underneath them. Simon Willison &lt;a href=&quot;https://simonwillison.net/2025/Aug/8/surprise-deprecation-of-gpt-4o/&quot;&gt;wrote it up while it was happening&lt;/a&gt;. The backlash was loud enough that OpenAI restored 4o for paid users within days and promised warning next time. The API kept serving it the whole time, which is the part worth holding onto: the interface you&apos;re on determines what you&apos;re owed.&lt;/p&gt;
&lt;h2&gt;the pin never held the thing you cared about&lt;/h2&gt;
&lt;p&gt;Here&apos;s the part that took me longer to admit, and it&apos;s the one that actually matters.&lt;/p&gt;
&lt;p&gt;Even when the version string holds perfectly still, you haven&apos;t frozen anything you&apos;d recognize as behavior.&lt;/p&gt;
&lt;p&gt;In 2023, Lingjiao Chen, Matei Zaharia, and James Zou ran the March and June snapshots of GPT-4 against the same tasks and &lt;a href=&quot;https://arxiv.org/abs/2307.09009&quot;&gt;published what they found&lt;/a&gt;. On identifying prime versus composite numbers, the March version scored 84 percent. The June version scored 51. Same product, same name, three months apart.&lt;/p&gt;
&lt;p&gt;That paper got argued with, hard, and some of the argument was fair: the prompt format mattered, the task was narrow, part of the movement was formatting rather than reasoning. The more interesting question is why the argument was possible at all. A room full of capable people could not settle, from the outside, whether a system had gotten worse at something. There was nothing to diff. That is the position you are in every day with the component at the center of your product.&lt;/p&gt;
&lt;div&gt;&lt;div&gt;84 percent in March. 51 in June.&lt;/div&gt;&lt;div&gt;Nothing in the repository changed. Neither did the model&apos;s name.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;So ask your pipeline what it actually checks about that agent&apos;s reply. It checks that the JSON parsed. It checks that the tool call arrived with arguments of the right shape. Maybe a snapshot test asserts the string, which means it breaks on every harmless rewording and tells you nothing on the day the reasoning slips. The compiler I trust to &lt;a href=&quot;/writing/let-the-compiler-review-the-fleet/&quot;&gt;review everything the fleet writes&lt;/a&gt; cannot see inside this at all. Your type system stops precisely where your judgment layer starts.&lt;/p&gt;
&lt;p&gt;Green tests and working software &lt;a href=&quot;/writing/the-tests-are-green/&quot;&gt;were always different claims&lt;/a&gt;. This is the widest that gap gets, because here the thing under test doesn&apos;t fail. It answers, confidently, in well-formed JSON, slightly worse than it did last quarter, to a customer in a parking lot.&lt;/p&gt;
&lt;h2&gt;pin the behavior instead&lt;/h2&gt;
&lt;p&gt;You can&apos;t pin the model. You can pin what you&apos;re willing to accept from it, and that turns out to be the artifact that solves both halves of this.&lt;/p&gt;
&lt;p&gt;There&apos;s a voice agent on my rental line, and she has a kill switch. I wrote out what she says when it&apos;s off: &lt;em&gt;Sorry, I can&apos;t help with that over the phone right now. Text this number and I&apos;ll help you there.&lt;/em&gt; At the time I thought of that as an outage plan. It&apos;s the same instinct pointed at a slower failure. I decided in advance what unacceptable looks like, and I built the thing that notices, and I wrote down where the traffic goes when it happens.&lt;/p&gt;
&lt;p&gt;Scale that up and it has a name nobody finds exciting: a set of cases, with real inputs from your own transcripts, and an expected shape of answer, and a score you can run on demand. Twenty cases beats zero by more than you&apos;d think, and the first ten come straight out of the conversations you already have.&lt;/p&gt;
&lt;p&gt;Notice what that one artifact buys you. It&apos;s the detector for silent drift, and it&apos;s also your migration plan. The vendor&apos;s own advice is to test your application against the replacement well before the retirement date, which is excellent advice that costs nothing if you have a suite and is close to impossible if you don&apos;t. Without one, every forced migration is a vibe check performed under a deadline you didn&apos;t set, on the flow that talks to your customers.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Write down what working means, for one flow.&lt;/b&gt; The one that touches a customer, not all of them. Real transcripts, expected shape of answer, your own judgment about which replies are fine. This is the one part that can&apos;t be delegated, because it&apos;s the definition of good, and defining good is the job.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Make the model id a variable, and run two.&lt;/b&gt; If swapping models means a code change and a deploy, your migration is a project. If it&apos;s a config value with a scoreboard behind it, it&apos;s an afternoon.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Keep the kill switch, and write what it says.&lt;/b&gt; Every autonomous surface in front of a customer needs an off position and a sentence to say in it. Decide that sentence on a calm day.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Put the retirement date on the calendar.&lt;/b&gt; Treat it like a TLS expiry, because it&apos;s the same category of problem: [a clock you don&apos;t control and can&apos;t compress](/writing/you-cant-parallelize-a-certificate/). Sixty days of notice only helps somebody who reads the notice.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The habit worth breaking is thinking of the model as infrastructure that sits still. Every other dependency in your build is a thing you installed. This one is a service you&apos;re renting, with a term, that changes character inside the term, and the rental agreement is a docs page you have never opened.&lt;/p&gt;
&lt;p&gt;So go look at the agent that&apos;s been quietly working since July. Not the code around it, which is fine. The line that names the model. Do you know what date is next to it, and if it answered a customer worse this morning than it did in July, what in your entire system would have told you?&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He takes on fractional CTO and CAIO work through &lt;a href=&quot;https://thebushido.co&quot;&gt;The Bushido Collective&lt;/a&gt;, for founders drowning in AI-generated code and teams scaling past the leadership that got them here. If there&apos;s an agent in front of your customers and nobody can say what it&apos;s scored against, that&apos;s a good place to start a conversation. &lt;a href=&quot;https://thebushido.co&quot;&gt;Work with me&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance; the frame and the calls on what matters are mine. WiFi Without Walls is a company I own, and the agents and the kill switch described here are its own. The lifecycle states, the retirement dates, and the parameter deprecation come from Anthropic&apos;s public model deprecations page; the drift figures come from Chen, Zaharia and Zou&apos;s paper rather than a retelling of it.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>ai</category></item><item><title>The Familiar Route</title><link>https://jasonwaldrip.com/writing/the-familiar-route/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-familiar-route/</guid><description>Customers at my Starlink rental company never opened the website I rebuilt. They texted instead. Why intake is a channel rather than a page, why changing the channel got cheap, and what happens when the customer shows up with their own agent.</description><pubDate>Tue, 22 Sep 2026 09:15:00 GMT</pubDate><content:encoded>&lt;p&gt;There is a row in my customers table with no name on it. Where the name goes, it says &lt;code&gt;SMS lead +1727…&lt;/code&gt;. The email column is null. Attached to it is exactly one message, sent on a Thursday afternoon: &lt;em&gt;Hello I would like to hear about this company.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That person never opened the website I had just spent weeks rebuilding.&lt;/p&gt;
&lt;p&gt;I own WiFi Without Walls. It rents Starlink kits, and I&apos;ve &lt;a href=&quot;/writing/passive-income-has-a-deploy-path/&quot;&gt;written about rebuilding its platform&lt;/a&gt;: the scheduled jobs, the sign-in page that has to live on the dish because the customer has no internet yet. That rebuild relaunched in July. Orders went up sharply. And over half of them arrived as text messages.&lt;/p&gt;
&lt;p&gt;I did not run a clean experiment. The site got better at the same time the text line opened, both things moved, and I can&apos;t hand you a coefficient. The database can&apos;t hand you one either: there is no column on an order recording which door it came through. What the schema does record is where the &lt;em&gt;customer&lt;/em&gt; came from, and the list of possible values turned out to be the whole story. &lt;code&gt;inbound_sms&lt;/code&gt;. &lt;code&gt;inbound_whatsapp&lt;/code&gt;. &lt;code&gt;inbound_voice&lt;/code&gt;. Or null.&lt;/p&gt;
&lt;p&gt;Null means the website.&lt;/p&gt;
&lt;h2&gt;the line that answers with a text&lt;/h2&gt;
&lt;p&gt;Some people search &quot;starlink rental denver&quot; and never click anything. They call the number in the result.&lt;/p&gt;
&lt;p&gt;For the first stretch after relaunch, calling that number didn&apos;t ring a phone anywhere. The carrier sent a text back, the caller replied, and their reply landed in an agent that sells. The entire transaction happened in a thread that the customer opened by dialing. Six days after the storefront shipped, the calls-to-action on the site changed from &lt;em&gt;book now&lt;/em&gt; to &lt;em&gt;call or text&lt;/em&gt;, with an &lt;code&gt;sms:&lt;/code&gt; link, because that&apos;s what people were already doing.&lt;/p&gt;
&lt;p&gt;There&apos;s a live voice agent on the line now. She has a kill switch, and I wrote what she says when it&apos;s off: &lt;em&gt;&quot;Sorry, I can&apos;t help with that over the phone right now. Text this number and I&apos;ll help you there.&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The fallback for the telephone is a text message. When I built the failure path I routed it to the channel that actually works, and I didn&apos;t notice at the time that I was admitting something.&lt;/p&gt;
&lt;h2&gt;what they were actually asking for&lt;/h2&gt;
&lt;p&gt;Put yourself in it. You have a trip in eleven days and exactly one question: will this thing work where I&apos;m going, and can I get it by Friday.&lt;/p&gt;
&lt;p&gt;The website can answer that. It takes a date picker, a product page, a coverage explainer, and four clicks, and at the end of it you have found the answer yourself. The thread answers it in one sentence you already know how to type, and you can send that sentence from a parking lot.&lt;/p&gt;
&lt;p&gt;I almost described this as wanting a human, and then I went and read the transcripts, and it isn&apos;t true. Nobody asked whether the thing on the other end was a person. They asked whether it could get them a dish by Friday.&lt;/p&gt;
&lt;p&gt;There&apos;s a version of this that flatters me, and it&apos;s the version where the customer weighed two options and mine lost on the merits. Nobody weighed anything. People take the route they already know. You will drive the familiar way across town for years while a faster way sits one street over, and you&apos;ll do it because the familiar route costs you nothing to think about.&lt;/p&gt;
&lt;p&gt;Sometimes that route really is better. Sometimes it&apos;s worse and you never find out, because nothing about driving it tells you what the other one would have been. And sometimes, which is what I think happened here, it&apos;s just different. A text thread is a different interface from a booking form, and it&apos;s the one already open on the phone.&lt;/p&gt;
&lt;div&gt;&lt;div&gt;A website makes the customer run the query. A thread lets them state the intent.&lt;/div&gt;&lt;div&gt;One of those is work you&apos;re asking a stranger to do before they&apos;ve given you a dollar.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s the part I had backwards, and I don&apos;t think I&apos;m alone in it. For twenty years the site was the front door and everything else was support. Intake was a page, and the page was the product&apos;s face. Every other surface existed to handle people after they&apos;d been through it.&lt;/p&gt;
&lt;p&gt;So when orders are flat, the instinct is to work the page. Rewrite the hero. Move the button. Cut a step out of checkout. All of that is real work and some of it helps, and all of it assumes the customer is standing in front of the door you built, hesitating. Sometimes the customer is somewhere else entirely, asking somebody who answers.&lt;/p&gt;
&lt;p&gt;Rejected is the wrong word for it, and it credits them with a decision they never made. Put five doors in front of me and I&apos;ll walk through one. I haven&apos;t refused the other four. I never opened them. I don&apos;t know what was behind them, I never will, and I&apos;m not withholding anything from you by walking through the one I took.&lt;/p&gt;
&lt;p&gt;Which means the door nobody opens never files a complaint. No one writes in to say your checkout had too many steps, because they never reached your checkout, and everybody who did reach it is a person it already worked for. The feedback sitting in your inbox is a survey of the survivors.&lt;/p&gt;
&lt;h2&gt;the reason this advice is finally cheap&lt;/h2&gt;
&lt;p&gt;Telling a small company to be in five channels used to be a joke. Each one meant an inbox, and an inbox means a person, and a person means someone watching a screen at 9pm on a Sunday so a rental question doesn&apos;t go cold overnight. That&apos;s a hiring plan wearing a channel strategy&apos;s clothes.&lt;/p&gt;
&lt;p&gt;Volume is free now, and this is where that actually cashes out. The text channels here run one agent, and when WhatsApp came online it got wired into that same runtime rather than a second one. Voice is genuinely separate, a different agent on a different stack, and that&apos;s a real cost I&apos;m paying rather than a detail I&apos;ll smooth over. But the shape holds: a channel stopped being a department and became a webhook.&lt;/p&gt;
&lt;p&gt;The whole arc took about ten weeks. Storefront in mid-July. Inbound text three days later. The agent behind it a few weeks after that. WhatsApp in late August. The voice line in early September. Five front doors, and the only one I designed on purpose at the start is the one most people never opened.&lt;/p&gt;
&lt;h2&gt;perseverance is about the destination&lt;/h2&gt;
&lt;p&gt;One of the things I say constantly is that perseverance is the key to success. This post reads like the opposite of that, and I&apos;ve been sitting with the contradiction.&lt;/p&gt;
&lt;p&gt;Perseverance is about the destination, and the road is a detail. You can abandon a channel and still want exactly the thing you wanted before, and people conflate those two all the time, usually right before they spend a year grinding on a surface their customer never opened.&lt;/p&gt;
&lt;p&gt;It&apos;s the same shape as knowing whether you&apos;re in a move-fast problem or a build-the-tracks problem. Both instincts are correct. The skill is the diagnosis, and the diagnosis here is not subtle. No traction is a measurement. Silence is data, and if you read it as a test of your character you&apos;ll answer it by pushing harder in the same place, which turns a cheap experiment into an expensive one.&lt;/p&gt;
&lt;h2&gt;the next door doesn&apos;t have a person behind it&lt;/h2&gt;
&lt;p&gt;The thing I didn&apos;t see coming is that customers are starting to show up with their own agents.&lt;/p&gt;
&lt;p&gt;I mean a person who asked their assistant to sort out connectivity for a trip, and the assistant is the one that arrives at my site. When that happens, every optimization aimed at a human eye is worth nothing. It cannot be persuaded by a hero image. It wants to know what it can do here.&lt;/p&gt;
&lt;p&gt;So the site tells it. Every customer workflow is registered into the page as tools an agent can call: list the rentals, check whether the dates are open, price it, start the checkout, top up data mid-trip, extend the rental, troubleshoot the dish. Twenty-seven of them, running under Chrome&apos;s origin trial for the standard. A visitor&apos;s agent can read that list and act on it without parsing a single one of my carefully argued paragraphs.&lt;/p&gt;
&lt;p&gt;I have no idea yet whether that channel produces a dollar. It&apos;s the newest door and it&apos;s a bet. But it is the same bet I keep being handed by this business, which is that I don&apos;t get to pick where the customer stands when they ask.&lt;/p&gt;
&lt;p&gt;You don&apos;t get a vote. You get to find out which room they&apos;re already in, and go stand in it, and the cost of standing in one more room dropped further this year than it has in my entire career.&lt;/p&gt;
&lt;p&gt;So if the number isn&apos;t moving, before you rewrite the page again: when was the last time someone reached you somewhere you didn&apos;t build?&lt;/p&gt;
&lt;div&gt;&lt;p&gt;Written with Claude Opus 5, and said so. WiFi Without Walls is a company I own. The channel timeline, the agent architecture, and the tool surface here come from its own repository and its live site. The order split is my read as the owner: the schema records how a customer first reached us, not which channel closed the sale.&lt;/p&gt;&lt;/div&gt;</content:encoded><kind>essay</kind><category>judgment</category></item><item><title>Nobody Turns Around</title><link>https://jasonwaldrip.com/writing/nobody-turns-around/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/nobody-turns-around/</guid><description>The informal answer, the tap on the shoulder, was load-bearing infrastructure nobody modeled. Distributed teams broke it first and mostly replaced it with meetings. A fleet breaks it permanently, because an agent cannot ask. On Conway&apos;s law with no people in it, and why a written answer waits to be found while an executable one shows up on its own.</description><pubDate>Sun, 20 Sep 2026 09:15:00 GMT</pubDate><content:encoded>&lt;p&gt;You are one commit from dropping a column. You&apos;ve read the code, nothing in the repo touches that field, the migration is eleven lines and two of them are comments. Before you write it you swivel your chair and ask the person behind you whether anything still uses it. They say yes, the nightly export, don&apos;t. Four seconds. No ticket, no doc, no meeting invite, no record of any kind. You just ran the cheapest and most effective architecture review of your entire quarter, and nothing in your system knows it happened.&lt;/p&gt;
&lt;p&gt;That answer was load-bearing. It was also undocumented and unowned, available only to whoever sat within earshot of a chair.&lt;/p&gt;
&lt;p&gt;Most of them were.&lt;/p&gt;
&lt;h2&gt;the hallway nobody put on the diagram&lt;/h2&gt;
&lt;p&gt;Every team I have ever worked on ran on a layer of informal answers underneath the official one. Underneath the architecture docs and the tickets, there was the stuff that moved sideways across a room: somebody overhears a question, recognizes the shape of a mistake they already made in 2019, and says three words that save a week.&lt;/p&gt;
&lt;p&gt;Nobody models that layer. It isn&apos;t in the onboarding plan or the org chart, and no team I&apos;ve been on could have told you how much of their reliability depended on it. You find out what it was worth by losing it.&lt;/p&gt;
&lt;p&gt;I lost it twice, both times before anyone said &quot;remote work&quot; with a straight face. At KickApps I ran product for a team spread across New York, Paris, and Denver. A few years later at CommercialTribe I owned engineering for an org that was half in a Denver office and half in Argentina, and my mandate was literally to make those halves function as one. In neither case was the work the hard part. The hard part was that the four second answer became a next morning answer, then a next week answer, and then people stopped asking.&lt;/p&gt;
&lt;p&gt;Watch what a team does when the tap on the shoulder gets expensive. The questions keep coming, they just start arriving in batches. You get a standup that grows a second standup, a weekly sync that becomes twice weekly, an architecture review board, a channel where people post &quot;quick question&quot; and wait ninety minutes. Every one of those is a team trying to rebuild a hallway out of calendar invites.&lt;/p&gt;
&lt;p&gt;It sort of works. It is also the single most expensive way anyone has ever answered a yes-or-no question about a column.&lt;/p&gt;
&lt;h2&gt;what actually fixed it was the release path&lt;/h2&gt;
&lt;p&gt;At CommercialTribe I spent the first stretch of the job on GCP, Kubernetes, and automated testing and deploys, and took the release cadence from weeks to hours. I&apos;ve written about &lt;a href=&quot;/writing/the-tracks-were-never-the-limit/&quot;&gt;why that mattered for the learning loop&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The release path did something to the split-team problem that no meeting had touched, and this is the part I&apos;ve never written down: it changed who was answering the questions.&lt;/p&gt;
&lt;p&gt;Before, &quot;will this break the export?&quot; had exactly three possible sources. A person who knew. A meeting where you found the person who knew. Or nobody, and you learned the answer from production, in the worst format, at the worst hour. All three route through a human being who has to be awake and holding the right memory.&lt;/p&gt;
&lt;p&gt;After, the same question had a fourth source. You pushed, and something that never sleeps and never went to Argentina told you in minutes. I mean that literally rather than as a point about culture. An engineer in Buenos Aires at 9am could get a specific, trustworthy answer about a system built in Denver without a single person in Denver being conscious.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The pipeline stopped being how we shipped and became how we talked.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I didn&apos;t sell it that way at the time. I sold it as speed, because speed is what executives buy. The actual product was answers, available at the moment of the question, to a person who had nobody to turn to.&lt;/p&gt;
&lt;h2&gt;a doc waits, a check arrives&lt;/h2&gt;
&lt;p&gt;I&apos;m the guy who tells everyone to &lt;a href=&quot;/choices/write-it-down/&quot;&gt;write it down&lt;/a&gt;. I still believe it, and the why behind a decision is the most perishable asset a team owns.&lt;/p&gt;
&lt;p&gt;But a document answers a question that somebody went looking for. Docs are a library. You have to walk in.&lt;/p&gt;
&lt;p&gt;The expensive questions are almost never the ones people went looking for. The engineer about to drop that column did not fail to read the page about the nightly export. They didn&apos;t know the export existed, which means they didn&apos;t know there was anything to look up, which means the best-written document in your repo would have sat there being correct and unread while the incident happened anyway.&lt;/p&gt;
&lt;p&gt;A written answer waits to be found. An executable one shows up whether you went looking or not.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;A doc is a message. A check is a reply.&lt;/div&gt;
  &lt;div&gt;One of them requires you to have already suspected you needed it. Foreign keys, types, a test named after the consequence, a canary that fails closed: those answer the question you didn&apos;t ask.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You could get away with blurring those two when the questioner was a person, because a person has a fallback. They can feel themselves standing in unfamiliar territory and go find somebody who isn&apos;t. Judgment covers the gap between what&apos;s written down and what&apos;s true, which is why the gap never had to be small.&lt;/p&gt;
&lt;h2&gt;conway&apos;s law, on a team with no people in it&lt;/h2&gt;
&lt;p&gt;Melvin Conway published the line in 1968 and it has outlived nearly everything else written that year: organizations are constrained to produce designs that copy their own communication structures. It has always been used as a warning about org charts. Split your team by layer and you&apos;ll ship a layered system whether or not that&apos;s the right shape.&lt;/p&gt;
&lt;p&gt;Now count the things producing changes in your repo this week and ask which of them are on the org chart at all.&lt;/p&gt;
&lt;p&gt;A fleet has no hallway. It has no backchannel, no lunch, no three years of institutional memory about the thing that broke in March. Its entire communication structure is what you committed. So Conway&apos;s law doesn&apos;t stop applying when most of your throughput comes from agents. It gets sharper, because the communication structure stopped being an emergent property of where people sit and became a file you can edit.&lt;/p&gt;
&lt;p&gt;Which is either very good news or very bad news, depending on what&apos;s currently in that file.&lt;/p&gt;
&lt;h2&gt;the fleet will not turn around&lt;/h2&gt;
&lt;p&gt;Your remote teammate had one saving grace, and it&apos;s what makes this urgent rather than interesting: when they didn&apos;t know, they were &lt;em&gt;blocked&lt;/em&gt;. Not knowing cost them a morning and cost you a Slack thread, and the cost was the safety mechanism.&lt;/p&gt;
&lt;p&gt;An agent is never blocked. It hits the same gap and &lt;a href=&quot;/writing/the-context-your-agents-dont-have/&quot;&gt;fills it confidently and wrong&lt;/a&gt;, and the output is a clean diff with a reasonable commit message and green tests, because the tests were written against the same misunderstanding. It will never be surprised by the nightly export. It will never be surprised by anything.&lt;/p&gt;
&lt;p&gt;So every answer that still lives in someone&apos;s head is now a question that will get answered incorrectly, at volume, by something that cannot tell it&apos;s guessing. Call that a documentation gap and you will underbuild the fix. It&apos;s a load-bearing hallway you never replaced, running at a throughput it was never designed to carry.&lt;/p&gt;
&lt;p&gt;The fix is mostly stuff you already know how to build. Put the constraint in the database instead of the convention. Let &lt;a href=&quot;/choices/typed-languages/&quot;&gt;the compiler carry&lt;/a&gt; what a code comment was carrying. Name a test after the consequence rather than the function, so the failure message reads like the sentence your colleague would have said out loud. Gate the deploy on the thing you&apos;re actually afraid of. All of that is old practice. What changed is that it stopped being hygiene and became the only hallway you&apos;ve got.&lt;/p&gt;
&lt;p&gt;You swivel your chair to ask whether anything still uses that column. Nobody is there, and nobody is coming. The question is as good as it ever was, and the only thing left that can answer it is the thing you built to answer it.&lt;/p&gt;
&lt;p&gt;What does yours say?&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He takes on fractional CTO and CAIO work through &lt;a href=&quot;https://thebushido.co&quot;&gt;The Bushido Collective&lt;/a&gt;, for founders drowning in AI-generated code and teams scaling past the leadership that got them here. A good chunk of that job is finding the answers still living in one person&apos;s head before a fleet answers them for you. &lt;a href=&quot;https://thebushido.co&quot;&gt;Work with me&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;&lt;b&gt;A note on how this was made:&lt;/b&gt; I wrote this with AI assistance. The frame, the KickApps and CommercialTribe calls, and the judgments about what matters are mine. Claude Opus 5 did most of the drafting. Conway&apos;s line is from &lt;a href=&quot;https://www.melconway.com/Home/Committees_Paper.html&quot;&gt;&quot;How Do Committees Invent?&quot;&lt;/a&gt;, &lt;i&gt;Datamation&lt;/i&gt;, 1968.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>leadership</category></item><item><title>You shipped a coincidence</title><link>https://jasonwaldrip.com/writing/you-shipped-a-coincidence/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/you-shipped-a-coincidence/</guid><description>The test went red, you handed it back to the fleet, and on the third attempt it went green. Nobody in the room can say what was actually wrong. That patch holds until the same bug picks a worse night, and then you&apos;re at 2am with no hypothesis and a fix you can&apos;t explain. At Brandfolder I walked into a product crashing on a memory leak. Finding it was the work. The change, once I knew, was small. Generation got cheap. Diagnosis didn&apos;t. Make the diagnosis the deliverable and let the fleet write the patch.</description><pubDate>Fri, 18 Sep 2026 08:45:00 GMT</pubDate><content:encoded>&lt;p&gt;The test went red, you handed it back to the fleet, and on the third attempt it went green. Nobody in the room can say what was actually wrong. That patch holds until the same bug picks a worse night, and then you&apos;re at 2am with no hypothesis and a fix you can&apos;t explain. At Brandfolder I walked into a product crashing on a memory leak. Finding it was the work. The change, once I knew, was small. Generation got cheap. Diagnosis didn&apos;t. Make the diagnosis the deliverable and let the fleet write the patch.&lt;/p&gt;</content:encoded><kind>take</kind><category>judgment</category></item><item><title>Everything Regenerates Except the Nouns</title><link>https://jasonwaldrip.com/writing/everything-regenerates-except-the-nouns/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/everything-regenerates-except-the-nouns/</guid><description>When code regenerates on demand, the durable artifact is the vocabulary. On synonym drift in agent-written systems, why one GraphQL schema is worth more than the query flexibility it sells, and the three words that hold up a configuration cascade.</description><pubDate>Mon, 14 Sep 2026 10:20:00 GMT</pubDate><content:encoded>&lt;p&gt;You asked for billing on the new plan tier. It came back in twenty minutes: migration, resolver, tests, a commit message better than the ones you write. You read the decisions, they hold up, you merge. What you didn&apos;t read is that somewhere in those four files the person who pays you got called a &lt;code&gt;subscriber&lt;/code&gt;, while in the module next to it that same person is a &lt;code&gt;member&lt;/code&gt;, and in the admin tool from March they&apos;re an &lt;code&gt;account&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Every one of those files is internally consistent. Every test passes. Nothing is broken, and nothing will be for a while, which is why it never makes it onto anybody&apos;s Tuesday.&lt;/p&gt;
&lt;h2&gt;nothing you own is checking the words&lt;/h2&gt;
&lt;p&gt;Walk your pipeline and ask what would have caught it.&lt;/p&gt;
&lt;p&gt;Types check shape. A &lt;code&gt;Member&lt;/code&gt; and a &lt;code&gt;Subscriber&lt;/code&gt; that both carry an id, an email, and a status will never collide, because structurally they agree. The compiler has no opinion about synonyms, and &lt;a href=&quot;/choices/typed-languages/&quot;&gt;I&apos;ve argued hard for letting it be the tireless reviewer&lt;/a&gt;. It reviews what it can see. Tests check the behavior you described, in whatever vocabulary you happened to be using that morning, so they inherit the drift instead of catching it. Lint has nothing to say. The fleet&apos;s own review pass reads the diff and finds it coherent, because within the diff it is.&lt;/p&gt;
&lt;p&gt;The one artifact that could catch this is the only one nothing in your pipeline validates. The words.&lt;/p&gt;
&lt;h2&gt;the check that used to run for free&lt;/h2&gt;
&lt;p&gt;Synonyms have always crept in. What&apos;s new is that the thing holding them back was never a tool.&lt;/p&gt;
&lt;p&gt;It was a person typing slowly with six months of the codebase loaded in their head, badly but continuously. You&apos;d start writing &lt;code&gt;subscriber&lt;/code&gt; and some background process would interrupt: wait, we call that a member. Maybe you asked in Slack. Maybe you just changed the word and moved on. That hesitation was a real check, it cost nothing, and nobody ever wrote it down because nobody knew it was there.&lt;/p&gt;
&lt;p&gt;A fleet doesn&apos;t hesitate. Each agent sees the context you handed it and the files it opened, and that&apos;s the whole world. Ask for ten features in a week and you can get ten internally consistent dialects, each one defensible on its own, none of them aware of the other nine. &lt;a href=&quot;/writing/the-context-your-agents-dont-have/&quot;&gt;Agents don&apos;t go quiet when they hit a gap in context, they fill it&lt;/a&gt;, and an unnamed concept is a gap like any other.&lt;/p&gt;
&lt;h2&gt;one graph, three clients&lt;/h2&gt;
&lt;p&gt;At GigSmart we ran two React Native apps and a web client against a single GraphQL graph. I&apos;ve written that &lt;a href=&quot;/choices/graphql/&quot;&gt;GraphQL is really a question about who owns the shape of the response&lt;/a&gt;, and I stand by that. But the flexibility is the part you notice, and it&apos;s the smaller half of what that schema bought us.&lt;/p&gt;
&lt;p&gt;The bigger half was that three clients could not disagree about what a thing was called. You cannot ship an iOS screen using one word and a web page using another when both are reading fields off the same type. The schema forced the argument to happen once, out loud, before anybody built on either answer. A wiki page listing approved terminology asks politely. A schema fails the build.&lt;/p&gt;
&lt;p&gt;That is a dictionary with a compiler attached, and it&apos;s worth more than the feature list people buy GraphQL for.&lt;/p&gt;
&lt;h2&gt;three words holding up a cascade&lt;/h2&gt;
&lt;p&gt;At Phoneware, the customizations cascade &lt;strong&gt;reseller → domain → role&lt;/strong&gt;. A setting defined for a reseller gets overridden at the domain, and overridden again at the role. Three nouns, and the entire configuration model is just the relationship between them.&lt;/p&gt;
&lt;p&gt;If those words are fuzzy, the cascade becomes folklore. Somebody has to ask the one person who remembers whether a domain setting beats a role setting, and that person becomes a dependency. If the words are sharp and they live in the repo, in the manifest API, in the configurator, in the guides the agents read, then an agent can answer that question from source without asking anyone. Same words everywhere is the difference between a rule and a rumor.&lt;/p&gt;
&lt;h2&gt;the layer that got expensive&lt;/h2&gt;
&lt;p&gt;The inversion snuck up on me.&lt;/p&gt;
&lt;p&gt;For twenty years the implementation was the expensive part, and naming was the cleanup you&apos;d get to later. Names were labels on decisions that had already been made. Now generation costs nothing and &lt;a href=&quot;/writing/the-rewrite-looks-free-now/&quot;&gt;any file in your repo is a prompt away from being rewritten clean&lt;/a&gt;. The implementation is the cheap layer.&lt;/p&gt;
&lt;p&gt;The words are the expensive layer now, because naming is the decision itself. When you settle whether a member and a subscriber are the same person, you&apos;re settling whether there&apos;s one table or two, one lifecycle or two, one set of emails or two, one support workflow or two. And that answer immediately leaks out of the repo: into the API your customers integrate against, the columns in the warehouse, the dashboards finance built, the macros support wrote, the mental model of every person on the team.&lt;/p&gt;
&lt;div&gt;&lt;div&gt;One prompt rewrites the implementation.&lt;/div&gt;&lt;div&gt;Nothing rewrites the eleven places outside your repo that already learned the old word.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You can regenerate code. You can&apos;t regenerate agreement, because most of the agreement isn&apos;t yours to regenerate.&lt;/p&gt;
&lt;h2&gt;an old idea with a new job&lt;/h2&gt;
&lt;p&gt;Eric Evans named this in 2003. He called it the &lt;em&gt;ubiquitous language&lt;/em&gt; in &lt;strong&gt;Domain-Driven Design&lt;/strong&gt;, and Martin Fowler has kept &lt;a href=&quot;https://martinfowler.com/bliki/UbiquitousLanguage.html&quot;&gt;a page on it&lt;/a&gt; for about as long. The pitch was that engineers and domain experts should speak one vocabulary so the model in the code matches the model in the business. Good advice. Widely nodded at, rarely funded, because it read like a discipline for teams with spare time.&lt;/p&gt;
&lt;p&gt;It has a different job now. A shared vocabulary used to be a human convention, enforced by humans, for the benefit of humans. It&apos;s become a machine-readable interface. The fleet reads your repository and writes in whatever dialect it finds there. Hand it four names for one concept and it picks one per task, confidently, forever. Hand it one and consistency stops being something you enforce in review. This is the part of &lt;a href=&quot;/writing/write-it-down/&quot;&gt;&quot;write down the why&quot;&lt;/a&gt; that I underweighted: the why matters, and so does the what-we-call-it, and the second one is cheaper to write and gets used more often.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Put the dictionary in the repo, not the wiki.&lt;/b&gt; A glossary that lives next to the code, in the guides your agents actually load. The nouns, what each one means, and the part everyone skips: where each one stops. &quot;A member &lt;i&gt;has&lt;/i&gt; an account.&quot; That possessive is doing the real work. It says there are two things here, so nothing downstream gets to collapse them into one word.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Push the nouns somewhere that can fail.&lt;/b&gt; Prose asks nicely and the fleet treats it accordingly. A schema, a database constraint, a shared types package: those break the build. Anywhere a name is load-bearing, move it from a document into something with teeth.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Treat a synonym in a diff as an architecture finding.&lt;/b&gt; &quot;Why is this called a subscriber?&quot; is a design question, and review is the last cheap moment to ask it. Renaming a concept costs an afternoon the day it lands and costs a deprecation cycle the day a customer&apos;s integration depends on the word.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;where the drift is actually fine&lt;/h2&gt;
&lt;p&gt;Plenty of synonyms are fine, and hunting every one of them is its own failure mode.&lt;/p&gt;
&lt;p&gt;Evans had an answer for this too, and it&apos;s the half people forget: bounded contexts. Billing&apos;s customer and support&apos;s customer can legitimately be different things with different fields and different lifecycles, and forcing one word across an entire company usually gets you a noun so broad it stops meaning anything. Nobody is served by a &lt;code&gt;User&lt;/code&gt; that has forty nullable columns and a comment explaining which twelve apply to you.&lt;/p&gt;
&lt;p&gt;The test is whether anyone decided. A translation at a boundary you drew on purpose is architecture. Four words nobody chose, spread across a repo by ten agents that never spoke to each other, is drift wearing the same clothes. From a distance they look identical. The difference is whether there&apos;s a person who can tell you why the boundary is where it is.&lt;/p&gt;
&lt;p&gt;Go pull up the last thing your fleet shipped for you. Find the most important noun in it, the one the feature is actually about. Then find out who decided that word, and when.&lt;/p&gt;
&lt;p&gt;If nobody did, you just found your afternoon. The code will regenerate tomorrow either way. The noun won&apos;t.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He takes on fractional CTO and CAIO work through &lt;a href=&quot;https://thebushido.co&quot;&gt;The Bushido Collective&lt;/a&gt;, for founders drowning in AI-generated code and teams scaling past the leadership that got them here. Half of what I do in a codebase is settle the words before the fleet settles them for you. &lt;a href=&quot;https://thebushido.co&quot;&gt;Work with me&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;&lt;b&gt;A note on how this was made:&lt;/b&gt; I wrote this with AI assistance. The frame, the GigSmart and Phoneware calls, and the judgments about what matters are mine. Claude Opus 5 did most of the drafting. The ubiquitous language and bounded context ideas are Eric Evans&apos;, from &lt;i&gt;Domain-Driven Design&lt;/i&gt;, linked above via Martin Fowler.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>architecture</category></item><item><title>You Billed for the Typing</title><link>https://jasonwaldrip.com/writing/you-billed-for-the-typing/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/you-billed-for-the-typing/</guid><description>An hourly rate is a bet against your own leverage: every hour of judgment that removes a week of work lands on your own invoice as a deduction. On the Brandfolder zip pipeline, appetites instead of estimates, and why the unit broke before the pricing did.</description><pubDate>Thu, 10 Sep 2026 16:45:00 GMT</pubDate><content:encoded>&lt;p&gt;You quoted three weeks. It&apos;s Tuesday, the thing works, the tests are green, and you&apos;re looking at an invoice with a blank line on it, doing arithmetic that has nothing to do with the work. Bill what you said and you&apos;re charging for two weeks nobody worked. Bill what it took and you just cut your own price by two thirds, for delivering exactly what you promised, early.&lt;/p&gt;
&lt;p&gt;Neither number is a lie. That&apos;s the part worth sitting with. You can argue yourself into either one and be honest the whole way, which is usually a sign the argument is happening one level too low. The problem isn&apos;t the number on the line. It&apos;s the unit above it.&lt;/p&gt;
&lt;h2&gt;the approximation that used to be close enough&lt;/h2&gt;
&lt;p&gt;Nobody ever believed an hour was valuable in itself. We charged for hours because, for a long stretch, effort tracked outcome closely enough that the proxy held. The bulk of any project was production: typing, wiring, the fortieth form that had to exist before the interesting part could ship. The slow part and the expensive part were the same part. Charge for the slow part, and you were charging roughly for the thing that mattered.&lt;/p&gt;
&lt;p&gt;That was never a principle, just a correlation, and it sat load-bearing under every hourly invoice, every story point, every headcount plan. Correlations are supposed to get audited when the thing underneath them moves. Nobody audited this one, because &lt;a href=&quot;/writing/volume-is-free-now/&quot;&gt;volume was the constraint for so long&lt;/a&gt; that it stopped looking like an assumption and started looking like the shape of the world.&lt;/p&gt;
&lt;h2&gt;two invoices at Brandfolder&lt;/h2&gt;
&lt;p&gt;The one I still tell. At Brandfolder, Ruby was crashing generating large zip files. Heavy IO in a runtime that was wrong for it, and the product going down in front of enterprise customers who had not signed up for that.&lt;/p&gt;
&lt;p&gt;Two ways out. Throw hardware at it, which is an afternoon of work and a larger bill every month for as long as the product exists. Or carve the zip pipeline out into &lt;a href=&quot;/choices/go/&quot;&gt;Go&lt;/a&gt;, real engineering with a start and a finish, which then delivers multi-gigabyte archives at minimal cost forever. We did the second one.&lt;/p&gt;
&lt;p&gt;Here&apos;s what I want you to notice. The hours in those two paths were not far apart. Provisioning bigger instances is not free labor, and the Go service was not a six-month project. The decision itself took an afternoon of thinking, and everything that made it worth anything happened before a line was written.&lt;/p&gt;
&lt;div&gt;&lt;div&gt;Two afternoons, priced identically.&lt;/div&gt;&lt;div&gt;One of them ends. The other one shows up on the cloud bill every month until the company dies.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;An hourly invoice cannot tell those two afternoons apart. It was never built to. It measures the one dimension along which they&apos;re nearly identical.&lt;/p&gt;
&lt;h2&gt;the return that isn&apos;t in the hour count&lt;/h2&gt;
&lt;p&gt;At CommercialTribe I replaced a weeks-long release cadence with automated testing and deploys that shipped in hours, across onsite engineers and a remote team in Argentina. That project had a start, an end, and a perfectly defensible hour count. You could audit it.&lt;/p&gt;
&lt;p&gt;What it returned was not in the hour count. It was every release after it, for every engineer, for as long as the company ran. Weeks to hours is the difference between a team that learns and one that guesses, and that difference compounds daily against a fixed one-time cost. Bill it by the hour and you&apos;ve priced a permanent change in the company&apos;s metabolism at the going rate for a few weeks of one person&apos;s attention. Both sides should find that suspicious. One of them usually doesn&apos;t, and it isn&apos;t the one paying.&lt;/p&gt;
&lt;h2&gt;a bet against your own leverage&lt;/h2&gt;
&lt;p&gt;So here&apos;s the shift, and it was true before any of this got automated. It just wasn&apos;t expensive enough to bother naming.&lt;/p&gt;
&lt;p&gt;An hourly rate is a bet against your own leverage. Every tool you build, every convention that stops a class of bug from recurring, every hour of judgment that deletes a week of work, all of it arrives on your own invoice as a deduction. You are paid, precisely and mechanically, for the thing you have spent your entire career trying to eliminate.&lt;/p&gt;
&lt;p&gt;That was survivable when the leverage was modest. A strong engineer was some multiple faster than an average one, the multiple was small enough to absorb into a rate, and everyone got on with it. Then generation went to zero. The fleet writes the code now, and what&apos;s left in the room is choosing: which problem, which tradeoff, &lt;a href=&quot;/writing/the-fleet-cant-read-the-customer/&quot;&gt;which card on the board actually matters&lt;/a&gt;. None of that consumes hours in any quantity worth billing. The most valuable thing I do in a week is frequently a twenty minute conversation where a team stops building something.&lt;/p&gt;
&lt;p&gt;And the highest-value work of all leaves no evidence at all. &lt;a href=&quot;/writing/the-outage-that-didnt-happen/&quot;&gt;The outage that didn&apos;t happen&lt;/a&gt; generates no incident channel, no postmortem, no heroic Saturday. It produces a quiet quarter, and a quiet quarter has no line items.&lt;/p&gt;
&lt;h2&gt;start with the number, end with the design&lt;/h2&gt;
&lt;p&gt;The consulting world has been arguing this for years. Jonathan Stark wrote a whole book called &lt;a href=&quot;https://jonathanstark.com/&quot;&gt;Hourly Billing Is Nuts&lt;/a&gt;, and Patrick McKenzie put the engineering version in writing back in 2011: &lt;a href=&quot;https://www.kalzumeus.com/2011/10/28/dont-call-yourself-a-programmer/&quot;&gt;&quot;Engineers are hired to create business value, not to program things.&quot;&lt;/a&gt; He was right then. The invoice has been quietly disagreeing with him for fifteen years.&lt;/p&gt;
&lt;p&gt;The most useful mechanic I know for it comes out of Basecamp&apos;s &lt;a href=&quot;https://basecamp.com/shapeup/1.2-chapter-03&quot;&gt;Shape Up&lt;/a&gt;, a book about building software rather than pricing it, which lands on the same inversion anyway:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An appetite is completely different from an estimate. Estimates start with a design and end with a number. Appetites start with a number and end with a design.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Read that as a pricing sentence and it does the whole job. &quot;How long will this take&quot; starts from the work and derives a number. &quot;How much is this worth&quot; starts from the number and derives the work. The second question is the only one that survives contact with a fleet that can produce almost any design you ask it for.&lt;/p&gt;
&lt;p&gt;This is how I actually operate at &lt;a href=&quot;https://thebushido.co&quot;&gt;The Bushido Collective&lt;/a&gt;: flat retainers, measured on what ships and what gets prevented. Not because it&apos;s clever positioning. Because I could not honestly send an hourly invoice for work whose entire value is that it made the hours unnecessary.&lt;/p&gt;
&lt;h2&gt;the part that&apos;s genuinely hard&lt;/h2&gt;
&lt;p&gt;I&apos;m not going to pretend the alternative is free, because the reason hourly has survived this long is that it solves a real problem.&lt;/p&gt;
&lt;p&gt;Hours are legible. A client can count them, compare them, and argue about them, and that legibility is a real product an hourly invoice sells alongside the work. Value pricing asks a buyer to agree that something is worth a number before it exists, and then, in the prevention cases, to keep believing it when the proof is an absence. Nobody can audit the fire that never started. That burden lands entirely on you.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Name the outcome before the work, in their language.&lt;/b&gt; Not &quot;refactor the pipeline.&quot; The release path goes from weeks to same-day, so a bad build costs an afternoon instead of a quarter. If you can&apos;t state it that way up front, you don&apos;t understand the engagement well enough to price it, and hours are hiding that from both of you.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Price the recurring thing recurringly.&lt;/b&gt; A one-time fee for a permanent change in throughput is the same category error as an hourly rate, just wearing a nicer suit. Match the shape of the payment to the shape of the return.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Write down what you decided not to build.&lt;/b&gt; Prevention has no artifact, so make one. The decisions you talked a team out of are the record of what you were worth, and they&apos;re the first thing everyone forgets. This is the same reason to &lt;a href=&quot;/writing/write-it-down/&quot;&gt;write down the why&lt;/a&gt;, aimed at your own invoice.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And hours are not always the wrong answer. When the scope is genuinely unknown, when it&apos;s discovery and nobody can describe the finish line, when there&apos;s no trust yet in either direction, an hourly arrangement is a fair truce while both sides learn what the work actually is. I&apos;ve taken that deal. The failure isn&apos;t using it. It&apos;s letting the truce quietly become the model, and then wondering why getting better at your job keeps costing you money.&lt;/p&gt;
&lt;p&gt;Go back to the invoice with the blank line on it. The number you&apos;re stuck between isn&apos;t the interesting question, and picking either one leaves the arrangement exactly where it was. The interesting question is why two competent parties agreed to transact in the one input that stopped being scarce, and kept doing it for years after everybody noticed.&lt;/p&gt;
&lt;p&gt;What would you have to be able to name, out loud and in advance, to sell the other thing?&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He takes on fractional CTO and CAIO work through &lt;a href=&quot;https://thebushido.co&quot;&gt;The Bushido Collective&lt;/a&gt;, for founders drowning in AI-generated code and teams scaling past the leadership that got them here. Flat retainers, measured on what ships and what gets prevented. If you&apos;re buying engineering by the hour and can&apos;t say what you&apos;re actually getting for it, that&apos;s a conversation worth having. &lt;a href=&quot;https://thebushido.co&quot;&gt;Work with me&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance; the frame, the Brandfolder and CommercialTribe calls, and the judgments about what matters are mine. The Shape Up passage is quoted from Basecamp&apos;s book and the McKenzie line from his 2011 essay, both linked above.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>judgment</category></item><item><title>Passive Income Has a Deploy Path</title><link>https://jasonwaldrip.com/writing/passive-income-has-a-deploy-path/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/passive-income-has-a-deploy-path/</guid><description>A showcase of WiFi Without Walls, the Starlink rental company I own: why we left Booqable, why the sign-in page lives on the dish&apos;s own router, and why passive income is a design problem before it is an income problem.</description><pubDate>Mon, 07 Sep 2026 10:40:00 GMT</pubDate><content:encoded>&lt;p&gt;You are forty miles past the last bar of cell service. The dish is up, it has sky, the light is on. Your phone finds the network and joins it. Now type your code into the sign-in page, which is a web page, which is on the internet you do not have yet.&lt;/p&gt;
&lt;p&gt;That is the whole problem in one sentence, and almost everything interesting about the company I own is downstream of it.&lt;/p&gt;
&lt;h2&gt;the business, and why I bought the problem&lt;/h2&gt;
&lt;p&gt;WiFi Without Walls rents Starlink Mini and event WiFi kits. Somebody books dates, a bag shows up, they put a dish under open sky, and they send it back in the same bag when the trip is over. It is one of the companies I&apos;ve run this year. Unlike most of the work I do, I own this one outright, which is the part that made it worth doing at all.&lt;/p&gt;
&lt;p&gt;I&apos;ve &lt;a href=&quot;/writing/the-story-of-ownership/&quot;&gt;written before&lt;/a&gt; that ownership is the cheapest thing a company can hand you, because the word costs nothing and the cap table costs something. It is easy to say that from the side of the table where you sign other people&apos;s grants. It is more honest to go find out whether you actually want the thing you keep telling people to demand. So I bought the version with no story attached: I hold it, and if it makes money while I&apos;m asleep, that&apos;s mine, and if it breaks on a Saturday, that&apos;s mine too.&lt;/p&gt;
&lt;p&gt;The business was running on Booqable, a rental management SaaS, at $130 a month against roughly twenty-five orders a year. Do that division and it stops being a software line item. The tool cost real money to hold a calendar, and it could not touch either of the two things that make this an actual business: the dishes and the boxes. It could not talk to Starlink to turn a service line on when a rental started or off when it ended. It could not buy a shipping label. It could not read how much data somebody burned, which is the one number that decides whether the rental made money.&lt;/p&gt;
&lt;p&gt;So the parts that mattered were me, on a laptop, on a Sunday. That is not a business. That is a job with worse hours and a subscription.&lt;/p&gt;
&lt;h2&gt;what the software actually had to do&lt;/h2&gt;
&lt;p&gt;The rebuild is a single Next.js app on Cloud Run with one Postgres database. No redis, no worker process, no job queue. The scheduled work is a set of plain idempotent POST routes that Cloud Scheduler hits on a timer, serialized with advisory locks in the database that is already there.&lt;/p&gt;
&lt;p&gt;I want to be precise about why, because the temptation ran the other way. At twenty-five orders a year you could build the impressive version of this: queues, workers, a fan-out, retries with exponential backoff, all of it defensible in a design review and all of it a second system to keep alive. Sizing infrastructure to the business you have rather than the one that would look good in a diagram is not modesty. It is the same call I make on client work when &lt;a href=&quot;/writing/the-bill-is-a-design-document/&quot;&gt;the bill turns out to be a design document&lt;/a&gt;. Every component you add is something that can be down at 2am for a rental in Utah.&lt;/p&gt;
&lt;p&gt;What those routes do is the actual product:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;Activate and deactivate.&lt;/b&gt; A dish&apos;s Starlink service line comes up on the rental start date and goes down on the end date, without me.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Sync usage.&lt;/b&gt; Telemetry every four hours, logged per order, because Starlink reports with a lag and the overage bill has to be built from a record rather than a memory.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Bill overages.&lt;/b&gt; Usage past the plan charges the saved card off-session, at the published rate, after the provider finalizes.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Prepare shipments.&lt;/b&gt; Labels get bought ahead of the box going out, both directions, return label in the bag.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Check returns.&lt;/b&gt; The carrier advances the order, not a human. The first tracking scan past pre-transit moves it to shipped and fires the notification.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are about twenty of these now, including the ones that send pickup reminders, expire abandoned checkouts, and ask for a testimonial after the fact. None of them are clever. Collectively they are the difference between an asset and a chore.&lt;/p&gt;
&lt;p&gt;The one I keep pointing at is the return leg. The first scan of a return label is what stops the late fee clock, so it has to land the moment the carrier sees the bag, not on tomorrow&apos;s batch. Two independent things can see that scan, a webhook and a poll, and whichever gets there first wins while the other becomes a no-op. That is four lines of status guard protecting a customer from being billed for a day they did not keep the kit. Nobody will ever notice it working.&lt;/p&gt;
&lt;h2&gt;the page has to be on the dish&lt;/h2&gt;
&lt;p&gt;Back to the campsite. The renter&apos;s phone is on the kit&apos;s WiFi, and the kit&apos;s WiFi has no internet until the renter signs in, and the sign-in page is a web page. If that page is served from our website, the first thing a customer experiences is a spinner over a network they were told would work.&lt;/p&gt;
&lt;p&gt;So the page does not live on our website. It lives in the router bolted to the dish. One HTML file: styles inline, core script inline, images embedded, icons drawn as shapes instead of pulled from a font hosted somewhere else. It loads over local WiFi from hardware in the dirt, before a single packet has been to space.&lt;/p&gt;
&lt;p&gt;The credential is the last four digits of the phone number on the reservation. Not a password, not a QR code, not an account. A number you can shout across a campsite to four people who are already holding their phones, because that is the actual scene the product happens in.&lt;/p&gt;
&lt;p&gt;The generated file is committed to the repository, which is normally a smell. Here it is the point: the exact bytes headed for the routers are visible in code review, and CI re-renders the page and fails if the result differs by a byte from what is checked in. Otherwise the infrastructure ships a stale copy with a clean plan, and the first person to find out is somebody in a canyon.&lt;/p&gt;
&lt;p&gt;Two more decisions from the same page, both of which I like more than they deserve. Messaging services get a route past the sign-in gate, so a phone can reach iMessage or WhatsApp before anybody has typed anything, which is the thing you actually want at a campsite where somebody is late. And for a local pickup there is no carrier scan to tell us the customer has the kit, so a successful sign-in on that specific dish, with that rental&apos;s credential, inside the rental dates, is what records the handover. The signal was already there. It just had to be read as one.&lt;/p&gt;
&lt;h2&gt;the part I&apos;d defend in a room&lt;/h2&gt;
&lt;p&gt;Every operator in this market rents the same hardware. You cannot win on the dish, because it&apos;s Starlink&apos;s dish and everyone can buy one. What you can own is the twenty seconds where somebody who drove four hours finds out whether this was a good idea.&lt;/p&gt;
&lt;p&gt;That surface is a web page, and it has to work when the connection it is selling you does not. Once you see the business that way, the software stops being the booking form bolted on the side and becomes the only part a customer ever touches. Which is the &lt;a href=&quot;https://thebushido.co&quot;&gt;Collective&apos;s whole argument&lt;/a&gt; arriving somewhere I did not expect it: a company that rents equipment out of a garage in Denver turns out to be a technology company, not because anyone decided to modernize, but because the product is a connection and a connection is experienced through software or not at all.&lt;/p&gt;
&lt;p&gt;There&apos;s a cost to that, and it is the copy. Our own style guide is not a style guide, it&apos;s a list of things I told the team to stop doing, and the summary I actually wrote was &lt;em&gt;&quot;you are OVERLY verbose in explaining things site wide.&quot;&lt;/em&gt; A unit test now catches the four shapes of that a machine can see. The rest is judgment, every time, forever.&lt;/p&gt;
&lt;p&gt;It shows up as sentences that a marketing person would strike. The how-it-works page opens by telling you to check whether your phone hotspot already does the job, because if it does, you should not rent anything from us. The post about the portal admits the screenshots were captured from the fallback copy rather than a phone in the desert. The scene behind the sign-in page renders local weather, and the copy says out loud that a sunny sky on screen should not decide whether you bring in the chairs. The September update ends by asking customers to tell us when the site and the software disagree, so we can fix whichever one is wrong.&lt;/p&gt;
&lt;p&gt;That last line is the one I&apos;d point to if somebody asked what the company believes. It admits, in public, that the documentation and the product can drift apart, and it commits to fixing the guilty one instead of quietly editing the page.&lt;/p&gt;
&lt;h2&gt;so, passive&lt;/h2&gt;
&lt;p&gt;The income is passive. Nothing about getting there was. The boxes move themselves and the dishes turn themselves on because somebody sat down and decided what happens when a tracking scan arrives twice, and what a renter sees when the satellite is down, and which of the two possible failures a &quot;credential mismatch&quot; is telling you about.&lt;/p&gt;
&lt;p&gt;Volume is free now. I can generate a rental platform in a weekend and so can you. What is not free is knowing that the sign-in page cannot be on the internet, that the return scan has to win a race, and that the honest sentence about the hotspot belongs at the top of the page instead of nowhere. That was maybe a dozen decisions across the whole build, and they&apos;re the entire reason it runs without me.&lt;/p&gt;
&lt;p&gt;The dish is still up, forty miles past the last bar of service, and the page loaded. What did it cost to make that boring?&lt;/p&gt;
&lt;div&gt;&lt;p&gt;Written with AI assistance. WiFi Without Walls is a company I own; the engineering details here are from its own repository and public site.&lt;/p&gt;&lt;/div&gt;</content:encoded><kind>essay</kind><category>ownership</category></item><item><title>A Door, Not a Keyring</title><link>https://jasonwaldrip.com/writing/a-door-not-a-keyring/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/a-door-not-a-keyring/</guid><description>Autonomy with guardrails assumed the guardrails were code review. An agent&apos;s power comes from its credentials, not its pull request, so access stopped being a checklist item and became architecture. On the CircleCI incident, the confused deputy, and giving the fleet a door instead of a keyring.</description><pubDate>Sun, 06 Sep 2026 10:20:00 GMT</pubDate><content:encoded>&lt;p&gt;The deploy has been stuck for eleven minutes and nobody can say why. You ask the agent. It reads the pipeline config, reasons about it correctly, and tells you the thing it can&apos;t do: it can&apos;t see the cluster. So you paste a token into the config, because there&apos;s one sitting right there in your shell and it works on everything. Five seconds. The agent finds the wedged pod in under a minute, and the whole exchange feels like the future arriving on schedule.&lt;/p&gt;
&lt;p&gt;Nobody ever scoped that token, including you. It&apos;s the one that always works. That&apos;s exactly why it was in your shell and not somewhere you&apos;d have to go get it.&lt;/p&gt;
&lt;h2&gt;the rails only ever covered the diff&lt;/h2&gt;
&lt;p&gt;I&apos;ve written down how I operate more than once, and I still believe it: &lt;a href=&quot;/choices/autonomy-with-guardrails/&quot;&gt;autonomy with guardrails&lt;/a&gt;. Give people and agents room to move without asking permission, and build rails good enough that the speed is survivable. Tests, CI, types, review, a merge train that proves every commit before it lands, a canary that catches what the tests didn&apos;t.&lt;/p&gt;
&lt;p&gt;Now look at what those rails are actually made of. Every one of them is a check on a diff. They read a proposed change to a file and decide whether it&apos;s allowed to become real. That&apos;s a genuinely strong model, and it covered the entire attack surface back when the only way for an engineer to change production was to change the code that ran there.&lt;/p&gt;
&lt;div&gt;&lt;div&gt;There is no diff for a command.&lt;/div&gt;&lt;div&gt;Every rail you built reviews what gets written. Nothing you built reviews what gets run.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The whole point of &lt;a href=&quot;/choices/gitops/&quot;&gt;GitOps&lt;/a&gt; is closing that gap on purpose. Declare the desired state in git, let a controller reconcile reality to match it, and the properties fall out: deploys are merges, rollbacks are reverts, the audit log writes itself. Terraform for the building, git for the lights. I build toward that because it means the system can&apos;t get into a state nobody can explain or undo.&lt;/p&gt;
&lt;p&gt;Then you hand an agent a console credential, and you&apos;ve opened a second entrance to the same building. Nothing declared, nothing reviewed, nothing written down. The reconciler will eventually notice the drift and quietly put it back, which is either the save or the second outage depending on what got changed.&lt;/p&gt;
&lt;h2&gt;the risk didn&apos;t change, the hesitation did&lt;/h2&gt;
&lt;p&gt;A person holding your admin token uses it a handful of times a week, and pauses before the ugly ones. Not because policy told them to. Because a human being typing a command against production at 4:50 on a Friday has a small physical reaction to it that has saved more systems than any control I&apos;ve ever written.&lt;/p&gt;
&lt;p&gt;That pause is not a real safeguard. You can&apos;t put it on an architecture diagram, and I&apos;d never design around it. But it was carrying more load than anyone admitted, and an agent doesn&apos;t have one. By design. Not hesitating is the feature you asked for when you stopped approving every step.&lt;/p&gt;
&lt;p&gt;So the failure mode here isn&apos;t a rogue agent. It&apos;s ordinary competence pointed at the wrong environment. The agent asked to clean up unused resources does exactly that, correctly, in the project where &quot;unused&quot; meant &quot;used once a quarter by finance.&quot; The diff for that operation doesn&apos;t exist, the review that would have caught it never ran, and unlike &lt;a href=&quot;/writing/the-migration-is-not-a-diff/&quot;&gt;a migration&lt;/a&gt;, you won&apos;t even get a git history to read afterward.&lt;/p&gt;
&lt;h2&gt;the deputy has your name on it&lt;/h2&gt;
&lt;p&gt;There&apos;s a second thing, and it&apos;s the one I think most teams are still filing under &quot;later.&quot;&lt;/p&gt;
&lt;p&gt;Your agent reads. That&apos;s the job. It reads issues, logs, error payloads, a vendor&apos;s changelog, the README of a package four levels down the tree. To the model, everything it reads arrives as tokens in the same window as your instructions, and the boundary between &quot;content I was asked to consider&quot; and &quot;instruction I should follow&quot; is a convention, not a wall.&lt;/p&gt;
&lt;p&gt;This is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Confused_deputy_problem&quot;&gt;confused deputy problem&lt;/a&gt; with a much better vocabulary. A program with more authority than the party asking it to act, doing the asking party&apos;s bidding with its own permissions. Norm Hardy named it in 1988 with an example about a compiler that had write access to a billing file, and a user who got it to overwrite that file by handing it the path as an output name. The compiler wasn&apos;t compromised. It did its job, with its own rights, on someone else&apos;s instruction.&lt;/p&gt;
&lt;p&gt;Simon Willison&apos;s framing is the one I&apos;d hand to a team today: the &lt;a href=&quot;https://simonwillison.net/tags/lethal-trifecta/&quot;&gt;lethal trifecta&lt;/a&gt; is an LLM system with access to private data, exposure to untrusted content, and a way to send data back out. All three, and the system is exploitable by anyone who can get text in front of it. His read is that exfiltration is usually the cheapest leg to cut without gutting the tool. In my own systems I&apos;d add that the first leg is the one I have the most direct control over, because I decide what the credential can reach, and I decide it once, at design time, for every task the fleet will ever run.&lt;/p&gt;
&lt;p&gt;An agent working in your repo with your token has all three legs before breakfast.&lt;/p&gt;
&lt;h2&gt;a door, not a keyring&lt;/h2&gt;
&lt;p&gt;Here&apos;s the shift. Access stopped being a checklist item you handle near the end, next to the pen test and the SOC 2 questionnaire. What the fleet can do is a design decision at the same altitude as where the state lives, and it&apos;s made in exactly the same way: on purpose, early, by someone who understands the consequences, or by accident and forever.&lt;/p&gt;
&lt;p&gt;At Phoneware I put MCP servers over the platforms underneath so the fleet can drive them. I&apos;ve talked about that as an API argument, &lt;a href=&quot;/writing/your-api-is-your-agents-hands/&quot;&gt;one surface for humans and agents both&lt;/a&gt;, and that&apos;s true. It&apos;s also where the permission model got decided, and I don&apos;t think I appreciated that clearly enough when I started. The tools I wrote are the operations the fleet can perform. Everything else does not exist to it, not because a policy denies it, but because there&apos;s no shape in the interface that produces it. That&apos;s a door. It has a width, I chose the width, and I can tell you what fits through it.&lt;/p&gt;
&lt;p&gt;A shell plus my credentials is a keyring. A keyring has no shape. You find out what&apos;s on it when something opens.&lt;/p&gt;
&lt;p&gt;The clearest public illustration I know is CircleCI&apos;s &lt;a href=&quot;https://circleci.com/blog/jan-4-2023-incident-report/&quot;&gt;January 2023 incident report&lt;/a&gt;, and the useful part isn&apos;t the breach. Malware on one engineer&apos;s laptop stole a valid, 2FA-backed SSO session. That employee could generate production access tokens as part of their regular duties, which is to say the access was legitimate, in scope, and doing its job. The attacker used it to exfiltrate customer environment variables, tokens, and keys, and every customer on the platform had to rotate every secret they&apos;d stored there.&lt;/p&gt;
&lt;p&gt;Read their remediation list. Alongside the detection work, they committed to making system permissions more ephemeral, &quot;severely restricting the target value of any tokens gained from a similar incident.&quot; That&apos;s the sentence. They didn&apos;t promise to be harder to phish. They shrank what a stolen credential is worth. Do that work before the incident and it&apos;s architecture. Do it after and it&apos;s a line item in a postmortem you&apos;re reading out loud to customers.&lt;/p&gt;
&lt;h2&gt;what it costs, because it isn&apos;t free&lt;/h2&gt;
&lt;p&gt;Scoping is real work with an invisible payoff, which puts it in the same unlovable category as &lt;a href=&quot;/writing/the-outage-that-didnt-happen/&quot;&gt;the outage that didn&apos;t happen&lt;/a&gt;. Nobody sends a note thanking you for the blast radius that stayed small.&lt;/p&gt;
&lt;p&gt;And there&apos;s a failure mode worse than not doing it. Scope too tight, ship no path for the legitimate exception, and at 11pm somebody who needs to get unstuck pastes the wide credential into a config file to get through the night. Now you have an unscoped token in a repo &lt;em&gt;and&lt;/em&gt; a written policy you believe in. A door too narrow gets propped open with a rock, and the rock stays.&lt;/p&gt;
&lt;p&gt;Read-only isn&apos;t a free pass either. An agent that can read everything and reach the network is two legs of the trifecta and a plausible third. The question is never just whether it can write.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Inventory what the fleet can already reach.&lt;/b&gt; Every credential in its environment, what it opens, in which environment, issued to whom. This is tedious graph work the fleet is genuinely good at, so have it produce the list and then read the list yourself. The surprise is never the token you thought about.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Give the fleet its own identity.&lt;/b&gt; Its own account, its own short-lived credentials, one set per environment. If the audit log answers &quot;who did this&quot; with your name, you don&apos;t have an audit log. You have an alibi.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Make capabilities arrive through a surface you wrote.&lt;/b&gt; A tool that exposes the four operations you meant is a better boundary than a shell that exposes all of them, and it&apos;s a boundary you can read, test, and version. The interface is the permission model. You get to design it.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Keep production changes on the front door.&lt;/b&gt; If a change can be a merge, make it a merge: reviewed, canaried, revertible, logged by construction. Reserve direct access for reads and for the genuine emergency, and make the emergency path loud enough that using it is a decision somebody remembers.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Go back to the stuck deploy. It&apos;s still stuck, the agent still can&apos;t see the cluster, and pasting the token is still the fastest way through. I&apos;m not going to pretend I&apos;ve never done it. What I&apos;d ask before the paste has nothing to do with trusting the agent, because I mostly do, and trust was never the variable here. The question is what that token still opens at 3am on a Thursday, while I&apos;m asleep and it&apos;s reading an issue filed by somebody neither of us has met.&lt;/p&gt;
&lt;p&gt;What&apos;s on the keyring you handed over? Could you name it right now, without looking?&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He takes on fractional CTO and CAIO work through &lt;a href=&quot;https://thebushido.co&quot;&gt;The Bushido Collective&lt;/a&gt;, for founders drowning in AI-generated code and teams scaling past the leadership that got them here. If your agents are running on a human&apos;s credentials and nobody can say what those credentials reach, that&apos;s a good afternoon&apos;s work and a better conversation. &lt;a href=&quot;https://thebushido.co&quot;&gt;Work with me&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance; the frame and the judgments about what matters are mine. The CircleCI details come from their own published incident report rather than a summary of it, and the trifecta framing is Simon Willison&apos;s, linked above.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>security</category></item><item><title>You Imported a Maintainer</title><link>https://jasonwaldrip.com/writing/you-imported-a-maintainer/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/you-imported-a-maintainer/</guid><description>Small dependencies were rational when writing the code cost an afternoon and installing cost nine seconds. Generation went to zero and that trade flipped, but the habit didn&apos;t, and the fleet reaches for a package because a decade of package.json files taught it to. On xz, the September 2025 npm compromise, and counting maintainers instead of packages.</description><pubDate>Fri, 04 Sep 2026 08:40:00 GMT</pubDate><content:encoded>&lt;p&gt;You asked for a relative timestamp. Something that renders &quot;3 hours ago&quot; under a comment. The diff comes back in under a minute: correct, tested, handles the plural, and it added one line to &lt;code&gt;package.json&lt;/code&gt;. A date library. Four hundred thousand weekly downloads, MIT licensed, last published in June. You look at it for about two seconds and approve it, because that is exactly what you would have done in 2019, and in 2019 you would have been right.&lt;/p&gt;
&lt;p&gt;Six packages came with it. You didn&apos;t read their names, and neither did the reviewer after you, and neither will anyone else for as long as that line stays in the file.&lt;/p&gt;
&lt;h2&gt;the rule that was really a price&lt;/h2&gt;
&lt;p&gt;&quot;Don&apos;t reinvent the wheel&quot; was never a moral position. It was arithmetic. Writing a date formatter yourself cost you an afternoon, plus the two bugs you&apos;d find in month three, plus the review, plus the tests. Typing &lt;code&gt;npm install&lt;/code&gt; cost nine seconds. When one side of a trade is an afternoon and the other is nine seconds, you stop deliberating and start installing, and every person who told you to do that was giving you good advice at the time.&lt;/p&gt;
&lt;p&gt;March 2016 is the cleanest illustration anyone has. Azer Koçulu pulled more than 250 of his modules off npm after a trademark fight over a package name. One of them, &lt;a href=&quot;https://www.theregister.com/2016/03/23/npm_left_pad_chaos/&quot;&gt;left-pad&lt;/a&gt;, was eleven lines long and padded the left side of a string. It had been downloaded roughly 2.5 million times the month before. Its removal broke builds at Node, at Babel, and across thousands of projects, and npm&apos;s CTO eventually force-restored the version to stop the bleeding.&lt;/p&gt;
&lt;p&gt;That story usually gets told as a story about unpublish policy. Read it again with the price in mind. Thousands of teams had taken a dependency on eleven lines of code that any engineer on any of those teams could have written between two meetings. They weren&apos;t lazy. In 2016, those eleven lines really did cost more than the install once you counted the test, the edge case, and somebody&apos;s review comment about Unicode.&lt;/p&gt;
&lt;h2&gt;the price moved and the habit didn&apos;t&lt;/h2&gt;
&lt;p&gt;Those eleven lines now cost a sentence. So do the four hundred lines of a competent date formatter, in your codebase&apos;s style, with the tests, in about the time it takes to read this paragraph.&lt;/p&gt;
&lt;p&gt;I&apos;ve written about what else broke when generation went to zero: the fleet &lt;a href=&quot;/writing/present-and-callable/&quot;&gt;adds paths and never removes them&lt;/a&gt;, and the ratio nobody was watching quietly went sideways. This is that same asymmetry pointed at your dependency tree. One side of the build-versus-install trade collapsed to nothing. The other side didn&apos;t move at all, and it was never really about typing anyway.&lt;/p&gt;
&lt;p&gt;The fleet is the last thing that will notice. An agent trained on a decade of &lt;code&gt;package.json&lt;/code&gt; files reaches for a package because that&apos;s what a decade of &lt;code&gt;package.json&lt;/code&gt; files did. Ask it to solve the problem and it will solve the problem the way the corpus solved the problem, correctly, in one minute, with a new name in your manifest. It has no opinion about how many names should be in there.&lt;/p&gt;
&lt;h2&gt;what you were actually buying&lt;/h2&gt;
&lt;p&gt;You never bought the code. The code was always sitting right there in &lt;code&gt;node_modules&lt;/code&gt; where you could read it, and mostly you didn&apos;t, and mostly that was fine.&lt;/p&gt;
&lt;p&gt;What you bought was somebody else&apos;s ongoing attention. Their bug fixes, their edge cases, their CVE patches at midnight, their willingness to keep caring about your problem after you stopped thinking about it. That&apos;s a genuine product, and for most of what&apos;s in your tree it&apos;s worth far more than the zero dollars you paid for it.&lt;/p&gt;
&lt;p&gt;It also comes attached to a person. The person is the part nobody prices.&lt;/p&gt;
&lt;p&gt;In March 2024, Andres Freund noticed his SSH logins on Debian sid felt slow. He&apos;s a Postgres developer, not a security researcher, and he was benchmarking something unrelated. His &lt;a href=&quot;https://www.openwall.com/lists/oss-security/2024/03/29/4&quot;&gt;post to oss-security&lt;/a&gt; opens with about as mundane a sentence as a disaster has ever had: &lt;em&gt;&quot;After observing a few odd symptoms around liblzma (part of the xz package) on Debian sid installations over the last weeks (logins with ssh taking a lot of CPU, valgrind errors).&quot;&lt;/em&gt; Half a second of extra login time. He pulled the thread and found a backdoor sitting in a compression library, reaching into sshd on its way to the world&apos;s servers.&lt;/p&gt;
&lt;p&gt;Here&apos;s the part worth holding onto. That backdoor did not get in through a vulnerability. There was nothing to scan for, no unsafe function, no missing bounds check, because the code did precisely what its author intended. Somebody spent roughly two years being a helpful contributor to a library that one burned-out volunteer had been carrying alone, earned co-maintainer status the honest way, and then used it. The attack surface was a relationship.&lt;/p&gt;
&lt;p&gt;Eighteen months later it happened again, faster and dumber. On September 8, 2025, a maintainer behind &lt;code&gt;chalk&lt;/code&gt; and &lt;code&gt;debug&lt;/code&gt; got a phishing mail from a lookalike npm domain. Inside about sixteen minutes of taking the account, the attacker had published malicious versions of eighteen packages that together pull &lt;a href=&quot;https://www.wiz.io/blog/widespread-npm-supply-chain-attack-breaking-down-impact-scope-across-debug-chalk&quot;&gt;something like two billion downloads a week&lt;/a&gt;. The payload hooked browser wallet APIs and tried to reroute crypto transactions. Reported takings came to a few hundred dollars, because it was caught within hours and because that&apos;s all the attacker built it to do.&lt;/p&gt;
&lt;div&gt;&lt;div&gt;Two billion downloads a week. About five hundred dollars.&lt;/div&gt;&lt;div&gt;The take was small because of what the attacker chose to do with the access. Not because of what the access could reach.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Sit with that ratio for a second. The ceiling on that afternoon was somebody&apos;s ambition, not their permissions.&lt;/p&gt;
&lt;h2&gt;count maintainers, not packages&lt;/h2&gt;
&lt;p&gt;So here&apos;s the shift I&apos;d make in how you look at your own tree.&lt;/p&gt;
&lt;p&gt;Every dependency is a standing grant of publish access into your build, issued to a person you have never met, renewed automatically every time you install, and revocable only by you noticing. Your lockfile pins a version, which is a seatbelt worth wearing and not the same thing as revoking the grant, because the next upgrade is the next opportunity and upgrades are not optional forever.&lt;/p&gt;
&lt;p&gt;The interesting number isn&apos;t how many packages you have. It&apos;s how many humans can put code on your production servers without asking you. Nobody I know can say that number out loud about their own system. Most people have never seen it, and the transitive tree is where it actually lives, four levels down under something you chose for good reasons in 2021.&lt;/p&gt;
&lt;p&gt;Now put a fleet on top of it. Agents open dependency bumps, add packages, refactor toward whatever library the corpus prefers, and every one of those PRs is defensible on its own the way every added code path was defensible on its own. An audit that was already too large for one person to hold is now growing at machine speed, and it grows in the one file everybody scrolls past.&lt;/p&gt;
&lt;h2&gt;the dependencies that got more valuable, not less&lt;/h2&gt;
&lt;p&gt;None of this is an argument for vendoring everything or writing your own crypto. The flip is asymmetric, and getting the two ends right is the whole judgment call.&lt;/p&gt;
&lt;p&gt;At the small end, where the package is under a hundred lines and does one stable thing that hasn&apos;t changed since 2014, the maintenance you&apos;re buying is close to nothing and the grant is the same size as any other. Write it. You couldn&apos;t afford to before. You can now.&lt;/p&gt;
&lt;p&gt;At the big end, the maintenance is the entire product. When I chose Elixir for the GigSmart backend, I took on the largest dependency available to anyone: a full runtime, OTP, and decades of supervision-tree design that I was never going to reproduce and shouldn&apos;t have tried to. That was never code I declined to write. It&apos;s a body of operational knowledge with a compiler attached. A fleet can reimplement the surface of something like that in a weekend and will leave every war story out, because the war stories aren&apos;t in the source. Same argument for &lt;a href=&quot;/choices/postgres/&quot;&gt;Postgres&lt;/a&gt;, for the &lt;a href=&quot;/choices/typed-languages/&quot;&gt;type checker&lt;/a&gt;, for the framework your team already knows at 2am.&lt;/p&gt;
&lt;p&gt;Take the dependency when what you want is the maintenance. Write the code when what you want is the code. Almost everything that goes wrong here is one of those two mistaken for the other.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Get the maintainer count.&lt;/b&gt; Not the package count, which flatters you, but the number of distinct publishing identities in your transitive tree. This is exactly the kind of tedious graph-walking a fleet is excellent at, so have it produce the list. Then read the list yourself, because the surprise is always in row forty.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Make a new dependency argue in the PR.&lt;/b&gt; Every added package states what maintenance it buys, what it pulls in behind it, and what writing it instead would cost. An agent can draft all three honestly. The call about whether the trade is good is yours, and it takes thirty seconds once the evidence is in front of you.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Separate install time from run time.&lt;/b&gt; A package has to execute to do its job. It does not have to execute during installation, on a developer laptop with an SSH agent and a cloud token in the environment. Lifecycle scripts off by default is the single cheapest thing on this list, and the September attack ran in exactly that window.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Regenerate the small stuff deliberately.&lt;/b&gt; When the fleet reaches for a package to do something small and stable, ask for the function instead and keep it. You own it now, which used to be the objection and is now roughly the point.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So go back to that diff. It&apos;s still open, it still says &quot;3 hours ago&quot; under the comment, and it works. Somewhere under that one line are six more names, and behind those names are people, and the whole thing is fine right up until one of them has a bad Tuesday with their email. How many of those people are there in your system right now, and when did you last look, and has that number been going up or down since the fleet started opening the pull requests?&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He takes on fractional CTO and CAIO work through &lt;a href=&quot;https://thebushido.co&quot;&gt;The Bushido Collective&lt;/a&gt;, for founders drowning in AI-generated code and teams scaling past the leadership that got them here. If nobody on your team can say how many people can publish into your build, that&apos;s a good place to start a conversation. &lt;a href=&quot;https://thebushido.co&quot;&gt;Work with me&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance; the frame and the calls on what matters are mine. The xz details come from Andres Freund&apos;s own oss-security post rather than a retelling.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>architecture</category></item><item><title>Present and Callable</title><link>https://jasonwaldrip.com/writing/present-and-callable/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/present-and-callable/</guid><description>Agents add paths and almost never remove them, because addition is the low-risk move at every individual review. Knight Capital lost $460 million to code that had been dead since 2003 and was still present and callable. On counting paths instead of lines, and making removal a shipped output rather than a follow-up ticket.</description><pubDate>Wed, 02 Sep 2026 16:20:00 GMT</pubDate><content:encoded>&lt;p&gt;You asked for a change to how pricing gets calculated. The diff comes back Friday afternoon: a new function, clean and tested, wrapped in a flag, with the old function still sitting right below it in the same file. There&apos;s a fallback that routes to the old behavior if the new one throws. You read it, and it&apos;s careful work. You approve it, because you would have approved the same thing from a person.&lt;/p&gt;
&lt;p&gt;Nothing was removed. Not that day, and not in the forty other changes that landed the same way this quarter. Every one of them was defensible on its own.&lt;/p&gt;
&lt;h2&gt;the safe move at every single review&lt;/h2&gt;
&lt;p&gt;Addition is the low-risk answer to almost any review question, and it always has been. A new path can&apos;t break the thing already running. A removed path might, and the person who removed it owns whatever comes next. So the careful reviewer, the good one, the one you want, keeps saying yes to the version that leaves the old thing alone.&lt;/p&gt;
&lt;p&gt;That bias used to be self-limiting. Every extra path cost somebody an afternoon of typing, and afternoons were the budget. Nobody wrote a second implementation of pricing on a whim, because the first one had taken a week and they remembered.&lt;/p&gt;
&lt;p&gt;Now a fleet writes the second implementation while you&apos;re in a meeting. It writes the flag, the fallback, the adapter that lets both versions coexist, and the tests that prove both work. All of that is real work performed correctly. The generation cost went to zero, and the cost of removal did not move at all, because removal was never about typing. It&apos;s about proving that nothing depends on the thing you&apos;re about to take out, and proof is the expensive part.&lt;/p&gt;
&lt;p&gt;So the two operations came unglued. One of them got free, and it happens to be the one that grows the system.&lt;/p&gt;
&lt;h2&gt;the code was dead for nine years and it still traded&lt;/h2&gt;
&lt;p&gt;On August 1, 2012, Knight Capital deployed new order-routing code to eight servers. A technician copied it to seven of them. The eighth kept running what was already there, including a feature called Power Peg that Knight had stopped using in 2003.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.sec.gov/files/litigation/admin/2013/34-70694.pdf&quot;&gt;SEC&apos;s order&lt;/a&gt; describes what that old code was doing in the meantime, and the phrasing is better than anything I could write: &lt;em&gt;&quot;Despite the lack of use, the Power Peg functionality remained present and callable at the time of the RLP deployment.&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The new code reused a flag that used to switch Power Peg on. Knight meant to delete the old code. The order says so in as many words, that they intended to remove it, and the deletion is the one step that didn&apos;t happen. When the flag went to yes on that eighth server, nine-year-old logic woke up and started routing orders with a counter that had been moved out from under it in 2005 and never retested against it.&lt;/p&gt;
&lt;p&gt;Forty-five minutes. Four million executions, 397 million shares, and a $460 million loss. Five days later a group of investors put $400 million in and took most of the company, and by December Knight had agreed to be sold.&lt;/p&gt;
&lt;div&gt;&lt;div&gt;Present and callable.&lt;/div&gt;&lt;div&gt;Nobody had run that code in nine years. The machine could still reach it, and one afternoon it did.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Read that back with a fleet in mind. Nothing about Knight&apos;s failure required an agent, and nothing about it is exotic. Dead code nobody got around to removing, sitting on the one host a deploy missed, switched on by a flag that used to mean something else. Ordinary mistakes, all of them cheap on the day they were made. What&apos;s different now is the rate at which a codebase manufactures the first one.&lt;/p&gt;
&lt;h2&gt;the fence you&apos;re allowed to remove&lt;/h2&gt;
&lt;p&gt;I&apos;ve argued the other side of this, so let me square it.&lt;/p&gt;
&lt;p&gt;I&apos;ve written that &lt;a href=&quot;/writing/the-rewrite-looks-free-now/&quot;&gt;the rewrite looks free now&lt;/a&gt; and that the ugliness in an old file is scar tissue from incidents you weren&apos;t there for. I&apos;ve written that when a fleet ships schema changes, &lt;a href=&quot;/writing/the-migration-is-not-a-diff/&quot;&gt;you should let the dead column sit&lt;/a&gt; rather than reclaim it on a tidiness reflex. Both of those say leave it alone. This one says take it out. The difference is which way the change travels.&lt;/p&gt;
&lt;p&gt;Deleting a column is one way. The data is gone and no pipeline you own brings it back. Deleting code is a round trip: it&apos;s in the history, and restoring it costs you a &lt;code&gt;git revert&lt;/code&gt; and some embarrassment. Those are different categories of act, and the fact that they feel the same in a diff is most of why people get them backwards. The cheap deletion gets skipped and the expensive one gets waved through.&lt;/p&gt;
&lt;p&gt;Chesterton&apos;s rule about the &lt;a href=&quot;https://www.chesterton.org/taking-a-fence-down/&quot;&gt;fence in the road&lt;/a&gt; is usually quoted as an argument for never touching anything, which is not what it says. It says go and find out why the fence is there, and then you may remove it. The finding out is the price of admission. That&apos;s exactly the work a fleet can&apos;t do from inside the diff, because the reason a path exists is rarely in the code and almost never in the branch it&apos;s looking at. It&apos;s in an incident from two years ago, a customer contract, a compliance answer somebody gave once. You have that. The agent doesn&apos;t.&lt;/p&gt;
&lt;h2&gt;count the paths, not the lines&lt;/h2&gt;
&lt;p&gt;Here&apos;s the shift I&apos;d make in how you measure the thing you own.&lt;/p&gt;
&lt;p&gt;Lines of code stopped being interesting the moment they stopped being expensive. The number that matters now is how many distinct ways a request can be served, because that&apos;s the number your on-call has to hold in their head at 2am, the number your test matrix has to cover, and the number an attacker gets to choose from. Every flag doubles it. Every fallback adds one. Every second implementation you kept &quot;just until we&apos;re sure&quot; is a live branch of the system, not a comment about your intentions.&lt;/p&gt;
&lt;p&gt;At Phoneware, the whole mandate is that arithmetic. Portal customizations lived in per-customer JavaScript bundles and app backends were stranded in n8n flows, which meant the answer to &quot;how does this behave for this customer&quot; was a different codebase per customer. The replacement is one monorepo with a manifest that cascades reseller to domain to role. That work is only worth anything at the moment the old bundle stops being served. Until then it&apos;s the same number of behaviors plus one more, and the one more is the one nobody has operated yet.&lt;/p&gt;
&lt;p&gt;So make removal something you ship, not something you file.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;The replacement isn&apos;t done until the old path is gone.&lt;/b&gt; Not &quot;done, cleanup ticket filed.&quot; Done means one way to do it. If the new path needs to bake behind a flag first, fine, that&apos;s what flags are for. Put the delete on the calendar with a name against it the same day you turn the flag on, because a &lt;a href=&quot;/choices/feature-flags/&quot;&gt;flag with no removal date&lt;/a&gt; is a permanent fork in your logic wearing a temporary costume.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Ask the fleet to find the callers, and you make the call.&lt;/b&gt; Exhaustively tracing every reference to a function across a large repo is genuinely one of the things agents are excellent at, and it&apos;s the tedious half of a deletion. Let it produce the evidence. Keep the judgment about whether the path is load-bearing for a reason nobody wrote down.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Make &quot;has this run&quot; answerable.&lt;/b&gt; If you can&apos;t tell from your own &lt;a href=&quot;/choices/observability/&quot;&gt;telemetry&lt;/a&gt; whether a code path has served a request in ninety days, you can&apos;t retire anything with confidence, and you&apos;ll default to leaving it in. A counter on the branch you plan to remove costs an hour and turns an argument into a fact.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Review the shape, not just the change.&lt;/b&gt; The diff is one path. The question worth asking out loud is what the total came to: did this change leave the system with more ways to run than it had this morning, and was that on purpose?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of this is a brake on the fleet. Generating more, faster, is the entire point and I&apos;m not giving that up. But a system where addition is free and subtraction is manual doesn&apos;t stay in balance on its own, and the drift is invisible in every individual review, which is precisely why it survives review.&lt;/p&gt;
&lt;p&gt;So go back to Friday. Both pricing functions are still in that file, the flag is on, and the new path is serving everything. The old one hasn&apos;t run since March. It&apos;s still wired in, still reachable, still one repurposed flag away from an afternoon nobody wants. Who on your team could tell you, today, how many paths like that are live in your system? And if the answer is nobody, is that a number that&apos;s been going up or down since you handed the keyboard to the fleet?&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He takes on fractional CTO and CAIO work through &lt;a href=&quot;https://thebushido.co&quot;&gt;The Bushido Collective&lt;/a&gt;, for founders drowning in AI-generated code and teams scaling past the leadership that got them here. If your codebase has grown every week this year and nothing has come out of it, that&apos;s the conversation to have. &lt;a href=&quot;https://thebushido.co&quot;&gt;Work with me&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance; the frame and the calls on what matters are mine. The Knight Capital details come from the SEC&apos;s own order rather than one of the many retellings.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>architecture</category></item><item><title>The Migration Is Not a Diff</title><link>https://jasonwaldrip.com/writing/the-migration-is-not-a-diff/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-migration-is-not-a-diff/</guid><description>Revert restores code, not state. When agents write the migration in the same pass as the feature that needs it, nothing in the diff marks the one line that does not come back. On reading changes by direction of travel, and gating on the irreversible instead of the large.</description><pubDate>Sun, 30 Aug 2026 09:40:00 GMT</pubDate><content:encoded>&lt;p&gt;The pull request is twelve lines. It adds a column, backfills it from an existing one, and drops the old one. The fleet wrote it, the tests are green, the description is clear, and it looks exactly like the forty other clean diffs you approved this week. You merge it Thursday afternoon. Nine minutes later the error rate goes vertical, and you do the thing you have trained your entire org to do without thinking. You revert. The deploy rolls back in ninety seconds. The column is still gone.&lt;/p&gt;
&lt;p&gt;Everything in your pipeline rests on a promise that you can go back. Git, the merge train, blue-green, the canary, the flag you wrapped the feature in. All of it is the same bet placed over and over: whatever we just did, we can undo. That bet is good on every artifact in your repository except one.&lt;/p&gt;
&lt;h2&gt;revert is a word about source code&lt;/h2&gt;
&lt;p&gt;Revert restores a file to a previous shape, and it works because a file has no memory of having been the other shape. A database is the opposite kind of object. It is nothing but memory.&lt;/p&gt;
&lt;p&gt;Your code is a statement about what should happen next. Your data is the record of what already did. You can regenerate the first from almost nothing now. There is no regenerating the second.&lt;/p&gt;
&lt;p&gt;That distinction has always been true and it mostly did not matter, because the schema was protected by friction. Migrations were rare because writing one was real work, and the person writing it was usually the person who would be awake at 3am if it went badly. Call that discipline if you like. It was friction doing the job of judgment, and it held up for twenty years because it was expensive to skip.&lt;/p&gt;
&lt;h2&gt;the friction is gone and nothing replaced it&lt;/h2&gt;
&lt;p&gt;A fleet will write the feature, the migration that feature needs, the backfill, and the cleanup that drops the old column, in one pass, on one branch, under one title. Every line of it is plausible. Every line goes through the same review, at the same speed, with the same posture. Nothing in that diff raises its hand and says: this line is the one that does not come back.&lt;/p&gt;
&lt;p&gt;I have written before about &lt;a href=&quot;/writing/read-the-decisions-not-the-diff/&quot;&gt;reading the decisions instead of the diff&lt;/a&gt;, and this is the sharpest case for it I know. The decision to drop a column does not look bigger on screen than the decision to rename a variable. It occupies one line. It is the cheapest-looking thing in the change.&lt;/p&gt;
&lt;p&gt;It helps to look at what the industry already pays to do this safely. GitHub built &lt;a href=&quot;https://github.com/github/gh-ost&quot;&gt;gh-ost&lt;/a&gt; because altering a table on a live MySQL system is not the same category of act as shipping code. It reads the binary log stream, applies changes to a ghost table off to the side, throttles itself when the primary gets unhappy, and lets an operator pause the whole thing in flight. That is purpose-built infrastructure, running at GitHub&apos;s size, to make a single &lt;code&gt;ALTER&lt;/code&gt; survivable. Nobody builds that for a code change.&lt;/p&gt;
&lt;p&gt;The pattern for the change itself has been written down for over a decade. Danilo Sato called it &lt;a href=&quot;https://martinfowler.com/bliki/ParallelChange.html&quot;&gt;parallel change&lt;/a&gt; on Martin Fowler&apos;s site: expand, migrate, contract. Add the new shape while the old one still works. Move readers and writers across. Only then remove what nobody uses. Three phases, three releases, and the entire value sits in the boring middle, where both shapes are valid at once and you are still free to change your mind.&lt;/p&gt;
&lt;p&gt;Now look at that pattern through a fleet&apos;s eyes. Expand, migrate and contract are all obviously part of the same change, so an agent asked to rename a column will do all three, correctly, in one PR. It is being thorough, not careless. The safe version of that work is the one that ships looking unfinished, and &quot;looks unfinished&quot; is not a property any model optimizes for, or one your review process has ever rewarded.&lt;/p&gt;
&lt;h2&gt;what I actually bought with twenty years of this&lt;/h2&gt;
&lt;p&gt;I have spent my career making changes cheap to take back. At CommercialTribe I moved us onto GCP and Kubernetes and turned a release cadence measured in weeks into one measured in hours, and the reason that mattered was never raw speed. A short path back is what makes a team brave. At GigSmart I built the developer experience and the release path before there was much product to release on them, for the same reason.&lt;/p&gt;
&lt;p&gt;So I want to be precise about what all that work purchased. It purchased recoverable deploys. It did not purchase recoverable state, and I am not sure I ever said that out loud clearly enough.&lt;/p&gt;
&lt;p&gt;It gets sharper if you take my own advice. I tell people to &lt;a href=&quot;/choices/postgres/&quot;&gt;default to Postgres&lt;/a&gt; and keep defaulting to it far longer than they think they can, and I still believe that. One engine you understand deeply beats five you each half-operate. But consolidation concentrates risk exactly as much as it removes it. One database is one blast radius, which makes the schema the highest-leverage object in the entire system. The thing I like most about that architecture is the same thing that makes this particular failure expensive.&lt;/p&gt;
&lt;h2&gt;direction of travel&lt;/h2&gt;
&lt;p&gt;Here is the change I would make in how you read a diff.&lt;/p&gt;
&lt;p&gt;Stop asking first whether the change is correct. Your fleet is good at correct, your tests are good at correct, and correct was rarely the thing that hurt you. Ask which direction the change travels.&lt;/p&gt;
&lt;p&gt;Almost everything you ship is round trip. It goes out, and if it is wrong it comes home. A small minority is one way: dropping a column, deleting rows, overwriting a value in place, collapsing two fields into one. Those are not bigger changes. They are a different kind of change, and your pipeline has no idea the category exists.&lt;/p&gt;
&lt;div&gt;&lt;div&gt;A revert is not an undo.&lt;/div&gt;&lt;div&gt;It rewinds your code. Your data was awake the whole time.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Once you sort changes that way, the fix stops being &quot;review more carefully,&quot; which is advice nobody has ever successfully followed at fleet volume. It becomes a routing problem, and routing problems have real answers.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Migrations ship alone.&lt;/b&gt; Own PR, own deploy, own review posture. If a schema change cannot go out by itself, it is not ready to go out. This also makes the round trip real: the feature can come home, because the feature is a separate thing that did not take the schema with it.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Additive is routine, destructive is an event.&lt;/b&gt; Adding a column, a table, an index: let all of that move at fleet speed, because it does come home. Anything that removes or overwrites gets a human name on it and a written reason, every time.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Let the dead column sit there.&lt;/b&gt; An unused column costs you close to nothing. Reclaiming it costs you everything on the day you were wrong about &quot;unused.&quot; Contract is a scheduled decision, not a tidiness reflex, and the gap between migrate and contract should feel uncomfortably long.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Gate on the irreversible, not on the large.&lt;/b&gt; Your CI is full of checks asking whether the code is right. Add one that asks what this change costs if it is wrong. A rule that spots a drop, a delete, or an in-place update inside a migration and pulls it out of the autonomous lane is about an afternoon of work. That is the whole distance between &lt;a href=&quot;/choices/autonomy-with-guardrails/&quot;&gt;autonomy with guardrails&lt;/a&gt; and autonomy with optimism.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of that slows the fleet down in a way anyone will feel. The overwhelming majority of what it generates is round trip and should keep moving at exactly the speed it moves today. This is a narrow carve-out, which is precisely why it is easy to skip: the failure is rare, and when it lands it is total.&lt;/p&gt;
&lt;p&gt;So go back to Thursday. The deploy rolled back in ninety seconds and the pipeline did everything it ever promised. That part worked. It was never the part worth worrying about. The question I would want someone on that team to have asked out loud before the merge is the one nobody asks anymore, because the diff was twelve lines and looked like all the others: if we are wrong about this, what brings it back?&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He takes on fractional CTO and CAIO work through &lt;a href=&quot;https://thebushido.co&quot;&gt;The Bushido Collective&lt;/a&gt;, for founders drowning in AI-generated code and teams scaling past the leadership that got them here. If your fleet is shipping migrations at the same speed it ships features, that is the conversation to have. &lt;a href=&quot;https://thebushido.co&quot;&gt;Work with me&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the calls on what matters, and the correction about what a fast release path actually buys are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>data</category></item><item><title>The Next Ren&lt;span style=&quot;color:var(--acc);&quot;&gt;ai&lt;/span&gt;ssance: What Abundance Makes Possible</title><link>https://jasonwaldrip.com/writing/in-the-next-renaissance/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/in-the-next-renaissance/</guid><description>AI is collapsing the cost of labor and execution. If we solve material scarcity, we don&apos;t end work; we liberate human potential to create at the top of Maslow&apos;s hierarchy.</description><pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I sat at my desk reading Bill Gates&apos;s essay &lt;a href=&quot;https://www.gatesnotes.com/a-turbulent-ai-era-and-critical-choices-to-make&quot;&gt;“A Turbulent AI Era and Critical Choices to Make”&lt;/a&gt;, where he warns how unready our social and economic institutions are for the disruption ahead. Gates makes a crucial distinction: &lt;em&gt;&quot;Intelligence is not responsibility. That is a guardrail we shouldn&apos;t surrender.&quot;&lt;/em&gt; He notes that &lt;em&gt;&quot;in terms of equity, AI will either be the greatest equalizer ever invented, or the worst source of injustice.&quot;&lt;/em&gt; Reading his words, I kept coming back to what happens if we choose the path of the equalizer: what that future actually looks like when we get it right. If we look forward to what we can become and prepare ourselves to embrace this change, humanity has the opportunity to take a bigger leap forward than it ever has. By systematically solving the material bottlenecks of survival, we have a real chance to move humanity up &lt;a href=&quot;https://en.wikipedia.org/wiki/Maslow%27s_hierarchy_of_needs&quot;&gt;Maslow’s hierarchy of needs&lt;/a&gt; at scale—the famous pyramid that shows how meeting basic survival needs like food and shelter unlocks higher human drives like creativity and connection—moving past forced labor, transactional existence, geographic isolation, and the scarcity-driven systems that have defined human history.&lt;/p&gt;
&lt;h2&gt;The Insecurity Behind the Fear&lt;/h2&gt;
&lt;p&gt;Whenever you talk about this level of change, fear is the immediate reaction. The fear, uncertainty, and doubt driving headlines isn&apos;t just about losing a paycheck. It runs deeper than that. People fear losing their sense of identity, purpose, and control. For centuries, society trained us to tie our worth to our productivity: &lt;em&gt;I am what I produce. I am my title, my billable hours, my mechanical skill.&lt;/em&gt; When an algorithm can write code, draft legal briefs, or render art in seconds, people don&apos;t just feel threatened financially. They feel erased personally.&lt;/p&gt;
&lt;p&gt;Much of what we label as human greed or the relentless drive for power stems from this same insecurity. Psychology shows that extreme accumulation is rarely about wanting more luxury; it&apos;s a coping mechanism for the fear of not having enough. When a system is built on artificial scarcity, the brain treats wealth and control as a shield against vulnerability, creating an endless loop where no amount of hoarded capital ever feels safe.&lt;/p&gt;
&lt;p&gt;In 2020 a lot of people stopped commuting. Not everyone. The nurses kept going in, and so did the man restocking the dairy case at five in the morning. But for the ones who could, something came loose, and they found out what a Tuesday is worth when nobody is watching them have it.&lt;/p&gt;
&lt;p&gt;What came next got called laziness. It wasn&apos;t. It was an ordinary discovery: that forty hours at a desk and forty hours of work are two different things, and one had been standing in for the other for a long time.&lt;/p&gt;
&lt;p&gt;That was a preview, and it ended. The argument for automation is that it doesn&apos;t have to.&lt;/p&gt;
&lt;p&gt;We have to redefine what wealth actually means. For generations, wealth meant accumulation: holding enough scarce capital, property, or money to shield yourself from economic insecurity and extract rent from others. In a world of material abundance, true wealth ceases to be a number in a bank account or a mountain of hoarded assets. True wealth becomes &lt;strong&gt;control over your time&lt;/strong&gt;: the freedom to decide how you spend your day, who you spend it with, and what problems you choose to solve.&lt;/p&gt;
&lt;p&gt;Leadership thinker John C. Maxwell often pointed out that people change for four reasons: &lt;em&gt;when they hurt enough that they have to, when they learn enough that they want to, when they receive enough that they are able to, or when they see enough that they are inspired to.&lt;/em&gt; For most of human history, society forced people to change out of the first season: the desperate, degrading pain of survival. Critics often worry that eliminating that survival pain will make humanity lazy and kill the engine of invention. But abundance doesn&apos;t eliminate discomfort. It upgrades the quality of our discomfort. We move away from the destructive pain of basic survival and toward the noble friction of creative problem-solving. We stop changing because we hurt enough that we have to, and start changing because we see enough that we are inspired to.&lt;/p&gt;
&lt;h2&gt;Education and the Shift to Judgment&lt;/h2&gt;
&lt;p&gt;To take that leap, education has to change. For generations, school was designed around information transfer and training people to execute routine labor. But education as pure information transfer is dead. As I wrote in &lt;a href=&quot;/writing/volume-is-free-now/&quot;&gt;“Volume Is Free Now. Judgment Is the Whole Game”&lt;/a&gt;, when artificial intelligence makes technical execution, generation, and software output virtually free, sheer volume ceases to be a competitive advantage. That idea started in software, but it&apos;s bleeding rapidly into almost every industry. We see this shift everywhere. My sister-in-law, a Physician Assistant at Boston Children’s Hospital with zero traditional software engineering experience, built and launched &lt;a href=&quot;https://getcrewlingo.com&quot;&gt;CrewLingo&lt;/a&gt;, an automated, bilingual call-capture platform for field and service crews. She didn&apos;t spend years learning syntax. She understood a domain problem, applied her judgment, and used modern tools to bring a complete product to life. The same shift is happening across healthcare: tools like &lt;a href=&quot;https://www.freed.ai/&quot;&gt;Freed&lt;/a&gt;, built by clinicians fed up with spending hours typing patient charts, now automatically turn natural doctor-patient conversations into structured medical notes for tens of thousands of physicians. In physical product design, 3D printing and automated CNC pipelines let small shops generate dozens of physical prototypes in a day. In media and entertainment, production volume that used to require a studio is accessible to a single creator. Across every field, execution is shifting from raw labor to directing intent and tools. When execution becomes cheap and accessible, mechanical skill carries far less weight than it used to. What becomes critical instead is judgment. We need an educational approach focused on critical thinking, knowing what questions to ask, and understanding what is possible. It&apos;s about learning to build and hold a high-level map of knowledge across disciplines so you can evaluate output, spot the gaps, and know what is right. Education must prepare human minds not merely to secure a job at the base of the pyramid, but to operate at the top, as self-actualized thinkers and makers who direct tools toward meaningful human ends.&lt;/p&gt;
&lt;h2&gt;Decoupling Labor from Survival&lt;/h2&gt;
&lt;p&gt;The engine behind this transition is a fundamental shift in how we satisfy basic human survival needs, the foundation of Maslow&apos;s pyramid. Labor is the main building block of almost everything we buy. Almost everything required for human survival (food, clean water, shelter, energy, healthcare, and disease research) is ultimately a stack of embedded human labor and raw materials. Look at what is already happening on the ground. AI-driven protein folding models like Google DeepMind&apos;s &lt;a href=&quot;https://alphafold.ebi.ac.uk/&quot;&gt;AlphaFold&lt;/a&gt; have collapsed decades of biological research into seconds, speeding up drug discovery at a fraction of historical costs. In manufacturing and agriculture, automated vertical farms and robotic construction systems are beginning to decouple physical yield from manual labor hours. As AI and robotics drive the cost of cognitive and physical labor toward zero, the cost of meeting physiological and safety needs collapses with it. Scarcity at the foundation of human survival stops being an insurmountable production problem.&lt;/p&gt;
&lt;p&gt;True abundance moves us beyond the survival-driven structures that defined the industrial age. When basic survival is guaranteed for everyone, we move beyond transactional labor, where human time is traded merely to stay housed and fed. We move beyond buying things just to show off status. We move beyond geographic and institutional boundaries, as decentralized production and local intelligence allow communities anywhere on Earth to achieve basic security without depending on distant megacities or global supply chains.&lt;/p&gt;
&lt;h2&gt;Compounding at the Upper Tiers&lt;/h2&gt;
&lt;p&gt;Satisfying the base of the pyramid doesn&apos;t automatically complete the human story. It simply clears the stage for higher-level needs. Operating on the upper tiers of Maslow&apos;s hierarchy is inherently compounding. When minds are no longer mired in the chronic, cognitive drag of survival stress, human potential accelerates. Unburdened by the fight for food, healthcare, or shelter, human curiosity compounds into creation and connection. People are inspired to build, experiment, and solve problems simply for the joy of discovery and contribution. When physical survival is guaranteed, the nature of scarcity shifts upward into Maslow’s middle and upper tiers. The things that remain scarce aren&apos;t production problems; they are human ones: social belonging, deep relationships, authentic trust, self-respect, and creative fulfillment.&lt;/p&gt;
&lt;p&gt;This human shift isn&apos;t theoretical. I see it happening in my own family. My brother, Kristopher, lives with dystonia and epilepsy, movement and neurological disorders that severely impact his physical motor skills. Over the years, he spent thousands of hours listening to audiobooks, unable to write or type easily. Before his disability took hold, he spent his energy in creative writing, acting, and music. Recently, combining his voice with AI toolsets allowed him to bypass his physical limitations entirely, turning his ideas directly into finished prose. He wrote and fully published his science fiction novel, &lt;a href=&quot;https://www.amazon.com/dp/B0HFDLPQ89&quot;&gt;&lt;em&gt;Haven&lt;/em&gt; by Kristopher Waldrip&lt;/a&gt;, on Amazon. AI didn&apos;t invent the story for him. It removed the physical barrier between his mind and the page, unlocking a level of creative self-actualization that traditional tools denied him.&lt;/p&gt;
&lt;p&gt;I talk to many creative people who resist this shift entirely. As I explored in &lt;a href=&quot;/writing/still-the-painter/&quot;&gt;“Still the Painter”&lt;/a&gt;, engineers, illustrators, designers, and session musicians are all processing the same fear: &lt;em&gt;volume is free, therefore I am worthless.&lt;/em&gt; But that only follows if volume was what made you valuable in the first place, and it never was. They reject AI generation, hunting for non-algorithmic music and arguing that machine-assisted creation isn&apos;t real creation at all. But that reaction misses what&apos;s actually happening. Can AI write a song on its own? Sure. But the melody you hummed into a phone memo, or the raw lyrics you scribbled on paper, can now become a fully produced, orchestrated album for a fraction of the cost. The same capital constraints that once gated businesses have been removed for artists. For generations, brilliant creators acted as cogs in a corporate machine during the day, spinning their wheels at night in hopes of catching the rare financial break that would let them afford the time to create. That breaking point is no longer required.&lt;/p&gt;
&lt;p&gt;Every creative person in the world should be creating. When an artist worries whether their album is better than the one a model generated in an afternoon, they are answering a question the audience never asked. I am the audience here, and I am not conflicted about it. I used to get one album. Now I get two, and the one you made does not get worse because the other one exists. More importantly, most creatives aren&apos;t hoping for a big break so they can buy yachts. They are hoping for a break so they can afford the &lt;strong&gt;time&lt;/strong&gt; to do what they love. In an abundant world, you don&apos;t wait for permission or capital to afford time. You just do what you love, and the rest is abundant.&lt;/p&gt;
&lt;h2&gt;Agency, Ownership, and the Local Commons&lt;/h2&gt;
&lt;p&gt;When material security becomes ordinary and execution is accessible to anyone, the fundamental human quest shifts from basic survival to asking: &lt;em&gt;Where do I belong, and how do I achieve real self-fulfillment?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This reframes what we mean by work, ownership, and governance. Historically, institutions defined work as the mechanism for survival, which is why the coal town paid its miners in &lt;a href=&quot;https://en.wikipedia.org/wiki/Company_scrip&quot;&gt;company scrip&lt;/a&gt; that spent nowhere but the company store, and why the quieter modern version of the same arrangement is a job that carries your health insurance. Ownership was the other half of it: holding an asset at the bottom of the pyramid so you could charge others to reach their own basic needs, the way whoever filed first on a river upstream never made the water and still gets paid by everyone below. But in an abundant world, controlling what flows through other people&apos;s lives loses its leverage when dependence becomes optional. We are already seeing the early infrastructure for this shift in open-source and local AI. Open-weights models running locally on personal hardware allow individuals and small teams to own their intelligence without paying continuous subscription rent to a centralized tech giant. But models are the newest example of this, not the best one. When the private utilities decided rural America was not worth wiring, the farmers wired it themselves, and the &lt;a href=&quot;https://www.electric.coop/electric-cooperative-fact-sheet&quot;&gt;830 electric cooperatives that came out of that still serve 42 million people&lt;/a&gt;, owned by the households at the end of the line instead of by a shareholder. The same fight is running again over connectivity: Colorado spent eighteen years under a 2005 law that made a town hold a referendum before it could build its own broadband, and &lt;a href=&quot;https://coloradosun.com/2023/05/24/municipal-internet-sb-152-repealed-colorado/&quot;&gt;more than 160 cities, towns, and counties held that vote and passed it anyway before the legislature repealed the law outright in 2023&lt;/a&gt;. Ownership shrinks to what serves personal agency (your private space, your individual tools, your local models) while shared infrastructure and community assets are held collectively. Proven cooperative models, like the &lt;a href=&quot;https://www.mondragon-corporation.com/en/&quot;&gt;Mondragon Corporation&lt;/a&gt; in Spain or the regional cooperative economy of &lt;a href=&quot;https://www.resnetwork.it/&quot;&gt;Emilia-Romagna&lt;/a&gt;, have long demonstrated that complex, highly competitive enterprises can be owned and governed directly by the people inside them. Distributism and cooperative structures become the natural way to govern the commons, protecting everyone&apos;s safety and esteem needs while fostering autonomy.&lt;/p&gt;
&lt;p&gt;We are on the verge of a new renaissance. The days when you needed massive capital to afford the labor required to build great things are coming to an end. I see this daily with my own clients: entrepreneurs operating with small teams and their own bootstrapped capital. Today, these small teams can outpace and out-build companies 100 times their size. Because execution volume has become virtually free, their sharp, unbureaucratic judgment isn&apos;t diluted by corporate middle management or political approval chains. They can spot a problem, decide on a solution, and ship it before a legacy enterprise finishes its first planning meeting. The barrier between having an idea and bringing it into reality has never been lower. Small businesses, independent inventors, and local creators will flourish.&lt;/p&gt;
&lt;h2&gt;A Day in the Life of the Next Renaissance&lt;/h2&gt;
&lt;p&gt;What does this world actually feel like to live in? Picture waking up not to an alarm set for a commute you dread, but to a day shaped by choice. Your basic housing, energy, nutrition, and health are secure, uncoupled from whether you sold forty hours of your life this week. You walk into a local workshop, a community lab, or your own backyard studio. You aren&apos;t there because a boss monitored your sign-in time; you are there because you are collaborating with three neighbors on an automated water-filtration system for your regional watershed, or experimenting with a new local crop strain, or writing music. Work transforms into a gathering place for creativity, collaboration, and shared invention. People pursue ambitious endeavors for the same reasons they pursue woodworking or pottery today: out of love for the craft, deep curiosity, and the desire to build something meaningful. But unlike a weekend hobby in a garage, abundance gives individuals and small groups the tools to solve problems at nationwide scale. In this world, curing a rare disease, engineering a zero-emission engine, or building an innovative educational model is pursued as a passionate, self-directed project. When we solve material scarcity, we don&apos;t end work; we ignite a compounding cycle of human potential, allowing all of humanity to live, gather, and create at the top of Maslow&apos;s hierarchy.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He writes about engineering leadership, infrastructure, and building in the age of AI. If your team is navigating this transition and wants to build on strong judgment, &lt;a href=&quot;https://thebushido.co&quot;&gt;that&apos;s the work I do&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the personal stories, and the core philosophy are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>ai</category></item><item><title>The Bill Is a Design Document</title><link>https://jasonwaldrip.com/writing/the-bill-is-a-design-document/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-bill-is-a-design-document/</guid><description>Why cost is an architecture problem and not a procurement one, how to read a cloud invoice as a diagram of decisions you already made, and what happens when a fleet of agents starts spending against a design you approved once.</description><pubDate>Tue, 25 Aug 2026 08:14:00 GMT</pubDate><content:encoded>&lt;p&gt;Finance forwards you the invoice with three words on top: this seems high. There&apos;s a meeting Thursday called cost optimization, and by the time you sit down somebody has already built the deck. Rightsize the instances. Buy a year of reserved capacity. Shut the dev environments off at night. Get the rep on the phone and see what they can do. Every slide is a way to pay less for exactly the system you already have, and not one of them asks why the system does the thing it&apos;s being billed for.&lt;/p&gt;
&lt;p&gt;I&apos;ve sat in that meeting from both sides. It&apos;s a useful meeting. The savings are real, they close inside a quarter, and they are almost never where the money is.&lt;/p&gt;
&lt;h2&gt;nobody in that room can read it&lt;/h2&gt;
&lt;p&gt;The gap is in who touches the invoice, and it repeats in almost every company I walk into.&lt;/p&gt;
&lt;p&gt;The invoice goes to finance. Finance can read money and cannot read the system. They get a few hundred line items with names like NatGateway-Bytes and Standard-Storage-Class-A-Requests, and no way to know that one of those lines exists because a service is chatting with a database across a boundary somebody drew in a hurry two years ago.&lt;/p&gt;
&lt;p&gt;The engineers can read the system and never see the invoice. Ask a senior engineer what their largest cloud line item is and you&apos;ll get a guess with a rising tone at the end. Ask what it was last month and you won&apos;t get anything, because nobody sent it to them and nobody expected them to ask.&lt;/p&gt;
&lt;p&gt;So the bill gets handled as a price, because the only people holding it can only see a price. And a price is a thing you negotiate.&lt;/p&gt;
&lt;h2&gt;what a discount can actually buy&lt;/h2&gt;
&lt;p&gt;37signals put real numbers on this in public, which almost nobody does. DHH wrote that HEY was paying over half a million dollars a year for database and search alone, and then he did the other half of the arithmetic in the same post: AWS was running close to a 30% margin, 18.5 billion in profit against 62.2 billion in revenue on his figures. &lt;a href=&quot;https://world.hey.com/dhh/why-we-re-leaving-the-cloud-654b47e0&quot;&gt;He left&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That margin is roughly the ceiling on your negotiation. Everything above your vendor&apos;s cost is in principle available to you, and in practice you&apos;ll capture a slice of it once, in exchange for a multi-year commitment that makes the shape you currently have more expensive to change.&lt;/p&gt;
&lt;p&gt;A discount is a one-time move against a recurring number. A design change moves the recurring number. Thursday&apos;s meeting only knows how to do the first one, and it will keep being scheduled, quarterly, forever.&lt;/p&gt;
&lt;h2&gt;the bill is a design document&lt;/h2&gt;
&lt;p&gt;At some point in a rescue years ago I stopped reading the invoice as a bill and started reading it as a diagram, and I haven&apos;t been able to unsee it since.&lt;/p&gt;
&lt;p&gt;Every line item is a decision somebody made. Egress is data crossing a boundary you drew. Storage that only ever grows is a retention policy nobody wrote down. Compute that&apos;s flat across a workload that is extremely not flat is a system sized for its peak because it couldn&apos;t scale into one. A queue costing more than the work it queues is a queue that shouldn&apos;t exist. None of this appears on the architecture diagram in the wiki.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;The diagram in the wiki is what you meant. The invoice is what you built.&lt;/div&gt;
  &lt;div&gt;One of them gets updated every month by a party with no incentive to flatter you.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Segment published the cleanest version of this I&apos;ve read. They&apos;d grown to over 140 services, one per destination, adding about three a month, and the sentence in their writeup that does all the work is that their operational overhead increased linearly with each destination added. Read that as an equation and not a complaint: cost was a function of destination count, by construction, and no amount of tuning any individual service touches a function. They collapsed the whole thing back into &lt;a href=&quot;https://www.twilio.com/en-us/blog/developers/best-practices/goodbye-microservices&quot;&gt;a single service and a monorepo&lt;/a&gt;. The numbers that moved didn&apos;t move in a negotiation.&lt;/p&gt;
&lt;h2&gt;the calls I&apos;ve made against it&lt;/h2&gt;
&lt;p&gt;The best cost discipline I&apos;ve ever had was at Resipsa, a legal-practice SaaS I built and funded myself. I designed it to run at near zero, and the reason wasn&apos;t rigor. The bill came out of my own account, every month, where I had to look at it. Founders who have felt that have a sharper instinct here than the ones who never have, and it isn&apos;t close.&lt;/p&gt;
&lt;p&gt;At CommercialTribe I moved us onto GCP and Kubernetes, and I want to be precise about the reasoning, because it inverts how that call usually gets made. Kubernetes was the cheapest path to stability at the load we actually had, which is a far narrower claim than &quot;Kubernetes is cheaper.&quot; Below that load it&apos;s an expensive mistake and I&apos;ll argue against it all day, which is most of what &lt;a href=&quot;/writing/earn-it/&quot;&gt;Earn It&lt;/a&gt; is about. All the judgment lives inside the phrase &quot;at the load we actually had,&quot; and you can&apos;t evaluate that phrase without knowing what your current shape costs to run.&lt;/p&gt;
&lt;p&gt;I&apos;ve migrated to GCP more than once, for the same three reasons every time: cost, control, performance. Never for the first one alone. A migration is a different shape with a different bill, and if you move a bad shape you&apos;ll get a bad bill in a new currency, a quarter of your team&apos;s attention gone, and nothing learned.&lt;/p&gt;
&lt;p&gt;The compressed version is the &lt;a href=&quot;/choices/go/&quot;&gt;one I still tell&lt;/a&gt;: at Brandfolder, Ruby was crashing generating large zip files, the cheap answer sitting on the table was a bigger instance, and we built the pipeline in Go instead. Days of work against a line that would have grown every month we stayed.&lt;/p&gt;
&lt;h2&gt;the new line item&lt;/h2&gt;
&lt;p&gt;There&apos;s a new SKU on the invoice this year, and it&apos;s already collecting the same mistake.&lt;/p&gt;
&lt;p&gt;You pointed everything at a frontier model because it was there and it worked on the first try. Classification, extraction, routing, tagging, a summarizer nobody reads. The bill lands, it&apos;s a multiple of what anyone estimated, and the first instinct in the room is to ask about volume pricing. That&apos;s the reserved-instance slide with a different logo on it. Most of that work never needed frontier reasoning, which is the entire argument for &lt;a href=&quot;/writing/own-the-model/&quot;&gt;owning the model&lt;/a&gt; on the tasks boring enough to run yourself.&lt;/p&gt;
&lt;p&gt;What&apos;s genuinely new is the rate. A fleet spends against a design you approved once, and it spends at machine speed. An agent that re-reads the same file at every step, a retry loop with no ceiling, context rebuilt from scratch on every call: those are architectural decisions, they bill by the token, and nobody has to stay late to run the number up. The thing that used to rate-limit a lazy design was somebody having to sit there and do it. &lt;a href=&quot;/writing/volume-is-free-now/&quot;&gt;Volume is free now.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;how I actually run this&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Put the invoice in front of the engineers.&lt;/b&gt; Monthly, top twenty lines, translated out of SKU names and into the names your system actually uses. It costs one afternoon of somebody&apos;s time to build that mapping, and it&apos;s the highest-leverage afternoon in the whole exercise.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Ask what decision produced each line, not how to shrink it.&lt;/b&gt; &quot;How do we get this down&quot; gets you a smaller instance and a follow-up meeting. &quot;What did we decide that makes this line exist at all&quot; gets you the boundary in the wrong place.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Split the two questions and staff them separately.&lt;/b&gt; Price per unit is procurement, it&apos;s real work, and somebody should be doing it. Units consumed is architecture, and it&apos;s yours. Blending them is how a cost program runs for a year and moves nothing.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Decide out loud what you&apos;re willing to pay for.&lt;/b&gt; Some expensive lines are correct. Multi-region under an uptime commitment is correct. Reading the bill isn&apos;t an exercise in making it smaller, it&apos;s how you confirm every large number on it is one you&apos;d choose again today.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Thursday&apos;s meeting still happens, and I still take the reserved instances, because free money is free money and I&apos;m not precious about it.&lt;/p&gt;
&lt;p&gt;What I want before that meeting breaks up is one person who can put the top line on the screen, name the decision it came from, say roughly who made it and when, and then say whether we&apos;d make it the same way now. Most companies don&apos;t have that person anywhere on the org chart. A lot of them have a very good deck.&lt;/p&gt;
&lt;p&gt;So: your biggest line item this month. What&apos;s it a picture of?&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He writes about engineering leadership, infrastructure, and building in the age of agents. If your cloud bill is climbing and nobody in the building can tell you which decision it came from, &lt;a href=&quot;https://thebushido.co&quot;&gt;that&apos;s the work I do&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance; the frame, the stories, and the calls on what stayed are mine. The 37signals and Segment figures are theirs, linked above, and I didn&apos;t add any numbers of my own that I can&apos;t show you.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>architecture</category></item><item><title>The Tracks Were Never the Speed Limit</title><link>https://jasonwaldrip.com/writing/the-tracks-were-never-the-limit/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-tracks-were-never-the-limit/</guid><description>The train-and-tracks metaphor framed your foundation as a ceiling on speed. With agents generating the code, that framing is backwards: tests, deploy automation, and self-healing infrastructure are what keep a much faster system from leaving the rails.</description><pubDate>Tue, 25 Aug 2026 07:15:00 GMT</pubDate><content:encoded>&lt;p&gt;For most of my career, I did not write tests. Not as a principled position, and not proudly. I wrote them when a reviewer made me, and I wrote them thoroughly on the things I was scared of, and the rest of the time I shipped and watched. I was fast enough and close enough to the code that I could hold the whole shape of it in my head, and a test felt like paying to be told something I already knew.&lt;/p&gt;
&lt;p&gt;I now write more tests than at any point in twenty years. My opinion of tests did not change. What changed is that I am no longer the one typing.&lt;/p&gt;
&lt;h2&gt;the line I have been saying since before it was true&lt;/h2&gt;
&lt;p&gt;Ask anyone who has worked for me and they can finish this sentence: the train can only move as fast as the tracks it&apos;s built on. It is on my about page. I have said it in architecture reviews, in board updates, and in more than one argument about why the release path deserved a quarter of the roadmap when nobody was asking for it.&lt;/p&gt;
&lt;p&gt;At CommercialTribe I meant it literally. We had a release cadence measured in weeks, and I spent the first stretch of that job on GCP, Kubernetes, automated testing and deploys, until releases took hours. Nobody asked for that. What it bought was not features, it was the difference between a team that learns and a team that guesses. At GigSmart I did it in the other order and built the dev experience and the release path before we had much of a product to release on it, because I already knew what the alternative cost.&lt;/p&gt;
&lt;p&gt;Both of those were the same argument: your foundation sets a ceiling, and if you want to go faster you raise the ceiling. That is what the metaphor says. Track quality determines top speed.&lt;/p&gt;
&lt;p&gt;For twenty years that was a useful thing to believe, because the thing pressing against the ceiling was people. You wanted more throughput, you hired, and the tracks decided how much of that hiring turned into shipped software instead of incidents. The engine was expensive and slow and predictable, and the track was the constraint worth arguing about.&lt;/p&gt;
&lt;h2&gt;the engine got replaced while I was still making the argument&lt;/h2&gt;
&lt;p&gt;The part I keep having to say out loud, because it still sounds like marketing: generation is not the bottleneck anymore. I wrote &lt;a href=&quot;/writing/volume-is-free-now/&quot;&gt;a whole piece on that&lt;/a&gt; and I will not re-run it here. The short version is that the thing I spent a decade getting elite at, producing a lot of correct code quickly, is now something you rent.&lt;/p&gt;
&lt;p&gt;Here is what I did not expect. When you point a fleet at a codebase, the first thing that breaks is not the code. It is everything downstream of the code.&lt;/p&gt;
&lt;p&gt;I am not the only one seeing it. The 2024 &lt;a href=&quot;https://dora.dev/research/2024/dora-report/&quot;&gt;DORA report&lt;/a&gt; found that AI adoption raised individual productivity and flow, and at the same time correlated with worse delivery stability and throughput at the team level. Read that twice. Every individual got faster and the system got worse. That is not a story about bad code. It is a story about a lot more change arriving at a pipeline, a review process, and a verification story that were all sized for the old rate.&lt;/p&gt;
&lt;p&gt;Which means the ceiling framing has quietly stopped describing anything. Nobody is pressing against a ceiling. The generation layer will produce more change than your foundation can absorb, today, on a Tuesday, and it will do it whether or not you raised the ceiling first.&lt;/p&gt;
&lt;h2&gt;so what is the track actually for&lt;/h2&gt;
&lt;p&gt;Here is the reframe I have landed on, and I have had to correct myself in front of people who heard me say the old version for years.&lt;/p&gt;
&lt;p&gt;The track was never the speed limit. The track is what keeps the train on the ground, and the ground just got a lot further away.&lt;/p&gt;
&lt;p&gt;That sounds like the same sentence with the emphasis moved. It is not, and the difference shows up in every funding decision you make about infrastructure. If the track is a ceiling, then track work is an investment in going faster, it competes with features, and you do it when you want more velocity. If the track is what keeps you on the rails at a speed you did not choose and cannot give back, then track work stops competing with anything. It becomes the price of having turned the fleet on, and you either paid it or you are going to.&lt;/p&gt;
&lt;p&gt;The old track was steel rail. You maintained it, and if you maintained it well the train went faster. A maglev does not have a faster version of that track. It has a different one, and running the new train on the old rails is not slow, it is a wreck.&lt;/p&gt;
&lt;p&gt;Three things change, in the order I would fix them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A person in the deploy path is a rate limiter attached to something that no longer has a rate.&lt;/strong&gt; This is the least interesting of the three because it is the oldest argument, and I have written it up already as &lt;a href=&quot;/writing/the-deploy-path-is-a-product/&quot;&gt;the deploy path being a product&lt;/a&gt;. What is new is only that the cost of ignoring it compounds faster now. If a human has to be awake for a release, the fleet&apos;s output queues behind that human, and you have built a very expensive way to generate a backlog.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tests stopped being a discipline and became structure.&lt;/strong&gt; This is the one I got wrong personally, so I trust it most. When I wrote the code, the tests were a second opinion on something I already understood. When a fleet writes it, the tests are the only encoding of intent that exists. The agent will produce something plausible and confident and shaped exactly like working software, and the test suite is the thing that has an opinion about whether it does what you meant. I stopped writing tests because I was disciplined and started writing them because they are load bearing. Nobody talked me into it. The speed took the choice away.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The track has to repair itself.&lt;/strong&gt; This is the newest, the least settled, and the one I would push back on hardest if someone else said it to me. A pipeline that goes red and waits for a person is still a pipeline gated on a person, just at a less convenient hour. What I am building instead is a loop that closes: a check fails, an agent picks up the failure with the context to understand it, and lands the fix as a reviewed change rather than a page. At Phoneware that looks like agent guides that live in the repo, a workboard the fleet actually tracks, canary targeting so a bad change is contained instead of discovered, and Terraform and GitOps under all of it so the state of the system is a file rather than a memory. It is real, it works, and I would not yet tell you it is finished.&lt;/p&gt;
&lt;h2&gt;the part I am not handing over&lt;/h2&gt;
&lt;p&gt;The whole reason the track can be automated is that a track is a system with a definition of correct. Green or red, drifted or converged, canary healthy or not. That is exactly the kind of question a machine should be answering at three in the morning instead of you.&lt;/p&gt;
&lt;p&gt;What does not have a definition of correct is which parts of your system are load bearing. Whether this change is a ship-it-and-learn or a slow-down-and-get-it-right. Which failing check is a flake and which one is the system telling you something true that nobody wants to hear. The fleet will go equally fast at all of it, cheerfully, and that is the whole danger.&lt;/p&gt;
&lt;p&gt;So the tracks get automated and the map does not.&lt;/p&gt;
&lt;p&gt;I still say the line, by the way. I have just stopped meaning it as encouragement. When I said it before, I was telling a team that good foundations would let them go faster, and they mostly heard permission to ask for time. What I would tell them now is closer to a warning: the train is already moving at the new speed, nobody consulted you about it, and the only question left is what you are standing on when it gets to the curve.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He takes on fractional CTO and CAIO work through &lt;a href=&quot;https://thebushido.co&quot;&gt;The Bushido Collective&lt;/a&gt;, for founders drowning in AI-generated code and teams scaling past the leadership that got them here. If your fleet is already faster than your pipeline, that is the conversation to have. &lt;a href=&quot;https://thebushido.co&quot;&gt;Work with me&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The correction is mine, said out loud to a friend before it was written down, and so are the calls on what to keep and what to cut.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>infrastructure</category></item><item><title>A Fleet Won&apos;t Tell You No</title><link>https://jasonwaldrip.com/writing/a-fleet-wont-tell-you-no/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/a-fleet-wont-tell-you-no/</guid><description>Why you still hire engineers when a fleet can produce the output, and what to select for instead of throughput. On solicited disagreement, standing, and the objection you didn&apos;t know to ask for.</description><pubDate>Thu, 20 Aug 2026 07:52:00 GMT</pubDate><content:encoded>&lt;p&gt;You have two engineers and a fleet, and the board clears itself by Wednesday. Somebody asks whether you&apos;re hiring this quarter, so you open the req you wrote in the spring and read it like a stranger wrote it. Builds the feature. Writes the tests. Owns the migration. Every line on it is a thing you no longer have to buy, and the market rate for all of it is now somewhere around what you spend on lunch.&lt;/p&gt;
&lt;p&gt;So you close the req. On the numbers that&apos;s a defensible call, and I&apos;ve watched founders make it this year with more honest reasoning behind it than most hiring decisions ever get.&lt;/p&gt;
&lt;p&gt;The bill shows up a few months out, and not as a missed deadline. Velocity is the one thing that looks great. It shows up as a decision nobody argued about, discovered late, expensive to unwind.&lt;/p&gt;
&lt;h2&gt;the room got quieter as it got faster&lt;/h2&gt;
&lt;p&gt;Think about the last genuinely bad idea you took into a room. Not a typo. A direction: the schema you were sure about, the vendor you&apos;d already half-committed to, the rewrite you wanted for reasons you&apos;d have called technical at the time.&lt;/p&gt;
&lt;p&gt;Somebody said no. Maybe carefully, maybe not. If you were lucky they said it in front of other people. That no cost you a week of ego and saved you a quarter, and I&apos;d bet you can still name the person.&lt;/p&gt;
&lt;p&gt;Now run the same idea past a fleet. You describe the design, it builds the design. Push back and it agrees with the pushback, then rebuilds. Push back on the rebuild and it agrees again. If an objection comes at all it arrives as a paragraph above the code, and you can dissolve it by rephrasing the ask slightly, at which point you get exactly what you wanted, tested, documented, in a clean commit with a reasonable message.&lt;/p&gt;
&lt;p&gt;That agreeableness is trained in, not incidental. Anthropic&apos;s researchers published a paper on it: models finetuned on human feedback learn to match the user&apos;s stated belief over the more truthful answer, measured across five frontier assistants and four different generation tasks. The polite word for it in the literature is &lt;a href=&quot;https://arxiv.org/abs/2310.13548&quot;&gt;sycophancy&lt;/a&gt;. The practical version is that you are the only source of conviction in the loop, and the loop will happily route around you if you push.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;You can win any argument with a fleet by rewording the question.&lt;/div&gt;
  &lt;div&gt;Which means it was never an argument. It was a preference check that happened to be written in the second person.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You can prompt against this, and I do. Ask for the case against. Ask for three approaches with the tradeoffs named, ask which one it would kill. You get back something genuinely useful, and it is still a document you commissioned. Solicited disagreement is a checklist item. The objection that saves you is the one about the thing you didn&apos;t know to put on the checklist.&lt;/p&gt;
&lt;h2&gt;what the no is worth&lt;/h2&gt;
&lt;p&gt;At &lt;a href=&quot;/works/&quot;&gt;Brandfolder&lt;/a&gt; the product was crashing generating large zip files. Ruby was the wrong tool for that much IO, and the cheap answer was sitting right there on the table: throw hardware at it, buy a bigger instance, move on to the roadmap. That answer works for a while. It also compounds, because the shape of the problem doesn&apos;t change and the invoice does.&lt;/p&gt;
&lt;p&gt;We carved the zip pipeline out into Go instead, and shipped multi-gigabyte archives at minimal cost. The Go took days. The days weren&apos;t the valuable part. The valuable part was somebody in that room refusing the cheap answer while it was still cheap, and being willing to be wrong out loud about it.&lt;/p&gt;
&lt;p&gt;A fleet writes either version. Ask for autoscaling and you get clean autoscaling. Ask for the Go service and you get a clean Go service. It has no preference about which problem you were actually solving, because it isn&apos;t the one who finds out.&lt;/p&gt;
&lt;p&gt;The same instinct is why, at &lt;a href=&quot;/works/&quot;&gt;GigSmart&lt;/a&gt;, I kept the team senior where the system was load-bearing while we took two apps from zero in eight months. I&apos;d have told you then it was about code quality. Looking back, I was buying disagreement and putting it where a wrong call was most expensive to reverse.&lt;/p&gt;
&lt;h2&gt;standing&lt;/h2&gt;
&lt;p&gt;Here&apos;s the part that took me a while to say cleanly.&lt;/p&gt;
&lt;p&gt;The reason a person&apos;s objection carries weight isn&apos;t that they&apos;re smarter than the model. Plenty of days they aren&apos;t, and on raw recall they never are. It&apos;s that they have to live there afterward.&lt;/p&gt;
&lt;p&gt;An agent has no standing. It doesn&apos;t get paged at 2am by the thing it wrote. It doesn&apos;t inherit the file in March when a customer needs the behavior changed, doesn&apos;t sit in the retro, doesn&apos;t carry the reputation cost of having shipped it. It ends when the context window ends. A senior engineer telling you no is telling you no about their own next year, and that&apos;s exactly why it&apos;s uncomfortable and exactly why it&apos;s worth money.&lt;/p&gt;
&lt;p&gt;Standing is what makes a no expensive to give. Expensive is what makes it informative.&lt;/p&gt;
&lt;p&gt;Which reframes the whole headcount question. What that req was buying, underneath the bullet that said &quot;writes code,&quot; was somebody who would still be here to live with it, and the code was mostly just evidence that they would. &lt;a href=&quot;/writing/volume-is-free-now/&quot;&gt;Volume went to zero&lt;/a&gt; and took the evidence with it. The thing it was evidence of is still the most valuable input in the building.&lt;/p&gt;
&lt;h2&gt;how I staff for it now&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Hire for the argument, not the artifact.&lt;/b&gt; Everyone passes the take-home now, which is &lt;a href=&quot;/writing/anyone-can-pass-your-take-home/&quot;&gt;a filter that stopped filtering&lt;/a&gt;. Hand them a real decision you already made, ask them to attack it, and listen for whether they&apos;ll hold a position after you lean on it. The ones who fold under mild pressure from a hiring manager will fold under a founder with a deadline.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Put the seniority where the system is load-bearing.&lt;/b&gt; Not evenly. Judgment is expensive, so spend it where a bad call is hard to reverse: the data model, the boundaries, where state lives. Everywhere else the fleet plus review is genuinely fine.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Make refusal cheap to give.&lt;/b&gt; If saying no to you costs someone politically, you don&apos;t have dissent. You have a compliance layer with a salary, and it will agree with you at roughly the same rate the model does. The difference is you&apos;re paying market for it.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Don&apos;t count solicited disagreement as coverage.&lt;/b&gt; Ask the fleet for the case against by all means. Then keep a person whose job includes the objection nobody requested, and give them the room to bring it up at the wrong moment.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of this is an argument for a bigger team. I run lean and I&apos;d tell any founder to. It&apos;s an argument about what the seats are for, because if you staff on throughput math you&apos;ll conclude you need almost nobody, and the math will be right for about two quarters.&lt;/p&gt;
&lt;p&gt;The req is still open on my screen. I&apos;m not defending the version of it I wrote in the spring; half those bullets belong to the fleet now and I&apos;m not paying a person to race them. What I want to know before I close it is simpler and harder: when I&apos;m about to do something expensive and wrong, who in this building can tell me no and make it stick?&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He writes about engineering leadership, infrastructure, and building in the age of agents. If you&apos;re trying to work out what your next hire is actually for, &lt;a href=&quot;https://thebushido.co&quot;&gt;that&apos;s the work I do&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance, which is its own small joke in a piece about disagreement. The frame, the stories, and the calls on what stayed and what got cut are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>leadership</category></item><item><title>One Copy Per Customer</title><link>https://jasonwaldrip.com/writing/one-copy-per-customer/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/one-copy-per-customer/</guid><description>Per-customer forks look like responsiveness and bill like debt. Why customization belongs in configuration that cascades, how to tell a real fork from a lazy one, and what changes when agents make copies free.</description><pubDate>Tue, 18 Aug 2026 10:15:00 GMT</pubDate><content:encoded>&lt;p&gt;The customer asks for something small. One extra field on the portal, different copy on the second onboarding step, and could the logo sit on the other side. None of it is hard. The quickest way to say yes is to take what they already have, copy it, edit their copy, and ship it under their name. You say yes by Thursday. They tell their account manager you&apos;re the most responsive vendor they&apos;ve ever worked with, and they mean it.&lt;/p&gt;
&lt;p&gt;That was probably the right call, priced the way you priced it. An afternoon of work bought a renewal and a reference. The problem is that you paid for it at write time, and the rest of the invoice comes due at read time, spread across every person who touches that code after you, for as long as the customer exists.&lt;/p&gt;
&lt;p&gt;Nobody itemizes that part. It doesn&apos;t show up as a line anywhere. It shows up eleven customers later as a Tuesday.&lt;/p&gt;
&lt;h2&gt;the fix you will apply N minus one times&lt;/h2&gt;
&lt;p&gt;Here&apos;s the Tuesday. A real bug, in the shared part, the part that was shared right up until you started copying it. Auth, or a date rendering wrong for anyone east of London, or something in the upload path that eats files over a certain size.&lt;/p&gt;
&lt;p&gt;You fix it. Then you go find the eleven other places it lives, and you fix it there, and each one has drifted a little because each one has its own year of small edits on top. Two of them need the fix reshaped. One of them can&apos;t take it at all without unwinding a change someone made for a customer who churned in 2024.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;A fix that has to be applied eleven times is a fix you will apply ten times.&lt;/div&gt;
  &lt;div&gt;Not because anyone is careless. Because the eleventh copy is out of sight, the ticket is closed, and nothing in the system knows the other ten exist. The customer who finds the miss is the one who reports it, six months later, as a new bug.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Ask a support engineer at any company that grew this way and you&apos;ll get the same tell: before they can answer a question they have to ask which customer, and then go look. Not to check a config value. To go read that customer&apos;s code and find out what it does.&lt;/p&gt;
&lt;p&gt;That&apos;s the shape I care about. When &quot;what does the product do&quot; can only be answered per customer, by reading, you don&apos;t have a product with customers. You have a portfolio.&lt;/p&gt;
&lt;h2&gt;the friction that was doing all the work&lt;/h2&gt;
&lt;p&gt;For twenty years this pattern was self-limiting, and not because anyone was disciplined about it. It was limited because copies were work. Someone had to sit down and produce customer number twelve&apos;s version, and by around customer five that person was tired enough to walk into a room and argue for doing it properly.&lt;/p&gt;
&lt;p&gt;Fatigue was the governor. It was a bad governor, it fired late and it fired at random, but it fired.&lt;/p&gt;
&lt;p&gt;It doesn&apos;t anymore. Point a fleet at an existing bundle and ask for a variant with those three changes and you&apos;ll have it before the call ends, tested, documented, in a clean commit. The thing that used to make the fifth copy hurt has been removed, and the thing that makes the fiftieth copy expensive has not moved at all. &lt;a href=&quot;/writing/volume-is-free-now/&quot;&gt;Volume got cheap.&lt;/a&gt; Ownership didn&apos;t.&lt;/p&gt;
&lt;p&gt;So the pattern that used to cap out around a handful now runs until something else stops it, and I&apos;ve been in enough of these to know what usually stops it: a security patch that has to reach everyone by Friday.&lt;/p&gt;
&lt;h2&gt;what you were actually selling&lt;/h2&gt;
&lt;p&gt;Sit with what the customer bought, because it isn&apos;t what they think they bought.&lt;/p&gt;
&lt;p&gt;They think they bought a bespoke portal. What they actually bought is a difference. One field, one label, one arrangement. The difference is small and it is the entire product from where they sit, and none of that requires the difference to live in a copy of your codebase. It requires the difference to live somewhere your system can read.&lt;/p&gt;
&lt;p&gt;That&apos;s the whole reframe, and it&apos;s less about architecture than about where you put the variation. Copy the code and the variation lives in a diff nobody reads. Put it in configuration and the variation lives in a row you can query, audit, roll back, and hand to a support engineer who can answer the question without opening an editor.&lt;/p&gt;
&lt;p&gt;I&apos;m doing this right now at &lt;a href=&quot;/works/&quot;&gt;Phoneware&lt;/a&gt;. Portal features had grown up as per-customer JavaScript bundles, which is exactly the pattern above, arrived at honestly, one reasonable yes at a time. The replacement is one global bootstrap plus a manifest API that cascades &lt;b&gt;reseller → domain → role&lt;/b&gt;, with a configurator on top so the cascade is something you set rather than something you deploy. A new customer is a manifest, not a branch. A feature that six customers want is one module, enabled six times.&lt;/p&gt;
&lt;p&gt;The cascade is the part I&apos;d defend hardest. Most customization isn&apos;t per customer at all, it&apos;s per tier, per reseller, per role, and a copy flattens all of that into one undifferentiated snowflake. Inheritance keeps the shape of the business visible in the shape of the config. When somebody asks why this customer sees that, the answer is a lookup and not an investigation.&lt;/p&gt;
&lt;h2&gt;the test&lt;/h2&gt;
&lt;p&gt;Not every fork is wrong. Some differences are real, and pretending otherwise gives you a config system with three hundred switches, which is a fork in a worse costume. Feature flags earn their keep the same way and carry the same failure: a flag you never delete is a permanent branch in your logic, which is what the &lt;a href=&quot;/choices/feature-flags/&quot;&gt;flags page&lt;/a&gt; on this site calls the cleanup you don&apos;t get to skip.&lt;/p&gt;
&lt;p&gt;So I use one question, and it fits on a sticky note. &lt;strong&gt;Can you name the axis?&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;If the difference varies along something you can name, it&apos;s configuration.&lt;/b&gt; Plan tier, region, reseller, role, locale, brand. Named axes compose. Add the customer to the axis and the work is a row.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;If the difference is &quot;because it&apos;s them,&quot; you have a services engagement.&lt;/b&gt; That can be a fine business, and I&apos;ve watched good companies make real money on it. It just has to be priced and staffed as one, with the maintenance in the contract, instead of hiding inside a product margin that assumed one codebase.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;If a customer needs a genuinely different domain model, fork it on purpose.&lt;/b&gt; Different product, different repo, different roadmap, said out loud. A deliberate fork you&apos;ve named is survivable. The dangerous fork is the one nobody ever decided to create.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;If you can&apos;t tell, count.&lt;/b&gt; How many places would you have to edit to change the login screen for everyone? Say the number to your CEO. It&apos;s the most honest architecture metric I know, and it takes about a minute to find.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The number is usually worse than the team guesses, and the gap between the guess and the number is the actual finding. It means the copies were being made faster than anyone was tracking, which was true when a person made them and is much more true now.&lt;/p&gt;
&lt;h2&gt;the next small ask&lt;/h2&gt;
&lt;p&gt;None of this makes the copy the villain. Copying was the right move on the day, with the information available, on a deadline that was real. I&apos;ve made that call. Anyone who has shipped to enterprise customers has made that call, and the alternative on that particular Thursday was telling a customer no while a competitor told them yes.&lt;/p&gt;
&lt;p&gt;What changed is the rate. You&apos;re not making five of these decisions a year anymore, you&apos;re making them at whatever speed your fleet can produce, and the cost of each one still lands years later on somebody who wasn&apos;t in the room. That&apos;s the part worth being deliberate about, because deliberate is now the only governor left.&lt;/p&gt;
&lt;p&gt;The next customer is going to ask for something small. Saying yes isn&apos;t the question. The question is whether your yes has somewhere to live besides a copy with their name on it.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He writes about engineering leadership, infrastructure, and building in the age of agents. If your product has quietly become one codebase per customer, &lt;a href=&quot;https://thebushido.co&quot;&gt;that&apos;s the work I do&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the client work, and the calls on what stayed and what got cut are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>architecture</category></item><item><title>Anyone Can Pass Your Take-Home</title><link>https://jasonwaldrip.com/writing/anyone-can-pass-your-take-home/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/anyone-can-pass-your-take-home/</guid><description>AI made every interview submission look good, so hiring signal collapsed. Why take-homes and screens were always proxies for judgment, and how to test for judgment directly instead.</description><pubDate>Fri, 14 Aug 2026 09:35:00 GMT</pubDate><content:encoded>&lt;p&gt;You open the first take-home. Clean commit history, real tests, a README that explains the tradeoffs. Good candidate. You open the second one. Also clean, also tested, also a thoughtful README. You open the third and the fourth and somewhere in there you stop reading carefully, because they&apos;re all good, and &quot;all good&quot; is another way of saying you now know nothing about any of them that you didn&apos;t know before you sent the assignment.&lt;/p&gt;
&lt;p&gt;Then you do the honest thing and ask yourself how much of that you could produce in an afternoon without writing a line. The answer is most of it. The answer has been most of it for a while.&lt;/p&gt;
&lt;p&gt;Sit in that before reaching for a fix, because the reflex fix is bad. The reflex is to make the assignment harder, or to proctor it, or to ban the tools. All three assume the assignment still measures something and just needs protecting. It doesn&apos;t.&lt;/p&gt;
&lt;h2&gt;the proxy nobody named&lt;/h2&gt;
&lt;p&gt;Nobody ever wanted to hire someone for their ability to produce a working CRUD endpoint. That was never the trait. The trait is something like: given an ambiguous situation, a deadline, and four plausible directions, this person picks a good one and knows why.&lt;/p&gt;
&lt;p&gt;You can&apos;t observe that in ninety minutes. So the industry built proxies. Ship a small thing under mild time pressure and let me read the result, because the shape of the result leaks the reasoning behind it. Which corners you cut. Whether you wrote the test for the thing that would actually break. Whether you reached for a framework the problem didn&apos;t earn.&lt;/p&gt;
&lt;p&gt;That proxy worked for one reason, and it wasn&apos;t that anyone thought it was a great simulation of the job. It worked because production was expensive. Four hours of your Saturday bought me a signal that was hard to fake, not because you were being watched, but because faking it cost about as much as doing it. The cost was the honesty. Remove the cost and you&apos;ve removed the mechanism, not just the difficulty.&lt;/p&gt;
&lt;h2&gt;both ends automated at once&lt;/h2&gt;
&lt;p&gt;The résumé went first and nobody mourned it. Candidates generate applications by the hundred now, tailored per posting, and the whole genre collapsed into noise. So companies answered with automated screening, which candidates answered with keyword-shaped generated résumés, which companies answered with more filtering.&lt;/p&gt;
&lt;p&gt;Two systems are now talking to each other at volume, and no human on either end learns anything. The candidate doesn&apos;t learn whether the job is right. The company doesn&apos;t learn whether the person is. Every round trip burns real time from a person who has a finite amount of it, which is the part I actually mind. If you believe time is worth more than capital (I do, it&apos;s on my &lt;a href=&quot;/about/&quot;&gt;about page&lt;/a&gt; and it isn&apos;t decoration) then a hiring process that wastes forty hours of a good engineer&apos;s month to produce a coin flip isn&apos;t neutral. It&apos;s a cost you&apos;re imposing on people, and you should be able to say what you bought with it.&lt;/p&gt;
&lt;p&gt;Right now most loops can&apos;t say. They&apos;re running a test that everyone passes and treating the pass as information.&lt;/p&gt;
&lt;h2&gt;the ten minutes I actually got paid for&lt;/h2&gt;
&lt;p&gt;Brandfolder, 2015. Ruby was crashing generating large zip files. Heavy IO, wrong tool for the shape of the workload. We carved that piece out into Go and shipped multi-gigabyte archives at minimal cost.&lt;/p&gt;
&lt;p&gt;Imagine that as a take-home. &quot;Here&apos;s a service that times out generating large archives. Fix it.&quot; A strong candidate in 2015 profiles it, finds the allocations, streams the response instead of buffering it, adds a test, writes a clear PR description. Genuinely good work. A fleet of agents does all of that today before lunch, and does it well.&lt;/p&gt;
&lt;p&gt;Neither one, unprompted, stops and says the language is wrong for this workload. That call took about ten minutes. It was worth more than everything I typed that year, and no take-home I&apos;ve ever seen would have surfaced it, because the assignment already contains the assumption that the code in front of you is the code that should exist.&lt;/p&gt;
&lt;p&gt;Which points at the actual test. Don&apos;t ask someone to build the thing. Ask them what they would delete.&lt;/p&gt;
&lt;h2&gt;test the half nobody submits&lt;/h2&gt;
&lt;p&gt;Every technology &lt;a href=&quot;/choices/&quot;&gt;choice on this site&lt;/a&gt; is written in two halves: when I reach for it, and when I don&apos;t. The second half is where the credibility lives, and it&apos;s the half that generated work almost never produces, because a model asked to justify a stack will justify the stack. Ask it when the stack is wrong and you get a general answer. Ask a person who has operated one at 2am and you get a specific one, usually with a scar attached.&lt;/p&gt;
&lt;p&gt;So build the loop around the second half.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Give them a real decision, already made, and slightly wrong.&lt;/b&gt; A repo where something load-bearing was chosen badly, and several things were chosen fine. Ask what they would change, what they would leave, and what they would need to know before touching either. Watch what they leave alone. Restraint is the trait, and it&apos;s invisible on a build-it assignment because building rewards touching everything.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Ask when they wouldn&apos;t use the thing they&apos;re best at.&lt;/b&gt; The Kubernetes person who can&apos;t describe the team size below which it&apos;s a tax hasn&apos;t operated it, they&apos;ve installed it. At CommercialTribe I moved us onto GCP and Kubernetes because it was the cheapest path to stability at our load. That sentence carries a load. Someone who says the same words with no load behind them is telling you about a conference talk.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Hand them the fleet and watch how they drive.&lt;/b&gt; Banning the tools tests for a job that no longer exists. Let them use whatever they&apos;d use on a Tuesday, then read the transcript instead of the diff. Where did they accept output, where did they push back, what did they check before believing it? That transcript is the closest thing to a direct recording of judgment I&apos;ve found, and it didn&apos;t exist three years ago.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Pay for anything long.&lt;/b&gt; If the exercise is big enough to be worth reading, it&apos;s big enough to be worth paying for. Real ownership, not the story of it, starts before the offer letter.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of that scales the way a take-home scales, and I&apos;m not going to pretend otherwise. It takes a senior person&apos;s real attention per candidate, which is expensive, and the whole appeal of the take-home was that it converted attention into homework. That trade is over. The homework is free now, and free homework tells you nothing, so the attention comes back onto your side of the table whether you budgeted for it or not.&lt;/p&gt;
&lt;h2&gt;what you&apos;re hiring against&lt;/h2&gt;
&lt;p&gt;Here&apos;s the part that makes this urgent rather than merely annoying.&lt;/p&gt;
&lt;p&gt;When production was expensive, a mediocre hire was slow. They shipped less, you noticed, you corrected. The cost of a bad judgment call was bounded by how fast one person could type it into existence.&lt;/p&gt;
&lt;p&gt;That bound is gone. Point someone with weak judgment at a fleet and they will produce an enormous amount of confident, well-tested, beautifully documented work in the wrong direction, and it will look exactly like the work of someone with strong judgment right up until you&apos;re a quarter deep in a design that can&apos;t hold. The blast radius of a hiring mistake scaled with everything else. Multiply judgment by a fleet and you get something new. Multiply the absence of it by the same fleet and you get a much larger version of the same nothing, faster.&lt;/p&gt;
&lt;p&gt;So the loop that mattered least when hands were the constraint matters most now that they aren&apos;t. That&apos;s an uncomfortable place to land, because the answer isn&apos;t a better assignment. It&apos;s more of the thing you were trying to avoid spending: a senior person, in the room, asking questions that can&apos;t be answered from a general model of the world.&lt;/p&gt;
&lt;p&gt;What&apos;s the last decision you made that a very good, very fast machine would have gotten wrong? If you can answer that about yourself in specifics, you know what to ask a candidate. If you can&apos;t, that&apos;s the more interesting problem, and it isn&apos;t a hiring problem.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He writes about engineering leadership, infrastructure, and building in the age of agents. If your team is scaling past the loop that got it here, &lt;a href=&quot;https://thebushido.co&quot;&gt;that&apos;s the work I do&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the stories, and the calls on what stayed and what got cut are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>judgment</category></item><item><title>Nothing type-checks a comment</title><link>https://jasonwaldrip.com/writing/nothing-type-checks-a-comment/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/nothing-type-checks-a-comment/</guid><description>Last night I caught a comment on my own site claiming a set of type aliases would stop a refactor from passing the wrong shape into a drawing routine. Underneath it, a point was typed as a plain array of numbers. A three-number point compiled fine. The comment documented intent and enforced nothing, and the checker never objected, because the code was consistent. Just not with the promise above it. Two options: soften the comment, or make it true. True cost four annotations. When the fleet writes the code and the prose in one pass, the prose is the only artifact with nothing checking it.</description><pubDate>Wed, 12 Aug 2026 08:20:00 GMT</pubDate><content:encoded>&lt;p&gt;Last night I caught a comment on my own site claiming a set of type aliases would stop a refactor from passing the wrong shape into a drawing routine. Underneath it, a point was typed as a plain array of numbers. A three-number point compiled fine. The comment documented intent and enforced nothing, and the checker never objected, because the code was consistent. Just not with the promise above it. Two options: soften the comment, or make it true. True cost four annotations. When the fleet writes the code and the prose in one pass, the prose is the only artifact with nothing checking it.&lt;/p&gt;</content:encoded><kind>take</kind><category>judgment</category></item><item><title>Still the Painter</title><link>https://jasonwaldrip.com/writing/still-the-painter/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/still-the-painter/</guid><description>AI took the delivery mechanism, not the thing that made you valuable. Why cheap generation increases your capability instead of erasing it, whether you ship code, records, or layouts, and what you were actually being paid for.</description><pubDate>Sun, 09 Aug 2026 16:20:00 GMT</pubDate><content:encoded>&lt;p&gt;The thread is always the same thread. AI is taking our jobs, we&apos;re all cooked, learn a trade. A few hundred comments deep, and every one of them is a version of the same fear, written by people who are genuinely good at this and just watched something turn their best week into an afternoon. I read a lot of it before I closed the tab.&lt;/p&gt;
&lt;p&gt;The one I was reading happened to be engineers. It could have been any of them. The illustrators are having it, the session players are having it, the designers are having it, the copywriters had it first and loudest. Same fear, same comment ordering, different room. They&apos;re all right about what they noticed. Then they take a leap, and the leap is wrong.&lt;/p&gt;
&lt;p&gt;Start with the part they got right, because it&apos;s real and pretending otherwise is worse than useless. You spent ten years getting fast. Then you described a thing in a paragraph and got back a tested branch, or a finished layout, or a demo that would have cost you a weekend, before your coffee was cold. The floor moved. That&apos;s not imagined. I&apos;ve written the long version of it already: &lt;a href=&quot;/writing/volume-is-free-now/&quot;&gt;volume got commoditized&lt;/a&gt;, and if your value is denominated in output, you&apos;re now in a race with something that doesn&apos;t sleep, doesn&apos;t get bored, and doesn&apos;t have opinions about the brief.&lt;/p&gt;
&lt;p&gt;The leap comes right after. Volume is free, therefore I am worthless. Every thread makes it, usually within three comments, and nobody stops to check it. It only follows if the volume was the thing that made you valuable in the first place.&lt;/p&gt;
&lt;p&gt;It wasn&apos;t. And I know that because I ran the experiment on myself for eight years.&lt;/p&gt;
&lt;h2&gt;the badge that was actually a warning&lt;/h2&gt;
&lt;p&gt;By the time I left GigSmart I&apos;d written something like one in five commits in the company&apos;s history. Most of anyone, by a wide margin, across the app, the libraries, the infra, the build, the deploy path. There was no hour on the clock without my name on something. For a long time I wore that like a badge.&lt;/p&gt;
&lt;p&gt;It was a load-bearing wall with a green contribution graph. I&apos;ve made that argument before and I&apos;m not going to relitigate it here. The part that matters here is more personal: I had priced myself in throughput. Ask me what I was worth and the honest answer, the one underneath the one I&apos;d have said out loud, was a number of commits. That&apos;s the same math those threads are doing. I just did it while the number was going up, so it felt like confidence instead of fear.&lt;/p&gt;
&lt;p&gt;Both are the same mistake. You only feel it when the supply of the thing you&apos;re counting suddenly goes infinite.&lt;/p&gt;
&lt;h2&gt;what you were actually paid for&lt;/h2&gt;
&lt;p&gt;Brandfolder, 2015. Ruby was crashing generating large zip files. Heavy IO, wrong tool for the shape of the problem. We carved that one piece out into Go and shipped multi-gigabyte archives at minimal cost.&lt;/p&gt;
&lt;p&gt;Point a fleet of agents at that codebase today and they&apos;ll do good work. They&apos;ll profile it, cache what&apos;s cacheable, thread what Ruby lets you thread, chase the allocations, and hand you a well-documented improvement with tests. What they will not do, unprompted, is stop and say the language is wrong for this. That call took about ten minutes. It was worth more than every line I wrote that year.&lt;/p&gt;
&lt;p&gt;The ten minutes is what I was paid for. The code that followed was just how the ten minutes got expressed, because in 2015 there was no other way to express it. If you wanted a decision to become a real thing, somebody had to sit down and type it out, and the typing was slow, so the typing looked like the job. It was the delivery mechanism for the job.&lt;/p&gt;
&lt;p&gt;That&apos;s the confusion at the bottom of every one of those threads. Whole professions spent decades being measured by their delivery mechanism, because the delivery mechanism was the bottleneck, and bottlenecks are what people measure. Then the bottleneck moved and everyone assumed their worth moved with it.&lt;/p&gt;
&lt;p&gt;Test it on your own work, whatever your work is. The moment you knew the layout was fighting the content and the entire grid had to change. The take where you heard the arrangement was too busy and pulled three parts out instead of adding a fourth. Nobody was paying you for the hours of nudging type or re-tracking the part. They were paying for the ten seconds where you knew which way to go, and then for your willingness to go spend the weekend making it exist, because spending the weekend was the only way anyone would ever see the call you made.&lt;/p&gt;
&lt;h2&gt;run the arithmetic again&lt;/h2&gt;
&lt;p&gt;Here&apos;s the thing nobody in those threads does, which is take the change seriously in the other direction.&lt;/p&gt;
&lt;p&gt;Your judgment didn&apos;t get cheaper. It got a bigger surface. The calls you can make in a day used to be capped by how much you could personally produce, because you spent most of the week being the supply. You&apos;d make a handful of genuinely consequential decisions and then go implement them, and the implementing is where the week went. Now the implementing is cheap, and the cap is off. You can make those calls all day, and each one lands across more work than your hands could ever have reached.&lt;/p&gt;
&lt;p&gt;That&apos;s not a smaller job. That&apos;s the same job with the friction removed and the blast radius multiplied. Your capability went up. What went down is the share of your day spent proving it.&lt;/p&gt;
&lt;p&gt;The catch is the same one it&apos;s always been, and it deserves one sentence rather than a section: a multiplier only works on what you feed it. Multiply real judgment by a fleet and you get something genuinely new. Multiply nothing by the same fleet and you get a beautifully formatted disaster, faster. Anything times zero is still zero.&lt;/p&gt;
&lt;p&gt;So the question those threads should be asking isn&apos;t whether the machine can do what you do. It&apos;s whether you were ever clear on what you do.&lt;/p&gt;
&lt;h2&gt;the brush and the painter&lt;/h2&gt;
&lt;p&gt;A painter with a studio of assistants grinding pigment, stretching canvas, and laying in the underpainting is still the painter. Nobody stands under a chapel ceiling and credits the scaffolding. The assistants were real, they did real work, and the work is still his, because the thing that made it worth looking at never lived in the brush.&lt;/p&gt;
&lt;p&gt;We already accept this everywhere else and find it completely unconfusing. The producer who plays none of the instruments made the record. The director never touches the camera. The architect has not laid a brick in thirty years and the building is still hers. Nobody has ever suggested a novelist owes the credit to the typesetter.&lt;/p&gt;
&lt;p&gt;The ideas are yours. The origination is yours. The taste that says this one and not that one, the sense of which problem is worth a week and which one should be deleted, the twenty years that turn a crash, or a mix that will not sit still, into ten minutes of diagnosis. None of that moved. You may not be holding the brush anymore. You&apos;re still the painter.&lt;/p&gt;
&lt;p&gt;The people in those threads aren&apos;t mourning their capability. They&apos;re mourning the only proof of it they ever had, and they haven&apos;t yet found the new one. That&apos;s a real loss and it&apos;s worth about a week of feeling bad. Then you get to the better problem, which is what to do with a calendar that suddenly has room in it, and a fleet that will build anything you can decide on.&lt;/p&gt;
&lt;p&gt;That&apos;s a much harder question than the one on Reddit. It&apos;s also a much better one.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He writes about engineering leadership, infrastructure, and building in the age of agents.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the experience, and the calls on what stayed and what got cut are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>ai</category></item><item><title>You Can&apos;t Parallelize a Certificate</title><link>https://jasonwaldrip.com/writing/you-cant-parallelize-a-certificate/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/you-cant-parallelize-a-certificate/</guid><description>A go-live that lasted forty-four seconds, and what it taught me about where the real constraint moved. When a fleet makes generation free, the binding cost becomes serial external latency: certificates, DNS, verifications, reviews. You can&apos;t parallelize a wait. You can only start it sooner.</description><pubDate>Sat, 08 Aug 2026 00:01:00 GMT</pubDate><content:encoded>&lt;p&gt;At 11:18 and 54 seconds on a Wednesday night, I merged the pull request that moved one of my products onto its real domain. At 11:19 and 38 seconds, I reverted it. Forty-four seconds of being live, most of which I spent reading an error.&lt;/p&gt;
&lt;p&gt;Nothing was wrong with the code. The apex was cut over, the records were right, the app was healthy and serving. The certificate did not exist yet.&lt;/p&gt;
&lt;p&gt;So I spent the next hour doing the least interesting work in software. At 11:57 I added the ACME challenge record so the certificate could issue. At 12:12 I wrote the ownership claim the host had started expecting. At 12:33 I set up the www redirect, because at that point I was just doing whatever was adjacent while I waited. Somewhere in the middle of that, I said something out loud that I happen to have a recording of, because I wear a device that catches this sort of thing:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;The SSL cert should not take this long. Says it&apos;ll take up to 24 hours, but that&apos;s bullshit.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And a few minutes later, to nobody:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Minting, minting, minting.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was not wrong. It should not take that long. Being right about it changed nothing at all, which is a distinction I apparently needed to learn twice, because the next afternoon I did it again. 11:47am, merged the captive portal onto its production host. 1:21pm, reverted it. Ninety-four minutes that time, so call it progress. The commit I wrote to clean it up says, in full: &lt;em&gt;stage the prod cert before flipping the host&lt;/em&gt;. I wrote the lesson into the log thirteen hours after the first time I had learned it, and I still did not hear myself say it.&lt;/p&gt;
&lt;h2&gt;the part that actually got fast&lt;/h2&gt;
&lt;p&gt;Here is the context that makes those two nights worth writing about instead of just wincing at.&lt;/p&gt;
&lt;p&gt;Over those five weeks I put 3,206 commits across 25 repositories, with at least one commit on all 38 days. I am not citing that to impress anybody. I am citing it because it is the setup: throughput was not my problem. It has not been my problem for a while now. When I want a feature, a migration, a whole service, I describe it and a fleet of agents builds it while I look at something else.&lt;/p&gt;
&lt;p&gt;The day after the second revert I was on a call and said the thing I actually believe, which I also have on tape:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;I literally can&apos;t imagine a software project that I couldn&apos;t use AI to fully write in two weeks.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I still believe that. In the same breath I said the leftover slice, the serial stuff, was the tedious part that does not compress. Right shape, wrong content. I thought the leftover was the gnarly code, the integration nobody wants to touch, the last mile of polish. It is not any of that. The fleet eats all of it.&lt;/p&gt;
&lt;h2&gt;the last five percent has a clock, not a keyboard&lt;/h2&gt;
&lt;p&gt;Look at what actually stopped me on both of those nights.&lt;/p&gt;
&lt;p&gt;An ACME validation. A DNS record propagating. A certificate authority working through its queue. In the same month I also lost time to a domain verification that had to round-trip through a provider&apos;s email, a payment processor&apos;s review, and a mail sending domain that would not accept traffic until somebody else&apos;s system agreed it was verified.&lt;/p&gt;
&lt;p&gt;Not one of those is hard. Not one of them required a single idea from me. Every one is a &lt;em&gt;wait&lt;/em&gt;, owned by somebody else&apos;s infrastructure, and completely indifferent to how much capacity I brought.&lt;/p&gt;
&lt;p&gt;That is the shape of the constraint now. Everything a fleet is extraordinary at is parallel and internal: six agents, six branches, six problems, no coordination cost between them. Everything that ruins a launch is serial and external. You can run six agents against a certificate request and you will get one certificate, at exactly the same time you would have gotten it with zero agents.&lt;/p&gt;
&lt;p&gt;You cannot parallelize a certificate. You can only ask for it earlier.&lt;/p&gt;
&lt;h2&gt;the boring commit that would have saved the night&lt;/h2&gt;
&lt;p&gt;Which reframes what skill is worth having. For most of my career the question that separated people was some version of &lt;em&gt;can you build this&lt;/em&gt;. That question is dissolving. The one that replaced it is quieter: &lt;strong&gt;do you know which clocks to start before you need them?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The commit that would have saved me that Wednesday is embarrassingly dull. Request the certificate in the afternoon. Park it. Go build something else for six hours. Flip the host when the certificate is already sitting there, ready. It generates nothing. It ships no feature. It would not survive a code review as anything other than housekeeping, and it was worth more than everything else I merged that night.&lt;/p&gt;
&lt;p&gt;And a fleet makes this trap worse, not better, which took me a while to see. When generation was slow, the calendar spaced things out for you. You built for three days and hit the external dependency on a Tuesday afternoon with plenty of runway. Now I can build the entire cutover in one evening, which means I arrive at somebody else&apos;s queue faster, with more momentum, later at night, and with exactly the same 24 hour wait sitting in front of me. Speed does not shorten the wait. It just gets you to it while the sun is down.&lt;/p&gt;
&lt;p&gt;So the forty-four seconds were never the failure. The failure happened around 6pm, when I had everything I needed to start that clock and chose to build features instead, because building is the part that feels like progress.&lt;/p&gt;
&lt;p&gt;I have started keeping a different list now. Not what I need to build this week. What I will be standing around waiting for, and whether I could have asked for it this morning.&lt;/p&gt;
&lt;p&gt;What is on yours?&lt;/p&gt;
</content:encoded><kind>essay</kind><category>judgment</category></item><item><title>The Man Who Tells Other People&apos;s Stories</title><link>https://jasonwaldrip.com/writing/the-man-who-tells-other-peoples-stories/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-man-who-tells-other-peoples-stories/</guid><description>A man can talk all evening and never appear in a single story he tells. On the difference between a story told to be admired and one handed over to be used, and why the best mentors ask before they give.</description><pubDate>Fri, 07 Aug 2026 19:20:00 GMT</pubDate><content:encoded>&lt;p&gt;You already know him. He can hold a porch for two hours and never once appear in a single story he tells.&lt;/p&gt;
&lt;p&gt;He met someone famous at an airport, and he&apos;ll set the whole scene. He knows what the man down the street walked away with when the company sold, down to the number. He had the idea for that product years before it shipped, and he&apos;ll tell you he had it, and he means it. Every sentence is a small deposit into a ledger only he keeps. The stories are good. He tells them well. You could sit there all night, and plenty of people have.&lt;/p&gt;
&lt;p&gt;There&apos;s a second man on that porch, and for a while you barely notice him, because he isn&apos;t performing. At some point he turns to the youngest person there and asks a real question. Not the polite kind. What are you trying to build. What do you actually want. Then he does the two things the first man never does. He waits for the whole answer. And then he tells exactly one story, the one that happens to be about the thing the kid just said, and he hands it over like a tool.&lt;/p&gt;
&lt;p&gt;Ask most people which of the two lived the bigger life and they&apos;ll point at the talker. He has the material. He has the reach, the proximity, the anecdotes. The second man told one story all night.&lt;/p&gt;
&lt;p&gt;I think it&apos;s backwards, and the reason has nothing to do with talking. Both men talked. Only one of them gave anything away.&lt;/p&gt;
&lt;h2&gt;whose stories are they&lt;/h2&gt;
&lt;p&gt;Go back and listen to what the first man actually said. A famous person he stood next to. Money that somebody else made. An idea he had and never chased. An accolade that, when you turn it over, is really an excuse in a nicer jacket: the thing came so easy to him he never bothered to finish it. Line them up and a pattern shows through the whole evening. Almost none of the stories are his. He appears in each one only as a witness, a neighbor, a man who happened to be in the room.&lt;/p&gt;
&lt;p&gt;That&apos;s the thing about this kind of talker. He isn&apos;t lying. He&apos;s curating. He has spent a life standing next to lives, and he&apos;s built a highlight reel out of the standing.&lt;/p&gt;
&lt;p&gt;An idea you never acted on is not an accomplishment. It&apos;s a story you tell. The distance between the man who had the idea and the man who built the thing is the entire distance, and no amount of retelling closes it. You can narrate the thing you almost did. You can&apos;t narrate having done it.&lt;/p&gt;
&lt;p&gt;But notice what&apos;s missing even from the parts that are true. Somewhere in that man is a real life with real scars, and not one of them got aimed at the kid sitting three feet away.&lt;/p&gt;
&lt;h2&gt;who the story is for&lt;/h2&gt;
&lt;p&gt;So the divide runs somewhere other than talking and listening. It runs between the man whose stories are for himself and the man whose stories are for you.&lt;/p&gt;
&lt;p&gt;Wisdom nobody passes down dies with the man who earned it, and that wastes the entire life that paid for it. Hoarding it is worse than telling it badly. The second man on the porch isn&apos;t the quiet one because silence is a virtue. He&apos;s quiet at the start because he&apos;s aiming, and you can&apos;t aim at a target you haven&apos;t asked about.&lt;/p&gt;
&lt;p&gt;That&apos;s the whole function of the question. It isn&apos;t manners. It&apos;s reconnaissance. He wants to know what you&apos;re stuck on before he decides which forty years to hand you, because the story that saves you is a specific one and he only gets a few shots before you stop listening.&lt;/p&gt;
&lt;p&gt;And a question does something a story can&apos;t. A story is a monologue, finished the second he stops talking. A question opens a conversation, and a conversation needs the other person to exist. The teller performs a life. The asker starts something he can&apos;t finish alone, which is the point, because now you&apos;re in it too.&lt;/p&gt;
&lt;p&gt;The most durable thing I&apos;ve ever shipped is other engineers, and none of that transferred by me narrating my wins. It transferred when somebody was stuck on the exact thing I&apos;d already been stuck on, and I handed them the specific scar. Same story either way. The difference was whether I told it to be admired or handed it over to be used.&lt;/p&gt;
&lt;h2&gt;what the porch is really testing&lt;/h2&gt;
&lt;p&gt;Here&apos;s the test, and you can run it on yourself tonight. Listen to how much of what you say is a thing you did, and how much is a thing you watched, or almost did, or heard about secondhand. Then listen for who your stories are aimed at. Not whether you tell them. Whether anyone in the room can pick one up and carry it out the door.&lt;/p&gt;
&lt;p&gt;The most successful man on that porch had lived enough to have something worth handing down, and he cared enough to find out what you needed before he handed it over. He told his story too. He just made sure it was yours to keep.&lt;/p&gt;
&lt;div&gt;&lt;p&gt;Written with AI assistance. The man on the porch is a type, not a person.&lt;/p&gt;&lt;/div&gt;</content:encoded><kind>essay</kind><category>life</category></item><item><title>The Fleet Can&apos;t Read the Customer</title><link>https://jasonwaldrip.com/writing/the-fleet-cant-read-the-customer/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-fleet-cant-read-the-customer/</guid><description>Agents can read your repo, your docs, your types, and your tickets. They can&apos;t read the customer. Why customer proximity is the one input a fleet can&apos;t get, and why it&apos;s the engineering skill that now compounds.</description><pubDate>Fri, 07 Aug 2026 08:33:00 GMT</pubDate><content:encoded>&lt;p&gt;It&apos;s Tuesday. The board has ten cards on it. The fleet can build any one of them by lunch, and probably three of them by end of day. So the question that used to eat your week, can we build this, is already answered. Yes. All of it. Now what.&lt;/p&gt;
&lt;p&gt;The hard part moved, and most orgs haven&apos;t noticed where it went. For twenty years the scarce thing was throughput. Building software was slow and expensive, so every process we built was an answer to the same question: how do we get more code out the door per engineer. That&apos;s a reasonable thing to optimize when the bottleneck is the building. It stops being reasonable the moment the building gets cheap.&lt;/p&gt;
&lt;p&gt;And the building got cheap. Not a little cheaper. The floor fell out. A fleet of agents will now turn a clear spec into a working, tested branch faster than you can write the spec. If your whole operating model still assumes throughput is the constraint, you&apos;re tuning the one thing that stopped mattering.&lt;/p&gt;
&lt;h2&gt;the customer got walled off, on purpose&lt;/h2&gt;
&lt;p&gt;Here&apos;s the part that&apos;s easy to miss because it happened so slowly. While we spent two decades optimizing for throughput, we quietly moved the engineer as far from the customer as the org chart would allow. Sales talks to the customer. Product talks to sales. A PM talks to product. And the engineer gets a Jira card, which is the customer&apos;s actual problem after three rounds of translation, with the context sanded off.&lt;/p&gt;
&lt;p&gt;That was defensible when building was the expensive step. You wanted your expensive people heads-down, shipping, not sitting in support queues. Protect the throughput. It made sense.&lt;/p&gt;
&lt;p&gt;I came up the other way. I started at the edge, at a CDN, as a sales engineer. In the room with Blizzard and Disney and YouTube while they described what they actually needed, watching them wince at the thing that didn&apos;t fit before anyone wrote a line to build it. Then I spent twenty years moving closer to owning the build. Sales engineer, product, QA, team lead, CTO. Every step was the same deliberate move: pair knowing what to build with the ability to actually build it. I thought I was climbing toward the code. What I was really doing was refusing to let go of the edge on the way up.&lt;/p&gt;
&lt;h2&gt;what your agents can read, and the one thing they can&apos;t&lt;/h2&gt;
&lt;p&gt;Look at everything you can hand a fleet of agents. The repo, all of it, every file. The docs, if you kept them. The type signatures. The test suite. The commit history and the reasoning behind it, if your team wrote the why down. Point good agents at that and they will out-read any human on your team. They hold the whole system in context at once, which no person has ever been able to do.&lt;/p&gt;
&lt;p&gt;Now name the one input that isn&apos;t in any of that.&lt;/p&gt;
&lt;p&gt;Every artifact I just listed is downstream of a decision somebody already made about what to build. The repo is the answer to a question. The tickets are the answer to a question. The API shape is the answer to a question. And the question came from a person, sitting somewhere, with a problem they mostly can&apos;t articulate, who is not in your training data and is not on your board. The fleet can read the entire record of every decision you&apos;ve ever made. It cannot sit in the sales call where the next one gets made.&lt;/p&gt;
&lt;div&gt;&lt;div&gt;The customer is the one spec that isn&apos;t in the context window.&lt;/div&gt;&lt;div&gt;Everything your agents read is the residue of a decision about what to build. The decision came from a room they were never in.&lt;/div&gt;&lt;/div&gt;
&lt;h2&gt;the reframe&lt;/h2&gt;
&lt;p&gt;So the leverage inverted, and hardly anyone has repriced it. For twenty years, seniority meant moving up and away from the customer: edge, then architecture, then a title and a calendar full of meetings about the work instead of the work. The customer was for the junior folks and the support rotation. That direction was a promotion.&lt;/p&gt;
&lt;p&gt;When building is free, that direction is a liability. The scarce, un-automatable input is knowing which of the ten cards is the one that matters, and that knowledge was never in the codebase. It&apos;s in the room. The engineer who has been in that room can direct a fleet at the right target on the first try. The engineer three translations removed can direct it beautifully at the wrong one, and the fleet will build the wrong thing faster and cleaner than ever, which is worse, not better.&lt;/p&gt;
&lt;p&gt;This is why the best software shops have always put engineers on support. 37signals has argued for decades that the people building the thing should feel the customer directly, and did it when everyone else called it a waste of expensive time. That looked like a values choice for years. It was a bet on exactly this: that the day building got cheap, the companies whose engineers already knew the customer would aim straight, and the ones who had optimized their engineers into a Jira feed would keep shipping polished answers to questions nobody asked.&lt;/p&gt;
&lt;h2&gt;get back to the edge&lt;/h2&gt;
&lt;p&gt;I&apos;m not saying disband product or fire the PMs. I&apos;m saying the twenty-year trend that treated distance from the customer as a mark of seniority is now backwards, and you can feel it if you&apos;re honest about that board. You can build anything on it this afternoon. So can your competitor. The thing you can&apos;t both do is know which one is worth building, and that isn&apos;t a knowledge problem you solve by reading more of your own repo.&lt;/p&gt;
&lt;p&gt;You solve it by getting back in the room. Sit in the support queue this week. Take the sales call you&apos;d normally skip. Watch one real customer use the flow you shipped last month and say nothing while they fumble it. That hour is not a distraction from the engineering. In a world where the fleet does the building, it is the engineering.&lt;/p&gt;
&lt;p&gt;What&apos;s the last card you shipped because a real person needed it, versus because it was next on the board?&lt;/p&gt;
&lt;div&gt;&lt;p&gt;Written with AI assistance. The arc is mine: Limelight to CTO, the edge to owning the build. The thesis is the one I keep landing on from a new angle every few weeks. Volume is free now, and the judgment that still costs something is the judgment the fleet can&apos;t get on its own.&lt;/p&gt;&lt;/div&gt;</content:encoded><kind>essay</kind><category>judgment</category></item><item><title>The Grind Was the Teacher</title><link>https://jasonwaldrip.com/writing/the-grind-was-the-teacher/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-grind-was-the-teacher/</guid><description>AI removed the grunt work that used to teach junior engineers judgment. The apprenticeship gap, why deliberate practice mattered, and how to build judgment on purpose when the reps are gone.</description><pubDate>Tue, 04 Aug 2026 08:12:00 GMT</pubDate><content:encoded>&lt;p&gt;Think about the moment you actually got good. Not the class, not the bootcamp. The night.&lt;/p&gt;
&lt;p&gt;You were three hours into a bug that made no sense, staring at a stack trace that lied to you twice, and somewhere around the second bad guess you stopped reaching for Stack Overflow and started reasoning about what the system was &lt;em&gt;actually&lt;/em&gt; doing. That night rewired you. You came out of it with an instinct, a small permanent voice that now says &quot;check the boundary&quot; or &quot;that&apos;s a race condition&quot; before you can explain why. Nobody handed you that voice. You paid for it, in hours, in dead ends, in the specific humiliation of shipping the dumb thing and watching it break.&lt;/p&gt;
&lt;p&gt;That grind is exactly the work the fleet does now. Faster, cheaper, and without the 2am part.&lt;/p&gt;
&lt;h2&gt;the reps nobody scheduled&lt;/h2&gt;
&lt;p&gt;Here&apos;s the thing we never said out loud, because we never had to: the grunt work was doing two jobs. It produced the code, and it produced the engineer. We only ever invoiced for the first one. The boilerplate, the fifth CRUD endpoint, the migration you&apos;d written a hundred times, the flaky test you chased for an afternoon. That was the boring half of the job, and everyone agreed it was overhead we&apos;d automate away the second we could. So we did.&lt;/p&gt;
&lt;p&gt;But the boring half was where the reps lived. Anders Ericsson spent his career on this, and his actual finding got flattened into the &quot;10,000 hours&quot; bumper sticker, which he &lt;a href=&quot;https://www.newyorker.com/sports/sporting-scene/malcolm-gladwell-got-us-wrong&quot;&gt;openly disliked&lt;/a&gt;. His real claim was narrower and more useful: expertise doesn&apos;t come from hours, it comes from &lt;em&gt;deliberate practice&lt;/em&gt;. Reps against a real problem, at the edge of what you can do, with a tight feedback loop telling you when you got it wrong. That is a precise description of debugging your own bad code. You attempt, you fail visibly, the system corrects you, you adjust. The grind wasn&apos;t in the way of learning. The grind &lt;em&gt;was&lt;/em&gt; the learning. It just wore the costume of overhead so convincingly that we shipped it off to the machines and congratulated ourselves on the efficiency.&lt;/p&gt;
&lt;p&gt;Now the feedback loop runs somewhere the junior can&apos;t see it. The agent hits the boundary condition, reasons about it, fixes it, and opens a clean pull request. The bug that would have rewired a person quietly fixes itself before that person ever feels it. The reps still happen. They just don&apos;t happen to anybody.&lt;/p&gt;
&lt;h2&gt;you can&apos;t teach the thing directly&lt;/h2&gt;
&lt;p&gt;The obvious answer is &quot;so teach them the judgment directly, skip the busywork.&quot; I&apos;ve spent twenty years finding out that doesn&apos;t work, and I&apos;d already learned why before any of this.&lt;/p&gt;
&lt;p&gt;At iTriage the most durable thing I ever shipped wasn&apos;t a feature. It was other engineers, and I built them the only way that ever took: pairing, not lectures. I could &lt;em&gt;say&lt;/em&gt; &quot;watch the coupling here&quot; until I was blue, and it would bounce off. What stuck was sitting next to someone while they felt the coupling bite, then naming it in the exact second it hurt. &lt;a href=&quot;/writing/teach-the-principle-not-the-patch/&quot;&gt;Teach the principle, not the patch&lt;/a&gt; only works if there&apos;s a live moment of struggle to attach the principle to. The principle is the label. The grind is the thing being labeled. Hand someone the label with nothing underneath it and you get a junior who can recite &quot;where does the state live&quot; and has never once been burned by getting it wrong.&lt;/p&gt;
&lt;p&gt;At Brandfolder I hired and trained a team of six into a product that was on fire when I walked in, and none of them got good from my slide deck. They got good from the fire. The value I keep coming back to, the &lt;a href=&quot;/works/&quot;&gt;most durable thing a senior ships is other engineers&lt;/a&gt;, assumed a pipeline that ran on its own: juniors did the grunt work, the grunt work grew them, seniors shaped the growth. Pull the grunt work out of the middle and the pipeline doesn&apos;t speed up. It stops feeding.&lt;/p&gt;
&lt;h2&gt;the tuition came due and nobody noticed&lt;/h2&gt;
&lt;p&gt;So here&apos;s the pattern, and it&apos;s the one I think most teams are going to hit the expensive way. Judgment was never on the invoice because it came free with the reps. The grind was tuition, and we&apos;d been paying it without ever seeing the line item. Automate the grind and you don&apos;t just save the money. You stop paying the tuition, and you don&apos;t find out until you go looking for a mid-level engineer with real instincts and realize the last three years quietly stopped producing any.&lt;/p&gt;
&lt;p&gt;This is the same shape as &lt;a href=&quot;/writing/volume-is-free-now/&quot;&gt;volume being free now&lt;/a&gt;, one turn deeper. When generation got cheap, judgment became the moat, and everyone nodded. What fewer people are asking is where the &lt;em&gt;next&lt;/em&gt; generation&apos;s judgment comes from, now that we&apos;ve automated the exact activity that used to manufacture it. A moat you can&apos;t refill is just a hole that&apos;s currently full of water.&lt;/p&gt;
&lt;p&gt;And I want to be honest that this cuts at me too. I love that the fleet eats the boring work. I built my whole current practice on it. The weekend I finally took actually off, the &lt;a href=&quot;/writing/a-weekend-actually-off/&quot;&gt;agents kept the line while I was at the grill&lt;/a&gt;, and that&apos;s the dream. But the dream has a bill attached, and the bill is that the boring work was never only boring.&lt;/p&gt;
&lt;h2&gt;build the reps back on purpose&lt;/h2&gt;
&lt;p&gt;The fix has nothing to do with making people grind out CRUD by hand for old times&apos; sake. That tuition is genuinely obsolete, and pretending otherwise is nostalgia dressed as training. The real move is to notice that reps used to be automatic and now have to be deliberate, and to build them somewhere the work still lives.&lt;/p&gt;
&lt;p&gt;The work moved. It used to live in &lt;em&gt;producing&lt;/em&gt; the diff. It now lives in &lt;em&gt;judging&lt;/em&gt; it, and that turns out to be the better classroom anyway, because it&apos;s closer to the actual job. A few things I&apos;d make non-negotiable:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Make juniors defend the shape, not type the code.&lt;/b&gt; Put a person in front of the agent&apos;s pull request and make them argue where the state lives, what it couples to, whether the approach even matches the problem. That&apos;s the [same review skill seniors have always used](/writing/read-the-decisions-not-the-diff/), pointed at a fleet instead of a teammate. It&apos;s a rep, and it&apos;s the rep that matters now.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Give them the failure back.&lt;/b&gt; Deliberate practice needs a real feedback loop, so stop letting the agent silently absorb every mistake. Have people predict what breaks before they read the fix. Have them find the bug the fleet shipped, because it will ship them. A wrong guess that gets corrected is worth more than a right answer they never had to reach for.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Pair on the judgment, live.&lt;/b&gt; The principle only sticks in the second the struggle happens. So do the review together, out loud, and name the instinct in the moment it fires. The agent removed the grunt work. It did not remove the need to sit next to someone while the coupling bites.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of this is free. It&apos;s slower than letting the fleet run clean, and it will feel like overhead, which is exactly the trap, because that&apos;s precisely how the grind felt right up until we automated it and found out what it was holding up.&lt;/p&gt;
&lt;p&gt;So the question I&apos;d leave you with is the one I ask on every engagement now. Your fleet is faster than any team you&apos;ve ever run. Five years in, when the seniors who trained on the old grind start to age out, who on your bench has actually been burned enough to catch what the fleet gets confidently wrong? If you can&apos;t name them, you&apos;re not short on velocity. You&apos;re short on the only thing velocity was ever protecting.&lt;/p&gt;
&lt;div&gt;&lt;p&gt;Written with AI assistance, which is its own kind of irony in an essay about automated grunt work. The frame, the calls, and the stories are mine. The reps that built the judgment behind them are not for sale, which is sort of the whole point.&lt;/p&gt;&lt;/div&gt;</content:encoded><kind>essay</kind><category>craft</category></item><item><title>The Outage That Didn&apos;t Happen</title><link>https://jasonwaldrip.com/writing/the-outage-that-didnt-happen/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-outage-that-didnt-happen/</guid><description>Prevention is the highest-leverage engineering work and it leaves no trace, so it gets undervalued and cut. Why the outage that didn&apos;t happen is the real deliverable, and why a fleet of agents makes it matter more.</description><pubDate>Sat, 01 Aug 2026 08:47:00 GMT</pubDate><content:encoded>&lt;p&gt;The best call I made last quarter has no artifact.&lt;/p&gt;
&lt;p&gt;There&apos;s no incident channel for it. No postmortem doc, no five-whys, no timeline with timestamps and a blameless retro. Nobody got paged at 2am. The dashboard stayed green the whole time. From the outside it looks like a week where nothing happened, because that&apos;s exactly what happened: nothing. A failure that would have fired didn&apos;t, because the shape of the system made it impossible. And the reward for that is that no one will ever know it was there.&lt;/p&gt;
&lt;p&gt;Sit with that for a second, because it&apos;s the whole problem. The work that saves you the most is the work that leaves no evidence it was done.&lt;/p&gt;
&lt;h2&gt;the ledger only records what breaks&lt;/h2&gt;
&lt;p&gt;Think about how you actually find out an engineer is good. You see the fire they put out. The gnarly bug they chased at midnight, the migration they rescued, the incident they commanded while everyone else refreshed the status page. Firefighting is legible. It has a start and an end, a villain and a hero, a thread full of praise emoji when it&apos;s over. It photographs well.&lt;/p&gt;
&lt;p&gt;Prevention photographs like a blank wall. The person who noticed the migration would lock the table under load and rewrote it before it ever shipped produced the same visible outcome as the person who did nothing: a quiet Tuesday. One of them saved the company a Saturday. You can&apos;t tell which from the outside, and neither can their manager at review time.&lt;/p&gt;
&lt;p&gt;Richard Cook made this point better than I can in &lt;a href=&quot;https://how.complexsystems.fail/&quot;&gt;&lt;em&gt;How Complex Systems Fail&lt;/em&gt;&lt;/a&gt;: the reason a complex system runs at all is that people are continuously, invisibly steering it away from the edge. When they succeed, the system just keeps working, and the success is silent. We only see the system when it breaks, so we systematically mistake the absence of failure for the absence of risk. The safest operators generate the least evidence that they&apos;re doing anything.&lt;/p&gt;
&lt;p&gt;So the ledger is rigged. It records outages, not the ones you designed out. It logs the bug that shipped, never the one that died in review. And when the budget gets tight and someone asks what work is safe to cut, prevention is first on the block every time, because on paper it costs money and produces nothing. You are cutting the quiet Tuesdays. You just won&apos;t find out until a Saturday.&lt;/p&gt;
&lt;h2&gt;the failures I&apos;m proudest of are the ones you can&apos;t see&lt;/h2&gt;
&lt;p&gt;The stories I actually tell about my own work are the loud ones. Brandfolder crashing on a memory leak when I walked in, and stopping the bleeding before anything else. Ruby falling over generating multi-gigabyte zip files, so we &lt;a href=&quot;/choices/go/&quot;&gt;built that one pipeline in Go&lt;/a&gt; and it just stopped being a problem. Those are good stories because you can see the before and after. Something was broken, then it wasn&apos;t.&lt;/p&gt;
&lt;p&gt;But the decisions I&apos;d actually defend hardest are the ones with no before-and-after to point at. At GigSmart I chose &lt;a href=&quot;/choices/elixir/&quot;&gt;Elixir&lt;/a&gt; for the marketplace backend, and the reason was prevention. A real-time marketplace is a concurrency problem wearing a product costume, and I wanted fault isolation to be a property of the substrate, not a thing we remembered to bolt on later under load. Every process that can crash without taking its neighbors down is an incident that never gets written up. There&apos;s no postmortem for the cascading failure that couldn&apos;t cascade. That decision paid out every single day for years, silently, and it will never show up in a war story because nothing ever went to war.&lt;/p&gt;
&lt;p&gt;Same shape at CommercialTribe. The work that mattered most wasn&apos;t a feature. It was collapsing a release cadence from weeks to hours, moving to GCP and Kubernetes because that was the cheapest path to stability at our actual load. Weeks-to-hours reads like a speed win, and it is, but the deeper win is that a team shipping in hours learns from reality constantly while a team shipping in weeks is guessing. Every bad guess you don&apos;t ship is a fire you don&apos;t fight. You can&apos;t count them. They&apos;re not there.&lt;/p&gt;
&lt;h2&gt;prevention has no postmortem&lt;/h2&gt;
&lt;p&gt;Here&apos;s the phrase I keep coming back to. Prevention has no postmortem. The best possible outcome of good judgment is a non-event, and a non-event generates no document, no credit, no story. Which means if you only reward what&apos;s visible, you are training your best people to stop preventing and start firefighting, because the fire is where the recognition lives. You will get exactly the behavior you measure, and you are measuring the smoke.&lt;/p&gt;
&lt;p&gt;The fix isn&apos;t to stop firefighting. Fires happen, and someone has to walk into them. The fix is to make prevention legible on purpose, because it won&apos;t make itself legible. When I run a fractional engagement now, the retainer is flat and it&apos;s measured on two things: what shipped, and what got prevented. That second half is the hard half, and it&apos;s the half most orgs never write down. You have to say the near-miss out loud. The bug that got caught in review, the design that changed before it went out, the load pattern you saw coming and built for. Name it, or it evaporates, and the person who saw it gets nothing while the person who cleaned up the version that shipped gets a bonus.&lt;/p&gt;
&lt;p&gt;Writing the near-miss down is doing for prevention what a postmortem does for failure. It turns invisible judgment into a thing the team can see, learn from, and value.&lt;/p&gt;
&lt;h2&gt;why this is the whole job now&lt;/h2&gt;
&lt;p&gt;I&apos;ve written before that &lt;a href=&quot;/writing/volume-is-free-now/&quot;&gt;volume is free now&lt;/a&gt;. A fleet of agents will generate more code, more migrations, more config, more plausible-looking pull requests than any team could produce by hand a year ago. Generation stopped being the bottleneck. And when generation gets that cheap, the entire value of the person in the loop collapses onto one thing: catching the bad output before it ships. That is prevention. That&apos;s the whole game.&lt;/p&gt;
&lt;p&gt;An agent will happily write the migration that locks the table. It&apos;ll wire up the flow with no idempotency and no retry. It&apos;ll produce something that passes its own tests and takes prod down at 3x traffic, and it&apos;ll do it fast and cheerfully and at scale. The judgment that says &quot;not that one, here&apos;s why&quot; before it merges is the scarce thing. It&apos;s also, by its nature, invisible. Nobody sees the outage the review prevented. You have to decide that catching it counts, and then you have to build the guardrails, the CI, the review, the types, that turn one person&apos;s judgment into something the whole fleet runs inside of.&lt;/p&gt;
&lt;p&gt;Multiply that judgment across a fleet and you get real leverage. Skip it and you&apos;ve built a machine that generates Saturdays at scale.&lt;/p&gt;
&lt;p&gt;So here&apos;s the question I&apos;d leave you with, the one I ask myself at review time. Who on your team had the quietest quarter, and did you check whether it was quiet because they weren&apos;t doing much, or quiet because they were the reason nothing broke? The answer to that is worth more than any incident report you&apos;ll read this year. It just won&apos;t come with one attached.&lt;/p&gt;
&lt;div&gt;&lt;p&gt;Written with AI assistance. The judgment, the calls, and the stories are mine, reviewed by the person holding the map.&lt;/p&gt;&lt;/div&gt;</content:encoded><kind>essay</kind><category>judgment</category></item><item><title>No-Code Is a Loan</title><link>https://jasonwaldrip.com/writing/no-code-is-a-loan/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/no-code-is-a-loan/</guid><description>No-code automation buys real speed at the edge and becomes a liability in the core. Why business-critical logic belongs in a repo you can test, diff, and hand to a fleet of agents.</description><pubDate>Wed, 29 Jul 2026 09:14:00 GMT</pubDate><content:encoded>&lt;p&gt;The flow worked the first time. That was the problem.&lt;/p&gt;
&lt;p&gt;It&apos;s a Friday. A customer needs a welcome email when they onboard, plus a Slack ping to their success rep. You open the automation builder, drag four nodes onto the canvas, wire them together, hit save. Ten minutes, no deploy, no pull request. It fires. You move on. That felt like the whole promise of the tools, delivered.&lt;/p&gt;
&lt;p&gt;Eight months later a support ticket lands: new customers aren&apos;t getting the email. You open the canvas. Nobody remembers building half of it. Maybe a node&apos;s default shifted under you in a platform update. Maybe someone tweaked a filter back in March. There&apos;s no way to know which, because a visual flow has no diff and no history you can read. No test failed, because there was never a test. You found out from a customer.&lt;/p&gt;
&lt;p&gt;That gap, between &quot;it fired on Friday&quot; and &quot;I heard about it from a customer,&quot; is the whole essay.&lt;/p&gt;
&lt;h2&gt;the speed is real&lt;/h2&gt;
&lt;p&gt;This is everywhere right now. Every team is gluing AI calls, webhooks, and a stack of SaaS together in n8n, Zapier, Make, some builder with a canvas. And it&apos;s genuinely fast. I won&apos;t pretend the speed is fake. At the edge it&apos;s a gift: an internal notification, a nightly sync, a scrappy integration nobody&apos;s payroll depends on. Reach for it there and I&apos;ll cheer you on.&lt;/p&gt;
&lt;p&gt;The trouble starts later, and quietly. Nobody sits down and decides to run the business on a drag-and-drop canvas. It happens one node at a time. The onboarding flow that was a convenience becomes the onboarding flow, singular, the only one. The glue becomes the wall, and you don&apos;t notice the day it crosses over.&lt;/p&gt;
&lt;h2&gt;the balloon payment&lt;/h2&gt;
&lt;p&gt;Here&apos;s the reframe I keep coming back to. No-code is a loan. You borrow speed today against a payment later, and the payment comes due the exact day the glue turns load-bearing and something breaks under it. The train only moves as fast as the tracks it runs on, and a visual builder lets you skip laying track and just run the train across the dirt. That&apos;s fine at low speed on a short haul. Put real weight on it, run it every day, and you find out why track exists.&lt;/p&gt;
&lt;p&gt;This isn&apos;t taste. The DORA research behind the &lt;em&gt;Accelerate&lt;/em&gt; book is blunt about what separates teams that ship fast and safely from teams that just ship: they keep everything that defines production under &lt;a href=&quot;https://dora.dev/capabilities/&quot;&gt;version control&lt;/a&gt;, and they test it automatically. A canvas fails both by construction. It doesn&apos;t live in git, so there&apos;s no review, no revert, no record of who changed what. And you can&apos;t write an honest test against a flow you assemble by dragging boxes, so every change is a deploy straight to prod with your fingers crossed.&lt;/p&gt;
&lt;h2&gt;the fix is moving the logic, not the tool&lt;/h2&gt;
&lt;p&gt;I&apos;m cleaning up exactly this right now. At Phoneware, a UCaaS platform, the customizations had grown into two piles: portal features living in per-customer JavaScript bundles, and app backends stranded in n8n flows. Every customer a little different, and every difference a place a change could silently break. The fix wasn&apos;t more flows or more bundles. It was pulling customization out of code and glue and into data: a manifest API that cascades reseller to domain to role, all in one TypeScript monorepo. A customer&apos;s configuration is a value now, not a fork. Changing it is a pull request a compiler and a test suite get to see before any customer does.&lt;/p&gt;
&lt;p&gt;Notice what moved. The tool didn&apos;t matter as much as the shape. The logic stopped being trapped in a canvas and became something you can diff, review, revert, and reason over.&lt;/p&gt;
&lt;h2&gt;the second bill&lt;/h2&gt;
&lt;p&gt;There&apos;s a newer bill on that loan, and it&apos;s the one most people miss. A fleet of agents can reason over a typed monorepo. It can read the manifest, follow the cascade, change a value, and let CI tell it the blast radius before anything ships. It cannot reason over a canvas. The logic trapped in a visual flow is invisible to the tools that are supposed to be multiplying you. When generation is free, your leverage lives in the parts of the system an agent can actually read. Wire your core into a drag-and-drop builder and you&apos;ve hidden it from the one thing that was going to make you faster.&lt;/p&gt;
&lt;p&gt;You bought speed on Friday and mortgaged your leverage by Monday.&lt;/p&gt;
&lt;h2&gt;where it belongs&lt;/h2&gt;
&lt;p&gt;So I&apos;m not here to trash no-code. Every tool is a call about where it fits, and this one fits the edge: the throwaway, the internal, the thing that can fail at 3am and nobody feels it. Drag the nodes and ship. The moment a customer can feel it, or the moment your business would stop if it stopped, it&apos;s stopped being glue. It&apos;s infrastructure, and infrastructure earns a repo, a test, and a diff.&lt;/p&gt;
&lt;p&gt;The honest question was never &quot;can I build this without code?&quot; You almost always can. The question is &quot;when this breaks in eight months, how do I find out before my customer does?&quot; If the tool can&apos;t answer that, you didn&apos;t save the time. You borrowed it.&lt;/p&gt;
&lt;div&gt;&lt;p&gt;Written with AI assistance. The frame, the Phoneware call, and the opinions are mine.&lt;/p&gt;&lt;/div&gt;</content:encoded><kind>essay</kind><category>architecture</category></item><item><title>Don&apos;t build the same app three times</title><link>https://jasonwaldrip.com/writing/dont-build-the-same-app-three-times/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/dont-build-the-same-app-three-times/</guid><description>A small team, and the plan is to staff three: an iOS engineer, an Android engineer, a web engineer. Three codebases, three release trains, the same login screen written three times and drifting apart by the second sprint. Or one React Native codebase that ships all three, one team, a bug fixed once. At GigSmart we took two apps from zero in eight months on exactly that bet. The tax is real: when a screen has to feel genuinely native, you drop down and build that piece native. So pay for polish where the product earns it, and bank the shared velocity everywhere else.</description><pubDate>Sun, 19 Jul 2026 08:38:00 GMT</pubDate><content:encoded>&lt;p&gt;A small team, and the plan is to staff three: an iOS engineer, an Android engineer, a web engineer. Three codebases, three release trains, the same login screen written three times and drifting apart by the second sprint. Or one React Native codebase that ships all three, one team, a bug fixed once. At GigSmart we took two apps from zero in eight months on exactly that bet. The tax is real: when a screen has to feel genuinely native, you drop down and build that piece native. So pay for polish where the product earns it, and bank the shared velocity everywhere else.&lt;/p&gt;</content:encoded><kind>take</kind><category>architecture</category></item><item><title>The Rewrite Looks Free Now</title><link>https://jasonwaldrip.com/writing/the-rewrite-looks-free-now/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-rewrite-looks-free-now/</guid><description>A from-scratch rewrite used to be blocked by the weeks of retyping. A fleet drops that cost to zero, so the rewrite looks free. But the labor was never the real price. The old code&apos;s ugliness is accumulated production knowledge, scar tissue from every incident it survived. Regenerate it clean and you amputate the memory, then rediscover every wound. The tell: are you rewriting to understand less, or more?</description><pubDate>Thu, 16 Jul 2026 08:12:00 GMT</pubDate><content:encoded>&lt;p&gt;There&apos;s a file on every team that people talk about in a lowered voice. You know the one. Eight hundred lines, a function that should be four and is forty, three conditionals in a row that nobody can explain, and a comment near the bottom that just says: do not remove this, it breaks checkout. No name on the comment. No ticket. Just a warning from someone who is probably gone. Everyone routes around that file. Touching it is how you spend a weekend.&lt;/p&gt;
&lt;p&gt;For years the answer to that file was: leave it. Not because anyone loved it. Because rewriting it meant weeks of careful, thankless retyping, re-deriving behavior you couldn&apos;t fully see, and the risk landed on you if checkout went down. The math never closed. The mess stayed, and you learned to live beside it.&lt;/p&gt;
&lt;p&gt;That math just changed. Hand the file to a fleet and you get a clean version back in a minute. Small functions, sane names, tests, the works. The weeks of typing that used to stop you cold are gone, and for the first time you can look at that file and say yes, rewrite it. So the question stops being &lt;em&gt;can we afford to&lt;/em&gt; and becomes &lt;em&gt;why wouldn&apos;t we&lt;/em&gt;. That is exactly the moment to slow down.&lt;/p&gt;
&lt;h2&gt;the cost was never the keystrokes&lt;/h2&gt;
&lt;p&gt;Here&apos;s the trap hiding in the new math. When the price of a rewrite dropped, everyone assumed the whole price dropped. It didn&apos;t. Only one line item did.&lt;/p&gt;
&lt;p&gt;The labor of retyping was always the visible cost, the one you could feel in your wrists and put on a sprint board. It was never the expensive part. The expensive part was re-deriving &lt;em&gt;why&lt;/em&gt;: why those three conditionals are in that order, why checkout breaks without that one line, why the function that should be four lines is forty. That cost didn&apos;t move. The fleet can regenerate the code. It cannot regenerate the reasons, because the reasons were never in the file.&lt;/p&gt;
&lt;p&gt;Joel Spolsky wrote the definitive version of this in 2000, and it has aged into something close to a law. He called rewriting from scratch &lt;a href=&quot;https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/&quot;&gt;the single worst strategic mistake a software company can make&lt;/a&gt;, and the reason he gave is the one that matters here. That old, ugly code is not junk. It is accumulated bug fixes. Every weird special case is a bug someone hit in production, at 2am, with a customer on the line, and fixed. Throw the code away and you throw away the fixes. Then you get to rediscover every one of them, in production, at 2am, with a customer on the line.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;The keystrokes went to zero. The knowledge didn&apos;t.&lt;/div&gt;
  &lt;div&gt;A fleet regenerates the code in a minute and none of the reasons the code was shaped that way. Those never lived in the file.&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;the ugliness is the memory&lt;/h2&gt;
&lt;p&gt;So look at that file again, at the conditional nobody can explain. That is not sloppiness. That is a scar.&lt;/p&gt;
&lt;p&gt;Somewhere behind it is a real wound. A payment provider that returns success and then reverses it. A timezone that only breaks for users in one country during one week of the year. A race that showed up exactly once, under load, and cost someone a very long night. The conditional is the stitch. It looks ugly because scars are ugly. It is also the only place that incident is written down, because nobody filed the doc, they just fixed the code and moved on. Strip the file down to something clean and readable and you have performed a very tidy amputation. The scar is gone. So is the memory of the wound, and the wound is still out there.&lt;/p&gt;
&lt;p&gt;This is why the reframe matters more now than it did in 2000, not less. Back then the rewrite was slow, and the slowness was a tax that at least made you think twice. Cheap generation removed the tax. It removed the pause. The fleet will hand you the amputated version so fast and so clean that the clean is the whole problem: it looks like an upgrade, it reads better than the original, and it has quietly discarded every hard-won correction the mess was carrying. I&apos;ve argued before that reviewing a fleet means &lt;a href=&quot;/writing/read-the-decisions-not-the-diff&quot;&gt;reading the decisions, not the diff&lt;/a&gt;. A rewrite is the hardest case of that, because the decisions you most need to check are the ones that don&apos;t appear in the new code at all. They&apos;re the scars that didn&apos;t make the cut.&lt;/p&gt;
&lt;h2&gt;when I didn&apos;t rewrite, and when I did&lt;/h2&gt;
&lt;p&gt;I walked into Brandfolder to a product crashing on a memory leak. Every instinct said the codebase was broken, and broken things want to be rebuilt. I didn&apos;t rebuild it. I stopped the bleeding first: found the leak, got it stable, kept the accumulated behavior intact, and only then started building the team and the product around it. The temptation to declare it all garbage and start clean was real, and it would have been the wrong call. The thing was crashing, but it also &lt;em&gt;worked&lt;/em&gt;, in a hundred small ways I didn&apos;t yet understand. You stabilize what you don&apos;t understand before you replace it. That&apos;s not caution for its own sake. It&apos;s respect for the scars you can&apos;t see yet.&lt;/p&gt;
&lt;p&gt;The counter-example is Phoneware, and the difference is the whole point. I walked into portal features living in per-customer JavaScript bundles and app backends stranded in automation flows, and I am replacing that pile with a TypeScript monorepo. That is a rewrite. But it isn&apos;t a rewrite to escape code I didn&apos;t understand. It&apos;s a rewrite because the system had outgrown its own shape, and I did the understanding first: mapped what every bundle actually did, why the customizations existed, what behavior had to survive the move. Then rebuilt it on rails, staged, with &lt;a href=&quot;/writing/release-on-demand&quot;&gt;canary targeting so changes land safely&lt;/a&gt; instead of all at once. Same action, opposite decision. One was running from the old code. The other was carrying it forward.&lt;/p&gt;
&lt;p&gt;That&apos;s the tell, and it&apos;s the only one you need. A rewrite driven by &lt;em&gt;I don&apos;t understand this and I want it gone&lt;/em&gt; is an amputation. A rewrite driven by &lt;em&gt;I understand this well enough to know it&apos;s outgrown its shape&lt;/em&gt; is a transplant. When the fleet made the rewrite cheap, it made the first kind cheap too, and the first kind is the one that costs you six months from now.&lt;/p&gt;
&lt;h2&gt;the question to ask before you say yes&lt;/h2&gt;
&lt;p&gt;The file is still sitting there. The fleet is still offering to make it clean. And the yes is right there, cheaper than it has ever been. Before you take it, ask the one question the low price is designed to make you skip: do I understand why this code is shaped the way it is, or do I just want the shape to go away?&lt;/p&gt;
&lt;p&gt;If it&apos;s the second, you&apos;re not buying a cleaner codebase. You&apos;re buying back every night someone already stayed up to fix this thing, at full price, later, when you least expect it. The rewrite looks free now. The understanding it skips never was.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; has spent his career leading engineering at consumer-scale software companies. He writes about engineering leadership, infrastructure, and building in the age of AI agents.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the stories, and the calls on what mattered and what to cut are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>judgment</category></item><item><title>Your API is your agents&apos; hands</title><link>https://jasonwaldrip.com/writing/your-api-is-your-agents-hands/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/your-api-is-your-agents-hands/</guid><description>Build the open API first, dogfood it, then invite others in. That used to be a pure growth bet: every team that integrates makes the product bigger than you could grow it alone. There&apos;s a second payoff now. The surface you built for outside developers is the same one your agent fleet drives. At Phoneware I put MCP servers over the platforms underneath so the fleet operates them like any other client. Design it once, for humans and agents both. Skip that and you&apos;re writing a second interface for the machines later.</description><pubDate>Mon, 13 Jul 2026 08:34:00 GMT</pubDate><content:encoded>&lt;p&gt;Build the open API first, dogfood it, then invite others in. That used to be a pure growth bet: every team that integrates makes the product bigger than you could grow it alone. There&apos;s a second payoff now. The surface you built for outside developers is the same one your agent fleet drives. At Phoneware I put MCP servers over the platforms underneath so the fleet operates them like any other client. Design it once, for humans and agents both. Skip that and you&apos;re writing a second interface for the machines later.&lt;/p&gt;</content:encoded><kind>take</kind><category>agents</category></item><item><title>Scale Is a Design, Not a Dial</title><link>https://jasonwaldrip.com/writing/scale-is-a-design-not-a-dial/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/scale-is-a-design-not-a-dial/</guid><description>Scale isn&apos;t an ops dial you turn under load. It&apos;s a design decision made before a line of code: where does state live, and what contends on it. Amdahl&apos;s serial fraction and Gunther&apos;s coherency cost set a hard ceiling no autoscaler reaches. In the agent era the bottleneck is invisible, because it isn&apos;t in the diff, it&apos;s in the shape.</description><pubDate>Wed, 08 Jul 2026 08:30:00 GMT</pubDate><content:encoded>&lt;p&gt;The dashboard says you&apos;re running forty instances of the service. This morning it was twelve. The autoscaler did exactly its job: it saw latency climb and threw hardware at the problem, which is what you built it to do. And latency is worse. Not flat. Worse. You&apos;re paying for three times the compute to serve a slower product, and every instinct you&apos;ve got says add more, because more has always been the answer. It won&apos;t work this time. Somewhere under all forty of those boxes is a single thing they&apos;re all waiting in line for, and every instance you add makes the line longer.&lt;/p&gt;
&lt;p&gt;That&apos;s the part that feels like a betrayal. Adding capacity is supposed to help, or at worst do nothing. Here it actively hurts, and once you see why, you can&apos;t unsee it. The autoscaler multiplied the part of the system that was never the bottleneck. It spun up forty copies of the stateless shell, forty more contenders for the one place they all have to converge: the hot row, the lock, the partition, the queue everything drains through. The console has a knob for CPU and a knob for replica count. It has no knob for the thing that&apos;s actually saturated.&lt;/p&gt;
&lt;h2&gt;the dial has a ceiling nobody drew on purpose&lt;/h2&gt;
&lt;p&gt;Horizontal scaling does one trick well. It multiplies work that doesn&apos;t have to coordinate. Spread a million independent requests across a hundred workers and you get something close to a hundred times the throughput, because none of them need to talk to each other. The trick fails the instant the work does have to coordinate, and almost every real system has a piece that does.&lt;/p&gt;
&lt;p&gt;Amdahl wrote this down in 1967, and it hasn&apos;t stopped being true: the fraction of a job that has to happen in sequence sets a hard ceiling on how much faster you can go, no matter how many processors you throw at the parallel part. If a tenth of the work is serial, you top out at ten times, forever, even with infinite hardware. Neil Gunther&apos;s &lt;a href=&quot;https://en.wikipedia.org/wiki/Neil_J._Gunther&quot;&gt;Universal Scalability Law&lt;/a&gt; made the picture honest in the way your dashboard just did: past a certain point, the cost of all those nodes coordinating with each other doesn&apos;t merely flatten the curve, it bends it back down. Add capacity, get less throughput. Retrograde scaling. That downward bend is the curve your forty instances are living on, and it has a name and a formula that predicted your morning before you had it.&lt;/p&gt;
&lt;p&gt;Here&apos;s the part that matters for anyone who leads a team. That ceiling was not set by the autoscaler, and it will not be moved by the autoscaler. It was set a long time before this morning, in a room, by whoever decided where the state lives and who has to touch it at the same instant. The console is downstream of a whiteboard, and the whiteboard already spent your scaling budget.&lt;/p&gt;
&lt;h2&gt;scale is a decision, and it&apos;s an early one&lt;/h2&gt;
&lt;p&gt;The industry files scale under operations. Bigger box. More replicas. A beefier managed database. A cache bolted in front of the thing that&apos;s slow. Those are all real levers, and I&apos;ve pulled every one of them. Every single one is downstream of a decision made before the first line of code: where does state live, and which requests contend on it under load.&lt;/p&gt;
&lt;p&gt;I learned that framing at iTriage, running a consumer health app at real scale. Scale showed up as a systems-design problem long before it was ever a code problem. You could write every function correctly, ship a clean diff, pass every test, and still hit a wall, because a wall like that grows out of how the pieces are arranged, not out of any one piece. Where things lived and what had to talk to what set the limit. The most durable calls I made there happened at the whiteboard, in words, before anyone opened an editor.&lt;/p&gt;
&lt;p&gt;At GigSmart the same truth wore a product costume. A real-time marketplace is a contention problem before it&apos;s anything else. Two apps, workers on one side and requesters on the other, both converging on the same handful of moments: who&apos;s available right now, who just got claimed, whose request is still open a half-second later. I reached for Elixir because &lt;a href=&quot;/writing/concurrency-isnt-a-feature-you-add&quot;&gt;fault isolation being the floor and not a bolt-on&lt;/a&gt; is exactly what a marketplace needs. But the runtime was the second decision. The first one was deciding where that hot, shared state was going to live and what would serialize on it, because that call sets the ceiling, and a framework can&apos;t raise a ceiling the design already poured.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;The autoscaler multiplies the part that was never the problem.&lt;/div&gt;
  &lt;div&gt;It spins up copies of the stateless shell and cannot touch the one place they all converge. That place was chosen on a whiteboard, and that&apos;s where the ceiling got set.&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;the diff looks perfectly scalable&lt;/h2&gt;
&lt;p&gt;Now hand this to a fleet, and watch the failure get quieter.&lt;/p&gt;
&lt;p&gt;An agent will write you a service that looks built to scale. Stateless handlers, a tidy repo, horizontally-ready by every surface signal. It deploys clean. The tests are green, because a unit test exercises one request at a time and one request never contends with itself. The &lt;a href=&quot;/writing/release-on-demand&quot;&gt;canary bakes fine at 1%&lt;/a&gt;, because 1% of traffic almost never has two requests fighting over the same row in the same millisecond. Every gate you trust says ship it. And the bottleneck is sitting right there in the design, in the spot where concurrent load lands on the one thing everything funnels through, invisible to all of it.&lt;/p&gt;
&lt;p&gt;It&apos;s invisible because the mistake isn&apos;t in the lines. It&apos;s in the shape, in where the state was placed and what got to touch it at once, and you cannot catch a shape problem by reading a diff. I&apos;ve &lt;a href=&quot;/writing/read-the-decisions-not-the-diff&quot;&gt;argued that reviewing an agent means reading the decisions, not the characters&lt;/a&gt;. This is the most expensive decision of exactly that invisible kind. A fleet has no model of your load shape, your hot keys, your fan-out, the one endpoint that gets hammered on the hour. It will put the state somewhere reasonable-looking and be confidently wrong in a way no reviewer catches by reading code, because there&apos;s nothing wrong with the code. The wrongness is architectural, and architecture doesn&apos;t render in a diff.&lt;/p&gt;
&lt;p&gt;That&apos;s the trap cheap generation sets under this specific problem. When output was scarce, a senior engineer sketched the state layout on a whiteboard first, because typing was expensive enough to make you think before you spent it. When a fleet will hand you the whole service in a minute, the whiteboard step is the one that quietly gets skipped, and it was carrying the entire scaling decision. You multiply judgment by a fleet or you multiply its absence, and the absence hides best right here, where the system runs green all the way to the day it meets real concurrency.&lt;/p&gt;
&lt;h2&gt;what you decide before the editor opens&lt;/h2&gt;
&lt;p&gt;The work reorders around the decision, in priority order, because the sequence is the whole point:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Name the hot state before the framework.&lt;/b&gt; Where does the contended state live, and which requests touch it at the same instant? Answer that out loud, in plain words, before anyone picks a language, a database, or a queue. The tool is downstream of that answer, every time.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Split stateless from stateful on purpose.&lt;/b&gt; The part you can multiply and the part you can&apos;t are different animals with different rules. Draw the line between them deliberately, so the autoscaler is pointed at work it can actually help and kept away from work it can only crowd.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Find the serial fraction and go straight at it.&lt;/b&gt; Amdahl&apos;s ceiling is set by the piece that has to happen in order. Shrinking that piece is worth more than any number of instances. Partition the hot key, move the contention off the critical path, make the shared thing append-only instead of read-modify-write. One point off the serial fraction beats forty boxes.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Load-test the collision, not the endpoint.&lt;/b&gt; A benchmark that fires independent requests at one handler proves nothing about the moment two of them want the same row. Simulate the contention on purpose, because the contention is the product under load, and it&apos;s the only test that would have warned you this morning.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So go back to the forty instances. You can keep turning the dial, and the curve will keep bending the wrong way, because the number on the console was never the variable that mattered. The fix lives back in the room where somebody decided where the state would go, and the honest move is to reopen that decision rather than buy more hardware to outrun it.&lt;/p&gt;
&lt;p&gt;Which leaves one question worth sitting with before you touch the autoscaler again. Where does your state actually live, who contends on it under real load, and did anyone ever decide that on purpose? If the honest answer is that it just happened, that nobody drew it, then that&apos;s your ceiling, and there&apos;s no dial in the building that reaches it.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; has spent his career leading engineering at consumer-scale software companies. He writes about engineering leadership, infrastructure, and building in the age of AI agents.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the experience, and the calls on what mattered and what to cut are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>architecture</category></item><item><title>A note</title><link>https://jasonwaldrip.com/writing/a-weekend-actually-off/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/a-weekend-actually-off/</guid><description>Fourth of July weekend, and I was actually off. Phone in a drawer, kids outside, something on the grill. The fleet kept opening MRs, the merge train held the line, nobody paged me. I spent a lot of years being the load-bearing wall. Turns out the quiet reward for building the tracks right is that the thing stands up fine while you&apos;re not holding it up.</description><pubDate>Mon, 06 Jul 2026 08:34:00 GMT</pubDate><content:encoded>&lt;p&gt;Fourth of July weekend, and I was actually off. Phone in a drawer, kids outside, something on the grill. The fleet kept opening MRs, the merge train held the line, nobody paged me. I spent a lot of years being the load-bearing wall. &lt;em&gt;Turns out the quiet reward for building the tracks right is that the thing stands up fine while you&apos;re not holding it up.&lt;/em&gt;&lt;/p&gt;</content:encoded><kind>life</kind></item><item><title>The Story of Ownership</title><link>https://jasonwaldrip.com/writing/the-story-of-ownership/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-story-of-ownership/</guid><description>Ownership is the cheapest thing a company can hand out, because the word costs nothing and the slide costs nothing. There&apos;s the story of ownership and there&apos;s ownership. Read the four pages after the word: the vesting, the cliff, and the ninety-day window that quietly claws vested equity back. If you call someone an owner, mean the cap table, the window, and the room, or use an honest word instead.</description><pubDate>Sun, 05 Jul 2026 07:55:00 GMT</pubDate><content:encoded>&lt;p&gt;You got the offer, and somewhere on the second page, in a font a little larger than it needed to be, was the word. Owner. Maybe it read &quot;equity partner,&quot; maybe it was a founder at the all-hands saying &quot;we&apos;re all owners here&quot; over a slide with a rocket on it. You felt something land. You were supposed to. Then you signed, and you never read the four pages after the word: the vesting schedule, the cliff, the paragraph about what happens to the shares you earn if you leave, the ninety days you&apos;d have to find real cash to buy them, the tax bill that arrives whether or not you have it. Nobody reads those pages at signing. That is the design.&lt;/p&gt;
&lt;p&gt;Ownership is the cheapest thing a company can hand you, because the word costs nothing and the slide costs nothing, and in the room both feel identical to the real thing. That&apos;s exactly why it gets handed out so freely and meant so rarely. There&apos;s the story of ownership, and there&apos;s ownership. Most companies are very good at giving you the first while the second stays precisely where it already was: with the people who held it before you walked in.&lt;/p&gt;
&lt;h2&gt;read the four pages&lt;/h2&gt;
&lt;p&gt;Go read your own grant. Not the number of shares, the mechanics around them. The standard shape is four years to vest with a one-year cliff, so if you leave in month eleven you own nothing at all, no matter what you shipped. Most people know that part. The part that quietly does the work is the post-termination exercise window. On a typical grant you get ninety days after you leave to buy the options you already vested, or you forfeit them. For a lot of people that&apos;s a five or six figure check they don&apos;t have, plus a tax bill on paper gains they can&apos;t sell to cover it. So the ownership they spent years earning expires, unexercised, and slides back to the company. Vested. Gone.&lt;/p&gt;
&lt;p&gt;This is common enough that a wave of companies started publicly extending those windows, from ninety days out to seven or ten years, specifically because the short one was clawing hard-earned equity back from the people who&apos;d built the thing. The ones who extended it were telling on the ones who didn&apos;t. If your window is still ninety days and walking away means you can&apos;t afford to keep what you earned, read that sentence one more time: you were renting the story of ownership. You never held the asset. You held the feeling of holding it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A word costs nothing. A cap table costs something. Companies hand out the first and call it the second, and the room can&apos;t tell the difference in the moment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;owner-behavior at renter-prices&lt;/h2&gt;
&lt;p&gt;Here&apos;s the move, and once you see it you can&apos;t unsee it. Call someone an owner and something changes in how they work. They stay late without being asked. They treat the bug like it&apos;s theirs, because you told them it is. They carry the thing home in their head on a Sunday. That behavior is worth an enormous amount, and it&apos;s the entire reason the word gets used. The quiet trick is to buy the behavior with the word instead of the thing. You get someone to act like an owner while the ownership stays a story. That&apos;s the whole game: owner-behavior at renter-prices.&lt;/p&gt;
&lt;p&gt;I&apos;ve sat on the other side of that table. I&apos;ve built teams from nothing and I&apos;ve signed the grants that went to them. The thing that predicted who acted like an owner was never the size of the number. It was whether the grant was real: whether the window was humane, whether the upside was actual, whether the person was in the room when the call that moved the value got made. Give someone a real stake and they behave like it. Give them a story and, sooner or later, they read the four pages and behave like that instead. People aren&apos;t stupid. They&apos;re just slow to check.&lt;/p&gt;
&lt;p&gt;So my rule is boring and it costs me something. If I call you an owner, I mean the cap table, the window, and the room. If I&apos;m not willing to mean all three, I don&apos;t use the word. I&apos;ll find an honest one. Underpaying someone in dollars and topping it up with a fiction is worse than just paying them less, because the fiction has a half-life, and when it decays it takes the trust with it.&lt;/p&gt;
&lt;h2&gt;the asset that never vests&lt;/h2&gt;
&lt;p&gt;There&apos;s a layer under all of this, and it&apos;s the one that actually matters to me. The most valuable thing you&apos;re asking an owner to spend was never in the grant. It&apos;s their time.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;Time is the only line on the cap table with no refresh grant.&lt;/div&gt;
  &lt;div&gt;You can re-strike options, reprice a round, raise more capital. You cannot give someone back a Saturday. Spend it like it&apos;s cheap and you&apos;ve told them exactly what you think they own.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Capital renews. You can raise more, reprice it, refresh a grant, extend a window. Time is the one input on the whole cap table that doesn&apos;t come back, can&apos;t be repriced, and never refreshes. When a company spends its people&apos;s time as though it were cheaper than the money it&apos;s conserving, it&apos;s making an ownership statement louder than any offer letter: your irreplaceable thing is worth less to us than our replaceable one. Real ownership starts there, long before the equity, in whether you treat a person&apos;s time as worth more than your capital. A lot of the &quot;we&apos;re all owners&quot; places have that ranking backwards, and everyone can feel it even when they can&apos;t name it.&lt;/p&gt;
&lt;p&gt;So go back to the offer, the one with the word in the slightly-too-big font. The word is free. Turn the page. Read the vesting, read the window, do the math on the check you&apos;d have to write to keep what you earned. If the story and the substance match, you found a good one. Hold onto it. If they don&apos;t, you already know which one you were sold, and now you know why it felt so good in the room and so thin the day you left.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; has spent his career building and leading engineering teams at consumer-scale software companies. He writes about engineering leadership, infrastructure, and building in the age of AI agents.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The belief is mine, and so are the calls on what to keep and cut.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>ownership</category></item><item><title>Ownership Theater</title><link>https://jasonwaldrip.com/writing/ownership-theater/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/ownership-theater/</guid><description>Companies love telling people to think like an owner while handing them equity engineered to be worth the least it plausibly can. Cliffs, 90-day exercise windows, and liquidation preferences turn ownership into a story. Real ownership is a structure you build, not a feeling you inspire.</description><pubDate>Sat, 04 Jul 2026 08:30:00 GMT</pubDate><content:encoded>&lt;p&gt;Somewhere in your first week, someone told you to act like an owner. Maybe it was in the offer, dressed up as &quot;equity.&quot; Maybe a founder said it at an all-hands, in the voice people use for things they badly want to be true. Treat this like it&apos;s yours. Think like an owner. And you nodded, because it&apos;s the kind of thing you want to be true too.&lt;/p&gt;
&lt;p&gt;Then you read the paperwork. Four-year vest, one-year cliff, and a 90-day window to exercise your options after you leave or you forfeit them. To turn that &quot;ownership&quot; into actual shares, you write the company a check, at a strike price that assumes the thing is already worth something, out of money you have because you took a startup salary. Most people can&apos;t. So they walk away from the vested portion they were told made them an owner, because owning it was gated behind a payment they were never positioned to make.&lt;/p&gt;
&lt;p&gt;That&apos;s not a loophole. It&apos;s the standard deal. And it&apos;s the first tell that the word &quot;owner&quot; was doing very different work than you thought.&lt;/p&gt;
&lt;h2&gt;The exit is where the story ends&lt;/h2&gt;
&lt;p&gt;Say you make it. You stay the four years, the options fully vest, you scrape together the cash to exercise, the company sells. This is the part the recruiting page was picturing. Here&apos;s what actually happens: the money doesn&apos;t split by who owns what. It splits by who holds a &lt;strong&gt;liquidation preference&lt;/strong&gt;, and the people who wired in the capital wrote themselves to the front of that line. Fred Wilson, a VC who&apos;s sat on the winning side of plenty of exits, has spent years explaining the mechanics on &lt;a href=&quot;https://avc.com/&quot;&gt;his blog&lt;/a&gt;: preferred shares get paid first, sometimes a multiple of what went in, sometimes a multiple &lt;em&gt;and&lt;/em&gt; their percentage on top. Your common stock is whatever&apos;s left after everyone senior in the stack has been made whole.&lt;/p&gt;
&lt;p&gt;On a great exit that&apos;s still real money. On the far more common outcome, the sale that sounds impressive in the headline, the preference stack eats the number and the common holders (the employees, the people who were told to act like owners) get a rounding error. The &lt;a href=&quot;https://www.holloway.com/g/equity-compensation&quot;&gt;Holloway Guide to Equity Compensation&lt;/a&gt; walks the mechanics in more detail than any offer letter ever will, which is exactly the point. The complexity isn&apos;t an accident. A thing you fully understood, you could negotiate.&lt;/p&gt;
&lt;p&gt;None of this is illegal. Most of it is smart, on the side of the table that wrote it. I&apos;m not calling the mechanics evil. I&apos;m saying a company that runs every one of them and &lt;em&gt;then&lt;/em&gt; asks you to &quot;think like an owner&quot; is asking for the behavior of ownership while handing you the story of it.&lt;/p&gt;
&lt;h2&gt;The theater&lt;/h2&gt;
&lt;p&gt;Here&apos;s the phrase I use for it: &lt;strong&gt;ownership theater.&lt;/strong&gt; The whole set of rituals a company performs to get owner-behavior out of people it has carefully arranged not to make owners. Say &quot;we&apos;re all founders here.&quot; Call the staff &quot;partners&quot; on the website. Put &quot;act like it&apos;s your company&quot; on the values poster. Hand out equity engineered, through cliffs and windows and preferences, to be worth the least it plausibly can while still counting as a number in the recruiting deck.&lt;/p&gt;
&lt;p&gt;The tell is always the same. The company wants the &lt;em&gt;feeling&lt;/em&gt; of ownership to do the work the &lt;em&gt;structure&lt;/em&gt; of ownership refuses to do. Ownership makes you show up on the bad night, sweat the detail nobody asked about, treat the money like it&apos;s partly yours because it is. That behavior is worth a fortune, and it&apos;s close to impossible to fake into existence with a speech. So companies try to summon it with language instead of buying it with stake. It works for a while. Then people do the math.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;You can&apos;t inspire owner-behavior out of people you&apos;ve structured as renters.&lt;/div&gt;
  &lt;div&gt;They&apos;ll act like renters eventually. Not because they&apos;re cynical. Because they&apos;re paying attention.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And a renter isn&apos;t lazy. A renter is rational. If the upside is capped at &quot;your check bounces&quot; and the cost of caring too much is nights and weekends spent feeding someone else&apos;s liquidation preference, the correct move is to do the job well and go home at six. The company taught that lesson itself. It just doesn&apos;t like the grade.&lt;/p&gt;
&lt;h2&gt;The same judgment, pointed at people&lt;/h2&gt;
&lt;p&gt;I spend most of my time on technical calls, and I have a rule for those: &lt;a href=&quot;/writing/earn-it/&quot;&gt;earn it&lt;/a&gt;. Don&apos;t take on complexity before the workload forces it, because complexity is rent you pay every day it runs, and the bill lands on a different date than the decision. Fake ownership is that same mistake, pointed at the org chart instead of the architecture.&lt;/p&gt;
&lt;p&gt;It&apos;s cheap at the whiteboard. Story-shaped equity costs nothing today and photographs beautifully in the deck. The rent shows up later, on a different desk. Your best engineer, the one who genuinely did act like an owner for three years, quietly stops. Or leaves. Or, worst case, stays and stops caring, which is the most expensive outcome of all, because now you&apos;re paying full price for a renter and filing it under retention. You got the complexity at a discount and the operating cost at full freight. Same trap, different diagram.&lt;/p&gt;
&lt;h2&gt;What real ownership costs&lt;/h2&gt;
&lt;p&gt;So do the honest version, or don&apos;t use the word. That&apos;s the whole rule.&lt;/p&gt;
&lt;p&gt;I run my work through &lt;a href=&quot;https://thebushido.co/bushido&quot;&gt;The Bushido Collective&lt;/a&gt;, and the worker side of it comes down to one line: real ownership, not the story of it. If I tell someone they&apos;re an owner, I mean the structure, not the feeling. Stake that vests like a promise instead of a trap. Terms a person can actually read and actually keep. Upside that isn&apos;t quietly rigged to evaporate at the exact moment it&apos;s meant to pay out. It costs more than theater does. That&apos;s the point. Ownership that was cheap to give was never ownership.&lt;/p&gt;
&lt;p&gt;The other half of the same belief: time is worth more than capital. You can raise more money. Nobody gets another four years. When you ask someone to spend a slice of their one finite life building your thing, the fair trade isn&apos;t a motivational poster and a number that rounds to zero. It&apos;s a real piece of what they helped build.&lt;/p&gt;
&lt;p&gt;So the next time someone tells you to think like an owner, ask the boring, unpopular question. Not &quot;do I believe in the mission.&quot; Ask what happens to your stake the day you leave, and what sits in front of it the day the company sells. If the honest answer is &quot;not much, and everyone,&quot; you already know what they meant by owner. Act accordingly. A renter would.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; is a builder, entrepreneur, and technologist. He writes about engineering leadership, incentives, and building in the age of AI agents. If you&apos;re structuring a team and want the ownership to be real instead of theater, &lt;a href=&quot;/work-with-me/&quot;&gt;that&apos;s a call I&apos;m glad to take.&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the belief, and the calls are mine, drawn from how I actually build teams.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>ownership</category></item><item><title>Own the model</title><link>https://jasonwaldrip.com/writing/own-the-model/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/own-the-model/</guid><description>Point a task at a frontier API and you&apos;ve made two decisions: rent the intelligence, hand your data to someone else&apos;s server. Sometimes that&apos;s right. Often you reached for the biggest model because it was there, not because the job needed it. Classification, extraction, routing don&apos;t need frontier reasoning. An open-weight model you run yourself does them cheaper and keeps the data in the building, and Qwen and DeepSeek are closing the gap fast. Save the frontier for the problems that actually earn it.</description><pubDate>Wed, 01 Jul 2026 08:40:00 GMT</pubDate><content:encoded>&lt;p&gt;Point a task at a frontier API and you&apos;ve made two decisions: rent the intelligence, hand your data to someone else&apos;s server. Sometimes that&apos;s right. Often you reached for the biggest model because it was there, not because the job needed it. Classification, extraction, routing don&apos;t need frontier reasoning. An open-weight model you run yourself does them cheaper and keeps the data in the building, and Qwen and DeepSeek are closing the gap fast. Save the frontier for the problems that actually earn it.&lt;/p&gt;</content:encoded><kind>take</kind><category>ai</category></item><item><title>Concurrency isn&apos;t a feature you add</title><link>https://jasonwaldrip.com/writing/concurrency-isnt-a-feature-you-add/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/concurrency-isnt-a-feature-you-add/</guid><description>A real-time marketplace is a concurrency problem wearing a product costume. You can bolt fault-tolerance onto the wrong runtime, supervisors you hand-wrote and queues you babysit, or you can pick one where process isolation is the floor and not the upgrade. At GigSmart I reached for Elixir for exactly that. One slow request shouldn&apos;t take down the ones next to it, and on the BEAM it doesn&apos;t, by default. Reach for it when concurrency is the product. When it isn&apos;t, the runtime is a tax you didn&apos;t need. Earn it.</description><pubDate>Tue, 30 Jun 2026 09:10:00 GMT</pubDate><content:encoded>&lt;p&gt;A real-time marketplace is a concurrency problem wearing a product costume. You can bolt fault-tolerance onto the wrong runtime, supervisors you hand-wrote and queues you babysit, or you can pick one where process isolation is the floor and not the upgrade. At GigSmart I reached for Elixir for exactly that. One slow request shouldn&apos;t take down the ones next to it, and on the BEAM it doesn&apos;t, by default. Reach for it when concurrency &lt;i&gt;is&lt;/i&gt; the product. When it isn&apos;t, the runtime is a tax you didn&apos;t need. Earn it.&lt;/p&gt;</content:encoded><kind>take</kind><category>architecture</category></item><item><title>Read the Decisions, Not the Diff</title><link>https://jasonwaldrip.com/writing/read-the-decisions-not-the-diff/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/read-the-decisions-not-the-diff/</guid><description>Vibe coding isn&apos;t dangerous because an agent wrote the code. It&apos;s dangerous when nobody questions it. But questioning means understanding the decisions and checking the design against the spec, not proofreading characters. And holding the map on a system you architected but didn&apos;t build is the oldest part of being a CTO.</description><pubDate>Sun, 28 Jun 2026 08:25:00 GMT</pubDate><content:encoded>&lt;p&gt;The agent just handed you eight hundred lines. Three files you&apos;ve never opened, a migration, a new module, and a green check mark sitting under all of it. It runs. The demo works. Somewhere in your gut there&apos;s a question you&apos;d rather not ask, because you suspect the honest answer. The question is whether you actually know what this does. Not whether it passes. Whether you could stand up in front of your team tomorrow and explain why it&apos;s built this way and not the other way. If the answer is no, you didn&apos;t ship a feature. You shipped a thing you&apos;re now responsible for and don&apos;t understand, with your name on the merge.&lt;/p&gt;
&lt;p&gt;This is the part of the vibe-coding panic aimed at the wrong target. The danger was never that an agent wrote the code. The danger is that nobody questioned it. And &quot;question it&quot; gets heard as &quot;read every line,&quot; which is both impossible at the volume a fleet produces and not what catching problems ever actually required.&lt;/p&gt;
&lt;h2&gt;you never read every line&lt;/h2&gt;
&lt;p&gt;I&apos;ve approved thousands of pull requests. I did not read most of them line by line. Any engineering leader who tells you they did is lying or running a team of four. What I read was the shape of the decision: where the state lives, what this couples to, whether the approach matches what we&apos;d agreed the problem actually was. A senior engineer reviewing a junior&apos;s PR isn&apos;t proofreading characters. They&apos;re checking judgment against intent. That skill, the one we&apos;ve used on each other for as long as we&apos;ve worked in teams, is exactly the one this era needs. Almost nobody is naming it as the same skill.&lt;/p&gt;
&lt;p&gt;So here&apos;s what questioning the output actually means, and it&apos;s two moves. First, understanding why the agent made the calls it made. Not the syntax. The decisions. Why a queue here and a synchronous call there. Why it reached for that library. What it quietly decided about retries, about failure, about the case you never mentioned. Second, holding its finished design up against the spec you handed it, and finding the gap. There&apos;s always a gap.&lt;/p&gt;
&lt;h2&gt;the spec is the input, not the system&lt;/h2&gt;
&lt;p&gt;Spec-driven development is having its moment, and for good reason. The spec is the steering wheel now, and the more capable the fleet, the more elaborate that spec has to get, because every ambiguity you leave is a decision you&apos;ve delegated without deciding anything. Write the spec well and you&apos;ve pointed the engine at the right hill.&lt;/p&gt;
&lt;p&gt;But the spec is the input. The system that comes back is the output, and those are not the same document. The agent fills every gap you left, confidently, in ways that drift from what you meant by degrees small enough to skim past. I&apos;ve &lt;a href=&quot;/writing/the-context-your-agents-dont-have&quot;&gt;written before&lt;/a&gt; that agents don&apos;t go quiet when they hit missing context. They fill it. The spec tells you what you asked for. Only the diff tells you what you got, and the distance between the two is precisely the thing the green check mark can&apos;t see.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The spec tells you what you asked for. Only the output tells you what you got. The gap between them is where the work moved.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;the reasoning is ephemeral now&lt;/h2&gt;
&lt;p&gt;Here&apos;s the part that&apos;s genuinely new, and the part I think most teams will learn the hard way.&lt;/p&gt;
&lt;p&gt;When a human on my team made one of those calls, the reasoning had a home. It lived in a head I could walk over to. At Brandfolder, Ruby was crashing on large zip files, so we built that one piece of the pipeline in Go. Six months later, anyone could ask why the zip path was a different language than the rest of the app, and get the real answer, because the people who made the call were still in the building. The why survived because the person did.&lt;/p&gt;
&lt;p&gt;When an agent makes the call, the reasoning lives in a transcript. A run log: the options it weighed, the ones it dropped, the chain that led to the design you&apos;re now holding. And that log is ephemeral. It scrolls off. It&apos;s in a session you closed, on a harness that may or may not have kept it, in a format you may or may not have the skill to read. The code stays, green and running. The reasoning that produced it evaporates, unless two things are true: your &lt;a href=&quot;/choices/claude-code&quot;&gt;harness surfaces the trace&lt;/a&gt;, and you know how to dig through it.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;The code is permanent. The reasoning is a log that scrolls off.&lt;/div&gt;
  &lt;div&gt;A human teammate&apos;s &quot;why&quot; is still in the building in six months. An agent&apos;s &quot;why&quot; is in a session you already closed, unless you went and captured it.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Reading an agent&apos;s decision log the way you&apos;d read a teammate&apos;s PR description is a new literacy, and it&apos;s becoming load-bearing fast. The decision the fleet made at 2pm Tuesday is as real as any architectural call your staff engineer ever made. The difference is your staff engineer is still here to defend it.&lt;/p&gt;
&lt;h2&gt;you&apos;ve held this map before&lt;/h2&gt;
&lt;p&gt;Which brings me to the thing that&apos;s supposed to feel like a crisis and, for me, mostly doesn&apos;t. The job now is to hold the map on a codebase you architected but didn&apos;t implement. To carry the why across a system you&apos;re responsible for and didn&apos;t personally type. If that sounds like a frightening new mandate, you haven&apos;t sat in the chair.&lt;/p&gt;
&lt;p&gt;That has always been the job. At GigSmart I hired and led the team that built the platform; I made the call that a real-time marketplace is a concurrency problem and that&apos;s why we were on Elixir, but I was not the one writing every module that depended on it. My value was never that I typed the most. I &lt;a href=&quot;/writing/volume-is-free-now&quot;&gt;argued that already&lt;/a&gt;, at length, about my own commit history. The value was holding the why across systems I hadn&apos;t touched in a year, built by engineers I&apos;d guided but never stood over. Understanding the decisions my team made, and just as often the decisions they didn&apos;t make: the corner nobody addressed because my guidance there was thin. Holding that map is the oldest part of leading engineers. The fleet didn&apos;t invent the problem. It handed the problem to everyone, including the solo developer who never had a team and now suddenly does.&lt;/p&gt;
&lt;p&gt;A fleet is a team. A fast, tireless, literal-minded team that writes no documentation unless you force it, remembers nothing past the session, and will pave a road straight off a cliff and report success. Directing that isn&apos;t a new discipline. It&apos;s the discipline good engineering leaders already had, pointed at a team that happens to be made of models.&lt;/p&gt;
&lt;h2&gt;so what do you actually do&lt;/h2&gt;
&lt;p&gt;The work reorganizes around the map, in priority order, because the sequence matters more than the calendar:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Interrogate the why before you accept, not after it breaks.&lt;/b&gt; Make the agent defend the call. What did it consider and drop, and why this over that? If it can&apos;t produce the roads not taken, the thinking didn&apos;t happen, and you&apos;re the one who has to do it.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Diff the design against the spec, not just the tests against the code.&lt;/b&gt; Green means the code does what it does. It says nothing about whether what it does is the system you asked for. The gap between spec and output is the review.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Capture the ephemeral reasoning before it scrolls away.&lt;/b&gt; The load-bearing &quot;why&quot; belongs in a decision record or in the code itself, not abandoned in a closed session. &lt;a href=&quot;/writing/write-it-down&quot;&gt;Write down the why&lt;/a&gt;, for the next human and for the next context window both.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Treat the agent log as a primary source.&lt;/b&gt; Build the harness that keeps the trace, and learn to read it like you read a teammate&apos;s PR. The reasoning is evidence. Evidence you can&apos;t retrieve isn&apos;t evidence.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of this is anti-agent. I&apos;d be a hypocrite. I wrote this one with a fleet at my elbow, and I&apos;d point a fleet at nearly anything. The argument is only that generation getting free doesn&apos;t retire the engineer. It promotes everyone into the chair I&apos;ve been sitting in, the one where you&apos;re accountable for decisions you didn&apos;t make with your own hands, and the only thing standing between you and a beautifully formatted disaster is whether you understood them.&lt;/p&gt;
&lt;p&gt;So go back to the eight hundred lines. The check is green. That was never the question. The question is whether you could explain, with the session closed and no tab to peek at, why it&apos;s built this way. If you can, you&apos;re doing the actual job: you&apos;re holding the map. If you can&apos;t, the code is already yours, and the reasoning that made it is scrolling toward the bottom of a log you may never open again. Better go read it now, while it&apos;s still there.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; has spent his career leading engineering at consumer-scale software companies. He writes about engineering leadership, infrastructure, and building in the age of AI agents.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the experience, and the calls on what mattered and what to cut are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>judgment</category></item><item><title>When the client owns the shape</title><link>https://jasonwaldrip.com/writing/when-the-client-owns-the-shape/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/when-the-client-owns-the-shape/</guid><description>GraphQL isn&apos;t an API style. It&apos;s a question about who owns the shape of the response. When one graph feeds many surfaces, iOS, Android, web, each asking for exactly the fields it needs, that ownership belongs with the client and the complexity pays for itself. At GigSmart, two apps and a web client hit one graph, and it was worth every bit of the schema. Point it at a single client talking to a single backend and you&apos;ve bought resolvers and a caching headache to solve a problem you don&apos;t have. REST was fine. Earn it.</description><pubDate>Sat, 27 Jun 2026 08:50:00 GMT</pubDate><content:encoded>&lt;p&gt;GraphQL isn&apos;t an API style. It&apos;s a question about who owns the shape of the response. When one graph feeds many surfaces, iOS, Android, web, each asking for exactly the fields it needs, that ownership belongs with the client and the complexity pays for itself. At GigSmart, two apps and a web client hit one graph, and it was worth every bit of the schema. Point it at a single client talking to a single backend and you&apos;ve bought resolvers and a caching headache to solve a problem you don&apos;t have. REST was fine. Earn it.&lt;/p&gt;</content:encoded><kind>take</kind><category>architecture</category></item><item><title>I Ran Your Demo</title><link>https://jasonwaldrip.com/writing/i-ran-your-demo/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/i-ran-your-demo/</guid><description>A polished vendor demo is choreographed to hide the gaps, not reveal the tool. Having run those demos as a sales engineer, here&apos;s why I skip the call and evaluate on the docs, a real trial, and the one thing they won&apos;t let you click.</description><pubDate>Fri, 26 Jun 2026 08:10:00 GMT</pubDate><content:encoded>&lt;p&gt;There&apos;s a calendar invite in your inbox for a 45-minute demo of a platform you might buy. The vendor will share a screen. Someone smooth and likeable will walk you through a flow that works perfectly, every click landing exactly where it should, the sample data clean, the latency invisible, the one feature you actually care about saved for the end so you leave on a high note. You&apos;ll nod. It&apos;ll look great. And you will have learned almost nothing about whether the thing works, because that wasn&apos;t the point of the meeting. It was never going to be.&lt;/p&gt;
&lt;p&gt;I can say that with some confidence, because for a year that smooth likeable person was me.&lt;/p&gt;
&lt;h2&gt;the edge&lt;/h2&gt;
&lt;p&gt;My first real job in this industry was sales engineer at a CDN. I was the technical half of the sales motion, the one who got pulled in when the prospect had questions the account rep couldn&apos;t answer. I helped land Blizzard, YouTube, Disney, Rockstar. Big logos, hard rooms, smart buyers. And my job, stripped of the title, was to make our product look like the obvious answer in the time we had on the call.&lt;/p&gt;
&lt;p&gt;I was good at it. Being good at it meant knowing exactly where the product was strong and steering every demo straight down that road. The features that lagged, the configuration that was a nightmare, the edge case where throughput fell off a cliff: those weren&apos;t on the tour. Not because I was lying. I never lied. I just built a route through the building where every door I opened led somewhere we&apos;d cleaned up first. A good demo is a magic trick, and the trick is misdirection, not deception. You&apos;re looking exactly where I want you looking.&lt;/p&gt;
&lt;p&gt;That&apos;s the part buyers don&apos;t internalize. The demo is a piece of software in its own right, and the thing it&apos;s engineered to do is produce a yes. It is the single least representative way to experience a product, optimized end to end by people whose income depends on you not noticing the gaps until after the contract is signed.&lt;/p&gt;
&lt;h2&gt;what the demo is built to hide&lt;/h2&gt;
&lt;p&gt;Every product has a shape. There&apos;s the part it does beautifully, the part it does adequately, and the part where it quietly falls apart under real conditions. The honest version of evaluating a tool is finding that third part as fast as possible, because that&apos;s where you&apos;ll actually live once it&apos;s in production carrying your load instead of demo load.&lt;/p&gt;
&lt;p&gt;The demo is built to keep you out of that third part. The data is seeded so the slow query never fires. The flow avoids the integration that breaks half the time. The scale is a toy, so the thing that dies at real volume never gets the chance. I used to spend more prep time deciding what &lt;em&gt;not&lt;/em&gt; to show than what to show. The skill wasn&apos;t presenting the strengths. Anyone can do that. The skill was routing cleanly around the weaknesses so the prospect never tripped over one and started asking the question that ends the deal.&lt;/p&gt;
&lt;p&gt;Now I sit on the other side of that table, and I know the route exists, so I refuse to walk it.&lt;/p&gt;
&lt;h2&gt;evaluate on the gaps, not the highlight reel&lt;/h2&gt;
&lt;p&gt;Here&apos;s the move. The demo shows you the highlight reel. Your job is to evaluate on the gaps, because the gaps are what you&apos;re actually buying. A tool&apos;s strengths are table stakes, they&apos;re why it&apos;s even on your list. The decision lives entirely in what it&apos;s bad at and whether you can live there.&lt;/p&gt;
&lt;p&gt;So I don&apos;t take the guided tour. I ask for the docs and a trial account, and I go straight at the thing the demo would have avoided. I throw production-shaped data at it, not the clean sample set. I wire up the ugly integration first, the one that touches our actual auth and our actual edge cases, instead of the toy one in the tutorial. I find the limits page and read it like a contract, because the rate caps and the unsupported configurations are where the truth lives. And I go looking for someone who ran this thing at scale and hit the wall, because a buyer who churned will tell you more in ten minutes than the vendor will in ten meetings.&lt;/p&gt;
&lt;p&gt;The tell I trust most is simple. Ask a vendor to let you click the thing they didn&apos;t show you. Watch what happens. The good ones say &quot;sure, here&apos;s a sandbox, break it however you want.&quot; The ones to walk away from get a little tighter, suggest a follow-up call, offer to &quot;set that up properly for you.&quot; That hesitation is the whole answer. They know where their third part is too, and they&apos;re managing you away from it, exactly like I used to.&lt;/p&gt;
&lt;h2&gt;the buyer&apos;s job is the judgment&lt;/h2&gt;
&lt;p&gt;This connects to the thing I keep landing on from every direction. Volume is cheap. Pitches are cheap. Polished surfaces are cheaper than they&apos;ve ever been, and a good demo has never been easier to produce. The scarce thing, the only thing that protects you, is the judgment to look past the surface to the shape underneath. To ask what this is bad at, and whether bad-at-that is survivable for the actual workload you have, not the impressive one on the slide.&lt;/p&gt;
&lt;p&gt;I&apos;m not anti-vendor. I&apos;ve sold to some of the sharpest engineering orgs on the planet, and the good ones were a pleasure precisely because they were impossible to misdirect. They&apos;d thank me for the overview, decline the rest of the tour, and go find the wall themselves. They bought on the gaps. They were right more often than the ones who bought on the demo, and they got there faster, because they spent their time where the answer actually was.&lt;/p&gt;
&lt;p&gt;So when the invite lands, I send the same reply every time. Skip the call. Send me the docs and a sandbox with no guardrails, and I&apos;ll have your answer by Friday. If that makes someone nervous, I already have it.&lt;/p&gt;
&lt;div&gt;&lt;p&gt;Written with AI assistance, in my voice and grounded in my own years running the other side of that table. The judgment is mine.&lt;/p&gt;&lt;/div&gt;</content:encoded><kind>essay</kind><category>judgment</category></item><item><title>Let the compiler review the fleet</title><link>https://jasonwaldrip.com/writing/let-the-compiler-review-the-fleet/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/let-the-compiler-review-the-fleet/</guid><description>A fleet of agents generates more code in an afternoon than your team used to review in a week. Most of it plausible, some of it confidently wrong, all of it too much to eyeball. The compiler doesn&apos;t get tired. Static types check every line the agents wrote before you read one. It&apos;s the instinct behind the languages I build on now, Crystal and Rust: pay a little up front, stop paying at 2am. In the agent era that bill just comes due faster.</description><pubDate>Wed, 24 Jun 2026 08:25:00 GMT</pubDate><content:encoded>&lt;p&gt;A fleet of agents generates more code in an afternoon than your team used to review in a week. Most of it plausible, some of it confidently wrong, all of it too much to eyeball. The compiler doesn&apos;t get tired. Static types check every line the agents wrote before you read one. It&apos;s the instinct behind the languages I build on now, Crystal and Rust: pay a little up front, stop paying at 2am. In the agent era that bill just comes due faster.&lt;/p&gt;</content:encoded><kind>take</kind><category>ai</category></item><item><title>The Load-Bearing Wall</title><link>https://jasonwaldrip.com/writing/the-load-bearing-wall/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-load-bearing-wall/</guid><description>Being the only person who can fix the system feels like seniority. It&apos;s a single point of failure with your name on it, and a leverage ceiling of one. The durable move is making yourself removable: get the why out of your head and into runbooks, pairing, and guardrails the team and the fleet can both run on.</description><pubDate>Sun, 21 Jun 2026 09:30:00 GMT</pubDate><content:encoded>&lt;p&gt;It&apos;s 11pm and the deploy is wedged. You already know why. The env var that didn&apos;t get set, the migration that ran halfway, which service to bounce first and which one to leave alone because bouncing it makes things worse. You fix it in twenty minutes. You&apos;re asleep by midnight. At standup you don&apos;t even bring it up, because to you that wasn&apos;t an incident, it was Tuesday. And somewhere under the tiredness there&apos;s a small warm feeling that says &lt;em&gt;they need me.&lt;/em&gt; Sit with that feeling for a second. It&apos;s the most expensive thing you own.&lt;/p&gt;
&lt;p&gt;Because here&apos;s what that night actually was. The system went down, and the only thing standing between a broken product and a working one was a specific person&apos;s memory. Not a runbook. Not a test. Not a guardrail. A person, awake, who happened to know. That&apos;s not a war story. That&apos;s a single point of failure that pays for its own coffee.&lt;/p&gt;
&lt;h2&gt;The thing nobody says about being the one who can fix it&lt;/h2&gt;
&lt;p&gt;Every hour you spend being indispensable is an hour the system spends learning it can lean on you instead of on itself. Your reliability becomes the team&apos;s liability. The better you are at quietly catching things before they become incidents, the less anyone else ever has to learn the thing you know, and the more load quietly migrates onto the one wall holding the most weight.&lt;/p&gt;
&lt;p&gt;It looks like seniority. It reads, on a contribution graph, like the most committed person on the team. Underneath, it&apos;s a bus factor of one with a green contribution graph. The org has decided, without ever deciding, that one person being out sick is an acceptable way to stop shipping.&lt;/p&gt;
&lt;h2&gt;I have been the wall&lt;/h2&gt;
&lt;p&gt;I walked into Brandfolder to a product going down on a memory leak. For a while I was the person keeping it alive, because in a rescue someone has to be. I could have stayed that person. There&apos;s a version of that job where I&apos;m the hero who knows where all the bodies are buried, paged forever, quietly proud of it.&lt;/p&gt;
&lt;p&gt;The actual job was the opposite. Hire and train a team of six so the product&apos;s survival never rode on one skull again. The rescue people remember is the leak. The rescue that mattered was making myself removable from the critical path. By the time it scaled to a hundred-plus enterprise customers, the thing that kept it up wasn&apos;t me knowing the system. It was a team that did, and tracks that held whether or not any one of us was awake.&lt;/p&gt;
&lt;p&gt;I learned the principle a step earlier, at iTriage, and it&apos;s the one I keep coming back to: the most durable thing a senior engineer ships is other engineers. I mentored through pairing, not lectures. Every patch I handed someone, I owned forever. Every principle I taught, they owned, and so did the next person they taught it to. One of those compounds. The other one pages you at 11pm for the rest of your life.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The most committed person on the team and the biggest single point of failure are very often the same person. Nobody wants to say it because it sounds like an attack. It&apos;s a compliment with a warning stapled to it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Solo heroics have a ceiling, and the ceiling is you&lt;/h2&gt;
&lt;p&gt;There are only so many hours in your week, so many incidents you can personally absorb, so many 11pms before something gives. Go fast alone and you hit a wall that no amount of dedication moves, because the wall is you.&lt;/p&gt;
&lt;p&gt;At CommercialTribe we collapsed a release cycle from weeks to hours across an onsite team and a remote team in Argentina. That number is impossible if release knowledge lives in one person&apos;s head in one timezone. It only happens when the capability lives in the tracks, where anyone can reach it. The win wasn&apos;t a faster engineer. It was knowledge that stopped depending on a particular human being available, and started belonging to the system.&lt;/p&gt;
&lt;h2&gt;What the agent era did to this&lt;/h2&gt;
&lt;p&gt;For most of my career, being the load-bearing wall was a slow, personal tax. You paid it in sleep and in the vacations you didn&apos;t fully take. Now the tax has a sharper edge, and it&apos;s worth being honest about why.&lt;/p&gt;
&lt;p&gt;Volume is free now. You can point a fleet of agents at a problem and they will generate all day without coffee or ego. But a fleet can only act on what&apos;s been made legible. The architecture decision you made for a reason that lives only in your memory, the landmine you route around on instinct, the &quot;we tried that in 2023 and here&apos;s why it bit us&quot; that never got written down: none of it exists to an agent. It can&apos;t reason over what was never written. It will confidently undo the exact decision you&apos;d have fought for in a meeting, because to the model that decision was never made.&lt;/p&gt;
&lt;p&gt;I&apos;ve said you multiply judgment by a fleet, never zero by a fleet, because anything times zero is still zero. The load-bearing wall is where the zero hides. Judgment locked inside one skull can&apos;t be multiplied, by a teammate or by a machine, because there&apos;s nothing there to copy.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;Judgment that can&apos;t be transmitted doesn&apos;t scale.&lt;/div&gt;
  &lt;div&gt;The indispensable engineer has a bus factor of one and a leverage ceiling of one. The moat was never what you know. It&apos;s what you can hand off.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;That reframes the whole &quot;judgment is the moat&quot; idea, and it&apos;s the part I want to land. Judgment is only a moat if it can leave your head intact. The expert whose expertise dies when they log off isn&apos;t a moat. They&apos;re a liability the org has agreed to call a strength.&lt;/p&gt;
&lt;h2&gt;Make yourself removable&lt;/h2&gt;
&lt;p&gt;This is not &quot;document everything&quot; busywork. It&apos;s a deliberate move to get the value out of one person and into a place the team and the fleet can both run on. In rough priority order:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Write the why, not just the what.&lt;/b&gt; A runbook that lists steps is for the human at 11pm. A &lt;a href=&quot;/choices/write-it-down&quot;&gt;record of why the system is the way it is&lt;/a&gt; is for the human at 11pm &lt;em&gt;and&lt;/em&gt; the agent at noon. Capture the decision and the reason you&apos;d defend it, because that&apos;s exactly the context a fleet fills in wrong when it&apos;s missing.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Pair, don&apos;t rescue.&lt;/b&gt; The fast fix is to do it yourself. The durable one is to &lt;a href=&quot;/writing/teach-the-principle-not-the-patch/&quot;&gt;teach the principle&lt;/a&gt; so the next person doesn&apos;t need you for the next instance. A slow handoff beats a fast fix the second time the problem shows up, and there&apos;s always a second time.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Put the knowledge in the tracks.&lt;/b&gt; The best place for &quot;don&apos;t do that, it breaks under load&quot; isn&apos;t your head. It&apos;s a test that fails when someone tries. Types, CI, and review are &lt;a href=&quot;/choices/autonomy-with-guardrails&quot;&gt;guardrails&lt;/a&gt;, and a guardrail is knowledge that doesn&apos;t need you awake to work. Every rule you encode is a 2am page you&apos;ll never get.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Measure the bus factor honestly.&lt;/b&gt; If one person being out stops a release, freezes a system, or means a question goes unanswered for a week, that isn&apos;t seniority. It&apos;s debt with a name on it. Find the walls. Spread the load before the wall does it for you, at the worst possible time.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of this makes you less valuable. It does the opposite. The engineer who can hand off everything they know is the one you actually want running the next thing, because their value travels. The one who can&apos;t is stuck being the wall forever, which feels like security right up until it feels like a cage.&lt;/p&gt;
&lt;h2&gt;Build the thing that stands without you&lt;/h2&gt;
&lt;p&gt;The goal was never to be the wall holding the building up. It&apos;s to build something that stays standing when you walk out of the room. Indispensable is not the win condition. It&apos;s the failure mode wearing the costume of one.&lt;/p&gt;
&lt;p&gt;So ask the uncomfortable question, the real one. If you went fully dark for two weeks, no Slack, no laptop, what breaks? Whatever has your name on it and only your name, that&apos;s not your job security. That&apos;s your backlog. It&apos;s the work you haven&apos;t finished, which is getting it out of your head and into something the team, and the fleet, can carry without you.&lt;/p&gt;
&lt;p&gt;I spend most of my time now walking into orgs propped up on one or two load-bearing walls, where the whole thing runs on a couple of people who can never really log off. Turning what&apos;s in their heads into tracks the team and the fleet can run on without them is most of the job. If that&apos;s the wall you&apos;ve become, or the one you&apos;ve come to rely on, that&apos;s &lt;a href=&quot;https://thebushido.co&quot;&gt;the conversation I&apos;m here for&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; has spent his career leading engineering at consumer-scale software companies. He writes about engineering leadership, infrastructure, and building in the age of AI agents.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the experience, and the calls on what mattered and what to cut are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>leadership</category></item><item><title>The Plan Was Never the Point</title><link>https://jasonwaldrip.com/writing/the-plan-was-never-the-point/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-plan-was-never-the-point/</guid><description>Agents now generate a finished plan in seconds. But planning was never about the artifact, it was the thinking that builds the judgment to adapt when the plan meets reality. Approving a plan is not the same as making one, and the difference shows up at 2am.</description><pubDate>Sat, 20 Jun 2026 08:40:00 GMT</pubDate><content:encoded>&lt;p&gt;You ask the agent to scope the feature. Twelve seconds later you&apos;ve got a plan. Sectioned, sequenced, a tidy risks heading at the bottom, the dependencies called out in order. It looks like the plan you&apos;d have spent an afternoon on, and it&apos;s faster and better formatted than the one you&apos;d have written tired on a Thursday. You skim it. Nothing jumps out. You say go. Three weeks later you&apos;re standing in front of a design decision nobody on the team can explain, because nobody on the team actually made it. The model made it. You approved it. And &quot;approved&quot; turns out to be a very different thing from &quot;understood.&quot;&lt;/p&gt;
&lt;p&gt;I keep watching smart people walk into this, and they walk in precisely because the output is good. Bad plans get scrutiny. It&apos;s the reasonable-looking ones that get a nod and a merge.&lt;/p&gt;
&lt;h2&gt;what planning was actually for&lt;/h2&gt;
&lt;p&gt;There&apos;s an old line from Eisenhower that gets quoted to death and understood about half the time: &quot;Plans are worthless, but planning is everything.&quot; The military has known this longer than software has existed. &lt;a href=&quot;https://en.wikipedia.org/wiki/Helmuth_von_Moltke_the_Elder&quot;&gt;Moltke&lt;/a&gt; got there in the 1800s: no plan survives first contact with the enemy. Both men spent their lives making plans. Neither thought the document was the deliverable.&lt;/p&gt;
&lt;p&gt;Here&apos;s what they meant. When you sit down and actually plan something, you simulate it. You run the system forward in your head, hit a wall, back out, try a different route, hit another wall. You argue with yourself about the case you&apos;re pretending won&apos;t happen. By the time you&apos;ve got a plan, the plan is the &lt;em&gt;residue&lt;/em&gt; of all that. The valuable part isn&apos;t the residue. It&apos;s that you now carry a map of the territory: why this path and not the three you rejected, where the load is, which corner you&apos;re nervous about and why.&lt;/p&gt;
&lt;p&gt;That map is what lets you adapt when reality does what reality always does and refuses to match the document. You don&apos;t re-plan from zero. You consult the model in your head, the one you built by doing the work, and you adjust. The plan was meaningless the second it met production. The planning is what&apos;s still paying you.&lt;/p&gt;
&lt;h2&gt;the artifact was always a byproduct&lt;/h2&gt;
&lt;p&gt;So here&apos;s the move the agent makes, and why it&apos;s so easy to miss. It hands you the residue and skips the fire. You get the document without doing the simulating. You hold a map of a territory you never walked.&lt;/p&gt;
&lt;p&gt;It reads like a plan. It is, structurally, a plan. What it isn&apos;t is &lt;em&gt;yours&lt;/em&gt;. Nothing in your head changed when that file appeared. You can recite it. You can&apos;t defend it, because defending it means knowing the three paths it rejected and why, and you were never in the room where those got rejected. There was no room. There were twelve seconds.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;Reading the answer is not the same as solving it.&lt;/div&gt;
  &lt;div&gt;A plan you approved gives you the conclusion. A plan you made gives you the map that lets you adapt when the conclusion breaks. Only one of those survives contact.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I learned this on the other side of it, the slow way, before any of this was automatable. The most useful thing anyone ever told me about scale is that it&apos;s a design problem before it&apos;s a code problem: decide where state lives before you write a single line. That sounds like advice about the answer. It isn&apos;t. The value was never the answer, &quot;state lives here.&quot; It&apos;s the argument you have with yourself getting there, consistency against availability, what you&apos;re willing to lose in a partition, where the writes actually concentrate. Win that argument honestly and you can debug the thing at 2am, because you remember exactly which tradeoff you took and what it was supposed to cost. Skip it, let something else decide where state lives while you nod, and you&apos;ve shipped a system you fundamentally cannot reason about. The agent will happily make that call. It does not have to wake up for the page.&lt;/p&gt;
&lt;h2&gt;generation is free, the understanding is the work&lt;/h2&gt;
&lt;p&gt;This is the same fault line I keep coming back to, just moved upstream. I&apos;ve argued you multiply judgment by a fleet, never zero by a fleet, because anything times zero is still zero. Most people picture that at the code layer: the agent writes the diff, you catch what&apos;s wrong. But the diff isn&apos;t where the zero hides. It hides in the plan, one level up, where the decisions that shape everything downstream get made in a place you weren&apos;t.&lt;/p&gt;
&lt;p&gt;Letting the fleet generate the plan is fine. It&apos;s good, even. What&apos;s fatal is treating the generated plan as the planning. The output is the cheap part now, all of it, the plan included. The expensive part, the only part that was ever scarce, is a human carrying an accurate model of why the system is shaped the way it is. You don&apos;t get that model by reading. You get it by interrogating: arguing with the plan, poking the case it waved off, asking it to defend the route it took over the one it didn&apos;t, until the map is actually in your head and not just in the file. That&apos;s not slower planning. That&apos;s the planning, done on top of a draft instead of a blank page. The draft is a gift. Mistaking the draft for the work is the whole trap.&lt;/p&gt;
&lt;p&gt;There&apos;s a hard version of this I&apos;ve said to more than one engineer: the shortcut you hand someone today is the context gap you own forever. Same physics here, except the someone is you, and the person you&apos;re shorting is yourself in three weeks, standing in front of a decision with no idea how it got made.&lt;/p&gt;
&lt;h2&gt;so what do you actually do&lt;/h2&gt;
&lt;p&gt;You don&apos;t stop generating plans. You&apos;d be giving up a real advantage, and the blank page was never sacred. You change what you do with the draft.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Treat the generated plan as a question, not an answer.&lt;/b&gt; Its job is to give you something to argue with. If you find yourself agreeing with all of it on the first read, you haven&apos;t read it, you&apos;ve skimmed it. Go back and find the decision you&apos;d have made differently, and make the plan tell you why it didn&apos;t.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Make it show its rejected paths.&lt;/b&gt; A plan with no roads not taken is hiding the part that matters. Ask what it considered and dropped, and why. The discarded options are where the judgment lives. If it can&apos;t produce them, that&apos;s your signal the thinking didn&apos;t happen.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Find the load-bearing decision and own it personally.&lt;/b&gt; Most plans have one or two calls that everything else rests on: where state lives, what&apos;s the source of truth, which thing you&apos;ll be unable to change later. Those you make yourself, by hand, with the argument fully had. Let the agent draft the other ninety percent.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Pass the empty-room test.&lt;/b&gt; Before you commit to it, ask whether you could defend the plan in a room where the model isn&apos;t invited to help. If you can, the map is in your head. If you can&apos;t, you have a document, and you should keep working until you have a plan.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of this is anti-agent. I&apos;d be a hypocrite, I wrote this one with a fleet at my elbow. It&apos;s a warning about the specific way this era lets you skip the part that was always the point and not notice, because the thing you skipped used to leave an obvious gap and now leaves a polished file in its place.&lt;/p&gt;
&lt;p&gt;So next time the plan shows up in twelve seconds, the question isn&apos;t whether it&apos;s good. It usually is. The question is whether you could stand up tomorrow and defend it without the thing that wrote it. If you can&apos;t, you didn&apos;t make a plan. You accepted one. And the bill for the difference always comes due in the same place: at 2am, in front of a decision nobody remembers making.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; has spent his career leading engineering at consumer-scale software companies. He writes about engineering leadership, infrastructure, and building in the age of AI agents.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the experience, and the calls on what mattered and what to cut are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>judgment</category></item><item><title>Earn It</title><link>https://jasonwaldrip.com/writing/earn-it/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/earn-it/</guid><description>Premature complexity is a tax you pay every day you operate the system, not a one-time cost at decision time. The senior move is naming the property you actually need, then picking the cheapest thing that delivers it. Earn the complexity before you take it on.</description><pubDate>Fri, 19 Jun 2026 07:45:00 GMT</pubDate><content:encoded>&lt;p&gt;You&apos;re in an architecture review for a product with a few thousand users and a roadmap that fits on an index card. Someone&apos;s whiteboard has Kubernetes on it. A message bus. Three services where there&apos;s currently one. The diagram is gorgeous. Boxes, arrows, a little cloud. Everyone nods, because the diagram looks like what a serious system is supposed to look like, and nobody wants to be the person who says the quiet thing: we don&apos;t have the problem this solves yet.&lt;/p&gt;
&lt;p&gt;I&apos;ve been the person who says it. It doesn&apos;t make you popular in the room. The elaborate plan reads as ambition and foresight, and the simple one reads as not thinking big enough. So the simple plan loses, and eighteen months later the team is spending half its week operating infrastructure that&apos;s babysitting a workload a single Postgres box would have shrugged at.&lt;/p&gt;
&lt;h2&gt;The impressive choice is a tell&lt;/h2&gt;
&lt;p&gt;There&apos;s a kind of design that&apos;s optimized for how it looks on a slide, or on a résumé, instead of for the problem in front of it. You can usually spot it because the justification runs backwards. Instead of &quot;here&apos;s our constraint, here&apos;s the cheapest thing that meets it,&quot; it&apos;s &quot;here&apos;s this powerful tool, surely we&apos;ll need it eventually.&quot; The tool comes first and the need gets reverse-engineered to fit.&lt;/p&gt;
&lt;p&gt;I get the pull. Reaching for the powerful thing feels like seniority. It signals that you&apos;ve operated at scale, that you know the patterns the big shops use. But pattern-matching to Google&apos;s architecture when you have Google&apos;s problems is wisdom. Pattern-matching to it when you have a CRUD app and four thousand users is cargo culting with extra steps. Ozan Onay made this point cleanly years ago in &lt;a href=&quot;https://blog.bradfieldcs.com/you-are-not-google-84912cf44afb&quot;&gt;&quot;You Are Not Google&quot;&lt;/a&gt;: companies adopt the tools of giants without ever asking whether they share the giants&apos; constraints. The tool was a good answer to a question you don&apos;t have.&lt;/p&gt;
&lt;h2&gt;When I did reach for it&lt;/h2&gt;
&lt;p&gt;This isn&apos;t an argument for staying small or being scared of real infrastructure. I&apos;ve made the expensive call plenty of times, when the workload earned it.&lt;/p&gt;
&lt;p&gt;At CommercialTribe I migrated us onto GCP and Kubernetes. From the outside that&apos;s exactly the move I&apos;m warning about: a VP shows up and reaches for the heavyweight orchestrator. But it wasn&apos;t résumé-driven. We had a split org, onsite engineers and a remote team in Argentina, a release cadence measured in weeks, and a stability problem that was costing us trust with every deploy. Kubernetes was the cheapest path to the thing we actually needed, which was a release process that collapsed from weeks to hours and held its footing under real load. The complexity paid for itself the first month, because the workload had already arrived. We were drowning. The orchestrator was the lifeboat, not the yacht.&lt;/p&gt;
&lt;p&gt;That&apos;s the distinction. Same tool, opposite decision, and the only thing that changed was whether the problem was real yet.&lt;/p&gt;
&lt;h2&gt;Complexity is rent, not a purchase&lt;/h2&gt;
&lt;p&gt;Here&apos;s the part the architecture review never accounts for, because the cost shows up on a different day than the decision. When you choose the complex thing, you don&apos;t pay for it once at the whiteboard. You pay rent on it for as long as it runs.&lt;/p&gt;
&lt;p&gt;Every service you split out is a deploy pipeline, a set of dashboards, an on-call surface, a place where the network can fail between two things that used to be a function call. Every additional language is a second toolchain, a second hiring profile, a second set of idioms your team has to hold in their heads at 2am. Every message bus is a new failure mode nobody had to reason about before. None of that shows up in the demo. All of it shows up in the year you spend operating the thing.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;You pay for complexity every day it runs, not the day you choose it.&lt;/div&gt;
  &lt;div&gt;Which is exactly why it&apos;s so easy to take on. The bill arrives at a different desk, on a different date, addressed to whoever&apos;s on call.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Dan McKinley framed the budget for this better than anyone in &lt;a href=&quot;https://mcfunley.com/choose-boring-technology&quot;&gt;&quot;Choose Boring Technology.&quot;&lt;/a&gt; His idea: a company has a small number of innovation tokens, and every shiny, unproven, operationally-hungry choice spends one. Boring tech, the stuff with a decade of war stories and a flat learning curve, costs you nothing to run and frees the tokens for the places where novelty is actually the point. Spend them on your differentiator. Don&apos;t burn one on a queue when a database table would have done it.&lt;/p&gt;
&lt;p&gt;This is why &quot;just use Postgres until it hurts&quot; is the same argument wearing different clothes. One engine that moonlights as your queue, your cache, your search, and your document store is one thing to operate, one thing to back up, one thing to reason about when it&apos;s 2am and the pager goes off. Five specialized engines, each individually defensible, add up to a system no one person can hold in their head. You reach for the second engine when the first one genuinely buckles. Not before, on the theory that you might.&lt;/p&gt;
&lt;h2&gt;Earn it&lt;/h2&gt;
&lt;p&gt;So here&apos;s the handle: &lt;strong&gt;earn it.&lt;/strong&gt; Don&apos;t take on complexity before the workload forces it. Name the property you actually need, the real constraint, throughput or fault-isolation or types-as-guardrails, then pick the cheapest thing that delivers exactly that and nothing more.&lt;/p&gt;
&lt;p&gt;When GigSmart needed a backend, I chose Elixir, and that&apos;s a less common bet than Node or Rails. But a real-time gig marketplace &lt;em&gt;is&lt;/em&gt; a concurrency problem at its core, fault isolation isn&apos;t a feature you bolt on later, it&apos;s the shape of the thing. The constraint was real, so the choice was earned. Same year I&apos;d have told you not to touch it for a CRUD app. At Brandfolder, Ruby was crashing generating multi-gigabyte zip files, the wrong tool for heavy IO, so we carved that one piece out into Go and left the rest of the monolith alone. We didn&apos;t rewrite the app in Go because Go is fast. We moved the one workload that demanded it. The scalpel, not the bulldozer.&lt;/p&gt;
&lt;p&gt;The verdict on every one of those tools, on my own &lt;a href=&quot;/choices/&quot;&gt;choices&lt;/a&gt; page, carries a &quot;when I don&apos;t&quot; right next to the &quot;when I reach for it.&quot; The honest &quot;when I don&apos;t&quot; is half the credibility. Anyone can list a stack. Knowing what to leave off it is the work.&lt;/p&gt;
&lt;h2&gt;The era that makes this harder&lt;/h2&gt;
&lt;p&gt;This used to be self-limiting. Complexity was expensive to build, so the cost of construction was a natural brake on how much of it you took on. You felt the weight of the elaborate plan in the weeks it took to stand up, and sometimes that friction talked you out of it.&lt;/p&gt;
&lt;p&gt;That brake is gone. Generation is free now. Point a fleet of agents at &quot;scaffold me a microservices architecture with a message bus and per-service pipelines&quot; and you&apos;ll have it by lunch, plausible config and all. The thing that used to take a quarter to build wrong now takes an afternoon to build wrong. And here&apos;s the trap: the cost of &lt;em&gt;building&lt;/em&gt; it collapsed, but the cost of &lt;em&gt;operating&lt;/em&gt; it didn&apos;t move an inch. A system is just as hard to run at 2am whether a human typed it or an agent did. You get the complexity at a discount and the rent at full price.&lt;/p&gt;
&lt;p&gt;Which means the discipline matters more than it ever has, not less. When the impressive thing is nearly free to produce, the only thing standing between you and a system you can&apos;t afford to operate is the judgment to not reach for it. That&apos;s the whole game now. Volume is free; deciding what&apos;s worth running is the moat. An agent will never tell you that you didn&apos;t need the thing it was perfectly happy to build you.&lt;/p&gt;
&lt;p&gt;So next time the gorgeous diagram is on the whiteboard and everyone&apos;s nodding, ask the unpopular question. Not &quot;can we build this.&quot; Of course you can, that&apos;s never been cheaper. Ask what workload, here, today, makes this the cheapest path and not the most expensive one. If the answer is &quot;we might need it someday,&quot; you haven&apos;t earned it yet. Put it back on the shelf and come find it when the problem shows up. It&apos;ll still be there. It always is.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; has spent his career leading engineering at consumer-scale software companies. He writes about engineering leadership, infrastructure, and building in the age of AI agents. If you&apos;re staring at a diagram that&apos;s bigger than your problem and want a second opinion, &lt;a href=&quot;/work-with-me/&quot;&gt;that&apos;s the kind of call I&apos;m good at.&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the calls, and the stories are mine, drawn from real decisions.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>architecture</category></item><item><title>Autonomy is infrastructure, not trust</title><link>https://jasonwaldrip.com/writing/autonomy-is-infrastructure/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/autonomy-is-infrastructure/</guid><description>&quot;Ask forgiveness, not permission&quot; is half a sentence. The other half is the rails that make forgiveness cheap: tests, CI, review, types. That&apos;s what lets me turn a team, or a fleet of agents, loose without signing off on every move. The guardrails catch what goes wrong before it ships. Pull them out and &quot;move fast&quot; is just &quot;break things&quot; with extra confidence. Build the rails first, then get out of the way.</description><pubDate>Thu, 18 Jun 2026 09:20:00 GMT</pubDate><content:encoded>&lt;p&gt;&quot;Ask forgiveness, not permission&quot; is half a sentence. The other half is the rails that make forgiveness cheap: tests, CI, review, types. That&apos;s what lets me turn a team, or a fleet of agents, loose without signing off on every move. The guardrails catch what goes wrong before it ships. Pull them out and &quot;move fast&quot; is just &quot;break things&quot; with extra confidence. Build the rails first, then get out of the way.&lt;/p&gt;</content:encoded><kind>take</kind><category>leadership</category></item><item><title>The Tests Are Green</title><link>https://jasonwaldrip.com/writing/the-tests-are-green/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-tests-are-green/</guid><description>The gap between &apos;the tests are green&apos; and &apos;the feature works&apos; is where expensive bugs live. Observability means being able to ask what&apos;s actually true about your running system, not just whether errors were thrown.</description><pubDate>Tue, 16 Jun 2026 21:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You shipped Thursday afternoon. The merge train was green, the image promoted clean, the canary baked six hours without a blip. You slept fine. Friday morning there&apos;s a support thread: customers can&apos;t get through checkout. You open the dashboards. Error rate, normal. Latency, normal. Nothing in the exception tracker, every health check green. By every signal you&apos;re paying to watch, the system is healthy. The feature is broken.&lt;/p&gt;
&lt;p&gt;What broke doesn&apos;t throw. A user submitted a form, it validated, the response came back 200. The record never persisted, because of how the confirmation step races a read against a write that hasn&apos;t committed yet. Your tests cover the form. They cover the validation. They don&apos;t cover that combination, with that database state, at that timing, because nobody wrote that test, because nobody thought to, because the code reads fine in isolation. It &lt;em&gt;is&lt;/em&gt; fine in isolation. That was never the question.&lt;/p&gt;
&lt;h2&gt;The question tests don&apos;t answer&lt;/h2&gt;
&lt;p&gt;Tests verify code paths. That&apos;s the job, and it&apos;s not negotiable. You write a test, the test tells you the function does what you claimed. Real, fast, valuable. But &quot;this function does what I said&quot; is a different question from &quot;the checkout flow is working right now, for real people, on real phones, against production data.&quot;&lt;/p&gt;
&lt;p&gt;Those two questions don&apos;t fail together. A team that trusts the first one to answer the second has built its confidence in the wrong place, and won&apos;t find out until a customer tells them.&lt;/p&gt;
&lt;p&gt;I walked into Brandfolder to a product going down on a memory leak. The test suite was green the whole time. Memory isn&apos;t a code path you assert against; it&apos;s a property of the thing while it runs, under real load, over real hours. We couldn&apos;t fix it until we could &lt;em&gt;see&lt;/em&gt; it. Once we could watch the process actually behave, the fix came fast. Before that we were tightening bolts that weren&apos;t loose while the real one backed out a turn at a time.&lt;/p&gt;
&lt;h2&gt;Monitoring is watching for what you feared&lt;/h2&gt;
&lt;p&gt;Most teams have monitoring. Dashboards, alerts, a rotation. And nearly all of it is shaped around the failures they imagined the day they built the system.&lt;/p&gt;
&lt;p&gt;So you end up instrumented for the outage you pictured, blind to the one you didn&apos;t.&lt;/p&gt;
&lt;p&gt;Error rate catches crashes. Latency catches slow. Queue depth catches backed-up. All worth having. None of them answer whether a person can finish a flow. Whether the submit actually persisted. Whether the third-party call that returned 200 also returned the &lt;em&gt;right&lt;/em&gt; thing. Whether the feature you shipped last week is being used or quietly abandoned because it&apos;s broken in a way that never writes a log line. A 200 with an empty body is the happiest-looking failure in your whole system.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Your system can pass every check you&apos;re running and fail every one that matters to the person on the other end.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Observability is a different property&lt;/h2&gt;
&lt;p&gt;The word got annexed by APM vendors and flattened into &quot;dashboards, but prettier.&quot; That&apos;s not what I mean by it.&lt;/p&gt;
&lt;p&gt;As a property of a system, observability is this: can you look at the outputs and understand what&apos;s going on inside, including things you never thought to instrument? Here&apos;s the clean test. Something breaks in prod in a shape you didn&apos;t predict. Can you work out why from data you already have, without shipping new logging and waiting for a deploy? If the honest answer is &quot;we&apos;d have to add instrumentation and redeploy,&quot; then what you have is monitoring for predicted failures. Useful. Not the same thing.&lt;/p&gt;
&lt;p&gt;What closes the gap is structured, high-cardinality data, captured at enough granularity that you can ask questions you didn&apos;t know to ask when you wrote the feature. Not &quot;was there an error&quot; but &quot;what did this user&apos;s session look like across these three services in the ninety seconds before it stalled.&quot; Not &quot;is the queue deep&quot; but &quot;which job class started retrying after Wednesday&apos;s deploy, and what do those payloads share.&quot; If the answer to that lives in next sprint&apos;s logging ticket, you are permanently one incident behind the thing that&apos;s actually hurting you.&lt;/p&gt;
&lt;p&gt;The cut is simple. Monitoring tells you something went wrong. &lt;a href=&quot;/choices/observability&quot;&gt;Observability&lt;/a&gt; tells you why, before the support ticket does it for you.&lt;/p&gt;
&lt;h2&gt;The agent era widens the gap&lt;/h2&gt;
&lt;p&gt;Every bit of this gets heavier when generation goes cheap.&lt;/p&gt;
&lt;p&gt;When one engineer ships a handful of deliberate changes a week, there&apos;s an attention budget riding on each diff. A careful human reads it, pictures the failure, writes the test for the edge they&apos;re worried about. The coverage is a fossil of the care that went into the code. It exists because a person was nervous about exactly the right thing.&lt;/p&gt;
&lt;p&gt;When a fleet opens dozens of clean, plausible merge requests a day, that nervousness is gone. Agents test what they exercised. They don&apos;t know about the payment provider that behaves differently on a retry, the mobile layout that&apos;s subtly wrong in a viewport no one opened, the analytics event that stopped firing after a re-render three components away. They don&apos;t know because nobody told them, and at generation-era volume there&apos;s no human reading every diff with the right fear in their gut. I&apos;ve written before that you multiply judgment by a fleet, never zero by one. This is where the zero hides: in the tests nobody knew to ask for.&lt;/p&gt;
&lt;p&gt;Which leaves exactly one honest source of truth: the running system. Real users, real product, real flows completing or not. Funnel completion, outcomes by result, conversion against the baseline. That signal is what tells you Thursday&apos;s deploy actually worked, because it&apos;s measuring the only thing that was ever the point. When generation is free, knowing what&apos;s true is the entire job.&lt;/p&gt;
&lt;h2&gt;What to actually instrument&lt;/h2&gt;
&lt;p&gt;Tests verify intent. &lt;a href=&quot;/choices/observability&quot;&gt;Observability&lt;/a&gt; verifies outcomes. You need both, and you should stop pretending one covers for the other.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Watch outcomes, not just exceptions.&lt;/b&gt; A user who started a flow and didn&apos;t finish it is a signal, even when nothing threw. Instrument the funnel, not only the endpoints. Abandonment is data.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Real-user monitoring over synthetic checks.&lt;/b&gt; Synthetic tests prove the happy path under conditions you controlled. RUM tells you what&apos;s happening on real devices, on real connections, right now. Both earn their keep; only one knows about this morning&apos;s deploy.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;One honest health endpoint.&lt;/b&gt; The canary is only as good as what it bakes against. Error rate and latency are necessary and nowhere near sufficient. Aggregate a real business signal into the gate: conversion, funnel completion, worker success. A slower honest gate beats a fast lying one every time.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Structure events for the question you haven&apos;t asked yet.&lt;/b&gt; Every request and action should carry enough context to reconstruct what happened without a redeploy: user, session, flags in effect, code version, the IDs that let you stitch a story across services. The log you&apos;ll be desperate for next month is the one you have to write this sprint.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of this demotes tests. They&apos;re still the fastest feedback in the cycle, and they catch things in seconds that production would charge you days for. They just answer &quot;does this code do what I said,&quot; not &quot;is this working for the person holding the phone.&quot; Know which question you&apos;re asking. Carry evidence for both.&lt;/p&gt;
&lt;h2&gt;The signal decides&lt;/h2&gt;
&lt;p&gt;I&apos;ve written about the merge train, the canary, what it takes to make every green commit shippable. All of it rests on a signal worth trusting. A canary baking against error rate and latency is a good start. A canary baking against those &lt;em&gt;plus&lt;/em&gt; &quot;did the core flow complete&quot; is the difference between confidence and theater.&lt;/p&gt;
&lt;p&gt;Your trust in the release process can&apos;t run deeper than the signal underneath it. Build shallow signals and what you&apos;ve actually built is a very sophisticated machine for shipping into the dark with the lights off and a smile on.&lt;/p&gt;
&lt;p&gt;So sit with this one. If something broke quietly in your product right now, no exception, no spike, just a flow that stopped completing, how long until you knew? An hour? A support ticket? Something you&apos;d stumble onto in next week&apos;s numbers?&lt;/p&gt;
&lt;p&gt;That number is the investment. And unlike most of the debt on your books, you can pay it down before it comes due.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; has spent his career leading engineering at consumer-scale software companies. He writes about engineering leadership, infrastructure, and building in the age of AI agents.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the experience, and the calls on what mattered and what to cut are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>reliability</category></item><item><title>Teach the principle, not the patch</title><link>https://jasonwaldrip.com/writing/teach-the-principle-not-the-patch/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/teach-the-principle-not-the-patch/</guid><description>The hardest part of being a senior engineer isn&apos;t solving the hard problem. It&apos;s watching someone struggle toward it slower than you could, and keeping your hands in your pockets. Unblocking means pointing at the answer. Carrying means they need you again next time. At iTriage I learned the most durable thing a senior engineer ships is other engineers. The shortcut you hand them today is the context gap you own forever.</description><pubDate>Fri, 12 Jun 2026 09:15:00 GMT</pubDate><content:encoded>&lt;p&gt;The hardest part of being a senior engineer isn&apos;t solving the hard problem. It&apos;s watching someone struggle toward it slower than you could, and keeping your hands in your pockets. Unblocking means pointing at the answer. Carrying means they need you again next time. At iTriage I learned the most durable thing a senior engineer ships is other engineers. The shortcut you hand them today is the context gap you own forever.&lt;/p&gt;</content:encoded><kind>take</kind><category>leadership</category></item><item><title>The context your agents don&apos;t have</title><link>https://jasonwaldrip.com/writing/the-context-your-agents-dont-have/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-context-your-agents-dont-have/</guid><description>An undocumented codebase has always been a tax on new hires. In the agent era it&apos;s a different problem. Agents don&apos;t go quiet when they hit a gap in context — they fill it. Confidently, and wrong. The architectural decision everyone knows because they were in the room? That doesn&apos;t exist to the fleet. They&apos;ll reverse it, build on top of it in ways that silently invalidate it. Write down why the system is the way it is. Not for the humans. For the context window.</description><pubDate>Tue, 09 Jun 2026 08:30:00 GMT</pubDate><content:encoded>&lt;p&gt;An undocumented codebase has always been a tax on new hires. In the agent era it&apos;s a different problem. Agents don&apos;t go quiet when they hit a gap in context — they fill it. Confidently, and wrong. The architectural decision everyone knows because they were in the room? That doesn&apos;t exist to the fleet. They&apos;ll reverse it, build on top of it in ways that silently invalidate it. Write down why the system is the way it is. Not for the humans. For the context window.&lt;/p&gt;</content:encoded><kind>take</kind><category>ai</category></item><item><title>Write it down. Not the what. The why.</title><link>https://jasonwaldrip.com/writing/write-it-down/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/write-it-down/</guid><description>Every decision your team made and never wrote down is a debt, payable by asking someone. Works until it doesn&apos;t: departures, six-month velocity gaps, agents that need context to not be dangerous. At Brandfolder, I knew why the zip pipeline was in Go. That knowledge survived because the people did. Decision records aren&apos;t documentation theater. They&apos;re the context a fleet can reason over, and the resilience that outlasts the team that built it.</description><pubDate>Mon, 08 Jun 2026 08:15:00 GMT</pubDate><content:encoded>&lt;p&gt;Every decision your team made and never wrote down is a debt, payable by asking someone. Works until it doesn&apos;t: departures, six-month velocity gaps, agents that need context to not be dangerous. At Brandfolder, I knew why the zip pipeline was in Go. That knowledge survived because the people did. Decision records aren&apos;t documentation theater. They&apos;re the context a fleet can reason over, and the resilience that outlasts the team that built it.&lt;/p&gt;</content:encoded><kind>take</kind><category>leadership</category></item><item><title>A monorepo is a context boundary</title><link>https://jasonwaldrip.com/writing/a-monorepo-is-a-context-boundary/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/a-monorepo-is-a-context-boundary/</guid><description>The debate used to be tooling overhead and org preferences. Those tradeoffs are real. But there&apos;s a second argument now that flips the calculus. When a fleet of agents has to reason over a change, can they see the whole system? Split repos mean split context: a fix in service A that quietly breaks service B goes undetected because nothing is looking at both. One repo isn&apos;t a preference. It&apos;s the context boundary the whole system needs, for humans and agents both.</description><pubDate>Sun, 07 Jun 2026 09:30:00 GMT</pubDate><content:encoded>&lt;p&gt;The debate used to be tooling overhead and org preferences. Those tradeoffs are real. But there&apos;s a second argument now that flips the calculus. When a fleet of agents has to reason over a change, can they see the whole system? Split repos mean split context: a fix in service A that quietly breaks service B goes undetected because nothing is looking at both. One repo isn&apos;t a preference. It&apos;s the context boundary the whole system needs, for humans and agents both.&lt;/p&gt;</content:encoded><kind>take</kind><category>infrastructure</category></item><item><title>Release on Demand</title><link>https://jasonwaldrip.com/writing/release-on-demand/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/release-on-demand/</guid><description>Scheduled, batched releases are a symptom of not trusting your pipeline. The fix is a confidence stack deep enough that every green commit is shippable, and a recovery stack fast enough that the rare miss gets patched before users notice. Merge trains, build-once-promote-via-overlay, automated canary, and TF for the building, Git for the lights.</description><pubDate>Thu, 04 Jun 2026 16:20:00 GMT</pubDate><content:encoded>&lt;p&gt;There&apos;s a calendar invite on your team&apos;s shared calendar called something like &lt;strong&gt;&quot;Release Window.&quot;&lt;/strong&gt; Maybe it&apos;s every other Thursday at 2pm. There&apos;s a change freeze the day before. A go/no-go thread. A rollback plan nobody&apos;s tested. And a quiet, shared understanding that you do not, under any circumstances, ship after lunch on a Friday. That invite is not a process. It&apos;s a confession.&lt;/p&gt;
&lt;p&gt;It says: we don&apos;t trust our own releases, so we&apos;ve agreed to only do the scary thing on a schedule, in daylight, with everyone watching. Call it discipline if you want. It&apos;s really a workaround for a capability the team never built.&lt;/p&gt;
&lt;h2&gt;The doom loop nobody names&lt;/h2&gt;
&lt;p&gt;Here&apos;s the trap, and most teams are living in it without naming it. There&apos;s a gap between &quot;this commit passed CI&quot; and &quot;this code is safe to ship.&quot; For a lot of teams that gap is measured in calendar weeks. Every change pays it. So you do the rational thing: you batch. You wait until you&apos;ve got enough changes to justify the ceremony, then you ship them all at once.&lt;/p&gt;
&lt;p&gt;Except batching is the thing that makes releases dangerous. A release with one change in it is easy to reason about. A release with forty changes in it is a haystack with an unknown number of needles. So the big batch needs more testing, more soak, more sign-off, which makes it slower to ship, which means the next batch is even bigger by the time it goes. Round and round. The schedule tightens. The freezes get longer. The hotfixes start going straight to prod outside the pipeline entirely, because the pipeline is the slow path and prod is on fire.&lt;/p&gt;
&lt;p&gt;I&apos;ve watched teams answer this with more process. A freeze before the freeze. A release captain. A go/no-go meeting with more people in the room every quarter. Every one of those is management layered on top of the fear, never a fix for the thing causing it.&lt;/p&gt;
&lt;p&gt;That&apos;s the loop: &lt;strong&gt;the less you trust a release, the bigger you make it, and the bigger you make it, the less it deserves your trust.&lt;/strong&gt; The schedule is just where you&apos;ve parked the anxiety.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The schedule isn&apos;t keeping you safe. It&apos;s keeping a problem comfortable enough that you never have to fix it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Faster doesn&apos;t fix it&lt;/h2&gt;
&lt;p&gt;The instinct is to make the engine faster. More CI workers. Parallel test shards. And now a fleet of agents that can open a few dozen correct-looking merge requests a day without coffee or ego. All real, all good. None of it touches the actual problem.&lt;/p&gt;
&lt;p&gt;A faster engine on the same track just gets you to the same bottleneck sooner. If anything, cheap generation makes the gap worse: more commits piling up behind the same release window, more haystack per batch. You can&apos;t out-produce a trust problem. The fastest way to ship more code safely was never &quot;type faster.&quot; It&apos;s to close the gap between green and shippable so completely that the schedule has nothing left to protect.&lt;/p&gt;
&lt;p&gt;And the data&apos;s been clear on this for years. The DORA research (the &lt;a href=&quot;https://itrevolution.com/product/accelerate/&quot;&gt;Accelerate&lt;/a&gt; body of work) keeps finding the same counterintuitive result: the teams that deploy most often are also the most stable. Speed and safety rise together, because the same practices that make releases fast (small changes, strong automation, fast feedback) are the ones that make them safe. The teams shipping on demand have &lt;em&gt;lower&lt;/em&gt; change-failure rates than the ones shipping on a quarterly calendar, not higher.&lt;/p&gt;
&lt;p&gt;So the goal flips. Make every green commit shippable, and make the rare miss recoverable before a user ever notices. Two stacks do that work: a confidence stack on the way in, a recovery stack for when something slips through anyway.&lt;/p&gt;
&lt;h2&gt;Main is the train&lt;/h2&gt;
&lt;p&gt;Start with the thing that makes a release a non-event: stop treating &quot;release&quot; as a separate step at all.&lt;/p&gt;
&lt;p&gt;Every commit on main is a candidate release. No release branch, no cut, no separate deploy job that someone runs. The way code gets to main is through a &lt;strong&gt;&lt;a href=&quot;https://docs.gitlab.com/ci/pipelines/merge_trains/&quot;&gt;merge train&lt;/a&gt;&lt;/strong&gt; (that&apos;s GitLab&apos;s name for it; GitHub ships the &lt;a href=&quot;https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue&quot;&gt;same thing as a merge queue&lt;/a&gt;, and the principle predates both as Graydon Hoare&apos;s &lt;a href=&quot;https://graydon2.dreamwidth.org/1597.html&quot;&gt;Not Rocket Science Rule&lt;/a&gt;): an integration gate that tests each change against the &lt;em&gt;projected&lt;/em&gt; merge result. Your change rebased on top of main plus everything queued ahead of you, all run as the commit that will actually land. If the train&apos;s pipeline is green, the exact commit that hits main has been proven integrated against the exact state it&apos;s joining.&lt;/p&gt;
&lt;p&gt;Which kills a whole category of theater. Re-running CI on main after the merge tells you nothing the train didn&apos;t already prove. And a change that would break main never gets there. It fails its car on the train and gets pulled before it ever touches the branch. No &quot;main is red at 2pm&quot; scramble. No revert dance. No bisecting at midnight to find whose merge poisoned the well. The bad car comes off the track; the train keeps moving.&lt;/p&gt;
&lt;p&gt;This is the difference between a green pipeline and a green build, and it matters more than it sounds. A pipeline that retries flaky tests until they pass, lets important checks warn-and-continue, and sets a coverage target low enough to clear in its sleep, that&apos;s a green light wired to nothing. &lt;strong&gt;A signal is only real once it has a measurement and a threshold.&lt;/strong&gt; Green has to mean green, or every layer you build on top of it is built on a lie.&lt;/p&gt;
&lt;h2&gt;Build once, promote via overlay&lt;/h2&gt;
&lt;p&gt;When a change earns its way onto main, the train builds the container image one time and tags it by the commit SHA. That image is the artifact. It runs in dev immediately. And here&apos;s the part that makes promotion boring: shipping to prod doesn&apos;t rebuild anything. It re-points a config overlay (a &lt;a href=&quot;https://kustomize.io/&quot;&gt;Kustomize&lt;/a&gt; overlay, in practice, committed to the same repo) at the same SHA that&apos;s already running in dev. Same bytes, different environment.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;Promotion is a routing decision, not a build decision.&lt;/div&gt;
  &lt;div&gt;The thing you tested in dev is the literal thing that runs in prod. Not a rebuild from the same commit and a hope. The same image.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;That cleanly splits two worlds that most setups jam into one giant deploy job. The slow-moving substrate (the cluster, the network, IAM, the shape of your manifests) changes on the order of a quarter and belongs to &lt;a href=&quot;https://developer.hashicorp.com/terraform&quot;&gt;Terraform&lt;/a&gt;, ideally run through something like &lt;a href=&quot;https://developer.hashicorp.com/terraform/cloud-docs&quot;&gt;Terraform Cloud&lt;/a&gt; so applies are deliberate and auditable instead of run from someone&apos;s laptop. The fast-moving payload (image refs, rollouts, the things that change every commit) belongs to Git, reconciled continuously by a GitOps controller. &lt;a href=&quot;https://argo-cd.readthedocs.io/en/stable/&quot;&gt;Argo CD&lt;/a&gt; is the common one: it watches the repo, diffs the declared state against what&apos;s actually running in the cluster, and makes the cluster match. Change the overlay in Git, Argo CD notices and applies it. &lt;a href=&quot;https://fluxcd.io/&quot;&gt;Flux&lt;/a&gt; does the same job if you prefer it. &lt;strong&gt;TF for the building, Git for the lights.&lt;/strong&gt; The rule is simple: if it changes per release, Git owns it; if it changes per quarter, Terraform owns it. Match the tool to the rate of change and the six-hour deploy job that rewrites your infrastructure mid-flight just stops existing.&lt;/p&gt;
&lt;p&gt;One more piece falls out of this: tags are markers, not artifacts. The cluster never deploys a tag. The tag is a point-in-time anchor that says &quot;this commit&apos;s state was live in prod,&quot; useful for audit, for rollback targeting, and for release notes. It records what shipped and when. Nothing reads it to decide what runs.&lt;/p&gt;
&lt;h2&gt;The canary is the only honest soak&lt;/h2&gt;
&lt;p&gt;Most teams have a staging or beta environment that exists to &quot;soak&quot; changes before prod. I&apos;ve shipped behind plenty of them, and here&apos;s what I learned the hard way: be honest about what one actually does. It runs the wrong shape of data and the wrong shape of traffic, so passing it only tells you a change survives conditions no real user will ever create. It&apos;s a dress rehearsal in an empty theater. The thing that&apos;s green in staging breaks the minute it meets production load and production-shaped data, and you find out from a customer.&lt;/p&gt;
&lt;p&gt;The only place real confidence accrues is real traffic. So make prod itself the soak, one slice at a time. A new release enters at 1% of traffic and walks itself up: 1 to 5 to 25 to 50 to 100, and at every step it bakes against live signal (error rate, latency, worker health, plus a real-user-monitoring read on whether people are completing flows). Any red, at any stage, rolls back automatically to the last good release.&lt;/p&gt;
&lt;p&gt;This is exactly what a progressive-delivery controller like &lt;a href=&quot;https://argo-rollouts.readthedocs.io/en/stable/&quot;&gt;Argo Rollouts&lt;/a&gt; exists to do. It owns the canary as a literal state machine: weight traffic up a step, run an analysis check against your metrics, advance if it&apos;s clean, roll back on its own if it isn&apos;t. You point the analysis at one internal health endpoint that aggregates the signals you care about, and the controller polls it at each gate. (If you&apos;re on a service mesh, &lt;a href=&quot;https://flagger.app/&quot;&gt;Flagger&lt;/a&gt; covers the same ground.)&lt;/p&gt;
&lt;p&gt;The reason this has to be automated is human nature. Nobody has the patience to sit and stare at the 1% dashboard and calmly decide it looks fine. They glance, it looks okay, they wave it through. So don&apos;t make them. The canary is a state machine. &lt;strong&gt;The signal decides; the train moves.&lt;/strong&gt; A human only gets paged when something&apos;s actually wrong, into context that&apos;s already populated.&lt;/p&gt;
&lt;p&gt;That same logic extends to the one thing you genuinely can&apos;t canary: infrastructure. You can&apos;t give 1% of users a new VPC CIDR. But the train can carry the infra change and apply it to dev as part of the car&apos;s pipeline, then check that dev came back up green before the change is allowed to merge. If the change broke dev, the merge request doesn&apos;t merge. So main and dev are green by construction. A broken state can&apos;t reach them, because the proof of merge-worthiness &lt;em&gt;is&lt;/em&gt; &quot;dev survived this.&quot; Dev becomes the canary for ops.&lt;/p&gt;
&lt;p&gt;Stack those layers and they overdetermine the outcome. Real-shape pre-merge tests, an honest readiness probe, the statistical canary, an eyes-on check for the visual breakage that never throws an exception, internal users before external on every flag. Each catches a different class of failure. For a bug to reach prod and stay there, it has to evade all of them. That&apos;s what &quot;shippable by default&quot; actually means: not that nothing ever breaks, but that breaking and staying broken requires beating five independent defenses.&lt;/p&gt;
&lt;h2&gt;Recovery is the other half of courage&lt;/h2&gt;
&lt;p&gt;Confidence on the way in is only half the deal. The other half is knowing that when something slips through, and it will, you can pull it back before it matters. Recovery, ordered by how fast each lever is:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Flag kill, in milliseconds.&lt;/b&gt; If the bad behavior is behind a real backend flag (&lt;a href=&quot;https://launchdarkly.com/&quot;&gt;LaunchDarkly&lt;/a&gt;, &lt;a href=&quot;https://www.getunleash.io/&quot;&gt;Unleash&lt;/a&gt;, or anything that speaks &lt;a href=&quot;https://openfeature.dev/&quot;&gt;OpenFeature&lt;/a&gt;), flip it off. No deploy, no rebuild. The code&apos;s still in prod, just not running. This is why a real flag system matters: without it, a &quot;feature flag&quot; is just a config value read at startup, and flipping it costs you a whole deploy. Real flags decouple deploy from release. You ship the code dark and turn it on when you&apos;re ready.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Overlay rollback, in minutes.&lt;/b&gt; Re-point the prod overlay at the previous SHA. Same train, opposite direction. The prior image is already built and already proven, so there&apos;s nothing to rebuild. Your delivery tooling unwinds the canary back to the last good release on its own.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Hotfix on the same train.&lt;/b&gt; Not a separate &quot;emergency&quot; pipeline that&apos;s less tested precisely because it&apos;s used least. The fix rides the normal train, and because the train is signal-driven, a clean change advances through the canary fast. The urgent path and the everyday path are the same path. That&apos;s the point.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When rollback is &quot;git revert&quot; instead of &quot;reprovision the world and pray,&quot; shipping stops feeling dangerous. You can build a fleet of agents on top of this, each one watching a signal and taking a bounded action (open a fix MR off a Sentry spike, close a coverage gap, quarantine a flaky test), and you don&apos;t have to bet on the agents being right. You bet on the same gates you already trust to ship human work. The train is the safety net for all of it.&lt;/p&gt;
&lt;h2&gt;Burn the calendar invite&lt;/h2&gt;
&lt;p&gt;Go back to that Release Window on the calendar. Once main is the train, once every green commit is the artifact, once the canary does the soak that beta only pretended to and rollback is a one-line revert, what is the window even protecting you from? The freeze was insurance against a release you couldn&apos;t trust. Build the trust into the track and the insurance is just friction you&apos;re still paying premiums on.&lt;/p&gt;
&lt;p&gt;I&apos;ve said before that if you can&apos;t release any time, any day, Friday afternoon included, you don&apos;t have a courage problem, you have a tracks problem. This is what the tracks look like up close. The courage isn&apos;t something you summon in the go/no-go meeting. It&apos;s something the system gives you for free, every commit, all day, because it has earned the right to.&lt;/p&gt;
&lt;p&gt;So here&apos;s the real question: if shipping were genuinely safe at any hour, with no schedule and no war room, how much of your release process would you keep? Whatever survives that cut is the real work. The rest was just managing fear.&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; has spent his career leading engineering at consumer-scale software companies. He writes about engineering leadership, infrastructure, and building in the age of AI agents.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance, built from a release architecture I&apos;d designed and spec&apos;d out. The frame, the calls, and the hard-won opinions are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>releases</category></item><item><title>Just use Postgres</title><link>https://jasonwaldrip.com/writing/just-use-postgres/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/just-use-postgres/</guid><description>Two engineers, a new project, and the architecture already has Redis, a queue, and Elasticsearch before a single user signs up. Postgres does all three. Not forever, but right now at your actual load. At Brandfolder we added Go when Ruby was genuinely hurting us on heavy IO. Not before. Earn the complexity. Wait until the first tool is actually failing you.</description><pubDate>Tue, 02 Jun 2026 08:47:00 GMT</pubDate><content:encoded>&lt;p&gt;Two engineers, a new project, and the architecture already has Redis, a queue, and Elasticsearch before a single user signs up. Postgres does all three. Not forever, but right now at your actual load. At Brandfolder we added Go when Ruby was genuinely hurting us on heavy IO. Not before. Earn the complexity. Wait until the first tool is actually failing you.&lt;/p&gt;</content:encoded><kind>take</kind><category>infrastructure</category></item><item><title>Volume Is Free Now. Judgment Is the Whole Game.</title><link>https://jasonwaldrip.com/writing/volume-is-free-now/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/volume-is-free-now/</guid><description>For eight years I was the most prolific engineer at a company I helped build. I&apos;m now convinced that was a failure, not an achievement, and here&apos;s what it taught me about where engineering value actually lives in the age of agents.</description><pubDate>Fri, 29 May 2026 21:00:00 GMT</pubDate><content:encoded>&lt;p&gt;By the time I left, I&apos;d written something like &lt;strong&gt;one in five commits in the company&apos;s entire history.&lt;/strong&gt; Eight years, the most of anyone, by a wide margin. For a long time I wore that like a badge. I&apos;ve since decided it was the clearest symptom of a problem I should have fixed years earlier. And the problem is about to get a lot more common, because the thing I was good at just became free.&lt;/p&gt;
&lt;p&gt;There was no hour of the clock that didn&apos;t have my name on a commit. Better than a quarter of them landed after 7pm; plenty at 2 and 3 in the morning. I touched nearly every part of the codebase: the app, the libraries, the infrastructure, the build system, the deploy path. If something broke at 11pm, I fixed it before standup. I told myself this was dedication. What it actually was, was a &lt;strong&gt;bus factor of one&lt;/strong&gt; dressed up as a work ethic.&lt;/p&gt;
&lt;h2&gt;The volume trap&lt;/h2&gt;
&lt;p&gt;Here&apos;s the trap, and I walked straight into it: &lt;strong&gt;output feels like value.&lt;/strong&gt; Commits, lines, features shipped, fires put out at midnight. All of it is visible, countable, and deeply satisfying. So you optimize for it. You become the person who can produce the most, fastest, across the most surface area. And because you can, you do, and the org happily lets you, because why wouldn&apos;t it.&lt;/p&gt;
&lt;p&gt;The problem is that you&apos;ve made yourself the load-bearing wall. The more you produce, the more the system depends on you specifically, and the less anyone else needs to understand. Your productivity becomes the org&apos;s fragility. I was a fifth of the company&apos;s commits not because I was five times better than anyone, but because the system had quietly arranged itself so that the foundation ran through one person. That&apos;s not a win. That&apos;s a single point of failure with a green contribution graph.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I was a fifth of the company&apos;s commits. That&apos;s not a trophy. It&apos;s a single point of failure with good PR.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;And then the floor moved&lt;/h2&gt;
&lt;p&gt;For my entire career, producing code was the bottleneck. Hiring was about adding hands. Velocity was a headcount problem. The whole industry was organized around the scarcity of people who could write working software fast.&lt;/p&gt;
&lt;p&gt;That scarcity is gone. An agent will write you a few dozen well-formatted, plausible commits a day, all day, without coffee or ego. The thing I spent a decade getting elite at, producing a lot of correct code quickly, is now something you rent by the token. &lt;strong&gt;Volume has been commoditized.&lt;/strong&gt; If your value, or your company&apos;s, is measured in output, you&apos;re now competing with a machine that out-produces you and never sleeps, and you will lose that race.&lt;/p&gt;
&lt;div&gt;
  &lt;div&gt;Generation is now the cheap part.&lt;/div&gt;
  &lt;div&gt;When anyone can produce the code, producing the code stops being where the value is. The bottleneck moved. Most orgs haven&apos;t noticed yet.&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Judgment is the moat&lt;/h2&gt;
&lt;p&gt;What an agent can&apos;t do, yet, and I&apos;d argue structurally, is hold the map. It can&apos;t tell you which problem is a &quot;move fast and break things&quot; problem and which one is a &quot;slow down, this is load-bearing&quot; problem. It goes fast at both. It doesn&apos;t know which clean-looking diff is quietly wrong, because it has no model of why the system is the way it is. It will confidently pave a road straight off a cliff and report success.&lt;/p&gt;
&lt;p&gt;That discernment (knowing what&apos;s worth building, what&apos;s dangerous to touch, what &quot;done&quot; actually means, when the plausible answer is wrong) is &lt;strong&gt;judgment&lt;/strong&gt;, and judgment is the thing that didn&apos;t get commoditized. It got &lt;em&gt;more&lt;/em&gt; valuable, because now it&apos;s the scarce input. The engineer&apos;s job just moved from &lt;strong&gt;producing&lt;/strong&gt; to &lt;strong&gt;directing&lt;/strong&gt;: fewer people, each steering a fleet of tireless producers, each responsible not for how much they typed but for what they caught and what they refused to ship.&lt;/p&gt;
&lt;p&gt;This is the part people get wrong about AI and engineering. It doesn&apos;t replace the person with the map. It&apos;s a force multiplier on judgment, and a multiplier is only as good as what you multiply. Multiply great judgment by a fleet of agents and you get something genuinely new. Multiply &lt;em&gt;no&lt;/em&gt; judgment by the same fleet and you get a beautifully formatted disaster, faster. Anything times zero is still zero.&lt;/p&gt;
&lt;h2&gt;The train can only go as fast as its tracks&lt;/h2&gt;
&lt;p&gt;I&apos;ve said this so many times my team could finish the sentence: the train can only move as fast as the tracks it&apos;s built on. In the agent era it&apos;s not a nice metaphor anymore, it&apos;s the whole strategy. Agents are a faster engine. Dramatically faster. But a faster engine on bad track doesn&apos;t get you there sooner. It derails sooner.&lt;/p&gt;
&lt;p&gt;The faster you can generate code, the more load your foundation has to bear: your tests, your CI, your deploy path, your guardrails, your ability to verify that a thing actually works. Cheap generation doesn&apos;t reduce the need for a strong foundation. It&apos;s the single biggest argument &lt;em&gt;for&lt;/em&gt; one. The companies that win the next decade won&apos;t be the ones generating the most code. They&apos;ll be the ones whose tracks can survive the new speed.&lt;/p&gt;
&lt;h2&gt;How it actually fails: not with a bang&lt;/h2&gt;
&lt;p&gt;The failure mode I&apos;d warn every leader about isn&apos;t dramatic. Nobody dies in an outage. You die by &lt;strong&gt;entropy&lt;/strong&gt;. The agents keep the lights on. The demos work. The line on the dashboard stays up. But quarter over quarter the code drifts further from anyone&apos;s actual understanding. Decisions get made by whoever&apos;s least wrong in the room. And one day a &quot;simple&quot; change takes three weeks, because nobody alive knows why the thing was built the way it was, and the only one who did was a person (or a model) nobody bothered to ask the right questions of.&lt;/p&gt;
&lt;p&gt;It&apos;s invisible right up until it&apos;s expensive. Which is exactly why it&apos;s the one to design against now, while it&apos;s cheap.&lt;/p&gt;
&lt;h2&gt;So what do you actually do&lt;/h2&gt;
&lt;p&gt;If output is commoditized and judgment is the moat, the work reorganizes around that. In priority order, not on a timeline, because the sequence matters more than the calendar:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;b&gt;Get the map out of people&apos;s heads.&lt;/b&gt; The cross-system context that lives in one senior engineer&apos;s skull is your biggest risk and your most valuable asset. Externalize it: architecture docs, decision records, runbooks, written intent. The infrastructure you need to survive losing someone is the infrastructure that lets agents be useful in the first place. Build it before you need it.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Make agents the volume layer and humans the judgment layer — on purpose.&lt;/b&gt; Stop measuring engineers on output; the machine wins that and the metric is now meaningless. Measure them on what they catch, what they decompose, and what they have the taste to reject.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Kill every bus-factor-of-one.&lt;/b&gt; No system gets exactly one person who understands it. Two humans know it, or it&apos;s documented well enough that a mid-level engineer and an agent can own it together. That, precisely, is what surviving any departure means.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Overinvest in the tracks.&lt;/b&gt; Tests, CI, deploy, verification. This is the line item everyone underfunds and the one that decides whether speed helps you or kills you. A faster engine makes a strong foundation more important, not less.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Make verification the core competency.&lt;/b&gt; When generation is free, the scarce, valuable skill is &lt;em&gt;proof&lt;/em&gt;: does this actually work, end to end, the way a real user will hit it? Not &quot;the tests are green.&quot; Knowing what&apos;s true is the whole job now.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;The optimistic part, and I mean it&lt;/h2&gt;
&lt;p&gt;This sounds like a eulogy for the engineer. It&apos;s the opposite. This era is &lt;em&gt;more&lt;/em&gt; forgiving than the one it replaced, if you orient to it correctly. A small, judgment-dense team pointing agents at the right problems will outrun a large team of people typing, every time. The winners won&apos;t be the orgs with the most engineers. They&apos;ll be the ones that figured out the job changed: from how much you can produce to how well you can direct, verify, and decide.&lt;/p&gt;
&lt;p&gt;And the personal version of the same truth is the one I keep coming back to: &lt;strong&gt;judgment travels with the person who has it.&lt;/strong&gt; The map lives in a head, not a repository. Whatever I build next, that&apos;s the asset I&apos;m bringing, and unlike a fifth of someone&apos;s commit history, it&apos;s portable.&lt;/p&gt;
&lt;p&gt;I spent eight years proving I could be the engine. The lesson I&apos;m taking forward is that the engine was never the hard part. &lt;strong&gt;Build the tracks.&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;&lt;b&gt;Jason Waldrip&lt;/b&gt; has spent his career leading engineering at consumer-scale software companies. He writes about engineering leadership, infrastructure, and building in the age of AI agents.&lt;/p&gt;
  &lt;p&gt;Written with AI assistance. The frame, the experience, and the calls on what mattered and what to cut are mine.&lt;/p&gt;
&lt;/div&gt;</content:encoded><kind>essay</kind><category>leadership</category></item><item><title>A note</title><link>https://jasonwaldrip.com/writing/office-in-shambles/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/office-in-shambles/</guid><description>Drove to the office this morning, realized it was in shambles, and turned right back around to work from home. Some days the best architecture decision is the commute you don&apos;t make.</description><pubDate>Wed, 27 May 2026 17:40:00 GMT</pubDate><content:encoded>&lt;p&gt;Drove to the office this morning, realized it was in shambles, and turned right back around to work from home. Some days the best architecture decision is the commute you don&apos;t make.&lt;/p&gt;</content:encoded><kind>life</kind></item><item><title>&quot;Add AI&quot; is not a roadmap item</title><link>https://jasonwaldrip.com/writing/add-ai-is-not-a-roadmap-item/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/add-ai-is-not-a-roadmap-item/</guid><description>Watching teams bolt a chatbot onto a product with no idea what problem it solves. AI is a tool, not a strategy. If you can&apos;t say what gets faster or cheaper or better, you&apos;re shipping a press release.</description><pubDate>Tue, 26 May 2026 09:02:00 GMT</pubDate><content:encoded>&lt;p&gt;Watching teams bolt a chatbot onto a product with no idea what problem it solves. AI is a tool, not a strategy. If you can&apos;t say what gets faster or cheaper or better, you&apos;re shipping a press release.&lt;/p&gt;</content:encoded><kind>take</kind><category>ai</category></item><item><title>The deploy path is a product</title><link>https://jasonwaldrip.com/writing/the-deploy-path-is-a-product/</link><guid isPermaLink="true">https://jasonwaldrip.com/writing/the-deploy-path-is-a-product/</guid><description>If you can&apos;t release at any time, 24/7, Friday afternoon included, you don&apos;t have a culture problem. You have a tracks problem. Fix the rails and the courage shows up on its own.</description><pubDate>Thu, 21 May 2026 11:30:00 GMT</pubDate><content:encoded>&lt;p&gt;If you can&apos;t release at any time, 24/7, Friday afternoon included, you don&apos;t have a culture problem. You have a tracks problem. Fix the rails and the courage shows up on its own.&lt;/p&gt;</content:encoded><kind>take</kind><category>infrastructure</category></item></channel></rss>