<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kay Ashaolu</title>
    <description>The latest articles on DEV Community by Kay Ashaolu (@kayashaolu).</description>
    <link>https://dev.to/kayashaolu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2068399%2F94b886af-d71f-4c33-b979-05ccc7d32c8d.png</url>
      <title>DEV Community: Kay Ashaolu</title>
      <link>https://dev.to/kayashaolu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kayashaolu"/>
    <language>en</language>
    <item>
      <title>Course 0 is open: ask the AI what it thinks first</title>
      <dc:creator>Kay Ashaolu</dc:creator>
      <pubDate>Sun, 27 Sep 2026 21:43:38 +0000</pubDate>
      <link>https://dev.to/kayashaolu/course-0-is-open-ask-the-ai-what-it-thinks-first-24la</link>
      <guid>https://dev.to/kayashaolu/course-0-is-open-ask-the-ai-what-it-thinks-first-24la</guid>
      <description>&lt;p&gt;You ask the AI to build the feature. It writes something that looks right, the checks you thought to run pass, and you ship it before lunch. For a while, that feels like winning.&lt;/p&gt;

&lt;p&gt;Then production breaks at 2 AM, or code review asks why you built it this way, or an interviewer asks you to walk through a project with your name on it, and you go quiet. The code is yours. The understanding never was, because you were never really in the loop while it got built.&lt;/p&gt;

&lt;p&gt;That gap is not a discipline problem. It is the shape of the job right now, whatever your title says.&lt;/p&gt;

&lt;p&gt;If you are building software with AI, you are doing a senior engineering job. Not eventually. Now. An AI that builds in seconds still leaves the deciding to you: breaking the work down, questioning the plan before it builds, judging whether what comes back is good enough to ship. Those are the calls a senior engineer makes every day, and you are making them whether anyone told you or not.&lt;/p&gt;

&lt;p&gt;Picture a senior at the whiteboard before a single line gets written. She does not ask, can this be built? She asks, what is actually being decided here? And how would we know this plan is wrong before it ships? AI changed what gets typed. It did not change who has to ask that question.&lt;/p&gt;

&lt;p&gt;One move catches most of what goes wrong: before you let an agent build anything, ask it what it thinks. Then make it prove it. A weak answer just restates the plan. A real one points at the exact thing that would pass or fail. Ask what happens when two people hit this in the same second. A weak plan says it handles that. A real one names the exact row both writes land on. It costs you almost nothing. Skip it enough times, and you get the 2 AM version: fast code, no debugging trail, no answer when someone asks why.&lt;/p&gt;

&lt;p&gt;I built a course around that one move. I think it is the actual skill gap right now, not typing speed. Nobody had put it in one place. It teaches you to command an AI agent the way a senior engineer would. That is how you code. The four courses after it, I through IV, build the judgment to know whether what it built is any good. That is how you grow. It is called Course 0, and it opens today. That is why this letter is arriving on a Sunday instead of the usual Saturday.&lt;/p&gt;

&lt;p&gt;Self-paced: eight lessons and two hands-on labs where you run the method yourself instead of watching someone else run it. Ten short written questions close it out: feedback on your answers, not just a score, and unlimited retakes. Then three challenges on a small chat app you did not write, real code, real seams. A local chatbot you take over and make your own, real enough to break and rebuild: you complete two of the seven building blocks and work inside two more that are already running.&lt;/p&gt;

&lt;p&gt;It is built for wherever you actually are. The one who ships fast with AI and cannot explain how it works when asked. The one who checks every line by hand, and it is starting to feel like a fight instead of craft. The one who plans well with the AI and loses everything the moment the context clears. And the vibe coder, still building one specific rep: sitting in the loop and pushing back on a plan before it builds.&lt;/p&gt;

&lt;p&gt;Course 0 is $99, one time. Courses I through IV are $299, one bundle, open to anyone.&lt;/p&gt;

&lt;p&gt;The seven building blocks stay free, same as always. Course 0 is where they stop being something you read and start being something your hands do.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S. Course 0 is open. If you want the details, they are here: &lt;a href="https://systemthinkinglab.ai/course-0" rel="noopener noreferrer"&gt;https://systemthinkinglab.ai/course-0&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This letter goes out by email every Saturday. &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; or read the full archive at &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;systemthinkinglab.ai/newsletters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>Review is a rep, not a gate</title>
      <dc:creator>Kay Ashaolu</dc:creator>
      <pubDate>Sun, 27 Sep 2026 01:03:37 +0000</pubDate>
      <link>https://dev.to/kayashaolu/review-is-a-rep-not-a-gate-1ih0</link>
      <guid>https://dev.to/kayashaolu/review-is-a-rep-not-a-gate-1ih0</guid>
      <description>&lt;p&gt;The hard part of engineering moved this year. It is no longer writing the code. It is deciding whether to trust it.&lt;/p&gt;

&lt;p&gt;Addy Osmani put a rule on that in June, and the rule is good: tier your review by risk, not by who wrote it. A config change gets a linter. A payments path gets a human reading every line. Spend attention where being wrong is expensive. For a team shipping fast, that is exactly right.&lt;/p&gt;

&lt;p&gt;Here is the change it tells you to skip.&lt;/p&gt;

&lt;p&gt;Monday morning. Your agent opens a pull request: "Add retry to the receipt email worker." Sixty lines. Tests green. It is a background job, not a payment path, so the rule says the linter can have it. You have eleven other things open. Approve.&lt;/p&gt;

&lt;p&gt;Now read it instead. The job pulls a message off the Queue, renders the receipt, calls the email provider, and marks the order as notified. The retry the agent added wraps the whole job. A timeout anywhere inside it runs the whole job again from the top.&lt;/p&gt;

&lt;p&gt;Trace one bad afternoon. The email provider accepts the send, then the connection drops before it answers. The Worker sees a timeout. The retry fires. The customer gets two receipts for one order, and the second one arrives ninety seconds after the first, which is exactly the shape of a charged-twice email. Support gets the ticket. Nobody can find a bug, because there is no bug in any single line. There is a bug in where the retry boundary sits.&lt;/p&gt;

&lt;p&gt;The fix is small. Retry the render and the send separately, and make the send safe to repeat by handing the provider an idempotency key built from the order id. Four lines. But you only get to write them if you read the sixty.&lt;/p&gt;

&lt;p&gt;That is what the risk rule cannot see. It scores the change by what it touches. It cannot score what reading it would have taught you. The linter would have passed this pull request every time, forever, and you would have learned nothing from it every time, forever.&lt;/p&gt;

&lt;p&gt;This is the same shape in every system you will ever work on. Instagram's feed is a cache that has to be told when a post changes, and the interesting question is who tells it. Uber's dispatch is a Queue with a clock on it, and the interesting question is what happens to a ride request when the Worker holding it dies. None of those questions live in the code. They live at the seams between building blocks, and you only find seams by reading across them.&lt;/p&gt;

&lt;p&gt;So here is the thing to add to the rule if you are early in your career. Review is not only a gate. It is a rep. Reading code you did not write, deciding whether it holds, finding the edge the test did not cover: that is the whole exercise that builds judgment, and there is no other one. The throughput math says move on. The growth math says read it anyway.&lt;/p&gt;

&lt;p&gt;The wrong move is the obvious one. Approving faster looks like seniority. It is the opposite. A senior engineer is not someone who trusts more code. It is someone who has read enough code to know exactly which lines to distrust. Trust is not a setting you turn up. It is a residue that reading leaves behind.&lt;/p&gt;

&lt;p&gt;You do not have to read everything. Read the ones that would teach you something if they were wrong, which is most of them when you are starting. Five a day, for a year, is more system reading than most engineers do in five.&lt;/p&gt;

&lt;p&gt;In the seven building blocks I teach juniors to read systems before they write them: to trace one request across a Service, a Queue, a Worker, and a store, and to name where it can break. The reading is where the seeing gets built.&lt;/p&gt;

&lt;p&gt;You do not build trust by clicking approve. You build it by reading until you could have written it yourself.&lt;/p&gt;

&lt;p&gt;P.S. If you want reps that are not your own pull requests, I wrote up three real systems block by block, Netflix, Instagram, and Uber, and the seams are marked: systemthinkinglab.ai/learn/case-studies/&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This letter goes out by email every Saturday. &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; or read the full archive at &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;systemthinkinglab.ai/newsletters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>Three ways to undercharge a customer</title>
      <dc:creator>Kay Ashaolu</dc:creator>
      <pubDate>Sun, 20 Sep 2026 01:03:43 +0000</pubDate>
      <link>https://dev.to/kayashaolu/three-ways-to-undercharge-a-customer-3e2n</link>
      <guid>https://dev.to/kayashaolu/three-ways-to-undercharge-a-customer-3e2n</guid>
      <description>&lt;p&gt;Here is a ticket I use whenever someone asks me what senior actually means. Add a discount code field to checkout. It reads like twenty minutes of work: a text box, a lookup, a percentage off. You could hand that line to an agent and have working code back before your coffee cools.&lt;/p&gt;

&lt;p&gt;Before you write anything, walk the ticket past four stops it never mentions. Three of them are ways this same ticket can quietly undercharge someone. One of them, finance's ledger, is where the other three get found out.&lt;/p&gt;

&lt;p&gt;The first stop is the price the buyer sees. The code has to apply before tax, not after, and it has to round the same way every other price on the page rounds, or two customers checking out a minute apart see two different rules for the same 15 percent off.&lt;/p&gt;

&lt;p&gt;Then there is the card that actually gets charged. The number on the screen and the number the processor charges have to be the same number, captured at the same moment, even if the buyer sits on that page for ten minutes with the tab open before hitting pay.&lt;/p&gt;

&lt;p&gt;Then finance's ledger. A sale made at a discount is not a full-price sale with a note attached. Revenue, tax, and any commission owed on it all have to be calculated on what was actually paid, not on the sticker price, and the money has to get booked correctly even if "finance" is one person with a spreadsheet, or the monthly numbers stop matching the bank and someone spends an afternoon finding out why.&lt;/p&gt;

&lt;p&gt;The fourth stop is every refund that ticket will ever cause. Six months from now, a customer who used that code returns the item. Do you refund what they paid, or the full price on the listing? Get that wrong and you have quietly become a business that sometimes pays customers more than they gave you.&lt;/p&gt;

&lt;p&gt;None of that is written in the ticket. All of it is the part of the job that is still yours.&lt;/p&gt;

&lt;p&gt;The same shape shows up anywhere a ticket looks smaller than it is. A field that looks like one column touches five. A toggle that looks like a single boolean touches billing, permissions, and an email that fires the moment it flips. The ticket never says any of that. Seeing it anyway, before the first line, is the job now.&lt;/p&gt;

&lt;p&gt;An agent will happily write the discount field. It validates the code, applies the percentage, and returns a clean number to the page, because that is exactly what the ticket asked for. It has no way to know your refund window, how your finance team books discounted revenue, or what happens the day two codes are allowed to stack on the same order. That knowledge does not live in a tutorial anywhere. It lives in your product, your data, and the way your company already handles money.&lt;/p&gt;

&lt;p&gt;That is the part of engineering a tool cannot hand you. Clean code is a skill a tool can now point at and match. Seeing the four stops before you write the first line is not.&lt;/p&gt;

&lt;p&gt;Here is where it gets easy to measure yourself by the wrong number. If you spend the next few months grading your own worth by how clean the discount field turns out, how tight the diff is, how fast you shipped it, you are grading yourself on the part of the job that just went free. You built real things with that code, and that is a real skill. But an agent produces it now in less time than it takes you to describe the field, and if that is still where you look for your value, you will be measuring none of the leverage you are actually gaining.&lt;/p&gt;

&lt;p&gt;I built a course around practicing exactly this: running the discount-code ticket, and ones like it, with an agent doing the typing while you do the seeing.&lt;/p&gt;

&lt;p&gt;Shipping the field faster was never the point. Naming the four things the ticket never mentioned, before anyone has to ask, is.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S. The framework for spotting everything a ticket actually touches, before you write the first line, is free: &lt;a href="https://systemthinkinglab.ai/learn/building-blocks/decision-framework/" rel="noopener noreferrer"&gt;https://systemthinkinglab.ai/learn/building-blocks/decision-framework/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This letter goes out by email every Saturday. &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; or read the full archive at &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;systemthinkinglab.ai/newsletters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>Why your AI agent keeps starting from zero</title>
      <dc:creator>Kay Ashaolu</dc:creator>
      <pubDate>Sun, 13 Sep 2026 01:03:47 +0000</pubDate>
      <link>https://dev.to/kayashaolu/why-your-ai-agent-keeps-starting-from-zero-5fnp</link>
      <guid>https://dev.to/kayashaolu/why-your-ai-agent-keeps-starting-from-zero-5fnp</guid>
      <description>&lt;p&gt;Picture handing a brand-new engineer the raw Stripe API documentation on their first morning and telling them to ship a working payment flow by five o'clock. Nobody does this. A new hire is supposed to get a kickoff meeting, an onboarding doc, and a senior engineer who walks them through how this particular codebase works before they touch a line of it.&lt;/p&gt;

&lt;p&gt;Now picture what we do to an AI coding agent instead. Every session starts the same way that new hire's first morning would, except nobody runs the kickoff meeting. The agent opens a codebase it has never seen, guesses at your naming conventions, and writes code that works but matches nothing else in the repository. We call the result disappointing. The result was never the problem.&lt;/p&gt;

&lt;p&gt;Here is what that gap actually costs, across three sessions on one codebase. Session one: you ask an agent to add a webhook handler to a service with a dozen existing endpoints. It writes reasonable code. It also invents its own naming convention for the file, skips the retry wrapper every other endpoint in the service already uses, and never notices the codebase already has a small library built for exactly this kind of validation. You catch it in the diff, fix the naming by hand, and explain the retry pattern in the chat. The session ends. The explanation ends with it.&lt;/p&gt;

&lt;p&gt;Session two, new task, new context window, same codebase. The agent remembers none of it. It reinvents the naming convention, wrong in a different way this time. So instead of correcting it again and moving on, you write the two rules it keeps missing, naming and retries, into a short file the agent reads before it starts anything. You also ask it to add one line to a second file describing what it just learned about how this service handles errors. Two files. Ten minutes.&lt;/p&gt;

&lt;p&gt;Session three, same codebase, a different feature. This time the agent reads both files before writing anything. It matches the naming on the first try. It does not ask how to handle retries. It asks whether the new endpoint belongs in this service at all, or whether the work is slow enough that it should go through the queue the rest of the service already uses for background jobs. That is not a better answer. That is a better question, the kind a new hire only asks after someone has actually shown them how the system fits together.&lt;/p&gt;

&lt;p&gt;The two files were not a trick. They were the onboarding a new hire gets and an agent almost never does. The first file, a kickoff skill, is the version of that first-morning meeting: your naming rules, how errors get handled, how services are supposed to talk to each other, loaded before the agent writes a line. The second file, a wiki, is the version of a senior engineer explaining how this particular codebase works, except the agent writes it down itself, and it is there again waiting for the next session. Handing an agent the raw Stripe docs and expecting a shipped payment system by five o'clock was never going to produce clean work. The two files are what you would have given the new hire instead.&lt;/p&gt;

&lt;p&gt;The tempting move, especially the first time an agent gets something wrong, is to write a better prompt. Spend twenty minutes getting the instructions exactly right, ship the task, feel clever about it. That cost gets paid again next session, because a prompt lives inside one conversation and disappears with it. The kickoff skill and the wiki live outside the conversation. Session one is expensive because the agent is learning your codebase from nothing, the same as any new hire's first week. Session three is fast because the learning from session one and two is sitting in a file, waiting to be read instead of relearned. That is the entire difference between a cost you pay once and one that compounds.&lt;/p&gt;

&lt;p&gt;I am building this habit into a course I am finishing.&lt;/p&gt;

&lt;p&gt;You do not get a better agent by writing a better prompt. You get one by building the memory it reads before it writes the next line.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S. If you want the framework behind how I think about designing systems in the first place, it starts here: &lt;a href="https://systemthinkinglab.ai/learn/building-blocks/7-building-blocks/" rel="noopener noreferrer"&gt;https://systemthinkinglab.ai/learn/building-blocks/7-building-blocks/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This letter goes out by email every Saturday. &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; or read the full archive at &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;systemthinkinglab.ai/newsletters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>The seat that sold twice</title>
      <dc:creator>Kay Ashaolu</dc:creator>
      <pubDate>Sun, 06 Sep 2026 01:03:37 +0000</pubDate>
      <link>https://dev.to/kayashaolu/the-seat-that-sold-twice-2eg</link>
      <guid>https://dev.to/kayashaolu/the-seat-that-sold-twice-2eg</guid>
      <description>&lt;p&gt;Two strangers bought the same seat. Not seats near each other. The same seat. Row 14, seat 7, sold twice in the same second, to two people who have never met, and both of them are holding a confirmation email that says it is theirs.&lt;/p&gt;

&lt;p&gt;Here is how a system gets there. Picture the site selling tickets for an arena show, and picture yourself as the engineer who built the part that sells the seats. The design is the obvious one: a seats table in the database, one row per seat, with a status column. When a buyer clicks Buy, your code checks the row. Is the status open? If yes, charge the card and mark the seat sold. If no, show "seat taken." It reads cleanly. It passes every test. It works every time you click through it yourself.&lt;/p&gt;

&lt;p&gt;Then Friday at 10 AM arrives and the tickets go live. Ten thousand people are on the seat map at the same moment, and two of them click row 14, seat 7, inside the same tenth of a second. Buyer one's request reads the row: open. Buyer two's request reads the row a few milliseconds later, before buyer one's update has landed: still open. Both requests pass the check. Both charge a card. Both write sold, the second landing quietly on top of the first. Both buyers get the email. Your code did not misfire once. It did exactly what you wrote, twice.&lt;/p&gt;

&lt;p&gt;The failure costs nothing for three weeks. Then the show happens. Two people walk up to row 14, seat 7, each holding a ticket that looks completely real, and an usher gets to decide which one of them paid for a seat that exists. Behind that moment is a support queue, a refund, an apology email, and a buyer who will never quite trust the site again. The worst part is that nothing in your logs looks broken. Every request came back a success. The system never went down. It just quietly promised the same thing to two people.&lt;/p&gt;

&lt;p&gt;Look at where the failure lives. It is not in the check, which was correct, and not in the write, which was also correct. It is in the gap between them. Your code checked the seat at one moment and claimed it at a slightly later moment, and treated the world as if nothing could happen in between. On a quiet Tuesday, nothing does. During an on-sale, that gap is a door, and ten thousand simultaneous buyers means somebody walks through it.&lt;/p&gt;

&lt;p&gt;The way out is not to make the gap smaller. It is to hand the job to the one layer that can make the gap not exist. That layer is the Relational Database, and the tool is called a constraint: a rule you declare about what is allowed to be true in your data, which the database enforces at the moment of every write, inside the write itself. To use one here, change the shape of the sale. Selling a seat stops being an edit to a status field and becomes the creation of a claim: buying inserts a row into a tickets table, and the rule you declare says no two rows may ever name the same seat for the same show. Now when two claims race for row 14, seat 7, the database lets the first one through and refuses the second at the instant it tries to land. There is no check at one moment and claim at another. The check is the claim. Your code's job shrinks to catching the refusal and telling buyer two, "that seat just went."&lt;/p&gt;

&lt;p&gt;Notice what actually happened to the collision. It did not disappear. Ten thousand people still clicked at once, and two of them still wanted the same seat. The collision moved down a layer, out of your application code and into the database, which is the one place every claim must pass through, and which resolves competing writes to the same data by lining them up and taking them one at a time. Refereeing simultaneous claims on shared data is not a feature the Relational Database happens to have. It is a large part of what the block is for.&lt;/p&gt;

&lt;p&gt;Once you see the shape, you will find it everywhere. Two people signing up for the same username in the same second: the designs that survive it put exactly this rule on the username column, which is why the second person sees "already taken" instead of two accounts existing. A flash drop where the last hoodie in stock sells to two carts. Two meetings landing in the same room at 2 PM. Anywhere a design checks first and writes second, across a gap, two actors can pass the same check before either write lands.&lt;/p&gt;

&lt;p&gt;Now watch the fix that gets reached for first, because it is the wrong one: keep the check in application code and reinforce it. Check the seat again right before the write. Add a background job that sweeps for double-sold seats. Hold a lock in your server's memory while the purchase runs. Every one of these feels like defense, and every one of them is another racer. Your application does not run as one copy. It runs on several servers at once, each running the same checks, and no copy can see what another copy is about to write. Doubling the checks doubles the checkers, and the checkers are the thing that races. More checking makes the gap shorter. Application code cannot make it zero. At on-sale traffic, shorter still loses.&lt;/p&gt;

&lt;p&gt;The database can make it zero, because for any one seat it is one place, taking one write at a time. That is the whole trick. Not smarter checking. One referee.&lt;/p&gt;

&lt;p&gt;In Course 1 I teach the Relational Database as one of the seven building blocks. Every block earns its place by doing a job the others cannot. Refusing the second claim is this one's.&lt;/p&gt;

&lt;p&gt;You do not close the gap by checking faster. You close it by making the check and the claim one move.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S. The constraint is one reason the Relational Database earns its spot among the storage blocks. The free walkthrough of the three storage extremes, what each one is built to maximize and what each gives up, is at &lt;a href="https://systemthinkinglab.ai/learn/building-blocks/storage-extremes/" rel="noopener noreferrer"&gt;https://systemthinkinglab.ai/learn/building-blocks/storage-extremes/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This letter goes out by email every Saturday. &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; or read the full archive at &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;systemthinkinglab.ai/newsletters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>Your next song was already chosen</title>
      <dc:creator>Kay Ashaolu</dc:creator>
      <pubDate>Sun, 30 Aug 2026 05:25:07 +0000</pubDate>
      <link>https://dev.to/kayashaolu/your-next-song-was-already-chosen-3ek6</link>
      <guid>https://dev.to/kayashaolu/your-next-song-was-already-chosen-3ek6</guid>
      <description>&lt;p&gt;One song on a playlist ends and the next one starts before you notice a gap. That is worth stopping on. Something chose the exact next song out of Spotify's entire catalog, in the space between one note ending and the next one beginning. It did not pause to think about it.&lt;/p&gt;

&lt;p&gt;Here is the part most people get wrong. They picture the choice happening at the moment the song ends: some process wakes up, looks at your history, scores a few million candidate songs, and picks the best one, all in the half second before the next track starts. If that were true, you would hear it. A beat of dead air. A spinner. Some evidence that work was happening.&lt;/p&gt;

&lt;p&gt;That is not what happens. The real work happened hours earlier. A background process, what I call a Worker, had already taken your recent listening and turned it into a compact summary of your taste. That summary got compared against millions of other songs, ranked by fit, and the winner got written down and held ready, sitting in a Queue or a Key-Value Store tied to your account, the kind of storage built for exactly one job: answer fast when asked.&lt;/p&gt;

&lt;p&gt;So when the song actually ends, the app on your phone does not compute anything. It reads a value that was already sitting there waiting for it. The transaction is not "figure out the next song." It is "look up the answer to a question that was already answered."&lt;/p&gt;

&lt;p&gt;Once you see that shape, you cannot stop seeing it. Gmail does not scan every email in your inbox the moment you hit search. A Worker already built a search index while you were doing something else, and your query reads that index instead of your inbox. Google Maps does not calculate current traffic the instant you open the app. Probe data from other drivers gets folded into an estimate continuously, in the background, so the ETA is sitting there the moment you ask for it. Your feed, on whichever app you check first each morning, did not start from nothing when you opened it. Most of the ranking work was already done.&lt;/p&gt;

&lt;p&gt;Every one of these is the same trade: a Worker does expensive work on its own schedule, and a Queue or Key-Value Store holds the result until the exact moment someone needs it. The part the user sees is only ever a read.&lt;/p&gt;

&lt;p&gt;The tempting move, the one that feels smart, is to compute the answer when the question actually arrives. That is when you know the most: the real time of day, the real device, the real thing the user just did three seconds ago. Waiting feels like the more accurate choice, and for a junior engineer it usually is the first instinct.&lt;/p&gt;

&lt;p&gt;The senior move is the opposite. Spend the compute before the question shows up, and accept that your answer is built on slightly older information in exchange for one thing: the moment someone actually needs it, there is nothing left to do but hand it over.&lt;/p&gt;

&lt;p&gt;In Course 1 I teach this shape by name, the Worker that does the early work and the Queue or Key-Value Store that holds the answer until it is needed.&lt;/p&gt;

&lt;p&gt;You do not wait for the question to begin the work. You begin the work and wait for the question.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S. If this is the kind of thing you want to start seeing everywhere once you know to look for it, the free course walking through all seven pieces is at &lt;a href="https://systemthinkinglab.ai/learn/" rel="noopener noreferrer"&gt;https://systemthinkinglab.ai/learn/&lt;/a&gt;. This is one shape out of many, and it keeps showing up.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This letter goes out by email every Saturday. &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; or read the full archive at &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;systemthinkinglab.ai/newsletters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>All four courses are finished. Here's what's next.</title>
      <dc:creator>Kay Ashaolu</dc:creator>
      <pubDate>Sun, 23 Aug 2026 01:03:33 +0000</pubDate>
      <link>https://dev.to/kayashaolu/all-four-courses-are-finished-heres-whats-next-26f9</link>
      <guid>https://dev.to/kayashaolu/all-four-courses-are-finished-heres-whats-next-26f9</guid>
      <description>&lt;p&gt;Thank you for reading this letter, many of you since before the series was finished. Systems Thinking in the AI Era is the four-course series I teach: seven repeating primitives that every real system is built from, and how to design with them instead of just coding around them. You kept showing up while half of it was still unrecorded. That is not a small thing, and I do not say it enough.&lt;/p&gt;

&lt;p&gt;This week I recorded the last video. Every lesson, every discovery lab, every case study, every challenge, and every assessment across all four courses is now live. That part of the series is complete, and I am genuinely excited about what comes next.&lt;/p&gt;

&lt;p&gt;Because the four courses were never the whole plan. They were the first half.&lt;/p&gt;

&lt;p&gt;If you are writing code with an agent's help, you have been handed a senior engineer's job on day one. Nobody announced it. You are not writing every line anymore. You are breaking a task into pieces the agent can execute, judging what it hands back before you trust it, and deciding whether the design actually holds. That is senior work. The agent is your junior engineer. And nobody hands you the structure a senior spends years building to do it well.&lt;/p&gt;

&lt;p&gt;Course 0, coming late September, is that structure. It teaches how to hand a task to an agent with a plan it can actually execute instead of a vague ask, how to verify what comes back before it becomes production code instead of after it breaks, and how to set up an agent's memory so it gets better at your codebase every session instead of starting from zero each time.&lt;/p&gt;

&lt;p&gt;But structure alone will not save you. You can hand off a task perfectly and still have no idea whether the result is any good. That is the part Courses 1 through 4 exist for, and it is why I built them first. Course 1 is the framework: the seven building blocks themselves. Courses 2 through 4 are the case law, the same seven blocks traced through content systems like Instagram and Netflix, real-time systems like Slack and Discord, and business systems like Stripe and Shopify. You do not build judgment by reading a definition. You build it by watching the same primitive solve the same kind of problem enough times that you recognize it on sight.&lt;/p&gt;

&lt;p&gt;Put together, that is the pathway this series was always meant to be. Not a course you finish and file away. A way to work with AI that makes you sharper while it makes you faster, on the same work, at the same time. Course 0 gets you moving. Courses 1 through 4 make sure what you are moving toward is good.&lt;/p&gt;

&lt;p&gt;Four ways in, depending on what you already own.&lt;/p&gt;

&lt;p&gt;If you already own all four courses: Course 0 is free for you the day it ships. Nothing to buy, no extra step. You are covered already, and I wanted you to hear that directly instead of guessing.&lt;/p&gt;

&lt;p&gt;If you own some of the four courses but not all of them: complete the set for $300, and Course 0 is free the day it ships. This one is for finishing what you started.&lt;br&gt;
&lt;a href="https://checkout.systemthinkinglab.ai/b/8x2fZhfm43Jg2WMeaV7ok08" rel="noopener noreferrer"&gt;https://checkout.systemthinkinglab.ai/b/8x2fZhfm43Jg2WMeaV7ok08&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have not bought a course yet: the full catalog, all four, is $399, and Course 0 is free at launch too. This one is for taking the whole thing at once.&lt;br&gt;
&lt;a href="https://checkout.systemthinkinglab.ai/b/14A6oH3Dmgw21SIaYJ7ok09" rel="noopener noreferrer"&gt;https://checkout.systemthinkinglab.ai/b/14A6oH3Dmgw21SIaYJ7ok09&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both of these offers end when Course 0 ships.&lt;/p&gt;

&lt;p&gt;If you would rather start with one course and see how it fits: every course is still $149 individually, at systemthinkinglab.ai.&lt;/p&gt;

&lt;p&gt;No pressure on any of it. If you are just here for the letter every Saturday, that is genuinely enough, and I am glad you are here for it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S. Course 0 is coming late September. Already own all four? It is free for you, no extra step. Most of the way there? Finish the set before it ships and it is free too.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This letter goes out by email every Saturday. &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; or read the full archive at &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;systemthinkinglab.ai/newsletters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>The most boring service in the stack</title>
      <dc:creator>Kay Ashaolu</dc:creator>
      <pubDate>Sun, 16 Aug 2026 01:03:38 +0000</pubDate>
      <link>https://dev.to/kayashaolu/the-most-boring-service-in-the-stack-2kim</link>
      <guid>https://dev.to/kayashaolu/the-most-boring-service-in-the-stack-2kim</guid>
      <description>&lt;p&gt;The most reliable part of a stack is rarely the part anyone shows off. It has no clever layer to point at. That is the whole reason it never breaks.&lt;/p&gt;

&lt;p&gt;A payment service I want to walk through this week is a clean example of that. One queue sat in front of it, catching every incoming charge. One database sat behind it, recording each charge exactly once. That was the entire system, and it had looked that way for four years.&lt;/p&gt;

&lt;p&gt;Engineers rotated onto the team and asked the same question every time. Why is this so primitive? No event mesh. No service constellation. No clever caching layer sitting in front to make it feel faster.&lt;/p&gt;

&lt;p&gt;Twice a year, someone pitched a redesign. Twice a year, the answer was no.&lt;/p&gt;

&lt;p&gt;Then Black Friday arrived. The recommendation engine buckled under the traffic and stopped returning results. Search slowed to a crawl and started serving stale listings. The mobile app threw errors across half its screens, and the support queue backed up.&lt;/p&gt;

&lt;p&gt;The payment service kept working. Every single order that reached it got processed, exactly once, without a single duplicate charge.&lt;/p&gt;

&lt;p&gt;Boring was never the absence of ambition. It was the design.&lt;/p&gt;

&lt;p&gt;The parts doing the real work here have names. Use them. A Service is the piece that answers you while you are standing there waiting on it, the way a waiter takes your order and comes back with a plate. A Queue is a line for work that does not need to happen the instant it shows up, so a sudden rush of it lands somewhere safe instead of getting dropped. A Relational Database is the record book: the one place that can say, with certainty, this specific charge happened, once, and only once. One Service, one Queue, one Relational Database. Three pieces, not ten.&lt;/p&gt;

&lt;p&gt;You can see the same restraint inside Stripe's own payment API. Every charge you send Stripe can carry an idempotency key, a value that means "this is the same request if you see it twice." Your network drops the response, you retry the request, and Stripe uses that key to recognize the retry and hand back the original charge instead of billing your customer again. Stripe did not hand you a new service to run to catch duplicates. It handed you a key, and made one place the last word on whether a charge already happened. Same restraint. Same refusal to add a fourth. You do not need Stripe's traffic to use the same idea. You need one place your data trusts to be the last word on whether something already happened, and the discipline to let it do that job alone.&lt;/p&gt;

&lt;p&gt;The way a system like this actually gets worse is rarely neglect. It is ambition wearing a good disguise. An engineer joins the team, wants something to show for the quarter, and pitches the event mesh, or the extra caching layer, or a second message broker sitting in front of the first one. Every one of those pitches sounds like seniority. On a slide, an event mesh reads like foresight. Under real load, it is a new component that has to come up cleanly, hold a connection, and survive Black Friday: a new thing that can time out, drop a message, or disagree with the database about what actually happened, at the exact hour agreement matters most. Saying no twice a year was never stubbornness. It was refusing to add one more way to fail during the one week failure would have cost the most.&lt;/p&gt;

&lt;p&gt;In Course 1 I teach these seven building blocks before anyone draws a single box, because the skill this payment service is showing off is not stacking parts well. It is knowing when three of them are enough, and having the discipline to stop there.&lt;/p&gt;

&lt;p&gt;You do not protect a system by adding to it. You protect it by refusing what it does not need.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S. Knowing when three blocks are enough is a skill you can learn deliberately. The decision framework that teaches it is free here: systemthinkinglab.ai/learn/building-blocks/decision-framework/&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This letter goes out by email every Saturday. &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; or read the full archive at &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;systemthinkinglab.ai/newsletters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>The two opposite ways AI gets your system wrong</title>
      <dc:creator>Kay Ashaolu</dc:creator>
      <pubDate>Sun, 09 Aug 2026 01:03:46 +0000</pubDate>
      <link>https://dev.to/kayashaolu/the-two-opposite-ways-ai-gets-your-system-wrong-43k1</link>
      <guid>https://dev.to/kayashaolu/the-two-opposite-ways-ai-gets-your-system-wrong-43k1</guid>
      <description>&lt;p&gt;You asked an AI to help you build something, and it put the whole thing inside one service. I have written about this before: a Service is a waiter, it takes the order and comes back with an answer. Ask AI to write the code for your app and it puts everything behind that one order: validate the input, hit the database, send the email, all before the response goes back. It works in the demo. In production the email step is slow, so every user stares at a spinner while your server waits on someone else's mail service.&lt;/p&gt;

&lt;p&gt;Ask the same AI to design that system before you write a line of code, and you get the opposite mistake. Same AI. Same app. Opposite failure. You and one other engineer are building an app that lets roommates split rent and bills. Ask AI to design it, and it hands you five services: auth, billing, notifications, an API gateway in front of all of them, and a message broker connecting them.&lt;/p&gt;

&lt;p&gt;Five services sounds manageable until you count what is actually inside each one. Auth is not one thing. It is a Service, a Relational Database of user accounts, and a Key-Value Store holding sessions: three building blocks. Billing is a Service plus its own Relational Database of charges: two more. Notifications is a Service, a Queue, and a Worker to send the email: three more. The API gateway is a fourth Service sitting in front of the rest, and the message broker is its own Queue. Ten building blocks, minimum, spread across five separate deployments, for a team of two.&lt;/p&gt;

&lt;p&gt;What the app actually needs looks nothing like that. Someone logs in and adds a bill: one Service. The bill has to know which users it belongs to and how it is split: one Relational Database. When someone marks a bill paid, you want to email the other roommates, and that does not need to happen while anyone is watching a spinner, so it goes on a Queue, and a Worker picks it up a few seconds later. One Service, one Relational Database, one Queue and Worker: the whole system. Four blocks, one deployment, against ten blocks spread across five.&lt;/p&gt;

&lt;p&gt;Ask AI to write code and it defaults to the plainest possible shape: one function, one service, request in, response out. It never reaches for a queue, because a queue is a decision about what can wait, not the plain shape of code. Ask AI to design a system on its own and it defaults to the most-discussed shape it has read about, which is how large companies solve problems you do not have. Same root cause both times: it is matching the genre of your prompt, not your actual constraints.&lt;/p&gt;

&lt;p&gt;This is why the blocks matter more than the word "service." A microservice is not a building block. It is a whole deployment that can contain two or three of them. Count in services and "five" sounds like five things to build. Count in blocks and it is ten pieces you have to build, wire together, and keep alive, spread across five deployments you run separately. Against four pieces in one.&lt;/p&gt;

&lt;p&gt;Microservices earn their cost when separate teams need to ship without waiting on each other, when one part needs different hardware, or when one failure cannot be allowed to take down everything else. Two people building one app have none of that pressure. What you need is one place to change things, one deploy, one thing to reason about at 11pm: a monolith. Not the beginner version of something you graduate out of. At your stage, it is the correct design.&lt;/p&gt;

&lt;p&gt;Run every piece of the AI's answer, whether it built too little or too much, through one question: does the pressure that justifies this exist on my team, right now? Multiple teams stepping on each other's deploys. A component that needs different hardware. Traffic you can already measure, not traffic you are imagining for next year. If that pressure is not real, the piece comes out, whether it is a missing queue or an extra service.&lt;/p&gt;

&lt;p&gt;That is why I teach the seven building blocks in Course 1 before anyone draws a single box. Know what each one is for, and you can look at any answer, AI's or your own, and ask what it is actually built to survive.&lt;/p&gt;

&lt;p&gt;You do not fix the answer the AI gave you. You check the pressure behind every piece of it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S. If you want the repeatable version of that question, I wrote up the full decision framework: one question per building block, so you can point at any requirement and know exactly what it needs. &lt;a href="https://systemthinkinglab.ai/learn/building-blocks/decision-framework/" rel="noopener noreferrer"&gt;https://systemthinkinglab.ai/learn/building-blocks/decision-framework/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This letter goes out by email every Saturday. &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; or read the full archive at &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;systemthinkinglab.ai/newsletters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>What an AI Engineer job actually tests</title>
      <dc:creator>Kay Ashaolu</dc:creator>
      <pubDate>Sun, 02 Aug 2026 01:03:38 +0000</pubDate>
      <link>https://dev.to/kayashaolu/what-an-ai-engineer-job-actually-tests-4mch</link>
      <guid>https://dev.to/kayashaolu/what-an-ai-engineer-job-actually-tests-4mch</guid>
      <description>&lt;p&gt;An AI Engineer job posting almost never asks you to train a model. It asks for Python. Backend services. APIs. Deployment.&lt;/p&gt;

&lt;p&gt;Say you are two years into your career. You want the AI Engineer title, because that is where the hiring is right now. You open a listing. Under requirements you find things you already know: REST APIs, Postgres, a message queue. Then one line stops you: experience with LLM-based retrieval systems. You have never trained a model, so you assume the role is out of reach. You close the tab and go back to applying for titles that do not say AI.&lt;/p&gt;

&lt;p&gt;Open ten AI Engineer job listings yourself. Count how many ask you to design a training pipeline. Count how many ask you to call a model through an API, store some vectors, and ship a working service. The ratio is not close. And unlike most claims you will read this week, that is one you can check in ten minutes on any job board.&lt;/p&gt;

&lt;p&gt;That gap between the title and the requirements is not a trick played on the applicant. It is a plain description of what the job actually is. Model training is real machine learning work, PhD-deep, and it happens at a small number of companies with the budget and the data to do it. Everyone else shipping something called an AI feature is doing something else entirely.&lt;/p&gt;

&lt;p&gt;Most AI Engineer work is product engineering with a model in the stack. A Service takes the request from the user. The model sits behind an API call, an External Service in exactly the slot Stripe or Twilio occupies on any other project you have built. A Vector Database holds what gets retrieved before the model is asked anything, so the answer is grounded in real documents instead of a guess. The same relational databases and queues every other feature already needs round out the design. Perplexity answering a question with sources, the AI notes assistant, the AI coding sidebar: strip away the branding and each one is this same handful of parts, wired together with care.&lt;/p&gt;

&lt;p&gt;The model is one component. The composition is the job.&lt;/p&gt;

&lt;p&gt;And composition is learnable. It is the same skill that ships any production system you have already worked on, a checkout flow, a notification pipeline, a search page, pointed at one new primitive instead of a familiar one.&lt;/p&gt;

&lt;p&gt;Here is the wrong move I see most often, and it is the expensive one. An engineer decides the gap is technical: they need to learn embeddings math, or enroll in a machine learning certificate, before they can call themselves qualified for the title. That is solving the wrong problem. The company hiring for that AI Engineer role is not testing whether you can derive backpropagation. It is testing whether you can take a Service, an External Service, a Vector Database, and a queue, and compose them into something that survives real traffic on a Tuesday afternoon. Come back to the same listings six months later and the requirements have not moved: still a Service, still an External Service, still a Vector Database. Only now half a year has gone to the wrong half of the job. I believe this enough to grade on it: the course I am teaching at UC Berkeley this fall has students build real applications with agentic coding, then grades them on defending the design decisions.&lt;/p&gt;

&lt;p&gt;Composition, choosing the right primitive for the job and wiring it correctly, is the entire subject of the seven building blocks and three external entities I teach. A Service, an External Service, a Vector Database, and the storage and queues around them are not background theory here. They are the actual vocabulary behind the job title on that listing, named and taught, in the order you would actually build them.&lt;/p&gt;

&lt;p&gt;You do not need to master gradient descent. You need to build the composition around the model: what takes the request, what talks to the model, what remembers enough to make the answer good, and what quietly keeps the whole thing running when the model call is slow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S. The Vector Database is the one piece of that composition the AI era genuinely made essential. I wrote up how it actually works and why it is the retrieval half of almost every AI feature you have used: &lt;a href="https://systemthinkinglab.ai/learn/building-blocks/vector-database/" rel="noopener noreferrer"&gt;https://systemthinkinglab.ai/learn/building-blocks/vector-database/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This letter goes out by email every Saturday. &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; or read the full archive at &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;systemthinkinglab.ai/newsletters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>The junior engineer is not disappearing</title>
      <dc:creator>Kay Ashaolu</dc:creator>
      <pubDate>Sun, 26 Jul 2026 01:03:48 +0000</pubDate>
      <link>https://dev.to/kayashaolu/the-junior-engineer-is-not-disappearing-27ch</link>
      <guid>https://dev.to/kayashaolu/the-junior-engineer-is-not-disappearing-27ch</guid>
      <description>&lt;p&gt;You have probably seen the claim by now: AI is coming for the junior engineer first, so if you are early in your career, or trying to become one, the timing looks bad. If you are a senior who has repeated that line to someone below you, this is worth a second look too.&lt;/p&gt;

&lt;p&gt;I wrote a longer essay taking the other side of that argument this week, and I want to give you the short version here.&lt;/p&gt;

&lt;p&gt;Look closely at what those predictions actually describe. Not a junior engineer. A person whose entire job is turning a finished spec into working code. That role is real and it is shrinking fast. But it was never the same thing as "junior engineer." We welded the two together for forty years because, until recently, spec-to-code translation was the main thing a junior had the skill to do. AI is eating that task. It does not follow that it eats the title too, unless we insist on keeping them tied together.&lt;/p&gt;

&lt;p&gt;So the real question is not whether the junior engineer survives. It is what we train a junior engineer to do now that translation work is cheap.&lt;/p&gt;

&lt;p&gt;I think a lot of people land on "they are doomed" for a reason that has nothing to do with whether it is true. It is the easy conclusion. It asks nothing of us. Figuring out how to train a junior into a senior without the years of tickets we used to lean on is genuinely hard. "They are doomed" lets everyone off the hook. "How do we train juniors into seniors now" does not, but it is the question with a future in it.&lt;/p&gt;

&lt;p&gt;Here is what is actually disappearing. For as long as I have been in this field, the plan was the same: hire someone who can code, hand them small well specified tickets, and let them grind through years of execution until judgment showed up. Bugs, edge cases, code review, the slow accumulation of pattern recognition. Somewhere around year four or five, if it worked, they started asking "should we build this" instead of just "how do I build this."&lt;/p&gt;

&lt;p&gt;That path is closing, and not because anyone designed it to close. The years that used to build judgment were built entirely out of execution work, and execution work is exactly what agentic coding now absorbs. Take away the tickets and there is nothing left for the apprentice to practice on. The casualty is not the junior engineer. It is the apprenticeship.&lt;/p&gt;

&lt;p&gt;Somebody still has to build senior judgment. It just cannot happen the old way anymore, which means it has to be built somewhere else, on purpose, before the first job starts. That is school. That is workshops and bootcamps. That is the courses people take on their own time. Each of those has mostly taught something other than judgment: theory in school, syntax and tooling in bootcamps and workshops. That is what has to change. I believe this enough to grade on it: the course I am teaching at UC Berkeley this fall has students build real applications with agentic coding, then grades them on defending the design decisions.&lt;/p&gt;

&lt;p&gt;None of this waits on a school's calendar, either. If you are already working, or already past whatever program you paid for, you can start this week on any real project you have open right now: make the agent produce a plan before it writes a line of code, question every decision in that plan, then let what actually happens grade whether you questioned the right things. No enrollment required.&lt;/p&gt;

&lt;p&gt;The full essay goes further into the mechanism I think replaces the old apprenticeship. People are calling the discipline of directing an agent well "loop engineering," and most of its value in a company comes from designing the human out of the loop. I think the training version runs the opposite direction: the junior stays &lt;em&gt;in&lt;/em&gt; the loop on purpose, pushing back on the agent's plan until an area is genuinely understood, and only then earns the right to step out of it, one area at a time. That part, the graduation mechanism, is the piece worth the full read: &lt;a href="https://systemthinkinglab.ai/newsletters/the-junior-engineer-is-not-disappearing/" rel="noopener noreferrer"&gt;https://systemthinkinglab.ai/newsletters/the-junior-engineer-is-not-disappearing/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For now, the short version is this.&lt;/p&gt;

&lt;p&gt;You do not train a junior by handing them a shrinking task and hoping judgment shows up on its own. You train them by building the judgment on purpose, before the tickets that used to build it are gone.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S. If this is the first thing you have read from me, the free course is where the building blocks lens starts: &lt;a href="https://systemthinkinglab.ai/learn" rel="noopener noreferrer"&gt;https://systemthinkinglab.ai/learn&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This letter goes out by email every Saturday. &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; or read the full archive at &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;systemthinkinglab.ai/newsletters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>When "saved" does not mean saved</title>
      <dc:creator>Kay Ashaolu</dc:creator>
      <pubDate>Sun, 19 Jul 2026 01:03:46 +0000</pubDate>
      <link>https://dev.to/kayashaolu/when-saved-does-not-mean-saved-5ceb</link>
      <guid>https://dev.to/kayashaolu/when-saved-does-not-mean-saved-5ceb</guid>
      <description>&lt;p&gt;This week I put AI agents on a real job: rewriting the bios on all eight of my social profiles. They did the work. I reviewed and approved each one from my phone.&lt;/p&gt;

&lt;p&gt;I have profiles across LinkedIn, TikTok, Threads, and five others, and over the years they had drifted. Each one described what I teach a little differently. I wanted all eight saying the same thing, so the agents spent an evening rewriting every bio, and I approved each one as it came back.&lt;/p&gt;

&lt;p&gt;Simple job. Then one of the agents tried to save a new bio to TikTok, and the app said the save worked when it had not. The character counter read 78 of 80, the app returned a success, and the old bio was still sitting there untouched, exactly as before.&lt;/p&gt;

&lt;p&gt;That is the beat I want to write about, because it is not really about TikTok.&lt;/p&gt;

&lt;p&gt;When the agents started, they did the obvious thing: they read each platform's own documentation for how long a bio could be and wrote to fit. That was a mistake. Threads documents a 500-character limit; the real field holds 150. We also walked in with our own note that Facebook's bio maxed out around 101 characters; the real field held 255. One number was the platform's error and one was ours. Both failed the same way: nobody had opened the actual field and counted.&lt;/p&gt;

&lt;p&gt;Then there was the TikTok save that reported success and changed nothing. If no one had gone back to look, that bio would have stayed wrong for as long as no one looked, and nothing on the page would tell a visitor it had happened. The only thing standing between "the app said it worked" and "it actually worked" was someone opening the profile to check.&lt;/p&gt;

&lt;p&gt;That is the whole lesson, and it is smaller and less dramatic than it sounds. Verify the result, not the report.&lt;/p&gt;

&lt;p&gt;A few other things happened that night. Halfway through, I decided the bios should lead with a different idea than the one they had been leading with, so I asked the agents to rewrite all nine drafts, and they did, before anything shipped. Then, before a single change went live, a separate verification pass re-checked the whole batch against the live pages, hunting for exactly the kind of silent failure I just described. Ten of the twelve fields were verified against the live page before I looked at one screenshot. The last two waited for my thumbs: edits the platforms only allow from their mobile apps.&lt;/p&gt;

&lt;p&gt;Here is the part I think people get backwards about working this way.&lt;/p&gt;

&lt;p&gt;The agents did not replace my judgment. They asked more of it.&lt;/p&gt;

&lt;p&gt;Every decision that mattered was mine. Which bio was actually the right one. Which of two disagreeing numbers to trust. Whether to scrap the drafts at midnight and start over. What "done" meant, and when I was allowed to stop checking. The agents did the work. I judged the result at every step, against the real profile, not against what the app claimed about it.&lt;/p&gt;

&lt;p&gt;This is the same discipline the seven building blocks teach, only at the scale of a profile bio instead of a production system. A Service is not working because it returned a success code. It is working because you followed what actually happened after that response and it matched what you expected. A write that reports success while quietly saving nothing is not a rare bug. It is the ordinary failure mode of anything no one has personally checked.&lt;/p&gt;

&lt;p&gt;You cannot judge a system you cannot see. And you cannot see it by trusting what it says about itself.&lt;/p&gt;

&lt;p&gt;There are two ways to get this wrong, and I have watched engineers do both.&lt;/p&gt;

&lt;p&gt;One is to hand the whole thing to the AI and walk away: trust every "saved," every success code, every green check. That is how a bio stays broken for a month.&lt;/p&gt;

&lt;p&gt;The other is to refuse to hand off any of it: touch every field yourself, on every platform, because that feels like the only safe way. That does not scale to eight profiles in one night, and it will not scale to a real system with fifty moving parts either.&lt;/p&gt;

&lt;p&gt;The skill is in the middle. Decide what has to be verified, and build something, a person or an agent, that verifies it before you have to ask.&lt;/p&gt;

&lt;p&gt;In Course 1 I teach the seven blocks for exactly this: so you can trace what a system actually did, instead of taking its word for it.&lt;/p&gt;

&lt;p&gt;You do not trust the response. You verify the result.&lt;/p&gt;

&lt;p&gt;P.S. If this is the first thing you have read from me, the free course walks through the same instinct, one building block at a time: &lt;a href="https://systemthinkinglab.ai/learn" rel="noopener noreferrer"&gt;https://systemthinkinglab.ai/learn&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This letter goes out by email every Saturday. &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;Subscribe here&lt;/a&gt; or read the full archive at &lt;a href="https://systemthinkinglab.ai/newsletters/" rel="noopener noreferrer"&gt;systemthinkinglab.ai/newsletters&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>ai</category>
      <category>beginners</category>
      <category>career</category>
    </item>
  </channel>
</rss>
