<?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: Steve Fenton</title>
    <description>The latest articles on DEV Community by Steve Fenton (@_steve_fenton_).</description>
    <link>https://dev.to/_steve_fenton_</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%2F2913455%2F532f94ec-d896-44e0-ab98-a1cae91a8278.jpg</url>
      <title>DEV Community: Steve Fenton</title>
      <link>https://dev.to/_steve_fenton_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_steve_fenton_"/>
    <language>en</language>
    <item>
      <title>Continuous Delivery Office Hours Ep.6: Change approvals</title>
      <dc:creator>Steve Fenton</dc:creator>
      <pubDate>Mon, 07 Sep 2026 15:26:10 +0000</pubDate>
      <link>https://dev.to/_steve_fenton_/continuous-delivery-office-hours-ep6-change-approvals-4d3</link>
      <guid>https://dev.to/_steve_fenton_/continuous-delivery-office-hours-ep6-change-approvals-4d3</guid>
      <description>&lt;p&gt;When you add approval stages to increase stability, the last thing you expect is instability. That's the opposite of what you wanted. Yet that's what happens when organizations respond to incidents by increasing the weight of change approval processes.&lt;/p&gt;

&lt;p&gt;That means there's more art to change approvals than most people realize, and it's a threat to an organization's ability to deploy and operate software if they don't have &lt;em&gt;change finesse&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch the episode
&lt;/h2&gt;

&lt;p&gt;You can watch the episode below, or read on to find some of the key discussion points.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=ODzaXj889wA" rel="noopener noreferrer"&gt;Watch Continuous Delivery Office Hours Ep.6&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Organizational trauma
&lt;/h2&gt;

&lt;p&gt;Change approvals don't arrive without reason. If you have a heavyweight change approval process and frequent or extended change freezes, the chances are that they were introduced after a major incident. If you break financial software around tax year-end, banning deployments for a month before and a month after is, in theory, a reasonable resolution.&lt;/p&gt;

&lt;p&gt;Almost every industry has a cadence it wants to protect from instability. Retail has seasonal sales events, the music industry has superstar ticket launches, and finance has a peak as the end of the tax year approaches. The goal is to make sure you can operate your business during these times.&lt;/p&gt;

&lt;p&gt;With that goal in mind, we have to bust the myth of change approvals as the mechanism to achieve it. Attempting to protect these key moments with change freezes or cumbersome approval processes has one result: increased instability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Heavyweight change approvals
&lt;/h2&gt;

&lt;p&gt;Heavyweight change approvals make things less stable by delaying work and causing batches of unreleased changes to accumulate. Meanwhile, developers are starting new work and are losing the immediate familiarity with the oldest changes as they press ahead. One of the ways approvals gain weight is through approval chains, which we looked at in depth in the &lt;a href="https://octopus.com/publications/compliance-through-continuous-delivery" rel="noopener noreferrer"&gt;Compliance through Continuous Delivery report&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Large batches also come with admin that can introduce further problems. Testing becomes more difficult, the likelihood of merge issues increases, and pinpointing the source of a problem is far harder.&lt;/p&gt;

&lt;p&gt;This is why the DORA research placed &lt;a href="https://dora.dev/capabilities/streamlining-change-approval/" rel="noopener noreferrer"&gt;streamlined change approvals&lt;/a&gt; in their core model for software delivery. Centralized change approval boards don't work, and process is never the solution to your stability problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Streamlining
&lt;/h2&gt;

&lt;p&gt;There are some easy ways to streamline change approvals. Most of these don't look like traditional change management, which is good because we know that doesn't work.&lt;/p&gt;

&lt;p&gt;The first way to trim the process is to automate your verification stages. At every level of review, tasks can be automated, whether it's automatically linting and formatting code (instead of debating it), running automated builds and tests, or validating your SBOM is free from insecure dependencies.&lt;/p&gt;

&lt;p&gt;Where you need a human review, use a peer-review process for individual changes, enforced on commit, with humans brought in only after the automated validation has passed. If you have advanced change approval needs, categorizing changes by risk lets you apply your people to the changes that most need their perspective.&lt;/p&gt;

&lt;p&gt;You won't achieve all of this in one day. It's part of your continuous improvement process. You may improve your chances of stripping the bureaucracy if you follow the &lt;a href="https://octopus.com/devops/culture/capability-culture-cycle/" rel="noopener noreferrer"&gt;capability culture cycle&lt;/a&gt; pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small batches, again
&lt;/h2&gt;

&lt;p&gt;If you follow industry experts or the research, you'll notice that small batches keep cropping up as the answer to many kinds of dysfunction. That's not a coincidence. Large batches cause far-reaching problems that build superlinearly as more changes collect unreleased.&lt;/p&gt;

&lt;p&gt;Anything that causes batch size to increase, including change approvals, must be subject to fierce improvement.&lt;/p&gt;

&lt;p&gt;Happy deployments!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continuous Delivery Office Hours is a series of conversations about software delivery, with Tony Kelly, Bob Walker, and Steve Fenton.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can find more episodes on &lt;a href="https://www.youtube.com/playlist?list=PLAGskdGvlaw3CrxkUOAMmiy928lr5D4oh" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://podcasts.apple.com/us/podcast/continuous-delivery-office-hours/id1872101651" rel="noopener noreferrer"&gt;Apple Podcasts&lt;/a&gt;, and &lt;a href="https://pca.st/hwjaox59" rel="noopener noreferrer"&gt;Pocket Casts&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>software</category>
      <category>cicd</category>
    </item>
    <item>
      <title>AI Hasn’t Shifted The Bottleneck From Coding To Code Review</title>
      <dc:creator>Steve Fenton</dc:creator>
      <pubDate>Thu, 03 Sep 2026 11:10:26 +0000</pubDate>
      <link>https://dev.to/_steve_fenton_/ai-hasnt-shifted-the-bottleneck-from-coding-to-code-review-192j</link>
      <guid>https://dev.to/_steve_fenton_/ai-hasnt-shifted-the-bottleneck-from-coding-to-code-review-192j</guid>
      <description>&lt;p&gt;Since AI arrived, many people have mentioned that the bottleneck has shifted from coding to code review. This isn’t quite right, as coding wasn’t the bottleneck in the first place, and it’s not code review now. The reason we think either of these things is constraining the flow of value is that mossy hill we all stare past when we look at the mountains.&lt;/p&gt;

&lt;p&gt;Here’s a simple test. For the application or service you work on, &lt;em&gt;how many changes have passed code review but haven’t yet been deployed and enabled for users?&lt;/em&gt; If the answer is none or one, accept my apologies: in your specific case, I’m wrong. But I rarely get that answer. It’s usually more than one and that tells you the bottleneck is elsewhere.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F09ltwn1exsj4hinrmsf7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F09ltwn1exsj4hinrmsf7.png" alt="A bar chart showing batch sizes" width="800" height="494"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Number of changes per deployment batch (Source: &lt;a href="https://octopus.com/" rel="noopener noreferrer"&gt;Octopus Deploy&lt;/a&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We’re conducting original research in this area right now, and half of all teams have between 2 and 10 changes sitting in a batch, and a quarter have 11–50. Overall, more than 90% of teams ship in batches rather than one change at a time.&lt;/p&gt;

&lt;p&gt;This number reveals an industry-wide visibility gap. People believe Claude Code, Cursor, and GitHub Copilot have shifted the bottleneck from coding to code review, but that ignores everything that happens after the review and that’s not a personal failing, it’s an industry-wide misperception.&lt;/p&gt;

&lt;p&gt;We’ve grown so used to working in batches that the practice looks like it belongs. It’s overgrown with moss, indistinguishable from the surrounding hills. When you search for ways to speed up software delivery, you won’t see it, because it doesn’t look like a problem. It looks just as things have always been.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when AI floods a batch
&lt;/h2&gt;

&lt;p&gt;Writing code is a small part of a longer value stream that starts with an opportunity and ends when a user gets the value they need. The impact across this whole value stream is lumpy. AI will help more in some areas than others, and the end-to-end benefit depends on you noticing the areas where work accumulates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://about.gitlab.com/resources/ai-accountability-survey-2026/" rel="noopener noreferrer"&gt;GitLab’s 2026 AI Accountability Report&lt;/a&gt; found 85% of respondents agree AI has shifted the bottleneck from writing code to reviewing it. Yet we can see from deployment batches that 92% of these people are likely wrong, because if there’s accumulation after the code review, it means code review isn’t the bottleneck. It also means speeding up the reviews will make the real bottleneck worse.&lt;/p&gt;

&lt;p&gt;This isn’t to say increased coding speed doesn’t put pressure on code review. &lt;a href="https://www.faros.ai/blog/ai-software-engineering" rel="noopener noreferrer"&gt;Faros AI’s research&lt;/a&gt; across 10,000 developers found that teams with high AI adoption merge 98% more pull requests, but review time for those changes grows 91%, and average pull request size grows 154%. &lt;a href="https://cursor.com/blog/productivity" rel="noopener noreferrer"&gt;Cursor’s own study&lt;/a&gt;, run with a University of Chicago economist, found companies merge 39% more pull requests once its coding agent becomes the default.&lt;/p&gt;

&lt;p&gt;However, approving changes faster is a strategy that only works if the change then flows smoothly to production. In the majority of cases, it simply moves into the queue of changes awaiting some other handling, like testing and deployment. If you up the rate and size of changes passing through the review stage, pressure is simply transferred to the real bottleneck.&lt;/p&gt;

&lt;p&gt;Code review looks like a constraint only because it has a visible queue, while the downstream queues are hidden by their general acceptance across the industry. The job of your pipeline is to get changes to production, where they can be used, not to gather them in a “pending deployment” queue.&lt;/p&gt;

&lt;p&gt;And while all those unreleased changes are building up, risk accumulates with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Batches are signposts
&lt;/h2&gt;

&lt;p&gt;Ask the batch-size question, and you’ll find what’s really constraining your value stream: a manual verification step, a cumbersome change approval or release train process, or no easy way to deploy changes. Not coding. Not code review.&lt;/p&gt;

&lt;p&gt;It’s likely you were working in batches before you started your AI initiative. The introduction of AI will increase the size of your batches and that can cause problems. Increasing code review throughput doesn’t solve the problem, it simply moves changes to the bottleneck faster.&lt;/p&gt;

&lt;p&gt;Using the true constraint to set the pace of your whole value stream will help you invest in solving the right problem. If your retrospectives keep failing to produce noticeable improvements, you’re likely missing the batch problem. It’s why some AI initiatives pay off while others flop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The studies miss it, too
&lt;/h2&gt;

&lt;p&gt;The research into the impact of AI is useful, but like many studies on this topic, it stops at the point code gets merged. It looks at pull requests opened, pull requests merged, hours spent reviewing. None of it asks how long changes wait after the review, or how many are bundled together before anyone sees them in production. Without that number, you can’t find the real constraint.&lt;/p&gt;

&lt;p&gt;Having invested in AI to speed up coding, you’ll be tempted to fix code review next, or give up on code reviews altogether. If you’re shipping in batches, neither will make much difference to how quickly you remove risk or deliver value to the people using the software.&lt;/p&gt;

&lt;p&gt;The reason your organization resists fixing the batch problem is the real problem you need to solve.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>software</category>
      <category>devops</category>
    </item>
    <item>
      <title>Continuous Delivery Office Hours Ep.7: Modern multi-tenancy</title>
      <dc:creator>Steve Fenton</dc:creator>
      <pubDate>Mon, 24 Aug 2026 12:53:02 +0000</pubDate>
      <link>https://dev.to/_steve_fenton_/continuous-delivery-office-hours-ep7-modern-multi-tenancy-c17</link>
      <guid>https://dev.to/_steve_fenton_/continuous-delivery-office-hours-ep7-modern-multi-tenancy-c17</guid>
      <description>&lt;p&gt;Multi-tenancy is an old concept that dates back to machine sharing. It got a new life with the rise of SaaS and the need to share infrastructure and databases across many tenants. Still, with the rise of lightweight virtualization, the idea of managing multi-tenancy with high code complexity has lost its appeal.&lt;/p&gt;

&lt;p&gt;Modern multi-tenancy leans into the ease of allocating dedicated instances to customers, improving isolation, reducing the risk of data leaks, and making it trivial to charge a fair price based on use (instead of subsidizing the noisy neighbors with a volume of under-utilizers).&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch the episode
&lt;/h2&gt;

&lt;p&gt;You can watch the episode below, or read on to find some of the key discussion points.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=0whxP3T6U5A" rel="noopener noreferrer"&gt;Watch Continuous Delivery Office Hours Ep.7.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving away from tenanted applications
&lt;/h2&gt;

&lt;p&gt;There are 3 primary architectural approaches to multi-tenancy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A shared application instance and database: Many customers are using the same running instance, with the application taking care of isolating their use and data.&lt;/li&gt;
&lt;li&gt;A shared application instance and a dedicated database: While customers all use the same running instance, their data is stored in a dedicated database, which the application connects to based on the tenant.&lt;/li&gt;
&lt;li&gt;Fully isolated infrastructure: Every tenant has a dedicated instance and database running on an allocation of compute.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The shared approach comes with many drawbacks. The application’s code is more complex and requires more testing to reduce the risk of data being displayed to someone who shouldn’t see it. Having a dedicated database limits the complexity and risk to the mechanism that selects the appropriate connection string.&lt;/p&gt;

&lt;p&gt;When tenants share application instances, databases, or database servers, one tenant can disrupt service for others, for example, by running a resource-intensive operation. It’s difficult to pinpoint where the increased load is coming from, and mechanisms for charging based on use often rely on proxy metrics that don’t reflect actual use.&lt;/p&gt;

&lt;p&gt;With modern hosting options, like containers, it becomes far easier to achieve high resource use at the infrastructure level, removing the need for applications to be made tenant aware. You can avoid all the complexity by giving each tenant their own application and database.&lt;/p&gt;

&lt;p&gt;If you have a customer with high resource needs, their use doesn’t slow down other customers or cause an outage. If they need a more powerful instance, they can pay to have one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shifting tenants to deployment-time
&lt;/h2&gt;

&lt;p&gt;To make modern multi-tenancy work, you need to be able to deploy many more instances and apply the correct configuration when you do so. Modern CD tools take care of this, so you can share a single deployment process with hundreds or thousands of tenants.&lt;/p&gt;

&lt;p&gt;When CD tools push a software version out, they can install tenant-specific instances by applying configuration variables. If you have 100 tenants, 3 environments, and 5 settings, the CD tool eliminates the need to manage 1,500 configuration files. They can also help you progressively roll out a new version based on tags so that customers can opt for early access or only the most stable versions.&lt;/p&gt;

&lt;p&gt;Multi-tenancy has effectively shifted out of your code and is now managed by your deployment pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  A tenant isn’t always a customer
&lt;/h2&gt;

&lt;p&gt;We often think of tenants as “customers,” but they can just as easily be physical locations, like a hospital, restaurant, or retail store, that need a dedicated instance. Any time you need a dedicated instance, a tenanted deployment can provide it.&lt;/p&gt;

&lt;p&gt;If you want to learn more, we also have a white paper on modern multi-tenancy available for download.&lt;/p&gt;

</description>
      <category>architecture</category>
    </item>
    <item>
      <title>The Rego/OPA crucial policy pattern</title>
      <dc:creator>Steve Fenton</dc:creator>
      <pubDate>Mon, 03 Aug 2026 13:23:20 +0000</pubDate>
      <link>https://dev.to/_steve_fenton_/the-regoopa-crucial-policy-pattern-2ooe</link>
      <guid>https://dev.to/_steve_fenton_/the-regoopa-crucial-policy-pattern-2ooe</guid>
      <description>&lt;p&gt;hen you author policies in Rego to be evaluated by Open Policy Agent (OPA), there are a whole heap of patterns you can use to make policies correct, safe, predictable, and maintainable. You could write a whole book on this topic, and along with John Bristowe and Matt Allford, I have!&lt;/p&gt;

&lt;p&gt;Today, though, I want to share the most crucial pattern in the whole Rego realm. The allow/deny pattern.&lt;/p&gt;

&lt;p&gt;Using a policy engine like OPA means you are concentrating your highest-risk code in one place. In fact, that's the idea. Instead of implementing policies in many different languages and with many different execution environments you bet on Rego and OPA so you can write policies in a dedicated language and with an evaluation engine singularly purposed to this speciality.&lt;/p&gt;

&lt;p&gt;With all this superbly important code in one place, it becomes vital to increase your discipline. No more "we'll add tests later" or "we can make it more readable next time we change it". This is the code that's making all the decisions, so you need it to be correct all the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The allow/deny pattern
&lt;/h2&gt;

&lt;p&gt;It's time to meet the allow/deny pattern. This is the shape policies ought to take, even if they're simple. When you start a new policy that's going to decide if something is allowed, start with the first few lines of this file, then add your own partial set rules to collect reasons to say no.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rego"&gt;&lt;code&gt;&lt;span class="ow"&gt;package&lt;/span&gt; &lt;span class="n"&gt;rental&lt;/span&gt;

&lt;span class="ow"&gt;default&lt;/span&gt; &lt;span class="n"&gt;allow&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="c1"&gt;# Only allow if we found zero reasons to deny&lt;/span&gt;
&lt;span class="n"&gt;allow&lt;/span&gt; &lt;span class="n"&gt;if&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deny&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Collect reasons to deny&lt;/span&gt;
&lt;span class="n"&gt;deny&lt;/span&gt; &lt;span class="n"&gt;contains&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="n"&gt;if&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;
  &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s2"&gt;"membership is not active"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;deny&lt;/span&gt; &lt;span class="n"&gt;contains&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="n"&gt;if&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fees_outstanding&lt;/span&gt;
  &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"outstanding late fees of £%.2f"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;late_fees&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;deny&lt;/span&gt; &lt;span class="n"&gt;contains&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="n"&gt;if&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;to_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;film&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"premier"&lt;/span&gt;
  &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"member is %v, film requires age %v (or premier tier)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;film&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works by first saying no: &lt;code&gt;default allow := false&lt;/code&gt; to make sure the default is safe. We then describe the only condition that will change this to a yes: &lt;code&gt;allow if { count(deny) == 0 }&lt;/code&gt;, which means allow if we found zero reasons to reject the request.&lt;/p&gt;

&lt;p&gt;With this safety net in place, you add one or more partial set rules to collect reasons to say no, like this one that says you have to have an active membership.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rego"&gt;&lt;code&gt;&lt;span class="n"&gt;deny&lt;/span&gt; &lt;span class="n"&gt;contains&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="n"&gt;if&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;membership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;
  &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s2"&gt;"membership is not active"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OPA evaluates all these rules and collects up rejection reasons. If you get denied, you have a set of reasons to explain why. Otherwise, you meet the condition for saying yes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crucial but not sufficient
&lt;/h2&gt;

&lt;p&gt;This shape is such a solid approach, you should use it most of the time. You should keep in mind there are other potential problems that can be caused by missing data, invalid schemas, or lack of tests. You need to account for all the reasons policies can go wrong, but the allow/deny pattern works alongside the other methods of writing correct, safe, predictable, and maintainable policies.&lt;/p&gt;

&lt;p&gt;Those other necessary practices are covered in &lt;em&gt;Exploring Rego&lt;/em&gt;, which will be landing in bookshops near you soon.&lt;/p&gt;

</description>
      <category>programming</category>
    </item>
    <item>
      <title>The difference between a millrace and a waterfall</title>
      <dc:creator>Steve Fenton</dc:creator>
      <pubDate>Thu, 30 Jul 2026 08:16:43 +0000</pubDate>
      <link>https://dev.to/_steve_fenton_/the-difference-between-a-millrace-and-a-waterfall-16f0</link>
      <guid>https://dev.to/_steve_fenton_/the-difference-between-a-millrace-and-a-waterfall-16f0</guid>
      <description>&lt;p&gt;Winston Royce gets the blame for inventing “waterfall” in software delivery, even though the name was assigned six years after Royce’s paper &lt;em&gt;Managing the Development of Large Software Systems&lt;/em&gt;. It gets worse for Royce, because the same paper, written in 1970, also suggested using something far better than “waterfall”.&lt;/p&gt;

&lt;p&gt;Waterfalls have a natural beauty, and that’s why people love visiting them. What you don’t realize is their power. In the UK, many of our waterfalls have names that include the word “Force”, including our largest waterfall by volume, High Force in County Durham.&lt;/p&gt;

&lt;p&gt;At peak, 100 cubic meters drop over the edge of the 21.5-meter fall every second. A typical day still delivers a fifth of that. Either way, that’s a lot of water. Yet it’s not enough to make the global flow rate rankings, as only waterfalls with over 150 cubic meters per second make the cut.&lt;/p&gt;

&lt;p&gt;It might help to imagine between 12 and 62 bathtubs per second crashing down at High Force. You’d need 1,300 standard builder’s skips per minute to handle the water at peak.&lt;/p&gt;

&lt;h2&gt;
  
  
  Work is like water
&lt;/h2&gt;

&lt;p&gt;I wrote an article for The New Stack in 2025 titled &lt;a href="https://thenewstack.io/work-is-water-beat-developer-infinity-by-paying-attention-to-flow/" rel="noopener noreferrer"&gt;Work Is Water&lt;/a&gt;, in which I compared artificial dams, weirs, culverts, and sluices to how we approach work. Our desire to control nature leads us to build great concrete runways for water as we try to shift it quickly to a destination. This fails.&lt;/p&gt;

&lt;p&gt;We’ve now realized that the best way to control nature is with more nature. The winding path of a river, beaver dams, and the landscape slow the water and prevent downstream flooding better than our attempts to rush it downstream and away.&lt;/p&gt;

&lt;p&gt;Everyone has experienced this in the workplace. When you try to rush the work, all you do is create floods. Floods of testing. Floods of bugs. Floods of rework. We’re not listening to nature when we rush the work. But I promised to explain the difference between a waterfall and a millrace.&lt;/p&gt;

&lt;h2&gt;
  
  
  The waterfall and the millrace
&lt;/h2&gt;

&lt;p&gt;Waterfalls deliver a volume of water at their head, and gravity brings it crashing down. That’s beautiful in the British Countryside, but terrible in the workplace. When you create a large batch of work and push it into the air above a long drop, it becomes impossible to control.&lt;/p&gt;

&lt;p&gt;Overly specified software projects are the canonical example of this. They define too much of the system up front, tipping it over the edge and flooding all downstream stages. If you believe our industry has solved this problem, I want to make you reconsider, because research shows it is not solved by turning a 12-month project into a 2-week sprint. A 2-week sprint is better than a longer project, but it still causes flooding.&lt;/p&gt;

&lt;p&gt;That’s why you need to move away from waterfalls, no matter the flow rate, and switch to the millrace.&lt;/p&gt;

&lt;p&gt;The crucial difference between a waterfall and a millrace is that you can control the water entering the channel. You can shut off all water to make repairs, and you can deliver the precise amount of power to the wheel when you need it. The pace is set by your need for power, and water only enters when you need it.&lt;/p&gt;

&lt;p&gt;There is no need to let work enter the system if you haven’t completed what’s in flight. If you haven’t got feedback on the work and made improvements, you’re not done. Software teams have struggled with this definition for decades, and you can see the resistance to this definition when you find teams who call things “done”, or “done done” depending on “how done they are”. Perhaps “done” means they’ve stopped working on it, and “done done” means it’s deployed.&lt;/p&gt;

&lt;p&gt;Software teams are abandoning work unfinished in the majority of cases. They took the most important feature, ceased work on it, deployed it some time later, and never went to find out if it works. They are now working on a less important feature, while people grow frustrated with the sharp edges left on every prior development.&lt;/p&gt;

&lt;p&gt;Yes, the millrace is about working in small batches. That’s the big takeaway. Batches even smaller than you think, even now at the end of this sentence. The most successful team I was on worked on a single feature. Literally one. And they worked on it until people confirmed it solved their problem and had no sharp edges.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://octopus.com/devops/history/early-software-delivery-models/" rel="noopener noreferrer"&gt;Winston Royce told people this&lt;/a&gt;. He said you had to involve the customer and make small, incremental changes. How did people miss this for 25 years, assuming you take the lightweight methods revolution as the moment of realization (I’d argue the majority of organizations are still working this out).&lt;/p&gt;

&lt;h2&gt;
  
  
  The conflict, resolved
&lt;/h2&gt;

&lt;p&gt;Astute readers have noticed a metaphorical conflict. When I describe work as water, I’m leaning into the idea that nature has better water management than people do. We should remove all those human inventions that control water, I declared along the way. Then I told you to install a millrace to control the flow of work to your team. You think I’m riffing, and I haven’t thought this through.&lt;/p&gt;

&lt;p&gt;You may, then, enjoy the denouement, though it only re-explains what I’ve already said. The millrace is the tool that will return you to nature.&lt;/p&gt;

&lt;p&gt;Today, you have water cascading over the precipice, attempting to force work through the system and out the other end. The flooding triggers emergency mode, so you don’t take care along the way, you don’t listen for feedback signals, you can only race to “done done” abandonment, so you can rush onto the next thing.&lt;/p&gt;

&lt;p&gt;The millrace draws water before the waterfall. It provides a smooth and calm route for the water to flow into the system. It lets you close off the stream when you need a pause to fix something or improve how you work. It’s a healthy way to exit the world of constant flooding.&lt;/p&gt;

&lt;p&gt;But single-piece flow is the natural water course. The work trickles gently, yet the value of what you build increases because, instead of counting features, lines of code, or tokens scorched, you’re collaborating with the people using what you build to make something truly exceptional.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Hyde's Mill: Photo by Dave Hoefler&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>agile</category>
    </item>
    <item>
      <title>Continuous Delivery Office Hours Ep.5: Delivering database changes</title>
      <dc:creator>Steve Fenton</dc:creator>
      <pubDate>Mon, 27 Jul 2026 12:04:37 +0000</pubDate>
      <link>https://dev.to/_steve_fenton_/continuous-delivery-office-hours-ep5-delivering-database-changes-2k18</link>
      <guid>https://dev.to/_steve_fenton_/continuous-delivery-office-hours-ep5-delivering-database-changes-2k18</guid>
      <description>&lt;p&gt;In the previous episode, we talked about &lt;a href="https://dev.to/blog/continuous-delivery-office-hours-e4"&gt;different service design approaches&lt;/a&gt;. This time, we dive deeper into database changes.&lt;/p&gt;

&lt;p&gt;Even for teams that can effortlessly deploy their application code, database changes can be more stressful. Changing a schema is a high-stakes operation, and there are many ways to do it badly.&lt;/p&gt;

&lt;p&gt;Read on to find out why database deployments are different from application deployments, and what techniques you can use to make them worry-free.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch the episode
&lt;/h2&gt;

&lt;p&gt;You can watch the episode below, or read on to find some of the key discussion points.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=_rHyP_RZbQc" rel="noopener noreferrer"&gt;Watch Continuous Delivery Office Hours Ep.5&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why are databases different
&lt;/h2&gt;

&lt;p&gt;When you change your application's code and discover an issue, it's trivial to revert to the previous version. In rare cases where a change affects your data, there may be cleanup to do.&lt;/p&gt;

&lt;p&gt;You can use timestamps and a one-off process to fix those rare data-mess-up instances, but they hint at something fundamentally different about database updates. They have different levels and types of risk associated with them.&lt;/p&gt;

&lt;p&gt;If you think backups will save you from a bad database deployment, you haven't yet tried it. Sure, they prevent total data loss, but between your backup and your fix, the data moved. Often by a lot.&lt;/p&gt;

&lt;p&gt;There are techniques to apply transactions from the backup up to the point of failure, but if your change caused an issue you needed to roll back, you probably don't want to apply those transactions automatically. Welcome to the "data remediation project".&lt;/p&gt;

&lt;p&gt;If you added a new column or table as part of your database change and you need to roll back, you have to decide what to do with any data in those tables. Do you forget it, or do you need to keep hold of it and reapply it later when you make a new attempt to extend the schema?&lt;/p&gt;

&lt;p&gt;Modern software teams prefer fix-forward for application issues, which are reasonably easy to roll back. Databases take rollbacks to another level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crucial modernization steps
&lt;/h2&gt;

&lt;p&gt;Imagine you met a friend for lunch and they told you they store they application's source code on a network share, rather than in version control. You'd think it was a joke, and when you realize it's not, you'd form a strong opinion about the kind of sloppy outfit they must be running.&lt;/p&gt;

&lt;p&gt;When we meet for lunch, what are you going to tell me about your database schema and static data? Please tell me it's all in version control, not on a network share.&lt;/p&gt;

&lt;p&gt;You should make all database changes by updating the files in version control and deploying them like you would your application code. You progress the change through environments to ensure it works, and you avoid embarrassment caused by the application failing because someone forgot to add the new column in production.&lt;/p&gt;

&lt;p&gt;There are further choices to make, which we'll cover next, but failing to version-control your database is unforgivable.&lt;/p&gt;

&lt;h2&gt;
  
  
  State-based vs migration-based approaches
&lt;/h2&gt;

&lt;p&gt;On to the first choice for your database project. Do you make state-based or migration-based updates?&lt;/p&gt;

&lt;p&gt;State-based schemas describe the desired state of the database. It will list each table with its columns, indexes, and relationships. You use a model-based tool to deploy the database, which compares your current state with the desired state and applies the changes for you.&lt;/p&gt;

&lt;p&gt;Some state-based tools convert the differences into standard database scripts, like &lt;code&gt;ALTER TABLE...&lt;/code&gt; scripts. Others perform migrations by creating a new table with the changes and moving the data into it. This is important if you're using a technology like replication, which prevents the model migration mechanism from working.&lt;/p&gt;

&lt;p&gt;The alternative to state-based database updates is migration-based updates, where you write your own &lt;code&gt;ALTER TABLE&lt;/code&gt; scripts. You keep all your scripts in version control and use a tool that applies them in order and tracks when each was applied, preventing the same script from being applied twice to the same database.&lt;/p&gt;

&lt;p&gt;The main difference between the two is procedural. You can code-review the migration scripts on demand, but you'll need to review state-based migration scripts after your tools generate the implementation plan, which can make the review task more of a large batch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tooling and automation
&lt;/h2&gt;

&lt;p&gt;Whichever approach you use, tooling helps it work. Many of our customers use Redgate tools as part of their deployment process to manage database schema changes, and there's value in leaning on a tool written by folks who care deeply about the problem and how to solve it.&lt;/p&gt;

&lt;p&gt;Crucially, you shouldn't make any database changes outside of tool-based automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test data management
&lt;/h2&gt;

&lt;p&gt;Once you've automated your database schema and static data, it's worth considering your test data. When automated or manual acceptance tests fail, it's usually because someone unwittingly messed up the data. Prior test runs often leave data in an inconsistent state, especially if a test failure halts the run.&lt;/p&gt;

&lt;p&gt;You can resolve this issue by automating your test data setup. Not only does this make it easy to reset the data during your build and test cycle, but it also lets you provide a self-service runbook for the test team to reset the data in their test environment whenever they need to.&lt;/p&gt;

&lt;p&gt;There's an up-front investment in this, but I can promise that it takes fewer hours than fixing your test data a few times.&lt;/p&gt;

&lt;h2&gt;
  
  
  Database refactoring patterns
&lt;/h2&gt;

&lt;p&gt;The final thought to ponder concerns the steps you take in changing your database schema. When you're in the habit of deploying your database and application in the same release process, you start to depend on this change coordination.&lt;/p&gt;

&lt;p&gt;You delete a column from the database and immediately deploy the application, with all references to the deleted column removed. It looks like it works smoothly, but it's a trap.&lt;/p&gt;

&lt;p&gt;Imagine you had a critical bug in the application and had to redeploy the previous version. Now you can't, because the previous version will try to read from a column that doesn't exist. You no longer have a quick, easy back out plan, since you have to re-add the column, and you'll also need data to put in it.&lt;/p&gt;

&lt;p&gt;This approach also prevents you from making seamless deployments, as even if you progressively roll out the application version, the old version will error out due to the database change. You may deploy in the opposite order, application first, then database. You'll discover the same problem with new columns that the latest version expects to find in the database.&lt;/p&gt;

&lt;p&gt;You need to decouple database and application deployments, and there's a whole book on the topic, called Refactoring Databases (Ambler, Sadalage). You can start by following the expand/contract pattern, which splits updates into steps. The principle is that you don't delete a column until the production application has no reads or writes. You add a column and don't reference it in your code until you deploy to production.&lt;/p&gt;

&lt;p&gt;This means you can run the current version and the new version of the software against the same database, which means you can progressively roll out the new version and redeploy the prior version without touching the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Databases are only as hard as you make them
&lt;/h2&gt;

&lt;p&gt;The database is high-risk, which is why updating it can be scary. I hope you've found this post full of practical advice for making database deployments robust and stress-free.&lt;/p&gt;

&lt;p&gt;Database deployments, like application deployments, should be a happy time. You should be celebrating the new features and enhancements you've delivered to your users, not biting your nails and worrying that something's about to go horribly wrong.&lt;/p&gt;

&lt;p&gt;Happy deployments!&lt;/p&gt;

&lt;p&gt;Continuous Delivery Office Hours is a series of conversations about software delivery, with Tony Kelly, Bob Walker, and Steve Fenton.&lt;/p&gt;

&lt;p&gt;You can find more episodes on &lt;a href="https://www.youtube.com/playlist?list=PLAGskdGvlaw3CrxkUOAMmiy928lr5D4oh" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://podcasts.apple.com/us/podcast/continuous-delivery-office-hours/id1872101651" rel="noopener noreferrer"&gt;Apple Podcasts&lt;/a&gt;, and &lt;a href="https://pca.st/hwjaox59" rel="noopener noreferrer"&gt;Pocket Casts&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>devops</category>
      <category>database</category>
    </item>
    <item>
      <title>Auto-close GitHub pull requests</title>
      <dc:creator>Steve Fenton</dc:creator>
      <pubDate>Mon, 20 Jul 2026 11:14:52 +0000</pubDate>
      <link>https://dev.to/_steve_fenton_/auto-close-github-pull-requests-778</link>
      <guid>https://dev.to/_steve_fenton_/auto-close-github-pull-requests-778</guid>
      <description>&lt;p&gt;You might be like me. You open the dishwasher and there's no order or discipline to how it's been loaded. If you leave it that way, half of your cups will come out gritty. The baking tray is going to stop the spinning water blade. The bowl is going to be filled with water. It's a mess.&lt;/p&gt;

&lt;p&gt;If you're the person who re-loads the whole dishwasher, and if you're using GitHub Pull Requests... this post is for you.&lt;/p&gt;

&lt;p&gt;Just like the dishwasher, I sometimes open GitHub to find the Pull Requests tab on a repository has been loaded badly. It's a mess.&lt;/p&gt;

&lt;p&gt;The good news is, the fix is automated and easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stale PRs
&lt;/h2&gt;

&lt;p&gt;There's a GitHub-authored Action that tackles this problem, so you don't have to. Sadly, it doesn't work on dishwashers but let's take whatever wins we can get.&lt;/p&gt;

&lt;p&gt;You add a new Action to the &lt;code&gt;.github/workflows&lt;/code&gt; folder called &lt;code&gt;stale-pull-requests.yml&lt;/code&gt;, then add the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A schedule to run the Action. Once a week is usually sufficient&lt;/li&gt;
&lt;li&gt;A reference to &lt;code&gt;actions/stale&lt;/code&gt; with a dusting of configuration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For scheduling, once a week is enough and you can set it up as a mittwoch maintenance activity. The syntax for schedules takes some getting used to, but &lt;code&gt;0 1 * * 3&lt;/code&gt; fills the slots &lt;code&gt;minute hour day-of-month month day-of-week&lt;/code&gt;. If you don't need to supply a value (like day-of-month, because we're doing it every week) you just use a &lt;code&gt;*&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To help my friends, I always add a comment to explain the schedule.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Mark stale PRs&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;  &lt;span class="c1"&gt;# Every Wednesday at 1am UTC&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stale&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/stale@v9&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;stale-pr-message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Things&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;seem&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;have&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;gone&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;quiet&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;this&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;PR.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;There&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;has&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;been&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;activity&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;60&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;days,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;so&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;it&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;will&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;be&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;closed&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;14&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;days&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;if&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;there&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;still&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;movement.'&lt;/span&gt;
          &lt;span class="na"&gt;close-pr-message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Closing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;due&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;inactivity.'&lt;/span&gt;
          &lt;span class="na"&gt;days-before-pr-stale&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
          &lt;span class="na"&gt;days-before-pr-close&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;14&lt;/span&gt;
          &lt;span class="na"&gt;stale-pr-label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;stale'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the &lt;code&gt;actions/stale&lt;/code&gt; front, you add a couple of messages, some timings, and a label.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;stale-pr-message&lt;/code&gt; tells people what's about to happen; the PR seems to have wilted and it's going to get crushed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;close-pr-message&lt;/code&gt; explains why the PR got crushed when it gets auto-closed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;days-before-pr-stale&lt;/code&gt; is how long you wait before adding the &lt;code&gt;stale-pr-message&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;days-before-pr-close&lt;/code&gt; is how much longer you wait before crushing it&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;stale-pr-label&lt;/code&gt; is the label that will be applied to stale PRs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  There are two doors
&lt;/h2&gt;

&lt;p&gt;Two things will happen when you add this. People will realize they forgot all about the PR and will move it on and get it approved, merged, and closed. Or they won't, and it will be kicked out of the pub by Peggy Mitchell.&lt;/p&gt;

&lt;p&gt;Either way, the dishwasher is neat and tidy, and all your plates and cups get clean.&lt;/p&gt;

</description>
      <category>github</category>
      <category>software</category>
    </item>
    <item>
      <title>AI: You Asked for a Dog, They’re Selling You a Cheetah</title>
      <dc:creator>Steve Fenton</dc:creator>
      <pubDate>Mon, 13 Jul 2026 11:09:54 +0000</pubDate>
      <link>https://dev.to/_steve_fenton_/ai-you-asked-for-a-dog-theyre-selling-you-a-cheetah-4nck</link>
      <guid>https://dev.to/_steve_fenton_/ai-you-asked-for-a-dog-theyre-selling-you-a-cheetah-4nck</guid>
      <description>&lt;p&gt;&lt;strong&gt;Why I no longer believe organizations that adopt AI to speed up software delivery&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In my formative years, I had a Labrador/Whippet cross called Barclay. We did almost everything together. If I was digging a hole in the garden, he would be there snuffling around it. If I was reading a book, he’d lay on my legs until I got pins and needles. When my family went for walks in the forest, he would scout ahead and race back to check on us, running ten times as far as we walked in his excited loops.&lt;/p&gt;

&lt;p&gt;One of the best things about dogs is that you can talk to them when times are tough. They are great listeners and understand you when no one else does.&lt;/p&gt;

&lt;p&gt;If I were to get another dog, companionship would be my top reason. There are many other reasons to own a dog, but for me? That’s the top one.&lt;/p&gt;

&lt;p&gt;Now imagine I went to the rescue center and asked to see their dogs, but they wanted me to take home a cheetah, because it’s much faster than a dog. That’s what I hear when an organization says they are adopting AI with a myopic focus on speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed Is Not The Goal: Speed Was Never The Goal
&lt;/h2&gt;

&lt;p&gt;We’ve been here before. We should all lament how the Agile movement withered to a dried husk that only offered “speed”. Speed was never the goal. The primary reason to increase your throughput is to get feedback earlier. When you find out your amazing new feature doesn’t excite your users, you can stop working on it right away.&lt;/p&gt;

&lt;p&gt;You throw away far less when you can stop a bad idea early, and you get to move on to a better idea straight away. Nobody should be trying to build software with the most features and the fastest rate of change. When you have too many features and things are constantly changing to accommodate the ever-expanding list of stuff your software does, people start to hate what you built.&lt;/p&gt;

&lt;p&gt;Microsoft Word is the most powerful and full-featured word processor available today, yet nobody uses it anymore. They are using Google Docs, which has far fewer features. That means the features Google selected must be more compelling, or that fewer features make the software easier to use. In reality, it’s a combination of many small factors like these. Sometimes one really compelling feature eclipses all others, and the ease of collaborating on a Google Doc in a web browser might have been just that.&lt;/p&gt;

&lt;p&gt;If you’d asked someone twenty years ago, they would have told you Microsoft Word had an unbreakable hold on its category, but now it has 3.9% of the market, compared to Google Docs’ 9.6% (source: &lt;a href="https://6sense.com/tech/productivity/googledocs-vs-microsoftword" rel="noopener noreferrer"&gt;6sense&lt;/a&gt;. If you believe this market shift is solely a question of pricing, you’re probably working for the kind of organization that wants straight-line speed, because you’ve already stopped believing in the idea of creating software that users value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adopting AI For Speed Lacks Credibility
&lt;/h2&gt;

&lt;p&gt;Software leaders have a track record, and that should be considered when they announce they are adopting AI for straight-line speed. Very often, you’ll find that over the past decade or two, they have announced an Agile Transformation for straight-line speed, adopted DevOps for straight-line speed, and started a platform initiative for straight-line speed.&lt;/p&gt;

&lt;p&gt;The fact that they have burned through all these initiatives without achieving significant results is a strong indication that they don’t want speed as much as they claim. Sure, they want to slap a “DORA Elite Performance” badge on their work history. Still, they don’t have a genuine reason to go faster, because they aren’t interested in that fundamental outcome from shipping more often: feedback.&lt;/p&gt;

&lt;p&gt;Any leader who has put their teams through the mangle this many times in the name of speed and who now says AI will be the thing that finally brings it is deluded.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Feedback Metronome
&lt;/h2&gt;

&lt;p&gt;When you want the feedback more than the speed, you’ll let the feedback loop set the pace of the whole software delivery process. Setting the pace to this beat gives you crucial space to process that feedback and do the one thing Agile wants you to do, which is change direction quickly.&lt;/p&gt;

&lt;p&gt;Organizations and teams that use feedback as the metronome, setting the rhythm for the whole orchestra, are likely to seek out and eliminate work that disrupts the beat. They design teams to complete the work with minimal (and well-designed) dependencies. They streamline change approvals. They make sure the team can decide when to push the button to deploy their software and that they can observe what happens when they do.&lt;/p&gt;

&lt;p&gt;The DORA model, with its generative culture, transformational leadership, lean product management, and continuous delivery process, wasn’t created by accident. This is the result of decades of work. Teams applying these concepts have speed, but that’s not why they adopt the culture and practices. They want frequent high-quality feedback so they can discover what really needs to be built.&lt;/p&gt;

&lt;h2&gt;
  
  
  This Is What Team Elite Did
&lt;/h2&gt;

&lt;p&gt;Team Elite was a software team in a large healthcare company. The organization provided software for patient management and emergency triage. When it comes to safety-critical industries, this was software that really could mean life or death.&lt;/p&gt;

&lt;p&gt;They shipped their patient management system once every six months, and the testing cycle for their decision support system was two weeks, plus another two weeks if they found a problem. Repeat until a version passes!&lt;/p&gt;

&lt;p&gt;Despite this history, we managed to run a program of work for six months that created a deployable software version every three hours. We were following a set of very strong technical practices, but what we removed was likely more important than what we added. However, there’s a balance that came from adding specification by example with executable specifications and removing bureaucratic checking stages that were slower and less effective.&lt;/p&gt;

&lt;p&gt;When it comes to outcomes, a crucial deal with a new healthcare provider required a decision management API to integrate into their website. We delivered a working API safely in two weeks and went live on a contract valued at $1.8 million ($2.5 million in today’s money).&lt;/p&gt;

&lt;p&gt;If your organization hasn’t reviewed the route to production and made similar changes, nothing will deliver the speed you claim you want. You’ll introduce AI, just as you introduced Scrum, DevOps, and Platform Engineering, and it will make zero difference, just as before.&lt;/p&gt;

&lt;p&gt;The most important thing you could do right now is map the flow of value, especially from code commit to production deployment, and start fixing the parts that are broken. There is no secret to what needs to change. Dave Farley and Jez Humble gave away the magic in their book “Continuous Delivery: Reliable Software Releases Through Build, Test, and Deployment Automation”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Are You Adopting AI?
&lt;/h2&gt;

&lt;p&gt;Before today, you might have said you were adopting AI to speed things up. If you’re serious about software, I hope you’ll adjust your answer and make it clear to those around you that frequent feedback and decision agility are high on your list of priorities.&lt;/p&gt;

&lt;p&gt;Teams that have already solved the throughput/stability trade-off through practices like Continuous Delivery will be less attracted to speed. They are more likely to seek more valuable opportunities. I wanted to close by suggesting a couple of these.&lt;/p&gt;

&lt;p&gt;Small teams are better. We have compromised on this because we need things sooner than a very small team can manage. We might double the team size even though we know it won’t halve the time it takes. The COCOMO model had a complex calculation for this diminishing return, though Fred Brooks said it more memorably. Adding people to a late project makes it later.&lt;/p&gt;

&lt;p&gt;As a result, most software teams that understand the complexity of communication and coordination fall into the 6–12 team-member range. The famous two-pizza team. But it’s not an ideal team size; it’s too large. It has simply been a pragmatic way to balance several factors. With AI, we should look at one-pizza teams, and even a smaller pizza.&lt;/p&gt;

&lt;p&gt;Small teams with high autonomy working on a loosely coupled component could be the power move to unlock the value of AI-assisted software development.&lt;/p&gt;

&lt;p&gt;My final suggestion is that, rather than building the same software faster, AI may let your teams build more ambitious software. You could tackle that globalization work you’ve always lacked the courage to start. You might have a feature idea that has always been impossible to get sufficient clarity on, where an AI prototype would allow an exploration you couldn’t attempt before.&lt;/p&gt;

&lt;p&gt;In any case, start with a more aggressive improvement to your software delivery process and deployment pipelines. Make sure you’re joining up the feedback loop and that you use it like a metronome to set the rhythm. Once you’ve done these, you will seek something more imaginative than “speed” from your AI adoption.&lt;/p&gt;

&lt;p&gt;Dog photo by &lt;a href="https://unsplash.com/@syedabsarahmad?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Syed Ahmad&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/brown-short-coated-dog-in-tilt-shift-lens-7WBU6_iv-iU?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The thinking behind Millrace</title>
      <dc:creator>Steve Fenton</dc:creator>
      <pubDate>Mon, 06 Jul 2026 13:06:07 +0000</pubDate>
      <link>https://dev.to/_steve_fenton_/the-thinking-behind-millrace-1kf3</link>
      <guid>https://dev.to/_steve_fenton_/the-thinking-behind-millrace-1kf3</guid>
      <description>&lt;p&gt;Did you ever notice how digital task boards are suddenly all the same horrid thing. Heavy engines of compromise that are as happy to supply a Gantt chart and resource plan as they are to give you a Kanban board.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slow and steady, not slow and heavy
&lt;/h2&gt;

&lt;p&gt;That moment of realization happened for me a few months back and I spent a great deal of time playing “Crossy Road” by jumping between all the available tools to find a new home for my work. I hated them all.&lt;/p&gt;

&lt;p&gt;The thing that I found really disappointing was that the Kanban board felt so much like it was tagged onto something else. Something big, greasy, and hostile. Like when you realize that “Scrum Master” has decades under their belt as a pathological project manager. They will happily rename all their PMBOK shenanigans to remain employed, but their approach hasn’t changed a bit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finish the good stuff and let mediocre ideas fall away
&lt;/h2&gt;

&lt;p&gt;My work method merges ideas from Getting Things Done at the big-rock level, and Personal Kanban to slice things up and stay focused on what really matters. That lets me apply Pomodoro Technique at the smallest scale to build up chunks of focus time that move things forward.&lt;/p&gt;

&lt;p&gt;When it comes to a task board, that means creating a big-rock card with loosely formed ideas that I might choose to never work on. In fact, most of the ideas will be superseded by newer better ones and that’s a good thing. If the idea survives, I’ll slice chunks out of it and flow them across the board to get them done.&lt;/p&gt;

&lt;p&gt;My up-next and in-flight columns need limits. These are the areas I need to carefully weed. Other columns tend to have their pace set by those two handling-time columns. Sometimes I like to break rules, so WIP limits are a visual thing, not an enforced policy.&lt;/p&gt;

&lt;p&gt;Because all my work tends to happen on a screen, I like prominent links on the card, so I can teleport to where the work is without opening up the card. While I reject the idea of a due date, I do like to have my tasks wake up at relevant moments, so a next-action date is useful.&lt;/p&gt;

&lt;p&gt;To reflect on my work, I like to review my completed items each week. If I can tag the crucial stuff, I can see if it’s making it all the way to “done”. A few tasteful charts can be useful in checking myself when I go off the rails. They help direct me to areas that need improvement, which is helpful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fniciu498ep7tn1exp6qp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fniciu498ep7tn1exp6qp.png" alt="Work dashboard" width="800" height="829"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A certain level of polish
&lt;/h2&gt;

&lt;p&gt;There also needs to be a certain level of polish. The user interface doesn’t have to spark a new trend in app design, but what I can’t tolerate are paper cuts. A small irritation that I scrape past every time I check in on my work is a sure-fire productivity killer.&lt;/p&gt;

&lt;p&gt;When I was trying out all these “productivity tools”, I kept finding blatant, reproducible, and distracting issues. Like one tool where I added a new card to the board only for it to vanish as I was typing in the title. The steps to reproduce this involved moving a card that triggered an automation, then adding a new card before the automation completed. This would be a forgivable edge case if this wasn’t one of the most common moments you might add a new card.&lt;/p&gt;

&lt;p&gt;Or maybe it’s the tool that only let you add links to the rich-text field. Copy. Type. Locate icon. Click. Paste. Nope. On top of this, you could only see the link by opening the card. That’s too much friction when I have links on around 60-80% of my cards.&lt;/p&gt;

&lt;p&gt;A tool you use occasionally can have a rough patch or two, but one you use to orient your day and manage your energy has no room for splinters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Calm, slow, smooth, fast
&lt;/h2&gt;

&lt;p&gt;The thing is, we’ve all seen someone trying to achieve something under pressure. They transform from a sentient human into a comedic slapstick actor. You know what I mean! They are baking a cake and it’s boring to wait for stuff to happen, so they start doing other things at the same time. Maybe they wash up some of the bowls and spoons. No big deal.&lt;/p&gt;

&lt;p&gt;But then they catch a hint of that unmistakable burning smell. Oh no! The cake is burning. It’s not just that their calm has gone, the whole chain of calm-slow-smooth-fast has collapsed.&lt;/p&gt;

&lt;p&gt;They whip their hands out of the washing up bowl, splashing water over the kitchen floor. They make an urgent grab for the oven glove, but knock it off the worktop. They pick it up, pull open the oven door, and use the half-on glove to grab the baking tray. The start to pull the cake out of the oven, burn the bit of their hand that isn’t in the glove, and just before the cake gets flopped upside down on the floor they realize that the burning smell was just a thin edge catching.&lt;/p&gt;

&lt;p&gt;As the cake splatters on the floor, they realize it could have done with another ten minutes. Now it’s ruined. They should probably run their hand under a cold tap, but before they get to the sink they’ve slipped up on the wet floor.&lt;/p&gt;

&lt;p&gt;It’s ridiculous. I agree. But this is how most people approach their work. They are over-burdened and their response is to make the work harder.&lt;/p&gt;

&lt;p&gt;That’s why your Kanban board needs to be a source of calm. Calm is slow. Slow is smooth. Smooth is fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  &amp;nbsp;Fin
&lt;/h2&gt;

&lt;p&gt;And that’s it. That’s the thinking. I didn’t build a Kanban board. I created a calm space to think about my work, my energy, and my impact.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8o1ov0fmk6pbsbzip6dz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8o1ov0fmk6pbsbzip6dz.png" alt="Board view" width="800" height="782"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agile</category>
      <category>resources</category>
      <category>product</category>
    </item>
    <item>
      <title>Continuous Delivery Office Hours Ep.4: Mono, micro, mesco</title>
      <dc:creator>Steve Fenton</dc:creator>
      <pubDate>Mon, 29 Jun 2026 14:40:49 +0000</pubDate>
      <link>https://dev.to/_steve_fenton_/continuous-delivery-office-hours-ep4-mono-micro-mesco-3dc5</link>
      <guid>https://dev.to/_steve_fenton_/continuous-delivery-office-hours-ep4-mono-micro-mesco-3dc5</guid>
      <description>&lt;p&gt;After tackling the question of &lt;a href="https://dev.to/blog/continuous-delivery-office-hours-e3"&gt;which branching strategy is best&lt;/a&gt;, we turn our focus to architecture in this Continuous Delivery Office Hours episode. In particular, we discuss how big your building blocks should be and whether you should opt for a majestic monolith, granular microservices, or something in between.&lt;/p&gt;

&lt;p&gt;Traditional monoliths are often described as a &lt;em&gt;big ball of mud&lt;/em&gt; or &lt;em&gt;spaghetti code&lt;/em&gt; due to the complicated mess of dependencies. When all the code is co-located, it's common to find a tangled web of paths, with interfaces and facades skipped in favor of direct access to low-level functions and classes. This kind of code is hard to maintain.&lt;/p&gt;

&lt;p&gt;Majestic monoliths are well-structured and loosely coupled, with carefully designed dependencies that are sometimes enforced by architectural tools. By making things modular, you get the benefits often associated with microservices, but without the difficulty of finding the code or the runtime complexity of distributed systems.&lt;/p&gt;

&lt;p&gt;Microservices go a step further by physically separating parts of the system into independently deployable units. In addition to the architectural benefits, you can get faster build and test run times because you only build and test each service when it changes, which involves much less code. The trade-off is that your codebase becomes more complex, and you have to deal with versioning and issue pinpointing across all the deployed services.&lt;/p&gt;

&lt;p&gt;So, how do you choose between these approaches?&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch the episode
&lt;/h2&gt;

&lt;p&gt;You can watch the episode below, or read on to find some of the key discussion points.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=CuFg-Cjib5Q" rel="noopener noreferrer"&gt;Watch Continuous Delivery Office Hours Ep.4&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Architectural decision factors
&lt;/h2&gt;

&lt;p&gt;Many factors influence the decision between monoliths, microservices, and hybrid approaches. One of the most crucial is how your teams are structured and how much autonomy they need. There are different ways to design &lt;a href="https://octopus.com/devops/culture/team-structures/" rel="noopener noreferrer"&gt;team structures&lt;/a&gt;, like Team Topologies, that make your teams and architecture part of the same conversation.&lt;/p&gt;

&lt;p&gt;This is consistent with the &lt;em&gt;inverse Conway maneuver&lt;/em&gt;, in which you structure your teams to match your target architecture. This works because Conway's Law states that organizations design systems that mirror their communication structures. Working at the team level is more effective than creating an architectural diagram, as the structure will naturally yield the design you want.&lt;/p&gt;

&lt;p&gt;Having a mismatch between the number of teams and the number of components can add complexity, either because too many teams are working on a single module, or you have created so many modules that there aren't enough teams to own all the maintenance tasks associated with them. A sensible default is to match the number of teams to the number of components, ensuring sufficient autonomy for each team to work independently without overburdening them with excessive complexity.&lt;/p&gt;

&lt;p&gt;The matching of service and team design sits between monolith and microservices, and might be described as "mescoservices" to highlight the balance they strike between the macro level of monoliths and the fine-grained level of microservices.&lt;/p&gt;

&lt;p&gt;Another factor that can influence your decision is your deployment model. A managed software-as-a-service offering can use microservices without imposing complexity on its customers. In contrast, a self-hosted software offering may benefit from easier installation, troubleshooting, and upgrades if it uses a monolithic architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common microservice failure modes
&lt;/h2&gt;

&lt;p&gt;There are several common failure modes to watch out for when moving to a microservice architecture.&lt;/p&gt;

&lt;p&gt;Distributed monoliths look like microservices, except they have dependencies that mean you have to deploy services in a specific order. If you can't deploy independently, you don't have microservices. Similarly, you often find microservices at the application layer, but all sharing the same database. This prevents independent scaling of high-load services and can cause services to access data directly rather than through the appropriate service.&lt;/p&gt;

&lt;p&gt;When you deploy large numbers of microservices, you may need to introduce rules about which services can communicate. Allowing any service to call any other service means managing a complex web of dependencies, and it starts to look a lot like the proverbial &lt;em&gt;big ball of mud&lt;/em&gt;. This is often the result of splitting a monolith into microservices, as the old design tends to persist.&lt;/p&gt;

&lt;p&gt;Microservices should bring a high level of team independence, allowing teams to make decisions about their own services, persistence, and deployment schedules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pulling microservices together
&lt;/h2&gt;

&lt;p&gt;To make microservices successful, you need to establish data ownership and decide what level of data duplication is acceptable to support the business goals. For example, there's a temptation to store a single address for a customer, but it may be a better idea to store the address immutably against events, like orders. Even if the customer moves house, the address for a past order remains the same.&lt;/p&gt;

&lt;p&gt;Domain-driven design provides a method and a language for making decisions across service boundaries. A principal engineer or architect would usually set standards for service boundaries, contracts, and versioning to help keep services loosely coupled and independently deployable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fitness test
&lt;/h2&gt;

&lt;p&gt;The best test of your service-based architecture is independent deployability. If each team can deploy its services without cross-team coordination, then your architecture is working. For majestic monoliths, the test is similar; teams should be able to work independently on modules they own. While deployments will be coupled through a single build and deployment pipeline, they should be able to make and commit changes independently.&lt;/p&gt;

&lt;p&gt;Happy deployments!&lt;/p&gt;

&lt;p&gt;Continuous Delivery Office Hours is a series of conversations about software delivery, with Tony Kelly, Bob Walker, and Steve Fenton.&lt;/p&gt;

&lt;p&gt;You can find more episodes on &lt;a href="https://www.youtube.com/playlist?list=PLAGskdGvlaw3CrxkUOAMmiy928lr5D4oh" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://podcasts.apple.com/us/podcast/continuous-delivery-office-hours/id1872101651" rel="noopener noreferrer"&gt;Apple Podcasts&lt;/a&gt;, and &lt;a href="https://pca.st/hwjaox59" rel="noopener noreferrer"&gt;Pocket Casts&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>architecture</category>
      <category>software</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Generative AI: A model for acceptance</title>
      <dc:creator>Steve Fenton</dc:creator>
      <pubDate>Mon, 22 Jun 2026 07:19:42 +0000</pubDate>
      <link>https://dev.to/_steve_fenton_/generative-ai-a-model-for-acceptance-3311</link>
      <guid>https://dev.to/_steve_fenton_/generative-ai-a-model-for-acceptance-3311</guid>
      <description>&lt;p&gt;Throughout our history as a species, we have grappled in the quagmire of complexity around the decisions we make. There are ethical, moral, and social impacts to every new development and we continue to navigate this confusing landscape in a process where things constantly shift and no end state is available.&lt;/p&gt;

&lt;p&gt;This article, or perhaps essay, is long. This is necessary to capture the thought process, rather than just the outcome. Just as a student may gain bonus points for a wrong answer that uses the correct method of calculation, I hope we can debate where in this mental exercise the two of us diverge in agreement, rather than having a binary debate about it being entirely &lt;em&gt;right&lt;/em&gt; or &lt;em&gt;wrong&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;My expectation isn't that this is the final version or even that such a version is possible. But as a way to agree on the terms of debate, I believe it will be highly constructive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Regulating the motorwagen
&lt;/h2&gt;

&lt;p&gt;The motor car has been around for over 140 years and we've developed a suite of rules and practices to tackle conflicting interrelated concerns. A set of rules governs almost every aspect of a vehicle's design and use. Some of these are imposed on the manufacturer, others on the driver, and still more on the interaction of vehicles, pedestrians, and the spaces they operate in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm3783xgm0s7kb0wu4fr5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm3783xgm0s7kb0wu4fr5.jpg" alt="The Benz Patent-Motorwagen was the first practical automobile put into production" width="800" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://en.wikipedia.org/wiki/File:1885Benz.jpg" rel="noopener noreferrer"&gt;Wikimedia Commons&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One thing is very clear. 150 years has not been enough to perfect the system and we are still making adjustments as we balance a system that's subject to shifting concerns. There are vast differences in how these systems are governed around the world based on social views, like the priority of vehicles, bicycles, or pedestrians, or balancing personal autonomy with congestion. These social attitudes also shift over time in response to factors like environmental impact, or evolving views of fairness.&lt;/p&gt;

&lt;p&gt;At the time of writing, we seem close to proving that well-designed subsidized public transport is superior to personal transport in many cases. Congested cities are using freeway removal to introduce (or re-introduce) public spaces. This is a complete reversal of policies enacted in the second half of the 20th century, where freeway expansion proliferated.&lt;/p&gt;

&lt;p&gt;If the motorwagen had never been invented, what might our towns and cities look like? It's almost impossible to imagine as so many of us have grown up surrounded by roads, even if we don't own a vehicle. This is the question we must now ask in order to challenge the current state of things and create something better. And it would have been equally challenging for people in 1885 to imagine what the motorwagen would do to their towns, cities, and lifestyle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsnyz3uzfnoacej9css7i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsnyz3uzfnoacej9css7i.jpg" alt="Harbor Drive in Portland, Oregon, is an early example of freeway removal in the US." width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://en.wikipedia.org/wiki/File:Waterfront_Park,_Portland.jpg" rel="noopener noreferrer"&gt;Wikimedia Commons&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading the road ahead
&lt;/h2&gt;

&lt;p&gt;With the historical lesson of the motorwagen firmly in mind, we must now look ahead to imagine what our towns and cities might look like with generative AI. The analogy is apt because, just as with personal transport, the speed and convenience are much celebrated and the harms (emissions, road deaths, environmental impact, congestion, centralization) are far less clear.&lt;/p&gt;

&lt;p&gt;We might find it instructive to look at how the debate took shape in the 1920s, when the harms of motor vehicles were becoming more apparent as motorists began to compete in earnest with the space formerly occupied by people. While both public opinion and that expressed by judges was vastly in favour of the rights of pedestrians, the wealth at the disposal of the motoring minority allowed them to build the rhetorical force to petition for rights against the majority view.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The transformation was not a natural evolution, a side effect of technological progress, the choice of a democratic majority, or the product of a free market.&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;Peter Norton, &lt;a href="https://thereader.mitpress.mit.edu/when-cities-treated-cars-as-dangerous-intruders/" rel="noopener noreferrer"&gt;MIT Press&lt;/a&gt;.&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And now we must transfer these lessons to the subject of generative AI, a term we use to refer to the class of tools that build models based on training data, and generate text, image, audio, and video output based on these models in response to prompts that do not precisely determine the output.&lt;/p&gt;

&lt;h2&gt;
  
  
  A model concerning utility and harms
&lt;/h2&gt;

&lt;p&gt;Much of the conversation  around generative AI has been polarized into extremes labelled &lt;em&gt;hype&lt;/em&gt; and &lt;em&gt;hate&lt;/em&gt; to describe those with a positive or negative view of generative AI. We can certainly draw a comparison between pedestrians and motorists in this respect, though how large the minority is when compared to the majority is less clear.&lt;/p&gt;

&lt;p&gt;In fact, we might imagine the situation before the 1920s, when the motorwagen was a novelty and the true picture of the utility and harms were not yet clear. What model could have been used to integrate this new form of transport into society with the least harm?&lt;/p&gt;

&lt;p&gt;This is what I have grappled with as a technologist and creator trying to navigate the utility and harms of generative AI. It becomes impossible to think clearly of the utility when the harms are so obvious. This is why so many people have chosen to simply ignore the harms, or reject the technology.&lt;/p&gt;

&lt;p&gt;There may be a middle path, which is the assumption I am working with. It might also be the case that there is no middle path and we must choose to embrace without remorse or reject entirely the whole concept of generative AI (a choice many have already made, which is either premature or correct depending on which polar opposite was selected).&lt;/p&gt;

&lt;p&gt;The middle-ground solution I propose involves building around some questions I believe to be central to the discussion:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What harms do we see now, or predict in the future, that we could avoid?&lt;/li&gt;
&lt;li&gt;Who is responsible for each of these harms and could they take action now rather than in response to controversy and backlash?&lt;/li&gt;
&lt;li&gt;If there were no harms, what use could we make of this technology and it is fit for such purposes?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It appears on the surface that this lands closer to the "reject entirely" extreme position, but that's a deliberate choice. My perspective is that if we could find a path of minimal harm, we could focus on what utility generative AI has. While the harms are glaringly obvious, it is hard to imagine a level of utility that justifies the level of harm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Model of harms for the motorwagen
&lt;/h3&gt;

&lt;p&gt;We can  illustrate this with the motor vehicle example, then build a model for generative AI. We are a century beyond the flashpoint with motor vehicles, so we can be more circumspect in our treatment of the model. This will help us keep a clear head as we continue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source&lt;/strong&gt;: How are vehicles built and what materials does this process consume? What are the benefits and drawbacks of building a factory in a town? Are innovative design elements created by competitors appropriately licensed?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preparation&lt;/strong&gt;: What design elements could make the vehicle safe for motorists and other people occupying the same space as motor vehicles, like pedestrians and cyclists? How might consumable parts of the vehicle, like lightbulbs, lubricant, and brake pads, be replaced by the motorist?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Application&lt;/strong&gt;: How will the vehicle be used and how do other members of society respond to this use? Commuting and leisure travel is socially accepted while street cruising and causing an obstruction are considered anti-social. In some cases, the intent behind the application can be as important as the application itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outcome&lt;/strong&gt;: What do we achieve with the motor vehicle and what unanticipated outcomes result from this use? For example, we discovered vehicle emissions degrade local air quality and cause environmental damage. We also created a dependence on oil prices for everything that must be transported from farms and factories to stores and customers.&lt;/p&gt;

&lt;p&gt;The classification of harms allows us to assign responsibility, with regulators and government stepping up where required to create the rules and laws to ensure fairness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source&lt;/strong&gt; and &lt;strong&gt;preparation&lt;/strong&gt; are the responsibility of the manufacturer and their suppliers. The joint enterprise of this supply chain must be considered to prevent an end-supplier burying harms upstream in the production process.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;application&lt;/strong&gt; is the responsibility of the motorist. They must choose to travel at appropriate speeds based on signage and driving conditions. They decide how they drive and where they park their car. Motorists negotiate their use with society at various distances. They may decide they don't want to use their motor vehicle for short journeys, they might negotiate with neighbors to agree how they each park in a shared area, or the negotiations may be the result of a collective road safety campaign to reduce a speed limit near a school.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;outcome&lt;/strong&gt; is collectively owned. This is a process whereby we discover harms and seek their resolution. This will often bring an individual with little power up against a larger more powerful entity. Unanticipated harms often require city or state intervention to ensure a resolution, such as the introduction of pedestrianized high streets, or the ban on lead-based petroleum.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;Manufacturers&lt;/th&gt;
&lt;th&gt;Motorists&lt;/th&gt;
&lt;th&gt;Society&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Source&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Preparation&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Application&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outcome&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Removal of harm enables participation
&lt;/h3&gt;

&lt;p&gt;Removing harms invites broader participation and reduces the need for city and state authorities to regulate. With this model, you could say:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If the manufacturers resolved all major harms in the source and preparation of a vehicle:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;I will try being a motorist to see what utility a motor vehicle brings&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;I will negotiate with others how motorists and non-motorists co-exist&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;We will collectively look for new harms and pressure those responsible to remove them, and pressure authorities to remove them if those responsible neglect their duty&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Specifically, if we can now begin to move to the topic of generative AI, as a technologist who has always enjoyed trying new ideas, techniques, and technologies, I would be able to commit to experimenting with generative AI to discover its utility in depth, and could participate in the social process to determine where we accept its use and where we don't.&lt;/p&gt;

&lt;p&gt;My gut feeling is that generative AI has utility if the harms were to be removed, including those we haven't uncovered yet. For example, I have seen positive examples of generative AI being used to assist people through assistive technology. Even so, I'm convinced that I don't want to read books or articles written using generative AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model of harms for generative AI
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;Model providers&lt;/th&gt;
&lt;th&gt;Model users&lt;/th&gt;
&lt;th&gt;Consumers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Source&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Preparation&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Application&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outcome&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Source&lt;/strong&gt;: Where does the data come from? Does it contain bias or inaccuracy? Do we have permission to use the data?&lt;/p&gt;

&lt;p&gt;Examples of specific harms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Models trained on copyrighted work without license or permission, exacerbated by generative AI directly competing against the works contained in its training data&lt;/li&gt;
&lt;li&gt;Collecting data from users without their consent for use in training, for example by using their profile and conversation data with their explicit agreement&lt;/li&gt;
&lt;li&gt;Using data sources that contain hate speech, false information, or bias&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Preparation&lt;/strong&gt;: How do we detect and correct mistakes and bias? What resources do we consume during preparation? What are the local and global impacts of our operation?&lt;/p&gt;

&lt;p&gt;Examples of specific harms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use of power and water for datacenters used in the training process, affecting access to these resources for local populations&lt;/li&gt;
&lt;li&gt;The global environmental impact of the supply chain for datacenters&lt;/li&gt;
&lt;li&gt;Subsidizing the technology to artificially lower its cost to build a dependency prior to increasing costs or reducing what people get for their subscription level&lt;/li&gt;
&lt;li&gt;Exploiting low-paid workers during the training process, for example to label data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Application&lt;/strong&gt;: What is our motivation for using generative AI? Is the use appropriate? Do we discover the use of generative AI? Does what we produce meet our existing quality standards? Are we misleading people? If a person did this, would we accept it? What value exists in the work beyond the generated output?&lt;/p&gt;

&lt;p&gt;Examples of specific harms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using generative AI to make decisions without disclosing it and without providing an easy way to appeal the decision&lt;/li&gt;
&lt;li&gt;Using generative AI to misrepresent skills and abilities&lt;/li&gt;
&lt;li&gt;Using generative AI to save yourself time at the expense of other people's time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Outcome&lt;/strong&gt;: Is the output correct? What should we check before we call this done? What unintended consequences result from this?&lt;/p&gt;

&lt;p&gt;Examples of specific harms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lowering the value of works by real creators and artists by spreading suspicion that work was done by generative AI&lt;/li&gt;
&lt;li&gt;Reducing the ability for users of generative AI to develop skills and solve problems without the technology&lt;/li&gt;
&lt;li&gt;Lowering the bar for quality by normalizing poorly completed work tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical use of the model
&lt;/h2&gt;

&lt;p&gt;The model isn't final and the examples are illustrative, but we can now build a path forward. Based on the current examples, I could create a generative AI model using my own data, or data I've obtained permission to use for this purpose. During the preparation, I would use ecologically sound infrastructure and perform checks to identify sources that may pollute my model with inaccuracy or bias.&lt;/p&gt;

&lt;p&gt;When the model is put to use, I use it to crawl through my photographs and apply labels based on what is found in each image. The tags allow me to search my photographs when I need to find something, instead of scrolling through a huge collection of thumbnails.&lt;/p&gt;

&lt;p&gt;In this example, we've taken care to limit the known harms across all categories and responsibilities. The source, preparation, and application of the generative AI deal with known harms and the outcome has high utility. There may still be unintended harms, and we will tackle them as we identify them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it works
&lt;/h2&gt;

&lt;p&gt;The generative AI debate is highly charged and has quickly polarized into the hypers and haters, with each extreme focusing entirely on a single element. The hypers ignore the harms, and the haters dismiss all utility. While some will remain pinned to the extreme, I'm interested in advancing the debate to enable us to tackle the harms and test the true utility.&lt;/p&gt;

&lt;p&gt;The model is the mechanism to provide the path forward. It doesn't dismiss the harms, but actively surfaces them and offers them to those responsible to resolve, just as we asked motor vehicle manufacturers to make cars safer and motorists to drive responsibly. When manufacturers and motorists fail to meet the standards society demands, we ask authorities to intervene.&lt;/p&gt;

&lt;p&gt;Meanwhile, we choose our own relationship with motor vehicles within the agreed legal and social contracts, using them where we decide they are useful.&lt;/p&gt;

&lt;p&gt;Because our understanding and empathy shift all the time in society, we may one day decide that personal transportation isn't the appropriate solution to our transport needs. We might make a personal decision, or we might make structural changes to public transport and city design that affect everyone. These changes don't necessarily eliminate motor vehicles, but they can alter how we structure their use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get involved
&lt;/h2&gt;

&lt;p&gt;You can get involved in this project in various ways. I'm keen to obtain feedback from hypers and haters. I understand these terms are loaded, but I'm not judging the pragmatism of either group. Your thoughts on this model would be incredibly valuable. I'm also keen to find people who, like me, would enjoy experimenting if only the harms could be removed.&lt;/p&gt;

&lt;p&gt;For feedback on the model, I would appreciate understanding not only what you disagree with, but if there are any aspects you agree with. If you feel very strongly about what I've written, you may be tempted to aim for concision through bifurcation, but I'm seeking a more profound understanding of different perspectives and that will require a longer and more thoughtful explanation on your part. I'm grateful for your additional effort in this respect.&lt;/p&gt;

&lt;p&gt;Depending on the feedback, I may adjust the model or we may all reach the conclusion that it must be discarded and something new must be created to answer these questions. We will follow the wisdom of George Box; "All models are wrong, but some are useful." If the model proves useful, we will continue the work. If it turns out to have limited utility, our efforts can be directed elsewhere.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/Steve-Fenton/generative-ai-harms" rel="noopener noreferrer"&gt;generative-ai-harms&lt;/a&gt; GitHub repository will allow us to collaborate using discussions and pull requests.&lt;/p&gt;

&lt;p&gt;So, what do you think?&lt;/p&gt;

</description>
      <category>ai</category>
    </item>
    <item>
      <title>Continuous Delivery Office Hours Ep.3: Branching strategies</title>
      <dc:creator>Steve Fenton</dc:creator>
      <pubDate>Mon, 15 Jun 2026 12:09:50 +0000</pubDate>
      <link>https://dev.to/_steve_fenton_/continuous-delivery-office-hours-ep3-branching-strategies-4d8k</link>
      <guid>https://dev.to/_steve_fenton_/continuous-delivery-office-hours-ep3-branching-strategies-4d8k</guid>
      <description>&lt;p&gt;Your branching strategy can support Continuous Delivery, or make it an impossible goal. You should assess the impact of how you branch on your ability to deliver software at all times, and you'll find some branching techniques that work, while others that make software delivery more like walking in the dark through a field of rakes.&lt;/p&gt;

&lt;p&gt;Continuous Integration is the practice of integrating code changes frequently, typically multiple times a day. This means you should check your code multiple times a day and keep your main branch deployable. Continuous Integration is a prerequisite for Continuous Delivery.&lt;/p&gt;

&lt;p&gt;The name "Continuous Integration" provides solid hints about the crucial parts of the practice. Everyone should &lt;em&gt;integrate&lt;/em&gt; their code into a shared branch (feature branches don't count) and this should be done &lt;em&gt;continuously&lt;/em&gt;, which means you're doing it all the time; at least once a day, but ideally more often.&lt;/p&gt;

&lt;p&gt;You'll often speak to developers who want to stretch the definition of Continuous Integration, but you can't escape those foundations. Merging the main branch into a long-lived branch feels like Continuous Integration, but you'll notice no changes come back for ages until someone finally merges to main. Then you have to perform a large, complex merge, which you should avoid.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dora.dev/capabilities/continuous-delivery/" rel="noopener noreferrer"&gt;DORA research on Continuous Delivery&lt;/a&gt; includes the capabilities of Continuous Integration and trunk-based development. The statistics suggest you can get similar benefits as long as you limit yourself to 3 (or fewer) short-lived branches (less than a day old).&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch the episode
&lt;/h2&gt;

&lt;p&gt;You can watch the episode below, or read on to find some of the key discussion points.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=WDHZAHGxpR8" rel="noopener noreferrer"&gt;Watch Continuous Delivery Office Hours Ep.3&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The worst branching strategy
&lt;/h2&gt;

&lt;p&gt;Since the ability to branch code was invented, developers have applied a great deal of creativity to how to use branches. The most common approach is feature branching, where each feature gets a branch of main that evolves separately until the feature is complete, and it's merged back into main. Release branching allows development to continue on main by taking a cut of the main branch that will be released. This allows hotfixes to be applied to the release branch without further destabilizing it.&lt;/p&gt;

&lt;p&gt;The utility of branching strategies is often eroded by the coordination overhead of maintaining the separate branches and merging different changes back together. The more complex the branching strategy, the more likely it is that you'll have merge conflicts and lost bug fixes. For example, you might fix a release branch and forget to merge the fix back to main, so the next release reintroduces the bug.&lt;/p&gt;

&lt;p&gt;This is why the worst branching strategy is Gitflow. This is a complicated branching strategy that creates dedicated branches for features, releases, and hotfixes alongside permanent main and develop branches. The overhead of Gitflow vastly outweighs its benefits.&lt;/p&gt;

&lt;p&gt;This is where trunk-based development shines, as it removes unnecessary complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  The best strategy is trunk-based development
&lt;/h2&gt;

&lt;p&gt;Trunk-based development is the process of making all commits directly to the main branch. This is complemented by out-of-band reviews that don't block merging and by feature toggles that decouple deployments from releases. It should be possible to deploy your software from the main branch at all times, even if features aren't complete.&lt;/p&gt;

&lt;p&gt;The DORA research allows up to 3 short-lived branches, which can be useful for teams working remotely (like open-source project teams), who can use branches and pull requests to coordinate their work. Even so, the goal is to keep branches short-lived and to merge frequently.&lt;/p&gt;

&lt;p&gt;Trunk-based development is complemented by automated builds and checks that run when code is committed to the main branch. If a problem is found during these checks, the team should prioritize the fix over other development work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Elite performance comes from small batches
&lt;/h2&gt;

&lt;p&gt;Teams with the best software delivery performance work in small steps. Trunk-based development and Continuous Integration are crucial practices for controlling batch size. Problems are discovered sooner and are easier to fix when you only have a small amount of change to reason about.&lt;/p&gt;

&lt;p&gt;Making frequent commits makes it easy to back out a bad change. If a test fails, you can discard changes since the last commit and try again, instead of trying to debug the problem. This is especially true when using AI coding assistants or other code generation techniques.&lt;/p&gt;

&lt;p&gt;Ultimately, for trunk-based development to succeed without friction, the entire team must be aligned on the process. It doesn't work if only some of the team are on board.&lt;/p&gt;




&lt;p&gt;Continuous Delivery Office Hours is a series of conversations about software delivery, with Tony Kelly, Bob Walker, and Steve Fenton.&lt;/p&gt;

&lt;p&gt;You can find more episodes on &lt;a href="https://www.youtube.com/playlist?list=PLAGskdGvlaw3CrxkUOAMmiy928lr5D4oh" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://podcasts.apple.com/us/podcast/continuous-delivery-office-hours/id1872101651" rel="noopener noreferrer"&gt;Apple Podcasts&lt;/a&gt;, and &lt;a href="https://pca.st/hwjaox59" rel="noopener noreferrer"&gt;Pocket Casts&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>software</category>
      <category>git</category>
    </item>
  </channel>
</rss>
