<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><id>https://sebastiandedeyne.com/index.xml</id><link href="https://sebastiandedeyne.com/index.xml" rel="self"/><title>Information Overload</title><subtitle>Thoughts &amp; references from an engineering manager in Belgium</subtitle><updated>2026-04-10T11:31:29+02:00</updated><author><name>Sebastian De Deyne</name><email>sebastiandedeyne@gmail.com</email></author><entry><title>How I write feature specs</title><link rel="alternate" href="https://sebastiandedeyne.com/how-i-write-feature-specs"/><id>https://sebastiandedeyne.com/how-i-write-feature-specs</id><author><name>Sebastian De Deyne</name><email>sebastiandedeyne@gmail.com</email></author><updated>2026-04-10T11:31:29+02:00</updated><content type="html"><![CDATA[<p>I&rsquo;m not good at blank canvases. Unfortunately that&rsquo;s where feature specs always start. When I have a bunch of notes, transcripts, screenshots, and ideas to consolidate on an empty piece of paper, it can be hard to get going and stay in flow.</p>
<p>I write specs in three steps:</p>
<ol>
<li>Collect all input</li>
<li>Consolidate a cohesive list of requirements</li>
<li>Review &amp; edit</li>
</ol>
<p>Lately, I&rsquo;ve added a few tools to my workflow to guide me through the process.</p>
<h2 id="collecting-input">
  <a href="#collecting-input" class="heading-permalink" aria-label="Permalink to Collecting input"></a>
  Collecting input
</h2>
<p>First, I gather every piece of input I can find: my own notes, Slack threads, Linear tickets… One of my most useful resources is <a href="https://granola.ai">Granola</a>, which transcribes and summarizes every meeting I have. I organize projects into folders there, and before writing a spec, I&rsquo;ll ask Granola to pull together everything it knows about the topic.</p>
<p class="text-sm italic text-gray-500">(All snippets in this post are based on the output I had writing a spec yesterday. I can't share it since it's client work, but I've reworked the examples to revolve around an invoice builder feature.)</p>
<pre><code class="language-output-wrap">Give me a detailed list of specifications of everything you know of the invoice builder.
</code></pre>
<p>I also use <a href="https://monologueapp.com">Monologue</a>, a voice-to-text tool for Mac and iOS, to add extra ramblings.</p>
<h2 id="consolidating-everything-with-a-thinking-model">
  <a href="#consolidating-everything-with-a-thinking-model" class="heading-permalink" aria-label="Permalink to Consolidating everything with a thinking model"></a>
  Consolidating everything with a thinking model
</h2>
<p>Once I have everything in one place, I open my coding agent and attach everything. <em>(Currently defaulting to Codex GPT 5.4 High for these kinds of tasks.)</em></p>
<p>A few things I&rsquo;ve learned to always include in the prompt:</p>
<ul>
<li><strong>Be explicit about who the spec is for.</strong> A spec for a designer should focus on UI patterns and how the feature fits existing conventions in the app. A spec for a developer should go deeper on the data model, potential abstractions, and how this interacts with existing parts of the system.</li>
<li><strong>Ask to compare notes and surface discrepancies.</strong> Notes accumulated over months are full of contradictions. One meeting says to build it one way; another says something different. I ask the model to flag these and <a href="https://sebastiandedeyne.com/grill-me">grill me</a> on them until the ambiguity is resolved.</li>
<li><strong>Ask to explicitly list what is in &amp; out of scope.</strong> As I read notes I often skim over things that are implicitly out of scope for the project. But what <em>I</em> consider out of scope, someone else might have assumed was part of the project. AI is good at being critical about these small details.</li>
<li><strong>Reference the codebase.</strong> Look at what already exists for patterns we could reuse, and identify potential pitfalls based on existing functionality.</li>
</ul>
<p>Some of these checks might seem obvious, but the more explicit you are towards the agent about your own process, the better your results.</p>
<p>If all goes well, you&rsquo;ll be slammed with a few rounds of questions by the agent to refine the requirements and generate a final specification document.</p>
<p>This was my prompt yesterday:</p>
<pre><code class="language-output-wrap">I want to write a specification document for our designer to determine the UI and UX of the invoice builder. I want you to read all three documents I gave you. Grill me about anything that is unclear about the features or things across the document or even in the same document that contradicts each other. Grill me about anything that seems related to invoicing that is listed in documents but might not be part of this feature so we can decide to leave them out of the specs for now. Let's build a specification document together. Also look through the existing codebase and interface to understand the way products are set up and research potential pitfalls we could have implementing this in the existing system.
</code></pre>
<p class="mt-0 text-sm italic text-gray-500">(text-to-speech, who needs newlines?)</p>
<p>Here&rsquo;s a snippet of the output:</p>
<pre><code class="language-output"># Invoice Builder UI/UX Spec

## Purpose

Define the UI and UX for configuring and reviewing invoice templates, line items, and tax calculations within the invoice builder.

This document covers three surfaces:

- Organization-level setup
- Invoice-level review and override
- Discrepancy review and bulk reapply

This document is intended for product, design, and engineering alignment. It describes the behavior the interface must support, not the technical implementation details.

## Scope

### In scope

- Organization-level setup of tax rules, line item defaults, and payment terms
- Invoice-level display of the itemized breakdown associated with an order
- Invoice-level snapshotting from the organization template
- Invoice-level manual editing after snapshotting
- Visibility rules for clients, bookkeepers, and admins
- Discrepancy review UI for tax rate and line item drift
- Batch reapply flow from the current organization template to selected invoices

### Out of scope

- Payment processing or reconciliation
- Refunds
- Revenue recognition timing or accrual logic
- Report-generation workflows beyond discrepancy review
- Currency-specific tax logic
- Arbitrary reusable custom pricing objects
- Auditing payment term discrepancies

## Core Concepts

### Tax Calculation

Tax calculation is the applicable tax percentage for an organization in a given region or jurisdiction scope.

- Tax calculation belongs on the organization as a template
- Tax calculation is copied to the invoice when the invoice is created
- After the invoice is created, the invoice tax calculation is managed independently
- Clients should always be able to see their own tax breakdown
- Seeing the tax details of others requires a specific permission, which in practice is reserved for bookkeepers and admins
…
</code></pre>
<p>The content looks good on first sight but I don&rsquo;t like the way it&rsquo;s structured &amp; formatted. Time to edit.</p>
<h2 id="reviewing--editing">
  <a href="#reviewing--editing" class="heading-permalink" aria-label="Permalink to Reviewing &amp; editing"></a>
  Reviewing &amp; editing
</h2>
<p>At this point, I take a break from the AI tooling and re-read and edit everything in <a href="https://ia.net/writer">iA Writer</a>. Most importantly, I ensure everything is correct &amp; complete. Then I ensure the document is generally structured the way I want it to flow, cut noise &amp; repetition, and ensure everything&rsquo;s as clear as can be.</p>
<p>Then I throw it in <a href="https://app.writewithspiral.com/">Spiral</a> for another edit. I like how Spiral lets you edit with AI without AI taking over your writing. Spiral allows you to define &ldquo;styles&rdquo;. I created a style based on previous specs I&rsquo;ve written in the past so the specs can be re-edited into something closer to my voice.</p>
<p>Depending on who or what I&rsquo;m writing the specs for, I sometimes prefer a &ldquo;document style&rdquo;, and sometimes a &ldquo;single indented list&rdquo; style. In Spiral, I have some predefined prompts to toggle between the two formats.</p>
<pre><code class="language-output">- In scope
    - Organization-level setup of tax rules, line item defaults, and payment terms
    - Invoice-level display of the itemized breakdown associated with an order
    - Invoice-level snapshotting from the organization template
    - Invoice-level manual editing after snapshotting
    - Visibility rules for clients, bookkeepers, and admins
    - Discrepancy review UI for tax rate and line item drift
    - Batch reapply flow from the current organization template to selected invoices
- Out of scope
    - Payment processing or reconciliation
    - Refunds
    - Revenue recognition timing or accrual logic
    - Report-generation workflows beyond discrepancy review
    - Currency-specific tax logic
    - Arbitrary reusable custom pricing objects
    - Auditing payment term discrepancies
- Core concepts
    - Tax Calculation
        - Applicable tax percentage for an organization in a given region or jurisdiction scope
        - Belongs on the organization as a template; copied to the invoice at creation
        - After creation, managed independently from the organization record
        - Clients can always see their own tax breakdown
        - Seeing another client's tax details requires a specific permission
…
</code></pre>
<p>When I&rsquo;m done editing, I do one final review in iA Writer and it&rsquo;s good to go.</p>
<h2 id="has-ai-made-my-output-better">
  <a href="#has-ai-made-my-output-better" class="heading-permalink" aria-label="Permalink to Has AI made my output better?"></a>
  Has AI made my output <em>better</em>?
</h2>
<p>Three or four months ago, without a model to consolidate &amp; guide me with questions, writing this spec probably would have taken 3–4 hours. It took me about an hour and a half yesterday.</p>
<p>But the quality of my output hasn&rsquo;t really changed much. AI models are good at surfacing small details that might otherwise be overlooked, but at that level of detail it makes things <em>slightly</em> better, not orders of magnitude.</p>
<p>What&rsquo;s changed is that I&rsquo;m never staring at a blank document. The tools give me structure to work reactively and keep working in flow.</p>]]></content></entry><entry><title>Grill Me</title><link rel="alternate" href="https://sebastiandedeyne.com/grill-me"/><id>https://sebastiandedeyne.com/grill-me</id><author><name>Sebastian De Deyne</name><email>sebastiandedeyne@gmail.com</email></author><updated>2026-04-10T11:02:22+02:00</updated><content type="html"><![CDATA[<p>Matt Pocock shared a <code>/grill me</code> agent skill:</p>
<blockquote>
<p>Interview me relentlessly about every aspect of this plan until
we reach a shared understanding. Walk down each branch of the design
tree resolving dependencies between decisions one by one.</p>
<p>If a question can be answered by exploring the codebase, explore
the codebase instead.</p>
<p>For each question, provide your recommended answer.</p>
</blockquote>
<p>Incredibly simple, but the times I&rsquo;ve used it so far it has been incredibly effective. <em>(Almost annoyingly considering the amount of follow up questions you get; for a good cause!)</em></p>
]]></content></entry><entry><title>Current RSS reader</title><link rel="alternate" href="https://sebastiandedeyne.com/current-rss-reader"/><id>https://sebastiandedeyne.com/current-rss-reader</id><author><name>Sebastian De Deyne</name><email>sebastiandedeyne@gmail.com</email></author><updated>2026-04-09T09:10:15+02:00</updated><content type="html"><![CDATA[<p>I&rsquo;ve recently switched to Current as my main RSS reader. <a href="https://reederapp.com/">Reeder</a> will always have a place in my heart, but at some point you get to so much unread stuff that it becomes a chore to get through.</p>
<p>Current solves this with <em>&ldquo;the river&rdquo;</em>.</p>
<blockquote>
<p>The main screen is a river. Not a river that moves on its own. You&rsquo;re not watching content drift past like a screensaver. It&rsquo;s a river in the sense that matters: content arrives, lingers for a time, and then fades away.</p>
<p>Each article has a velocity, a measure of how quickly it ages. Breaking news burns bright for three hours. A daily article stays relevant for eighteen. An essay lingers for three days. An evergreen tutorial might sit in your river for a week.</p>
</blockquote>
<p>Outlets like The Verge have always been frustrating to follow with RSS because they generate 20+ posts a day and take over your feed. Essays from my favorite blogs often only appear once every few weeks and drown between the noise. The river balances them all out.</p>
<p>Current is made by Terry Godier. He also wrote <a href="https://www.terrygodier.com/current">a beautiful essay</a> on the design decisions he made building it.</p>
]]></content></entry><entry><title>Impact, agency, and taste</title><link rel="alternate" href="https://sebastiandedeyne.com/impact-agency-and-taste"/><id>https://sebastiandedeyne.com/impact-agency-and-taste</id><author><name>Sebastian De Deyne</name><email>sebastiandedeyne@gmail.com</email></author><updated>2026-04-08T10:03:32+02:00</updated><content type="html"><![CDATA[<p>If I were to share some thoughts on making a meaningful impact at work, Ben Kuhn&rsquo;s post would be it. His essay had me nodding yes, yes!, and YES! throughout, and it&rsquo;s written more eloquently than I ever could.</p>
<blockquote>
<p>Don’t rely too much on permission or encouragement. […] instead of asking people for approval to go do something, you can just tell them what you intend to do (implicitly giving them space to object or course-correct if they feel strongly).</p>
</blockquote>
<p>You can just do things.</p>
<blockquote>
<p>Make success inevitable. There’s a huge difference between the following two operating modes:</p>
<ol>
<li>My goal is to ship this project by the end of the month, so I’m going to get people started working on it ASAP.</li>
<li>My goal is to ship this project by the end of the month, so I’m going to list out everything that needs to get done by then, draw up a schedule working backwards from the ship date, make sure the critical path is short enough, make sure we have enough staffing to do anything, figure out what we’ll cut if the schedule slips, be honest about how much slop we need, track progress against the schedule and surface any slippage as soon as I see it, pull in people from elsewhere if I need them…</li>
</ol>
</blockquote>
<p>The hard part is being honest with <em>yourself</em>. I&rsquo;ve often fallen into trap (1) because I&rsquo;m afraid my plan will surface failure.</p>
<p>On taste:</p>
<blockquote>
<p>I’ve noticed a lot of people underestimate their own taste, because they expect having good taste to feel like being very smart or competent or good at things. […] For this reason, the prompt I suggest here is: <em>what does it seem like everyone else is mysteriously bad at?</em></p>
</blockquote>
<p>Taste isn&rsquo;t about being the best at something. It&rsquo;s about slowly lifting the whole by leaving small things in better shape than you found them.</p>
]]></content></entry><entry><title>In Praise of –dry-run</title><link rel="alternate" href="https://sebastiandedeyne.com/in-praise-of-dry-run"/><id>https://sebastiandedeyne.com/in-praise-of-dry-run</id><author><name>Sebastian De Deyne</name><email>sebastiandedeyne@gmail.com</email></author><updated>2026-04-07T09:39:40+02:00</updated><content type="html"><![CDATA[<p>Henrik Warne on the <code>--dry-run</code> flag:</p>
<blockquote>
<p>Early in the development process, when testing the incomplete application, I remembered that Subversion (the version control system after CVS, before Git) had a –dry-run option. Other linux commands have this option too. If a command is run with the argument –dry-run, the output will print what will happen when the command is run, but no changes will be made. This lets the user see what will happen if the command is run without the –dry-run argument.</p>
</blockquote>
<p>I&rsquo;ve added a <code>--dry-run</code> flag on scary destructive stuff I&rsquo;m planning to run on prod. But not as often as I&rsquo;ve wanted.</p>
<blockquote>
<p>The downside is that the dryRun-flag pollutes the code a bit. In all the major phases, I need to check if the flag is set, and only print the action that will be taken, but not actually doing it.</p>
</blockquote>
<p>This is one of the things that has become less of a downside with AI writing more code for us. AI helps us write code faster, but what especially entices me is having more breathing room to add affordances like this.</p>
]]></content></entry><entry><title>The gold standard of optimization: A look under the hood of RollerCoaster Tycoon</title><link rel="alternate" href="https://sebastiandedeyne.com/the-gold-standard-of-optimization-a-look-under-the-hood-of-rollercoaster-tycoon"/><id>https://sebastiandedeyne.com/the-gold-standard-of-optimization-a-look-under-the-hood-of-rollercoaster-tycoon</id><author><name>Sebastian De Deyne</name><email>sebastiandedeyne@gmail.com</email></author><updated>2026-04-06T22:39:40+02:00</updated><content type="html"><![CDATA[<p>RollerCoaster Tycoon, a classic game from 1999 is still worth dissecting for its performance to this day. First a quick primer on bit shifting (new to me—I&rsquo;m used to high level languages!):</p>
<blockquote>
<p>What the <code>&lt;&lt;</code> operator does here [<code>NewValue = OldValue &lt;&lt; 2</code>] is called bit shifting, meaning all the bits that store the value of the variable are shifted to the left, in this case by two positions, with the new digits being filled in with zeros. Since the number is stored in a binary system, every shift to the left means the number is doubled.</p>
</blockquote>
<p>Since this is a lot faster than multiplication, Chris Sawyer decided to exploit this as much as possible:</p>
<blockquote>
<p>The even more interesting point about those calculations, however, is how often the code is able to do this. Obviously, bit shifting can only be done for multiplications and divisions involving a power of two, like 2, 4, 8, 16, etc. The fact that it is done that often indicates that the in-game formulas were specifically designed to stick to those numbers wherever possible, which in most modern development workflows is basically an impossibility.</p>
</blockquote>
<p>I do want to disagree with that last bit. Impossibility sounds too harsh. We can&rsquo;t decide the requirements for stakeholders, but plenty of things aren&rsquo;t as set in stone as they seem. It&rsquo;s our job to nudge things in the right direction, so the result works with the grain of our programs.</p>
]]></content></entry><entry><title>MarkerHighlight.js</title><link rel="alternate" href="https://sebastiandedeyne.com/marker-highlight-js"/><id>https://sebastiandedeyne.com/marker-highlight-js</id><author><name>Sebastian De Deyne</name><email>sebastiandedeyne@gmail.com</email></author><updated>2026-04-03T16:42:13+02:00</updated><content type="html"><![CDATA[<p>I love digital tools that have some analog look or feel to them. <em>(Speaking as an <a href="https://app.excalidraw.com/">Excalidraw</a> super user.)</em> Going to have to find an excuse to use this beauty!</p>
<img src="https://sebastiandedeyne.com/media/marker-highlight-js.webp" alt="MarkerHighlight.js">]]></content></entry><entry><title>Agent Responsibly</title><link rel="alternate" href="https://sebastiandedeyne.com/agent-responsibly"/><id>https://sebastiandedeyne.com/agent-responsibly</id><author><name>Sebastian De Deyne</name><email>sebastiandedeyne@gmail.com</email></author><updated>2026-04-03T10:59:01+02:00</updated><content type="html"><![CDATA[<p>How to multiply your shipping cadence while using agents responsibly. Matthew Binshtok on the Vercel blog:</p>
<blockquote>
<p>There is a fundamental difference between relying on AI and leveraging it.</p>
<ul>
<li>Relying means assuming that if the agent wrote it and the tests pass, it&rsquo;s ready to ship. The author never builds a mental model of the change. The result is massive PRs full of hidden assumptions that are impossible to review because neither the author nor the reviewer has a clear picture of what the code actually does.</li>
<li>Leveraging means using agents to iterate quickly while maintaining complete ownership of the output. You know exactly how the code behaves under load. You understand the associated risks. You&rsquo;re comfortable owning them.</li>
</ul>
</blockquote>
<p>I&rsquo;ve seen a lot of strong opinions about disclosing whether code in a PR was written by hand or generated by AI. I don&rsquo;t really care. The author owns the code in the first place. The author and reviewer have a shared responsibility for what happens on production.</p>
<blockquote>
<p>Putting your name on a pull request means &ldquo;I have read this and I understand what it does.&rdquo; If you have to re-read your own PR to explain how it might impact production, the engineering process has failed.</p>
<p>The litmus test is simple: would you be comfortable owning a production incident tied to this pull request?</p>
</blockquote>
]]></content></entry><entry><title>Flood Fill vs the Magic Circle</title><link rel="alternate" href="https://sebastiandedeyne.com/flood-fill-vs-the-magic-circle"/><id>https://sebastiandedeyne.com/flood-fill-vs-the-magic-circle</id><author><name>Sebastian De Deyne</name><email>sebastiandedeyne@gmail.com</email></author><updated>2026-04-02T21:28:02+02:00</updated><content type="html"><![CDATA[<p>Musings from Robin Sloan:</p>
<blockquote>
<p>Most olive oil production at medium-or-greater scale depends on machines of this kind [over-the-row olive harvester]; they trundle over trees planted in long rows, almost like continuous hedges, and collect the fruit with vibrating fingers. Machine-harvested olives cost less to buy, and they arrive at the mill in better shape than olives harvested by hand.</p>
<p>The catch: most olives can’t be cultivated in this configuration; the trees don’t thrive so close together. Only a handful of varieties will tolerate it, so those handful have been planted in huge numbers, and the flavor of global olive oil has changed as a result.</p>
</blockquote>
<p>AI enables us to do things faster, and sometimes better than we&rsquo;ve been able to before. But it has its limits. And as we learn those limits, the work we do will shift to avoid them.</p>
<p>In a different section, the article dives into the limitations of the physical world.</p>
<blockquote>
<p>The project cut across several different magic circles — Ruby code, quasi-governmental APIs, the rules and standards of the postal system — but/and it also broke out into the physical world of paper, printers, and post offices. The project required manipulations including but not limited to: folding, peeling, sticking … gnarly!!</p>
<p>It’s possible that an AI coding agent could have helped me with #1 above, and of course it could have advised me on the rest. But it’s impossible to imagine the AI agent handling #2-5 autonomously; it would require such a Rube Goldberg tangle of support that “autonomously” would no longer apply.</p>
</blockquote>
<p>In our programming world, AI&rsquo;s impact looks limitless. But once you drift outside the boundaries of software, it&rsquo;s put into a different perspective.</p>
<blockquote>
<p>If indeed AI automation does not flood fill the physical world, it will be because the humble paper jam stood in its way.</p>
</blockquote>
]]></content></entry><entry><title>Optimize for optionality and build towards checkpoints</title><link rel="alternate" href="https://sebastiandedeyne.com/optimize-for-optionality-and-build-towards-checkpoints"/><id>https://sebastiandedeyne.com/optimize-for-optionality-and-build-towards-checkpoints</id><author><name>Sebastian De Deyne</name><email>sebastiandedeyne@gmail.com</email></author><updated>2024-09-11T21:48:00+02:00</updated><content type="html"><![CDATA[<p>In a project management-themed <a href="https://hackersincorporated.com/episodes/how-to-not-suck-at-project-management">Hackers Incorporated episode</a>, Adam Wathan introduced <em>derisking projects with save points</em>. The entire episode is definitely worth your time, but that specific piece of advice has changed the way I work as a developer and make decisions as a project manager.</p>
<p>In practice, it has taught me to optimize for optionality, not efficiency.</p>
<h2 id="the-monolithic-branch">
  <a href="#the-monolithic-branch" class="heading-permalink" aria-label="Permalink to The monolithic branch"></a>
  The monolithic branch
</h2>
<p>To illustrate what it means, we&rsquo;ll build a user account section as an example. The new account section will be shipped to users as one big launch. A user can…</p>
<ul>
<li>Update their basic profile information</li>
<li>Add their address with Google Maps autocomplete</li>
<li>Upload a profile picture</li>
<li>Connect social login accounts</li>
<li>Reset their password</li>
</ul>
<p>Let&rsquo;s make an estimate:</p>
<table>
  <thead>
      <tr>
          <th style="text-align: left"><strong>Task</strong></th>
          <th style="text-align: right"><strong>Estimate</strong></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: left">Basic information</td>
          <td style="text-align: right">6h</td>
      </tr>
      <tr>
          <td style="text-align: left">Address autocomplete</td>
          <td style="text-align: right">12h</td>
      </tr>
      <tr>
          <td style="text-align: left">Profile picture</td>
          <td style="text-align: right">4h</td>
      </tr>
      <tr>
          <td style="text-align: left">Social login</td>
          <td style="text-align: right">8h</td>
      </tr>
      <tr>
          <td style="text-align: left">Reset password</td>
          <td style="text-align: right">4h</td>
      </tr>
  </tbody>
</table>
<p>Summing up: <code>6 + 12 + 4 + 4 + 8 = 34</code>,  that&rsquo;s a 40-hour estimate. <em>(Gotta add that margin!)</em> We&rsquo;ll checkout a new <code>feature/user-account</code> branch, implement, and ship. The final logs in our time tracker:</p>
<table>
  <thead>
      <tr>
          <th style="text-align: left"><strong>Task</strong></th>
          <th style="text-align: right"><strong>Estimate</strong></th>
          <th style="text-align: right"><strong>Actual</strong></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: left">Basic information</td>
          <td style="text-align: right">6h</td>
          <td style="text-align: right">3h</td>
      </tr>
      <tr>
          <td style="text-align: left">Address autocomplete</td>
          <td style="text-align: right">12h</td>
          <td style="text-align: right">14h</td>
      </tr>
      <tr>
          <td style="text-align: left">Profile picture</td>
          <td style="text-align: right">4h</td>
          <td style="text-align: right">6h</td>
      </tr>
      <tr>
          <td style="text-align: left">Social login</td>
          <td style="text-align: right">8h</td>
          <td style="text-align: right">18h</td>
      </tr>
      <tr>
          <td style="text-align: left">Reset password</td>
          <td style="text-align: right">4h</td>
          <td style="text-align: right">2h</td>
      </tr>
  </tbody>
</table>
<p><code>3 + 14 + 6 + 18 + 2 = 43</code>. Not too far off of our (padded) estimate! Some tasks were easier to implement than expected, some took a lot longer. But we didn&rsquo;t ship 43 working hours later, it took 4 weeks to reach production. Why?</p>
<ul>
<li>We realized our application needed to be approved by our social login provider, that took a week. After that it took a lot longer than expected to implement.</li>
<li>When we started to implement the new reset password flow we found a few issues in the design, so the design team had to update the Figma file. The implementation went smoother than expected, but we had to wait for the changes.</li>
<li>Of course, the usual bugs and small feature requests that creep into our schedule pushed this project further down the road.</li>
</ul>
<p>That users had to wait longer than estimated for the new account feature isn&rsquo;t a problem. This post isn&rsquo;t a manifesto to ship incremental changes over big bang launches—I&rsquo;ll leave that decision to the product managers. Shoving everything into one branch is plain <em>easy</em>. Because we weren&rsquo;t going to ship anything individually, we were allowed to! What I care about, is how it affects everything <em>else</em>. Because meanwhile…</p>
<ul>
<li>Another developer needed an address autocompletion on the shipping page. Now we have two implementations and need to trash one.</li>
<li>Someone else refactored the user model and related code, causing a bunch of merge conflicts throughout the 4 weeks of development.</li>
<li>Another timeline-like feature design relies on profile pictures, but we wanted to wait until this branch was merged so we had access to the profile picture components that are already set up.</li>
</ul>
<h2 id="checkpoints">
  <a href="#checkpoints" class="heading-permalink" aria-label="Permalink to Checkpoints"></a>
  Checkpoints
</h2>
<p>Let&rsquo;s treat each task as an individual project. It will probably take longer—at least on our timesheet. We need to create a separate branch for every task and can&rsquo;t implement changes in bulk. Instead of one big <code>feature/user-account</code> merge, we created, reviewed, and merged a bunch of smaller branches over the weeks.</p>
<pre><code>feature/user-basic-information-views
refactor/share-google-maps-api-credentials
feature/google-maps-autocomplete
feature/profile-picture
refactor/user-authentication-changes
feature/social-login
fix/profile-picture-upload-bug
feature/reset-password-update
feature/reset-password-update-2
</code></pre>
<p>But what have we gained from this approach?</p>
<ul>
<li>If the address autocompletion was merged earlier, we wouldn&rsquo;t have ended up with two implementations. Even if the first wasn&rsquo;t shipped to production yet, it would have been a usable component in the codebase.</li>
<li>We wouldn&rsquo;t have spent as much time on merge conflicts because frequent merges keep them small or non-existent.</li>
<li>We could have decided postpone social login if we knew it was such a big investment. We didn&rsquo;t because it was too entangled in the monolithic branch.</li>
</ul>
<p>Working towards mergeable chunks doesn&rsquo;t only give the developer more optionality, it makes the entire organization more flexible.</p>
<p>Hindsight is 20/20. It could have gone differently: maybe working in the dark for a prolonged time didn&rsquo;t affect anyone. But you never know this ahead of time. Priorities change, and you don&rsquo;t have control of the external factors that force them to. If you were halfway the monolithic user account branch and a critical bug or competitor forces your hand, all of your code is held hostage until you get back to it. Even if you don&rsquo;t release it to your users, it&rsquo;s more valuable to have in your main branch.</p>
<p>When code is in a feature branch it doesn&rsquo;t contribute to the rest of the codebase. This 40-hour project is an innocent example. We often fall into the same trap for 250-hour projects. That&rsquo;s a month or two of work—a month or two of work in progress code dilly-dallying. Code rots over time. Work in progress code rots significantly faster.</p>
<p>To paraphrase Eliyahu M. Goldratt (I&rsquo;m a sucker for the <a href="https://literal.club/book/the-goal-guyo5">theory of constraints</a>): large amounts of work in progress masks inefficiencies and bottlenecks in the production process. Reducing work in progress can improve cash flow. As work in progress is converted to finished goods and sold more quickly, it accelerates the cash conversion cycle. In our language: code only becomes an asset after it&rsquo;s merged.</p>
<h2 id="action-items">
  <a href="#action-items" class="heading-permalink" aria-label="Permalink to Action items"></a>
  Action items
</h2>
<p>To make this plea actionable: treat each chunk of work as something that should be merged by the end of the week. That doesn&rsquo;t mean it needs to be &ldquo;done&rdquo; or available to the end user, it needs to become a citizen of The Codebase.</p>
<p>The hard part is finding your checkpoints. <strong>Identify the critical path</strong>. What can you strip from a feature while keeping it useful? Do that last. <strong>take a step back every few hours</strong>, ask yourself what the least amount of work would be to make what you&rsquo;re doing mergeable. <strong>Have a bug-free staging environment</strong> from day one and keep it that way to ensure frequent merges don&rsquo;t affect quality (read about <a href="https://en.wikipedia.org/wiki/Broken_windows_theory">the broken window theory</a>).</p>
<p>It takes a while to get used to, and will feel uncomfortable at first. But do this enough, and you&rsquo;ll see checkpoints all over the place. Working in small chunks means individual tasks may take longer. But in the long term you and the team as a whole will see gains in flexibility, optionality, and efficiency. These benefits vastly outweigh the time you would win from a bulk discount.</p>
<p>Some <a href="https://www.goodreads.com/quotes/184098-arrakis-teaches-the-attitude-of-the-knife---chopping-off">desert wisdom</a> to close:</p>
<blockquote>
<p>Arrakis teaches the attitude of the knife—chopping off what&rsquo;s incomplete and saying: &ldquo;Now, it&rsquo;s complete because it&rsquo;s ended here.&rdquo;</p>
</blockquote>]]></content></entry></feed>