<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Customer Obsessed Engineering]]></title><description><![CDATA[Elevate your career, execute with confidence, and build your customer obsessed mindset. Advice from an ex-Accenture Director, startup veteran, CTO.]]></description><link>https://blog.bosslogic.com</link><image><url>https://substackcdn.com/image/fetch/$s_!SRH_!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5de8a7cd-651e-4f84-b61d-8f100b23db5a_250x250.png</url><title>Customer Obsessed Engineering</title><link>https://blog.bosslogic.com</link></image><generator>Substack</generator><lastBuildDate>Sun, 24 May 2026 13:39:44 GMT</lastBuildDate><atom:link href="https://blog.bosslogic.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Boss Logic, Inc.]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[bosslogic@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[bosslogic@substack.com]]></itunes:email><itunes:name><![CDATA[Zac Beckman]]></itunes:name></itunes:owner><itunes:author><![CDATA[Zac Beckman]]></itunes:author><googleplay:owner><![CDATA[bosslogic@substack.com]]></googleplay:owner><googleplay:email><![CDATA[bosslogic@substack.com]]></googleplay:email><googleplay:author><![CDATA[Zac Beckman]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Good product team / bad product team]]></title><description><![CDATA[Marty Cagan&#8217;s good-team / bad-team list is a decade old and still the cleanest mirror in the business. Pin it to your wall. Ask yourself how many strike too close to home.]]></description><link>https://blog.bosslogic.com/p/good-product-team-bad-product-team</link><guid isPermaLink="false">https://blog.bosslogic.com/p/good-product-team-bad-product-team</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Thu, 21 May 2026 14:02:11 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!1WI6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1WI6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1WI6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1WI6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1WI6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1WI6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1WI6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg" width="1456" height="945" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:945,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:408816,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/198708208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1WI6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1WI6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1WI6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1WI6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd66be403-f6c5-435c-b7ca-470835ee9b89_3000x1947.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@jplenio?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Johannes Plenio</a> on <a href="https://unsplash.com/photos/black-sailing-boat-digital-wallpaper-DKix6Un55mw?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><p>Marty Cagan&#8217;s <a href="https://www.svpg.com/good-product-team-bad-product-team/">decade-old article</a> can be a real rabbit hole. It&#8217;s genuinely hard to stop reading his blog, especially when digging up old gems like this.</p><p>Here&#8217;s something that resonates right now: &#8220;Good teams are skilled in the many techniques to rapidly try out product ideas to determine which ones are truly worth building. Bad teams hold meetings to generate prioritized roadmaps.&#8221;</p><p>Most teams I meet are funded, staffed and measured entirely around output. Hit the date, close the ticket, ring the bell for delivering on a roadmap.</p><p>Too few are paying attention to what matters: did what we shipped really make a difference for our customer?</p><p>The reorg that actually changes delivery isn&#8217;t new ceremonies. It&#8217;s moving the moment you celebrate from &#8220;we shipped&#8221; to &#8220;it delighted our customer, it actually moved what matters.&#8221;</p>]]></content:encoded></item><item><title><![CDATA[Pull requests are a symptom of low trust: here’s the fix]]></title><description><![CDATA[T*D is the new name for the Playbook trifecta: Test-Driven Development, Trunk-Based Development and Team-Focused Development, fused into one operating model.]]></description><link>https://blog.bosslogic.com/p/pull-requests-are-a-symptom-of-low-trust</link><guid isPermaLink="false">https://blog.bosslogic.com/p/pull-requests-are-a-symptom-of-low-trust</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Sat, 16 May 2026 13:52:12 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Kp02!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Kp02!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Kp02!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Kp02!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Kp02!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Kp02!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Kp02!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg" width="1390" height="927" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:927,&quot;width&quot;:1390,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:265872,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/197994258?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Kp02!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Kp02!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Kp02!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Kp02!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f4f46f7-5e75-4350-9da9-92b2264ec340_1390x927.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@shiroscope?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Shiro hatori</a> on <a href="https://unsplash.com/photos/timelapse-photography-on-curved-road-beside-tree-WR-ifjFy4CI?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><p>Your team has probably spent more hours this year waiting on pull requests than it spent writing the code marooned inside them. Andrea Laforgia opens his March 2026 essay <em>Stop Using Pull Requests</em> with numbers from across the industry that count the cost. The piece is the most thorough reckoning I&#8217;ve seen of why the modern pull request workflow is mis-designed for the teams that use it. Go read it. Then come back here &#8212; because if you&#8217;re using the <em><a href="https://blog.bosslogic.com/s/delivery-playbook">Delivery Playbook</a></em>, Laforgia is describing the practice you already know. He just gives it a name. And I like it.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><p>That name is T*D &#8212; Test-Driven Development, Trunk-Based Development and Team-Focused Development, fused into one operating model. Hold on to it. We&#8217;ll come back to it.</p><h2>Don&#8217;t break the flow</h2><p>Chapter <a href="https://blog.bosslogic.com/p/28-delivery-tools-and-processes">2.8 Delivery processes &amp; tools</a> lays out what a well-wrought delivery pipeline does: ephemeral environments, test batteries, zero trust, release orchestration, observability, canary releases. The argument is that your pipeline is <em>part of your product</em>, and its job is reliability and repeatability through automation. The motto I&#8217;ve handed to more than one team &#8212; <em>the only path to higher environments is through automation</em> &#8212; comes straight out of that chapter.</p><p>Here&#8217;s the thing. If you map a typical team&#8217;s workflow against that pipeline, there is exactly one step where a human might still be gating the flow. Tests run automatically. Security scans run automatically. Infrastructure is provisioned automatically. Releases orchestrate automatically. And then &#8212; somewhere between &#8220;I pushed&#8221; and &#8220;it merged&#8221; &#8212; a colleague has to find time, open the diff, scroll through it and click <em>Approve</em>. That manual gate is the pull request. Everything else in the chapter is built around eliminating exactly this kind of step.</p><p>Pull requests are the routine human gate that survived a pipeline whose sole purpose is to remove them. Fix that, and the pipeline finally runs at the speed its design intended.</p><div class="pullquote"><p><em>If you&#8217;re new, welcome to Customer Obsessed Engineering! I publish about one article each week. Free subscribers can read about half of every article, plus all of my free articles.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/subscribe?"><span>Subscribe now</span></a></p></div><h2>Three findings that should bother you more</h2><p>Laforgia&#8217;s piece marshals the research that counts the cost. Three findings worth carrying into your next retro:</p><p><strong>Code review finds fewer bugs than you think.</strong> In Bacchelli &amp; Bird&#8217;s ICSE 2013 study, the authors manually classified roughly 570 review comments from Microsoft engineers and found that about one in eight &#8212; call it 12.5% &#8212; were about defects. The rest was structure, naming and style. A separate Microsoft study by Bosu and colleagues built a 1.5-million-comment dataset and asked a different question &#8212; were the reviews <em>useful</em>? &#8212; and concluded 64&#8211;68% were. Two distinct findings, often conflated. The honest read is that code review&#8217;s value lives in knowledge transfer and improving the code&#8217;s shape, not in catching bugs. And a blocking async queue is one of the clumsiest possible vessels for sharing knowledge.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a></p><p><strong>Most of the lead time is waiting.</strong> A change that takes ten minutes to write but waits four hours for review spends 96% of its existence in queue. Martin Fowler recounts one client whose team logged 130,000 hours waiting on pull requests in 2020 &#8212; 91% of which got no comment in return. The process extracted enormous delay and returned almost nothing.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a></p><p><strong>The lever is the speed of review, not review itself.</strong> The 2023 <em>State of DevOps</em> report, drawn from more than 36,000 professionals, found that accelerating code review alone improves software delivery performance by 50%. Elite performers who meet their reliability targets are 2.3 times more likely to use trunk-based development. DORA explicitly names heavyweight code review as a brake on delivery. The methodology that produced this question &#8212; the four DORA metrics &#8212; comes from Forsgren, Humble and Kim&#8217;s <em>Accelerate</em>; the 2023 numbers cited here come from the State of DevOps report that builds on it.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a></p><p>A caveat that Laforgia treats carefully and I want to carry into the body rather than burying in the close: this evidence speaks loudest for <em>intra-team</em> work, where colleagues know each other and the codebase. Trust is a gradient. For distributed teams collaborating across time zones, open source contributions or any genuinely cross-team change, the case for a gate is stronger. The mistake is importing the gatekeeping pattern wholesale from those high-trust-gap contexts into the daily work of a co-located team that already trusts each other.</p><h2>T*D is what the Playbook teaches as muscle memory</h2><p>This is where the Playbook and Laforgia line up. Each leg of T*D slots directly into something you have already been building.</p><p><strong>TDD/BDD fills the test batteries slot &#8212; properly.</strong> Chapter 2.8 says: <em>&#8220;If tests fail, the build fails, and the code can&#8217;t be merged (no exceptions).&#8221;</em> Test-driven and <a href="https://blog.bosslogic.com/p/delivering-customer-value-with-bdd">behavior-driven development</a> are how you make that sentence true in practice. The tests exist before the feature exists. They encode the acceptance criteria the team agreed to. They run on every commit, not just at the end. When the gate that decides whether code reaches the next environment is automated and trustworthy, the human gate becomes redundant &#8212; there is no class of defect a tired reviewer at 4pm is going to catch that a green CI run did not. This is the same argument I made in <em><a href="https://blog.bosslogic.com/p/the-balanced-power-of-tdd">The balanced power of TDD</a></em>: defects must be <em>prevented</em>, not <em>removed</em>. Deming wrote it down in 1982 &#8212; <em>Point Three: cease dependence on inspection to achieve quality</em> &#8212; and the software industry has been re-discovering it ever since.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-7" href="#footnote-7" target="_self">7</a></p><p><strong>Trunk-based development matches the Playbook&#8217;s stance on small increments.</strong> Chapter <a href="https://blog.bosslogic.com/p/30-delivery-phase-3">3.0 Delivery</a> is explicit: <em>&#8220;Delivery is intended to move quickly. That means working in small increments, not &#8216;feature trains&#8217; or monolithic releases.&#8221;</em> That is trunk-based development by another name. A long-lived feature branch is a feature train waiting to happen. The Playbook already prefers the alternative &#8212; ephemeral environments per branch are fine, but the branches themselves should be short-lived, with code returning to trunk daily and incomplete work hidden behind feature flags. The point is: code the gate has to inspect must be small enough that automated checks will validate it in seconds.</p><p><strong>Team-focused development is what you already started building when you killed the tester role.</strong> Pair programming and ensemble (mob) programming move review from a post-hoc inspection into a continuous one. In a 2005 controlled experiment, M&#252;ller and Tichy found that pair programming and solo-plus-review achieved comparable cost when quality was held constant &#8212; pairing did not cost more, it just moved the review work earlier. That experiment is small (38 students in one university), so don&#8217;t lean on it alone; Hannay and colleagues&#8217; 2009 meta-analysis casts a wider net across the practitioner record &#8212; with the caveat that pairing&#8217;s benefits depend strongly on task complexity and developer experience. In both lines of evidence, what changes is <em>when</em> review happens, not whether. I&#8217;ve argued the structural version of this case in <em><a href="https://blog.bosslogic.com/p/i-dont-hire-testers-anymore-and-im">I don&#8217;t hire testers anymore</a></em>: quality belongs inside the team, not bolted on at the boundary. Pairing is the same logic applied to review.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-8" href="#footnote-8" target="_self">8</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-9" href="#footnote-9" target="_self">9</a></p><p>This is what I&#8217;d like you to carry away: T*D is not three new things to adopt. For anyone running the Playbook, it is a name for the convergence of practices you have been heading toward. The pull request workflow is the last manual gate left after you&#8217;ve automated everything else. T*D is what you put in its place.</p><h2>What to do Monday</h2><p>Most teams cannot drop pull requests overnight. They shouldn&#8217;t try. The path is gradual, and every step buys real flow:</p><ol><li><p><strong>Optimise the PRs you have.</strong> Cap them at two or three hundred lines. Set a four-hour review SLA. Automate every style and lint check. Reduce required approvers to one. This is housekeeping, not transformation, but it removes the worst of the queue cost while you build the alternative.</p></li><li><p><strong>Adopt Ship / Show / Ask.</strong> Rouan Wilsenach&#8217;s three categories give a team a way to graduate routine changes off the gated workflow first. Routine changes <em>Ship</em> &#8212; straight to trunk, no PR. Notable changes <em>Show</em> &#8212; they go to trunk immediately, with a PR opened in parallel as the venue for post-merge discussion. Genuinely uncertain or risky changes <em>Ask</em> &#8212; they get the blocking review treatment. Most work, once you look honestly, is <em>Ship</em> or <em>Show</em>.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-10" href="#footnote-10" target="_self">10</a></p></li><li><p><strong>Pair on production code; merge to trunk daily.</strong> Feature flags carry incomplete work; automated tests are non-negotiable. This is also where the Playbook&#8217;s <em>Quality Engineer</em> rotation pays off &#8212; the engineer in that role this sprint is the one making sure the test batteries and the pipeline can carry the weight you&#8217;re about to put on them.</p></li><li><p><strong>Move to ensemble programming where the team is ready.</strong> Continuous review during creation. No post-hoc inspection. This is where most teams will need the most patience &#8212; it&#8217;s a cultural shift, not a tooling change, and it rewards a coach in the room for the first few weeks.</p></li></ol><p>Charity Majors gives you the lodestar: <em>speed is safety</em>. Small changes by single owners reach production fast, the blast radius stays small, and the fix is obvious because the intent is still fresh.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-11" href="#footnote-11" target="_self">11</a></p><h2>The harder question</h2><p>The question for your team is not <em>how do we do pull requests better?</em> It is <em>why do we still need them?</em> If the answer is fear &#8212; of regressions, of juniors, of complexity, of the codebase itself &#8212; address the fear directly through skills, automation and pairing rather than institutionalizing it as policy. The Playbook has been quietly pointing at this answer the whole time. Laforgia&#8217;s piece is the receipt for the empirical cost of ignoring it.</p><h2>Read the source</h2><p>Laforgia&#8217;s full essay carries the academic citations, the DORA data, the practitioner consensus and the honest caveats I didn&#8217;t hit here. He treats correlation versus causation carefully, draws the trust-as-gradient distinction in more depth than I did, and gives the transition path more nuance than four bullets allow. If you lead a team that still gates every change behind an async queue, read his piece end to end and bring it to your next retro. Then open the Playbook to <a href="https://blog.bosslogic.com/p/28-delivery-tools-and-processes">chapter 2.8</a> and ask which manual gates are still left in your pipeline. There won&#8217;t be many, and that&#8217;s the point.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-12" href="#footnote-12" target="_self">12</a></p><div><hr></div><p style="text-align: center;"><em>This newsletter grows by word of mouth&#8230; I&#8217;d really, truly appreciate it if you could refer a friend. Your referrals make it worthwhile.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>Andrea Laforgia, <em><a href="https://a4al6a.substack.com/p/stop-using-pull-requests">Stop Using Pull Requests</a></em>, March 19, 2026.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>Alberto Bacchelli &amp; Christian Bird, <em><a href="https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/ICSE202013-codereview.pdf">Expectations, Outcomes, and Challenges of Modern Code Review</a></em>, ICSE 2013. The figure cited here &#8212; roughly one in eight comments addressing defects &#8212; comes from the authors&#8217; manual classification of approximately 570 comments at Microsoft.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>Amiangshu Bosu, Michaela Greiler &amp; Christian Bird, <em><a href="https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/bosu2015useful.pdf">Characteristics of Useful Code Reviews: An Empirical Study at Microsoft</a></em>, MSR 2015. This is a distinct, larger study covering roughly 1.5 million review comments, which is sometimes conflated with Bacchelli &amp; Bird; its headline finding is that 64&#8211;68% of reviews were judged useful (a usefulness measure, not a defect rate).</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p>Martin Fowler, <em><a href="https://martinfowler.com/bliki/PullRequest.html">Pull Request</a></em> (bliki entry), martinfowler.com. The 130,000-hour figure is attributed to a colleague&#8217;s analysis of a single client in 2020.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p>Google Cloud, <em><a href="https://dora.dev/research/2023/dora-report/">Accelerate State of DevOps Report 2023</a></em>.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-6" href="#footnote-anchor-6" class="footnote-number" contenteditable="false" target="_self">6</a><div class="footnote-content"><p>Nicole Forsgren, Jez Humble &amp; Gene Kim, <em><a href="https://itrevolution.com/product/accelerate/">Accelerate: The Science of Lean Software and DevOps</a></em> (IT Revolution, 2018). Background methodology behind the DORA metrics; specific figures cited above are from the 2023 report.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-7" href="#footnote-anchor-7" class="footnote-number" contenteditable="false" target="_self">7</a><div class="footnote-content"><p>W. Edwards Deming, <em><a href="https://deming.org/inspection-is-too-late-the-quality-good-or-bad-is-already-in-the-product/">Quality, Productivity, and Competitive Position</a></em> (MIT, 1982), re-titled <em>Out of the Crisis</em> in 1986. Point Three of the Fourteen Points: cease dependence on inspection to achieve quality.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-8" href="#footnote-anchor-8" class="footnote-number" contenteditable="false" target="_self">8</a><div class="footnote-content"><p>Matthias M&#252;ller &amp; Walter Tichy, <em><a href="https://www.sciencedirect.com/science/article/abs/pii/S0164121205000038">Two Controlled Experiments Concerning the Comparison of Pair Programming to Peer Review</a></em>, Journal of Systems and Software, 2005. Small-n controlled experiment with 38 students; useful as a point of evidence, not a final word.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-9" href="#footnote-anchor-9" class="footnote-number" contenteditable="false" target="_self">9</a><div class="footnote-content"><p>Jo E. Hannay, Tore Dyb&#229;, Erik Arisholm &amp; Dag I. K. Sj&#248;berg, <em><a href="https://www.sciencedirect.com/science/article/abs/pii/S0950584909000123">The effectiveness of pair programming: A meta-analysis</a></em>, Information and Software Technology, 2009. A broader synthesis than M&#252;ller &amp; Tichy; finds pairing&#8217;s benefits depend strongly on task complexity and developer experience.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-10" href="#footnote-anchor-10" class="footnote-number" contenteditable="false" target="_self">10</a><div class="footnote-content"><p>Rouan Wilsenach, <em><a href="https://martinfowler.com/articles/ship-show-ask.html">Ship / Show / Ask</a></em>, martinfowler.com, September 2021.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-11" href="#footnote-anchor-11" class="footnote-number" contenteditable="false" target="_self">11</a><div class="footnote-content"><p>Charity Majors, <em><a href="https://charity.wtf/2018/08/19/shipping-software-should-not-be-scary/">Shipping Software Should Not Be Scary</a></em>, charity.wtf, August 19, 2018. Source of the &#8220;speed is safety&#8221; framing.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-12" href="#footnote-anchor-12" class="footnote-number" contenteditable="false" target="_self">12</a><div class="footnote-content"><p>Andrea Laforgia, <em>Stop Using Pull Requests</em>, op. cit.</p></div></div>]]></content:encoded></item><item><title><![CDATA[Ask your team how to make this worse]]></title><description><![CDATA[A 30-minute workshop called TRIZ turns a comedy round into a confession booth &#8212; the most valuable half-hour you&#8217;ll spend this quarter.]]></description><link>https://blog.bosslogic.com/p/ask-your-team-how-to-make-this-worse</link><guid isPermaLink="false">https://blog.bosslogic.com/p/ask-your-team-how-to-make-this-worse</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Thu, 07 May 2026 14:22:22 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!kh_T!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kh_T!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kh_T!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg 424w, https://substackcdn.com/image/fetch/$s_!kh_T!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg 848w, https://substackcdn.com/image/fetch/$s_!kh_T!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!kh_T!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kh_T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg" width="1456" height="1090" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1090,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:366711,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/196719103?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!kh_T!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg 424w, https://substackcdn.com/image/fetch/$s_!kh_T!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg 848w, https://substackcdn.com/image/fetch/$s_!kh_T!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!kh_T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F044947a1-0de9-4f36-88b7-b041a60187ce_1712x1282.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@mrding?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Cexin Ding</a> on <a href="https://unsplash.com/photos/moss-covered-stone-statues-with-expressive-faces-5DNw4mP3LPY?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><p>Six people. One sticky.</p><p>A SWOT analysis at the top of a planning workshop. Strengths quadrant &#8212; a dozen sticky notes inside ten minutes. Opportunities, fine. Threats, fine. Weaknesses &#8212; <em>one sticky</em>.</p><p>The team has been together a year. Mixed group, some senior, some junior, some remote and some local. They&#8217;re smart &#8212; and obviously not weak in just one way. But one is all they were willing to write down, in front of each other, with their names attached. So the Weaknesses quadrant sat there, embarrassed and underfed, while the rest of the wall filled out around it.</p><p>Most retrospectives end this way. Most planning meetings, the same. The team knows. The team won&#8217;t say.</p><p>There&#8217;s a 30-minute exercise that breaks this open. It&#8217;s not subtle. It&#8217;s not high-tech. It&#8217;s a borrowed word from Soviet engineering, an inversion trick from a 19th-century mathematician. It takes a team from laughter to honesty to commitment in less time than your average standup. It&#8217;s called TRIZ &#8212; the Liberating Structures version, which I&#8217;ll come back to &#8212; and it&#8217;s the cheapest unlock I know for a team that won&#8217;t speak its own dysfunctions out loud.</p><p>Here&#8217;s how it works, why it works and how to run it next week.</p><div class="pullquote"><p style="text-align: center;"><em>If you&#8217;re new, welcome to Customer Obsessed Engineering! I publish about one article each week. Free subscribers can read about half of every article, plus all of my free articles.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/subscribe?"><span>Subscribe now</span></a></p><p style="text-align: center;"><em>Anytime you&#8217;d like to read more, you can upgrade to a paid subscription.</em></p></div><h2>The wrong question</h2><p>The silence in that Weaknesses quadrant is not random. It&#8217;s the predictable shape teams take when the question goes the wrong way.</p><p>&#8220;What are we doing wrong?&#8221; is one of the worst questions you can ask. It demands that someone you work with every day be the source of bad news, of blame &#8212; in a setting where their answer goes on the record. The forces working against honesty are stacked: the social cost of singling out a behavior, the political cost of singling out a person, the personal cost of being the one who said the thing nobody else was willing to say. So people hedge. They write harmless stickies. They give safe answers and stay quiet about the rest.</p><p>This isn&#8217;t about psychological safety being too low, exactly. It&#8217;s about requiring more safety than most teams I&#8217;ve known. An unusually safe team &#8212; the rare ones &#8212; can handle the direct question. Most teams can&#8217;t, even good ones. The Goldilocks zone for direct critique is narrow, and most teams sit just below it.</p><p>The wrinkle: the same team, asked the question a different way, will answer it. Same people, same room, same dysfunctions. The information is there. The mechanism for getting it out is what&#8217;s broken.</p><p>That&#8217;s the gap TRIZ fills.</p><h2>Inversion</h2><p>The 19th-century Prussian mathematician Carl Jacobi had a habit, when stuck on a problem, of saying <em>man muss immer umkehren</em> &#8212; &#8220;one must always invert.&#8221; If you can&#8217;t see how to make a thing succeed, see if you can describe how to make it fail. Charlie Munger, Warren Buffett&#8217;s late partner, popularized the move a century and a half later: &#8220;Invert, always invert,&#8221; he&#8217;d repeat, crediting Jacobi each time.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><p>Inversion is a cognitive shortcut. The forward question &#8212; &#8220;how do we make this succeed?&#8221; &#8212; runs into the usual social and intellectual walls. People hedge. People defer to whoever spoke first. People say what they think they&#8217;re supposed to say. The inverse question &#8212; &#8220;how do we <em>guarantee</em> it fails?&#8221; &#8212; jumps every one of those walls, because there&#8217;s no commitment. They&#8217;re describing a failure. They can be specific, vivid and sometimes uncomfortably accurate, and the room laughs instead of getting defensive.</p><p>Once the failure is on the wall, naming the parts of it that already exist is a much smaller step. You&#8217;re not confessing. You&#8217;re confirming.</p><p>That&#8217;s the whole engine of TRIZ.</p><h2>Why it works on teams that won&#8217;t speak up</h2><p>If you&#8217;ve never run TRIZ you&#8217;re probably thinking, &#8220;why does this work at all?&#8221; Why does asking a team to describe failure produce honesty when asking them to describe weakness doesn&#8217;t? It&#8217;s the same people in the same room talking about the same problem.</p><p>Here&#8217;s four reasons I keep coming back to. They aren&#8217;t independent &#8212; pull on one and the others move &#8212; and there are probably more I haven&#8217;t named. Their common thread: all four lower the cost of saying the thing.</p><p><strong>Hypotheticals are cheap.</strong> Saying, &#8220;we could skip estimation entirely&#8221; carries no social cost. Nobody is suggesting it. Saying, &#8220;we <em>do</em> skip estimation&#8221; costs you &#8212; especially if the person who set up the no-estimation pattern is in the room. TRIZ collects the cheap version first. It builds a list of behaviors the team is willing to discuss because the team isn&#8217;t yet committing to whether they&#8217;re real.</p><p><strong>Confirmation is easier than confession.</strong> By the time Movement 2 starts, the behavior is already on the wall. The team isn&#8217;t introducing a new criticism &#8212; that&#8217;s the hardest move. It&#8217;s confirming an existing one &#8212; that&#8217;s a much smaller move. &#8220;Ah, yea, we do that,&#8221; is far easier to say than, &#8220;we have a problem with X.&#8221; The board already said it. The team is just agreeing.</p><p><strong>Laughter changes the room.</strong> Ten minutes of laughing at exaggerated worst-case behaviors changes the social register. The same conversation about the same behaviors, started cold, would feel like an accusation round. Started after the comedy, it feels like camaraderie. Defensiveness drops. People interrupt themselves. The room is in a different mode.</p><p><strong>The quiet people speak.</strong> This is the move I see most reliably. In nearly every TRIZ I&#8217;ve facilitated, the first person to circle a behavior in Movement 2 &#8212; the first to commit to, &#8220;yea, that one&#8221; &#8212; has been the person who hadn&#8217;t said much yet. The senior engineer who watches more than she talks. The new hire who&#8217;d been listening for three months. They&#8217;d seen the dysfunction the whole time. They didn&#8217;t have a frame to say it. TRIZ gave them one.</p><p>You can put psychological safety theory on this if you want. You can talk about face-saving, about politeness norms, about the asymmetry between criticism and praise. All of it holds. But the practical version is simpler: it&#8217;s a lot easier to say things about hypotheticals than about reality, and TRIZ exploits that gap to get a team to say what it already knows.</p><p>That&#8217;s why a 30-minute exercise can do work that an hours-long retro can&#8217;t.</p><div class="pullquote"><p><em>This newsletter grows by word of mouth&#8230; I&#8217;d really, truly appreciate it if you could refer a friend. Your referrals make it worthwhile.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p></div><h2>The three movements</h2><p>The exercise has three movements. Together, they take 30 minutes if you keep the timing tight; you can stretch to 45 on a hard problem or compress to 20 with a small confident team. Each movement has a single question, and each question is doing different psychological work.</p><p><strong>Movement 1: the worst-possible-outcome brainstorm (10 minutes).</strong> Frame the outcome the team cares about &#8212; high-functioning sprint planning, a retrospective that actually changes things, a release process you&#8217;d be willing to demo. Then ask the inverted question: what could we do to <em>guarantee</em> the worst possible version of this? Wild, exaggerated, funny answers welcome. Suppress nothing. Two minutes of silent sticky-writing first, in <a href="https://deliveryplaybook.com/playbook/documentation/guides/1-2-4-all">1-2-4-All</a> style, then a round-robin share.</p><p>The laughter is the point. A team that&#8217;s laughing at &#8220;we could just cancel the retro and send an email instead&#8221; is a team becoming willing to say real things. Don&#8217;t rush this part &#8212; the comedy is what unlocks the next movement.</p>
      <p>
          <a href="https://blog.bosslogic.com/p/ask-your-team-how-to-make-this-worse">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Product teams really do outperform: bringing the receipts]]></title><description><![CDATA[Researchers at DORA, McKinsey and Google have spent a decade proving what good engineers already know. It&#8217;s time to put that knowledge into practice.]]></description><link>https://blog.bosslogic.com/p/product-teams-really-do-outperform</link><guid isPermaLink="false">https://blog.bosslogic.com/p/product-teams-really-do-outperform</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Thu, 30 Apr 2026 20:38:52 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!44-q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!44-q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!44-q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg 424w, https://substackcdn.com/image/fetch/$s_!44-q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg 848w, https://substackcdn.com/image/fetch/$s_!44-q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!44-q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!44-q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:517036,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/195978066?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!44-q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg 424w, https://substackcdn.com/image/fetch/$s_!44-q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg 848w, https://substackcdn.com/image/fetch/$s_!44-q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!44-q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6b5872-3961-486c-aca9-12e0cb6129a6_3228x2152.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@albertstoynov?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Albert Stoynov</a> on <a href="https://unsplash.com/photos/statue-of-lady-justice-holding-scales-indoors-kIM48Mpp9iY?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><p>I was chatting with a friend about team dynamics. We&#8217;d been talking about restructuring around product teams &#8212; the kind of empowered, durable, cross-functional teams I&#8217;ve written about before. He&#8217;s nodding along, asking sharp questions. Halfway through, he pushed back.</p><p>I&#8217;m paraphrasing, but the gist was, &#8220;Look, I get the theory. But where&#8217;s your proof? We&#8217;ve all heard the pitch. Cross-functional teams, durable squads, outcome metrics, two-pizza this, empowered that. Show me the data. Show me that any of this actually beats what we already do.&#8221;</p><p>It was a fair question. A great question, actually. I&#8217;d written the case in <a href="https://blog.bosslogic.com/p/what-a-product-oriented-team-looks-like">Building a product oriented team</a> and the prequel, <a href="https://blog.bosslogic.com/p/moving-away-from-the-monolith-faster-better-with-a-product-mindset-f8f0dc58653c">Moving away from the Monolith &#8212; faster, better with a product mindset</a>. But those pieces argued from reasoning and experience. They didn&#8217;t bring the math.</p><p>So today I want to bring it. Because the math is there &#8212; it&#8217;s been there for over a decade &#8212; and once you line it up, the conclusion is hard to escape: product teams, the real ones, ship faster, build less waste, deliver higher quality and produce dramatically better business outcomes than the alternatives. The evidence isn&#8217;t a single bombshell study. It&#8217;s a stack of independent research, all converging on the same answer.</p><p>Let me lay out the receipts.</p><p>One note before we start. None of the studies I cite below were designed to answer the question &#8220;do product teams outperform?&#8221; They were designed to answer narrower, related questions &#8212; about deployment, about feature usage, about team effectiveness, about developer velocity. What&#8217;s below is my synthesis: the act of lining up findings from different research traditions and showing where they converge. The convergence is the argument. Each citation is a thread; the rope is the pattern across them.</p><div class="pullquote"><p style="text-align: center;"><em>If you&#8217;re new, welcome to Customer Obsessed Engineering! I publish about one article each week. Free subscribers can read about half of every article, plus all of my free articles.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/subscribe?"><span>Subscribe now</span></a></p><p style="text-align: center;"><em>Anytime you&#8217;d like to read more, you can upgrade to a paid subscription.</em></p></div><h2>A quick refresher on &#8220;product team&#8221;</h2><p>Before the data, let&#8217;s get precise. &#8220;Product team&#8221; gets thrown around so loosely it&#8217;s often meaningless.</p><p>Marty Cagan and the Silicon Valley Product Group draw the cleanest distinction. A <strong>product team</strong> is a small, durable, cross-functional unit &#8212; typically a product manager, a designer and a handful of engineers &#8212; that owns a problem and is held accountable for outcomes. They are <em>given problems to solve</em>, not features to ship. The product manager owns value and viability. The designer owns usability. The tech lead owns feasibility. Together they own the result.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><p>A <strong>feature team</strong> looks similar on paper &#8212; same disciplines around the table &#8212; but is handed a prioritized list of features to build. Outcomes belong to a stakeholder upstream. The team is judged on output: did you ship what was on the roadmap? Velocity, story points, throughput.</p><p>A <strong>project team</strong> is even further from product orientation. It&#8217;s pulled together to execute a discrete project, then dissolved. Specialists rotate in and out. There&#8217;s no durable home for product knowledge.</p><p>The labels matter less than the operating model. As I wrote in <a href="https://blog.bosslogic.com/p/what-a-product-oriented-team-looks-like">Building a product oriented team</a>, the real distinction is <em>durability, ownership and empowerment</em> &#8212; long-lived teams that own the whole product end-to-end and have the authority to figure out the <em>how</em>.</p><p>Now &#8212; what the research says.</p><h2>Receipt #1: they ship dramatically faster</h2><p>Start with DORA &#8212; the DevOps Research and Assessment program, founded by Dr. Nicole Forsgren and now part of Google. Every year since 2014, DORA has surveyed practitioners &#8212; more than 3,000 in 2024 alone, and tens of thousands across the decade-long program &#8212; and statistically grouped them into performance tiers based on four metrics: deployment frequency, lead time for changes, change failure rate and mean time to restore service. The methodology, the math and the conclusions are documented in <em>Accelerate</em> &#8212; the book that emerged from the research and won the Shingo Publication Award.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a></p><p>The 2024 <em>Accelerate State of DevOps</em> report is the latest. Elite-tier teams deploy <em>182 times more frequently than low performers, with 127&#215; faster lead time for changes</em>. Elite teams hit lead time under a day, deploy on demand and are roughly 19% of the surveyed population. Low performers measure lead time in months.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a></p><p>That&#8217;s not a marginal advantage. It&#8217;s not &#8220;20% better.&#8221; It&#8217;s two orders of magnitude.</p><p>You might be tempted to dismiss this as a DevOps story rather than a team-structure story. But every time DORA digs into <em>what</em> differentiates elite teams, the answers are the same attributes that define product teams: small, cross-functional, owning the whole pipeline from code to production, empowered to make their own technical decisions. The opposite &#8212; handoffs across functional silos with stage-gate approvals from external groups &#8212; correlates strongly with low performance. <em>Accelerate</em> presents one specific finding bluntly: external change advisory boards do not improve stability. They make lead time worse without making anything safer.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a></p><p>McKinsey&#8217;s &#8220;Beyond Agile&#8221; work, which I cited in <a href="https://blog.bosslogic.com/p/how-waterfall-is-wrong-for-software">How waterfall is wrong for software</a>, puts a number on the same effect from a different angle. Across their consulting engagements, McKinsey observed that companies could compress the average time from &#8220;code complete&#8221; to live production from <strong>89 days to 15 days</strong> when they reorganised around DevOps and product-team principles. Same basic architectures, same kind of features. Six times faster, just from changing how the team takes work from &#8220;done&#8221; to &#8220;deployed.&#8221;<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a></p><p>The simplest summary: product teams own the value stream end-to-end. Feature and project teams hand off across silos. Handoffs cost time. Time turns into distance from the customer. Distance from the customer means everything you ship is stale.</p><div class="pullquote"><p><em>This newsletter grows by word of mouth&#8230; I&#8217;d really, truly appreciate it if you could refer a friend. Your referrals make it worthwhile.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p></div><h2>Receipt #2: they get more done &#8212; but redefine what &#8220;done&#8221; means</h2><p>&#8220;More done&#8221; is the wrong metric. The right metric is: did anyone use what we shipped?</p><p>In 2002, Jim Johnson &#8212; chairman of the Standish Group &#8212; presented a finding at the XP conference in Sardinia that&#8217;s been quoted ever since: across enterprise applications, only 7% of features are &#8220;always&#8221; used, 13% are &#8220;often&#8221; used and 16% are used &#8220;occasionally.&#8221; That leaves <em>64% of features as either rarely or never used</em>. Standish later extended the analysis to claim that <em>roughly 80% of features deliver low or no value</em>. On large projects, Standish data shows organizations deliver only <em>42% of the features they originally scoped</em><strong>.</strong> The Standish numbers have drawn methodology critiques over the years &#8212; fair enough &#8212; but more recent work points the same direction. Pendo&#8217;s 2019 <em>Feature Adoption Report</em>, drawing on telemetry from hundreds of B2B SaaS products, found roughly <em>80% of features are rarely or never used</em>.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a></p><p>Sit with that for a moment.</p><p>Now, &#8220;rarely used&#8221; isn&#8217;t synonymous with &#8220;no value.&#8221; Some rare features are quietly essential &#8212; compliance flags, account recovery, the audit trail your CISO will ask about exactly once. Both Pendo and Standish gloss over that distinction. Even granting it generously, though, the ratios still point at a meaningful misallocation: a lot of effort going into features customers rarely or never engage with. (I&#8217;m looking at you, Microsoft Office).</p><p>A feature team measured on roadmap output is, by these numbers, building a sizable wedge of low-value work. They look terrific on burndown charts and terrible on customer impact.</p><p>I&#8217;ve watched this play out enough times to be cynical about it. A feature team gets a quarterly roadmap. They estimate the work in story points, deliver on schedule, demo a sleek end-to-end flow and get applauded. Six months later, telemetry shows the feature gets touched by 3% of users. By then the team has moved on to the next item on the roadmap. Nobody is accountable for the gap between &#8220;shipped&#8221; and &#8220;mattered,&#8221; because shipped <em>is</em> the goal.</p><p>A product team would have caught that earlier. They wouldn&#8217;t have built the full feature on a quarterly roadmap; they&#8217;d have built the cheapest possible version that tested the hypothesis &#8212; a prototype, an A/B variant, a deliberately ugly first cut &#8212; and watched the data. If the data said 3%, they&#8217;d have killed the feature in week two and gone after a more promising hypothesis. That&#8217;s the discovery discipline Marty Cagan and Teresa Torres write about extensively, and it&#8217;s the operational reason product teams build less and deliver more. Not because they&#8217;re slower. Because they aim differently. They invest in discovery before commitment. They kill a feature that doesn&#8217;t earn its keep. They redefine &#8220;done&#8221; from &#8220;shipped&#8221; to &#8220;moved the metric.&#8221; And the metric they move is customer behavior, not story points. (I&#8217;ve made the same argument from a measurement angle in <a href="https://blog.bosslogic.com/p/stop-measuring-effort-4ed827b470ae">Stop measuring effort</a>.)</p><p>There&#8217;s a parallel finding in McKinsey&#8217;s <em>What makes product teams effective?</em> &#8212; a five-year study of <em>more than 1,700 teams across 75 organizations</em>. McKinsey identified two structural conditions that consistently predict throughput and velocity improvements: dedicated team membership (no context switching across projects) and team persistence of three to six months minimum. Teams meeting both conditions develop reliable estimates and sustained throughput. Teams that don&#8217;t, can&#8217;t.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-7" href="#footnote-7" target="_self">7</a></p><p>That finding isn&#8217;t surprising if you think about how knowledge accumulates. Product orientation depends on knowledge durability &#8212; context that only forms when the same people work on the same problem long enough to internalise it (more on this below). Project teams dissolve before that happens. Feature teams reorganise around the next quarterly priority. Product teams stay put. That&#8217;s why their throughput compounds.</p>
      <p>
          <a href="https://blog.bosslogic.com/p/product-teams-really-do-outperform">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Your AI is not your mentor]]></title><description><![CDATA[Use it relentlessly for code tutoring. But the formation work &#8212; being seen, stretched and told the truth &#8212; has to come from a person.]]></description><link>https://blog.bosslogic.com/p/your-ai-is-not-your-mentor</link><guid isPermaLink="false">https://blog.bosslogic.com/p/your-ai-is-not-your-mentor</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Wed, 29 Apr 2026 11:12:33 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!QbVr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QbVr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QbVr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg 424w, https://substackcdn.com/image/fetch/$s_!QbVr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg 848w, https://substackcdn.com/image/fetch/$s_!QbVr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!QbVr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QbVr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:334100,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/195521876?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!QbVr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg 424w, https://substackcdn.com/image/fetch/$s_!QbVr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg 848w, https://substackcdn.com/image/fetch/$s_!QbVr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!QbVr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87e17719-c764-4d7b-80fc-d7c1b351cce2_3000x2000.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@terry_quangt?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Terry Tran</a> on <a href="https://unsplash.com/photos/silhouette-of-man-under-blue-sky-during-sunset-6IncPZISGAs?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><p>A junior developer told me they&#8217;re using Claude as a mentor. They liked the patience that never wore thin, the availability that never closed, the way they&#8217;re never made to feel doltish.</p><p>Here&#8217;s what worried me: they said <em>mentor</em>. Not tutor. <em>Mentor</em>.</p><p>I don&#8217;t think they&#8217;re wrong about what they&#8217;re getting. But mentorship isn&#8217;t about answers. It&#8217;s about being seen &#8212; watched while you struggle, nudged when you&#8217;re avoiding hard conversations, sent on projects that stretch you in ways you didn&#8217;t ask for. Mentors have the nerve to tell you the truth in private because they&#8217;re invested in who you&#8217;re becoming.</p><p>AI can&#8217;t do that. Because it isn&#8217;t invested in you. Because it&#8217;s not &#8220;in the room.&#8221;</p><div class="pullquote"><p><em>If you&#8217;re new, welcome to Customer Obsessed Engineering! I publish about one article each week. Free subscribers can read about half of every article, plus all of my free articles.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/subscribe?"><span>Subscribe now</span></a></p><p><em>Anytime you&#8217;d like to read more, you can upgrade to a paid subscription.</em></p></div><h2>What AI is genuinely good at</h2><p>Let&#8217;s start with what&#8217;s actually working, because this isn&#8217;t a piece about being suspicious of the tools. The tutoring story is real. It&#8217;s the part of the AI hype that&#8217;s actually earned.</p><p>Benjamin Bloom&#8217;s famous 1984 paper described what he called the &#8220;2 sigma problem:&#8221; students who received one-on-one tutoring performed two standard deviations better than students in conventional classrooms &#8212; that&#8217;s the difference between an average student and the top 2 percent. The catch was scale. Personal tutors are expensive, and most students will never have one. For forty years that gap has been the unsolved promise of education technology.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><p>A well-configured AI is one way we&#8217;re closing it. When Khan Academy rolled out Khanmigo, built on GPT-4, the pitch was exactly this &#8212; a patient, infinitely available one-on-one tutor for every learner. In specific narrow tasks, the early returns are hard to dismiss. Harvard published a physics study in 2024 that found students using a properly designed AI tutor learned over twice as much in less time than their peers. They reported feeling more engaged and motivated.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a></p><p>I see the same thing in software. With the right model, a serious system prompt and a few well-built skills, AI can:</p><ul><li><p>Walk a junior through a debugger session, naming what each frame means and why it matters.</p></li><li><p>Explain <em>why</em> a piece of code is the way it is &#8212; not just what it does &#8212; and adjust the explanation when the question lands a level too high.</p></li><li><p>Run unfamiliar code, watch it fail and reason about the failure with the learner in real time.</p></li><li><p>Drill someone on a foreign language, a SQL idiom or a regex until it&#8217;s automatic.</p></li><li><p>Take the same question for the third time without sighing.</p></li></ul><p>That last one matters more than people admit. A great deal of human learning gets blocked by the social cost of asking again. Removing that cost is genuinely useful. It&#8217;s what the junior in my opening responded to. They felt safe.</p><div class="pullquote"><p><em>Hey, quick favor? Writing this stuff takes real work &#8212; and referrals keep the publication alive. If you&#8217;re finding the playbook valuable, share it with a friend who&#8217;d appreciate the link.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p></div><h2>How tutoring goes wrong</h2><p>It&#8217;s useful, but not magical. The same AI cheerfully invents APIs that don&#8217;t exist, pattern-match on the wrong context and confidently produce code that looks right but isn&#8217;t. Apple researchers showed last year that current LLMs aren&#8217;t doing genuine reasoning at all &#8212; performance on math problems dropped by as much as 65 percent when the team added a single irrelevant clause to the prompt. Andrew Zuo&#8217;s piece on the &#8220;-10X developer&#8221; makes the harder point: when an LLM writes code at or above your level and introduces a subtle bug, you may be the worst possible person to find it.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a></p><p>A newer concern is harder to wave off. An MIT Media Lab study published in mid-2025 used EEG to compare brain activity across people writing essays with no help, with a search engine and with an LLM. The LLM group showed the weakest neural connectivity and the worst ability to recall their own writing minutes after producing it. The researchers called it &#8220;cognitive debt.&#8221; That tracks. Outsource the struggle and the learning never lands.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a></p><p>So a serviceable tutor, yes. A <em>replacement</em> for thinking, no. None of that, though, is the central point. The central point is that tutoring and mentoring are not the same job, and the public conversation keeps blurring them.</p><h2>What a mentor actually does</h2><p>If you ask me what my mentors did for me over the last forty years, almost none of it was answering technical questions. The technical content I could get from books, from peers, eventually from Stack Overflow and now from Claude (as long as I&#8217;m careful and look for fantasy hallucinations). What my mentors did was something else entirely.</p>
      <p>
          <a href="https://blog.bosslogic.com/p/your-ai-is-not-your-mentor">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[3.7 Elaboration]]></title><description><![CDATA[Elaboration takes your specifications from skeleton to sprint-ready, fully fleshed out across every layer at which the system is tested &#8212; and live-linked to the engineering models that prove them out.]]></description><link>https://blog.bosslogic.com/p/37-elaboration</link><guid isPermaLink="false">https://blog.bosslogic.com/p/37-elaboration</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Tue, 28 Apr 2026 13:32:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!RGTp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!RGTp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!RGTp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg 424w, https://substackcdn.com/image/fetch/$s_!RGTp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg 848w, https://substackcdn.com/image/fetch/$s_!RGTp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!RGTp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!RGTp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg" width="1456" height="931" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:931,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:351525,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/195610561?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!RGTp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg 424w, https://substackcdn.com/image/fetch/$s_!RGTp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg 848w, https://substackcdn.com/image/fetch/$s_!RGTp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!RGTp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff95a84ed-c7de-45a7-b86a-5af551a06efb_1728x1105.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In <a href="https://blog.bosslogic.com/p/36-specification">3.6 Specification</a> we worked through the first two stages of Behavior Driven Development &#8212; <em>Discovery</em> and <em>Formulation</em>. We surfaced scenarios in three-amigos conversations and shaped them into Gherkin &#8220;Given-When-Then&#8221; statements. That gave us the <em>outline</em> of every feature in our product increment.</p><p>Elaboration is where we move from outline to depth.</p><p>A very important takeaway from chapter 3.6 bears repeating here, because the entire purpose of this activity hangs on it:</p><blockquote><p>The specifications you write now are living documents. They will evolve, change and be added to. That&#8217;s why it&#8217;s so important to create a live link to the implementation &#8212; the code that will validate the specifications. As the specifications change that live link will preserve our value chain from customer desires to delivered code.</p></blockquote><p>Hold on to that idea. Elaboration isn&#8217;t about freezing requirements before the team writes a single line of code. It&#8217;s about building the connections &#8212; between the spec and the marble, between the marble and the test, between the test and the production code &#8212; that let the spec keep evolving without the value chain ever going slack.</p><h2>Introduction</h2><p>This activity has three jobs.</p><p>First, we expand each scenario across the <em>levels</em> at which the system is tested: component and assembly. A login feature has UX scenarios about what the customer sees and experiences. It also has assembly scenarios about which events fire, which commands route through which aggregates and what payload comes back. Both layers need specifications. Both layers need to be testable. Skipping a layer means leaving a gap through which defects love to slip.</p><p>Second, we create a live link between every specification and the engineering model that implements it. Each Gherkin feature points back to a marble. Each marble points forward to a Gherkin feature. That bi-directional link is what makes our specifications living documents &#8212; when the spec changes, the marble updates with it, and vice versa.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p>
      <p>
          <a href="https://blog.bosslogic.com/p/37-elaboration">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Microsoft’s collaboration stack breaks every rule of a modern delivery toolkit]]></title><description><![CDATA[How SharePoint will sink your project: hidden pitfalls that suck the life out of teams. It&#8217;s getting worse, not better.]]></description><link>https://blog.bosslogic.com/p/microsofts-collaboration-stack-breaks</link><guid isPermaLink="false">https://blog.bosslogic.com/p/microsofts-collaboration-stack-breaks</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Mon, 27 Apr 2026 18:13:08 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!vSFM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vSFM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vSFM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg 424w, https://substackcdn.com/image/fetch/$s_!vSFM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg 848w, https://substackcdn.com/image/fetch/$s_!vSFM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!vSFM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vSFM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg" width="1456" height="798" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:798,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:297114,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/195427732?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vSFM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg 424w, https://substackcdn.com/image/fetch/$s_!vSFM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg 848w, https://substackcdn.com/image/fetch/$s_!vSFM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!vSFM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc604e379-5a99-45aa-8d7a-1b113a2a1062_1787x979.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@felixberger?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Felix Berger</a> on <a href="https://unsplash.com/photos/aerial-view-of-broken-hanging-bridge-fZFUlC0l00E?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><div class="pullquote"><p>This article speaks to technical delivery teams with a voice in their tooling decisions. For teams mired in SharePoint and Teams with no way out &#8212; I introduce some strategies to make things better toward the end.</p></div><p>Picture this: a program manager wants to confirm a design decision before a release. She asks, innocently enough, &#8220;Can someone point me at the current version of the architecture document?&#8221;</p><p>A pause. Then: &#8220;I think it&#8217;s in the Teams channel &#8212; the one from the February workshop.&#8221; Someone else chimes in, &#8220;No, there&#8217;s a newer one. Sriram emailed it last week.&#8221; A third voice: &#8220;That&#8217;s the draft. The signed-off version is in the SharePoint site. But the link in the meeting invite is broken because they restructured the folders.&#8221; A fourth: &#8220;I have a copy in OneDrive. It might be the latest, I&#8217;m not sure.&#8221;</p><p>Five people. Five different versions. Zero confidence that any of them is authoritative. And this is a team that <em>cares</em> about documentation.</p><p>The common denominator is always the same: a collaboration stack built on SharePoint, Teams and Microsoft&#8217;s various Office products. Sometimes with Azure DevOps (ADO) bolted on to handle tickets and code.</p><p>Here&#8217;s an argument that will sound harsh to anyone who&#8217;s invested in Microsoft 365 as their delivery platform: the Microsoft collaboration stack is <em>diabolically deficient</em> for serious product delivery. It wasn&#8217;t built for the problem delivery teams <em>actually</em> face. It has, piece by piece, gone after what enterprise IT wanted to solve in 2007: replacing the file share.</p><p>That&#8217;s not the same problem.</p><div class="pullquote"><p style="text-align: center;"><em>If you&#8217;re new, welcome to Customer Obsessed Engineering! I publish about one article each week. Free subscribers can read about half of every article, plus all of my free articles.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/subscribe?"><span>Subscribe now</span></a></p><p style="text-align: center;"><em>Anytime you&#8217;d like to read more, you can upgrade to a paid subscription.</em></p></div><h2>What a delivery team actually needs</h2><p>There are five table stakes a team needs. I describe the first three in <a href="https://blog.bosslogic.com/p/getting-started-using-the-delivery">Getting started: Using the Delivery Playbook</a>. I&#8217;ll restate those briefly here, along with the other two:</p><p><strong>1. Live collaboration.</strong> Multiple people must be able to work on the same artifact at the same time, editing simultaneously, seeing each other&#8217;s cursors, throwing virtual sticky notes on a board in real time. Design work is a collaborative act. The moment one person has to collect and collate feedback, fidelity drops off a cliff.</p><p><strong>2. Version control.</strong> Every change, by every author, is always captured and reversible. Not just &#8220;saved revisions&#8221; &#8212; the full, granular history, searchable, with diffs, always available. This is table stakes. Git has had it for two decades. Any tool that tracks <em>less</em> than Git doesn&#8217;t take the goal seriously.</p><p><strong>3. Immutable linking.</strong> A document&#8217;s URL must <em>never</em> change. Not when the file is renamed. Not when it&#8217;s moved to another folder. Not when the folder is reorganized. Not when the author leaves the company. A reference made today should still resolve in five years. Without this, every link in every other document becomes a ticking time bomb.</p><p><strong>4. Workflow integration.</strong> The documentation platform has to talk, fluently and deeply, to the work-tracking platform. Specs have to link to tickets. Tickets have to link to pages. Status changes in one system should not only be visible in the other, but trigger cross-tool workflow changes and render live embeds, not stale URLs. When that integration is tight, your specs, documentation and tickets stop drifting apart &#8212; they become a single living view of the work, not several systems the team has to reconcile.</p><p><strong>5. Universal, web-first access.</strong> One consistent experience for everyone, on any device. Not a degraded web version and a feature-rich desktop app &#8212; a single canonical surface, served through the browser, that everybody gets equally no matter what hardware they&#8217;re on.</p><p>These five criteria are the measuring stick. Let&#8217;s hold SharePoint &#8212; and Teams and ADO &#8212; up against them.</p><h2>Links that rot</h2><p>This is the most damning, and the one I want to spend the most time on, because it&#8217;s the one almost nobody takes seriously until they&#8217;re knee-deep in the damage.</p><p>In SharePoint, a document&#8217;s URL is a function of its name and its location in the folder hierarchy. Rename the file, and the URL changes. Move it to another folder, and the URL changes. Move the whole folder, and the URLs of every file inside it change. You can turn on &#8220;managed metadata&#8221; and &#8220;content types&#8221; and a bunch of other gears that promise to fix this, but in practice &#8212; across every tenant I&#8217;ve ever touched &#8212; they don&#8217;t. The URLs change. References break.</p><p>Microsoft has shipped &#8220;durable links&#8221; and &#8220;document IDs&#8221; &#8212; features that are off by default and rarely enabled. What a team actually encounters is: you renamed the file, the link in the meeting invite from three weeks ago is now dead. The problem is pervasive enough that a cottage industry of third-party tools has emerged just to detect broken SharePoint links.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><p>Compare that to Atlassian Confluence. Every page has a numeric ID assigned at creation. The ID is embedded in the URL (<code>/pages/12345</code>) and it does not change. You can rename the page, move it between spaces, reorganize the whole tree &#8212; the ID-based link still works. You can also use the human-readable URL (which does change when pages get renamed), but the ID-based URL is your forever-address. The system gives you <em>both</em>, and the tight URL is the one you automatically get when you cite the page in another document.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a></p><p>This seems like a small, technical detail. It is not. It is the single most consequential design choice a documentation platform makes, because it determines whether cross-references decay or persist.</p><p>Here&#8217;s what happens in practice when links rot: <em>people stop trusting links.</em></p><p>Think about that for a second. The entire promise of the web is that a URL is a durable reference &#8212; it says &#8220;here is the canonical thing, go fetch it when you need it.&#8221; That promise is what lets us build systems on top of systems. Every meeting invite, every wiki page, every code comment, every email that cites a document relies on that promise holding.</p><p>When SharePoint breaks the promise &#8212; which it does, routinely &#8212; teams develop a defensive response. They stop linking. Instead, they <em>attach</em>. They paste a copy of the document into the meeting notes. They email a copy to the distribution list. They download the file and re-upload it to their own folder &#8220;in case the original moves.&#8221; Multiply this by every team, every document, every month, and within a year you have a document landscape that looks like a hoarder&#8217;s basement &#8212; dozens of near-duplicates, none of them canonical, each one owned by a different person who genuinely believes theirs is the latest.</p><p>It&#8217;s <em>rational</em> response. Given that SharePoint links are not reliable, hoarding copies is the locally optimal strategy. However, the result is catastrophic: information silos full of stale documents and an immense toll in lost time and miscommunication.</p><p>The identity model that a platform chooses shapes the behavior of the people using it. SharePoint chose the wrong model &#8212; one that breeds inefficiency and defensive silo-building.</p><h2>The version control mirage</h2><p>SharePoint technically has version control. Open a file, click the ellipsis, choose &#8220;Version history,&#8221; and you&#8217;ll see a list of saves. This sounds like what you want. It is not.</p><p>The version history in SharePoint is coarse, inconsistent across product surfaces and frankly untrustworthy. Here are the problems I&#8217;ve personally run into, repeatedly:</p><ul><li><p><strong>Coauthored Office documents roll up edits from multiple people into &#8220;a version&#8221; at intervals that are not deterministic.</strong> If Alice and Bob are editing at the same time, you may end up with one version of their joint work and inaccurate attribution. Contrast with Git: every commit is atomic, attributed and reversible.</p></li><li><p><strong>The version history for a file in OneDrive, Teams and elsewhere varies.</strong> There is no single source of truth. If you open a file with Teams, you see one history. In SharePoint, you may see a different history &#8212; a consequence of Office 365 evolving from a constellation of separately-designed products Microsoft is still trying to stitch together.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a></p></li><li><p><strong>Restoring a prior version </strong><em><strong>might </strong></em><strong>overwrite the current one, rather than branching.</strong> If you discover at 4pm that something important got lost at 10am, &#8220;restore&#8221; could mean losing everything done between 10am and 4pm. Until recently, this was the default behavior &#8212; so be careful.</p></li></ul><p>Confluence, again, does this properly. Every save is a version. Every version compares cleanly against any other. You see what changed, who changed it and when. You can restore a prior version <em>as a new version</em>, preserving full history. This is how version control is supposed to work, and it has been the standard behavior in software since RCS shipped in 1982.</p><p>Why does this matter for delivery? Because design artifacts evolve, and the history of how they evolved is often as valuable as the current state. When the security auditor asks, &#8220;When did we add this API endpoint to the threat model?&#8221; &#8212; the answer lives in the diff. When a customer says, &#8220;The contract we signed described a different data retention policy,&#8221; &#8212; the answer lives in the history. When a post-mortem asks, &#8220;When did we know about this failure mode?&#8221; &#8212; the answer lives in the version log.</p><p>A platform that can&#8217;t answer these questions reliably is a platform that is actively hostile to engineering rigor.</p><h2>Teams, Teams Sites and the organizing layer</h2><p>If the first two failures are about individual artifacts, this one is about the landscape those artifacts live in.</p><p>Microsoft Teams is, at heart, a chat application. When it was first released in 2017, that&#8217;s primarily what it did. Over the years, Microsoft has tried to turn Teams into a &#8220;hub for teamwork.&#8221; Marketing-speak for bolting everything else Microsoft makes onto the chat app. The Files tab in a Teams channel is a SharePoint document library wearing a trenchcoat. A &#8220;Teams Site&#8221; is a SharePoint site with a slightly different navigation chrome. Meeting recordings live in OneDrive, not in the channel. Meeting transcripts live in the meeting artifact, which sometimes appears in the channel and sometimes doesn&#8217;t. Planner tasks live in a separate product surface that is also &#8220;integrated.&#8221;</p><p>If someone in your team wants to find something, they have to know, in advance, through which product surface it was shared. Was the spec posted in a channel? Check the chat history. Attached to a meeting? Check the meeting recap. Uploaded to the Files tab? That&#8217;s SharePoint under the hood, but the folder structure might only be reachable through the Teams UI. Created as a Teams Site? Different URL. Shared in a meeting chat? That goes to OneDrive, in a folder you might not have permission to browse.</p><p>There is no single &#8220;where did we put the thing&#8221; surface. There are five or six of them, depending on how the team has been using the tools, and the mapping between &#8220;what kind of content&#8221; and &#8220;which surface&#8221; is convention rather than enforced policy.</p><p>In contrast, Confluence is the document surface. Jira is the work surface. Each is a single, distinct product doing one thing well, and the integration points between them are narrow and explicit and <em>they work</em>. No guessing where a document lives &#8212; it&#8217;s in Confluence. Tickets live in Jira. No impedance mismatch, no cognitive dissonance.</p><p>Teams wants to be the union of every Office 365 capability. But integration isn&#8217;t about putting everything in the same UI. It&#8217;s about making the right connections <em>between</em> distinct tools, so that each one stays simple and focused, and the connections carry exactly the semantics you need. Teams never understood that distinction.</p><h2>Desktop is king, the browser is second-class</h2><p>SharePoint and the rest of Office 365 are web-accessible, but they aren&#8217;t web-<em>first</em>. Their heritage is Microsoft Office &#8212; a suite designed for the desktop and perfunctorily ported to the browser. The difference is not academic.</p><p>Open a Word doc in the browser and compare it to the desktop app. The feature set diverges. Advanced formatting, compare-versions, certain macro and formula capabilities, add-ins &#8212; these are missing or degraded on the web.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a></p><p>The consequences cascade. &#8220;The copy you want is on my laptop&#8221; is a phrase I hear almost every week. Co-authoring gets flakey or breaks entirely because of diverging copies. Changes sit in someone&#8217;s sync queue for hours. A document that looks current in SharePoint may be stale. Information silos reappear &#8212; not because anyone intended it, but because the tool keeps pulling work off the web and onto individual machines.</p><p>Contrast with Confluence, Jira and Miro. Every one of them is web-first by design. There&#8217;s no desktop app with a superset of features. The browser <em>is</em> the product. Everyone gets the same experience &#8212; Windows, Mac, Linux, iPad, phone, Chromebook &#8212; because there&#8217;s only one experience to get. One canonical home, universally accessible, identical for everyone.</p><p>This is what the web was built for. Atlassian and Google stacks lean into that. Microsoft fights it.</p><h2>The ADO integration gap</h2><p>This one is specific to teams that pair SharePoint with Azure DevOps for their ticket tracking and code hosting. It&#8217;s a common combo, because &#8220;we already have Microsoft&#8221; is an easy procurement story, and ADO does a lot of things adequately.</p><p>But the integration between SharePoint and ADO is thin. Thin to the point of &#8220;here is a hyperlink from the work item to the SharePoint page, good luck.&#8221; There is no live embed. There is no bidirectional status update, rich preview or shared workflow trigger. If I link to a SharePoint page from an ADO work item, you see a URL. If that URL breaks, the work item becomes an orphan.</p><p>In contrast, a Jira issue in a Confluence page renders a live, interactive issue card with issue key, title, status, assignee and priority &#8212; and that card updates when the issue does. If I embed a Jira query in a Confluence page, the page shows a table of live results &#8212; as of right now. A Confluence page can be the <em>dashboard</em> for a delivery effort: status pulled from Jira, specs authored inline, risks tracked in a live table, all rendering from the underlying systems of record.</p><p>You can build most of this in the Microsoft stack with enough Power Automate flows, Graph API queries, custom connectors and a patient engineer. I&#8217;ve seen it attempted. I&#8217;ve yet to see it done well enough to matter. The effort required to get SharePoint + ADO to mimic what Confluence + Jira does out of the box is roughly the effort of a mid-size integration project &#8212; a project that has to be maintained, re-tested with every platform update, and reverse-engineered when the person who built it leaves the company. That&#8217;s not an integration. That&#8217;s a liability.</p><h2>Workflow is an afterthought</h2><p>The last failure is workflow management &#8212; specifically the modeling and enforcement of state transitions for work items.</p><p>Jira gets this right. The workflow editor is a first-class product, with a first-class visual flow designer, transition conditions, validators, post-functions, custom statuses and permission checks. A non-engineer on the delivery team can design a workflow that enforces &#8220;a ticket cannot transition from &#8216;In Review&#8217; to &#8216;Done&#8217; unless the code review is merged with clean quality gates, the responsible stakeholder has reviewed the feature and all acceptance criteria are passing green.&#8221; Express it in the GUI, save it, extend with code as needed and the tool enforces it across every ticket that follows that workflow. The team controls its own process &#8212; and the workflow itself is a first-class artifact: auditable, exportable, evolvable.</p><p>ADO has &#8220;process customization.&#8221; It is possible to model custom workflows. In practice the feature is buried behind an admin gate, its conditions are a shallow subset of Jira&#8217;s, and most teams I&#8217;ve worked with never meaningfully touch it. They either live with the default &#8212; generic, not their actual process &#8212; or they reinvent the enforcement in spreadsheets, PowerBI dashboards, or human oversight routines that have to be re-explained to every new hire.</p><p>The reason this matters: workflow is the mechanism by which a team&#8217;s process becomes automatic. If your workflow tool doesn&#8217;t let you encode &#8220;we agreed code reviews are mandatory before a feature branch is merged,&#8221; then code reviews are not mandatory &#8212; they&#8217;re optional, governed only by vigilance, and skipped the moment someone is under pressure. Jira&#8217;s workflow editor is a force multiplier for team discipline, because it turns &#8220;we agreed to do this&#8221; into &#8220;the tool won&#8217;t let you skip it.&#8221; ADO gives you a <em>significantly</em> weaker version of that lever, and most teams don&#8217;t reach for it at all.</p><p>The cost is reliability. Teams using Jira-style workflow enforcement ship with fewer process escapes &#8212; missing reviews, missed gates, skipped steps. Teams using ADO&#8217;s default setup rely on human memory and goodwill &#8212; both fail at scale. The difference shows up in incident rates, audit findings and the quality of the artifacts the team produces.</p><div class="pullquote"><p><em>This newsletter grows by word of mouth&#8230; I&#8217;d really, truly appreciate it if you could refer a friend. Your referrals make it worthwhile.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p></div><h2>What all this costs the team</h2><p>If you&#8217;re keeping a tally, the SharePoint/Teams/ADO stack fails on every criterion. Links don&#8217;t persist. Version control is a mirage. The organizing layer is fragmented. The browser is a second-class citizen. Integrations are absent or thin. Workflow is an afterthought.</p><p>What does this actually cost a delivery team?</p><p>It costs <em>time</em>. A lot of it. The 2024 Stack Overflow Developer Survey (65,000 respondents) found that 61% of developers spend more than 30 minutes every day just searching for answers &#8212; and 30% say knowledge silos hit their productivity ten or more times per week.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a></p><p>It costs <em>trust</em>. When the documentation landscape is chaotic, people stop trusting it as a source of truth. They start relying on oral tradition &#8212; &#8220;ask Alice, she knows&#8221; &#8212; and on personal copies. Key decisions stop being recorded in a place anyone can find. Onboarding becomes a six-month apprenticeship rather than a process a new hire can self-serve. Organizational memory degrades.</p><p>It costs <em>quality</em>. DORA's research (2022 State of DevOps Report) found that documentation quality is one of the most powerful amplifiers of engineering performance: teams with above-average documentation quality see 12.8x the organizational performance lift from the same technical practices compared to teams with poor documentation.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a></p><p>It costs <em>morale</em>. Engineers are, as a group, unusually sensitive to tool quality. I&#8217;ve seen engineers turn down offers, quit, or burn out over the cumulative drag of bad tooling. A team that feels its own stack is working against them never reaches its potential, however talented the individuals. Tool quality is retention strategy.</p><h2>Stuck with the stack? Fight back.</h2><p>If you&#8217;re committed to SharePoint, Teams and ADO for the next few years, none of the above changes that. But a handful of disciplines can reduce the damage. None will turn the Microsoft stack into Confluence &#8212; they just stop the bleeding.</p><p>Here&#8217;s six specific strategies you can follow:</p>
      <p>
          <a href="https://blog.bosslogic.com/p/microsofts-collaboration-stack-breaks">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[When to go waterfall]]></title><description><![CDATA[If you're working in a multi-modal organization you'll find this helpful: the canonical waterfall / agile decision tree.]]></description><link>https://blog.bosslogic.com/p/waterfall-versus-agile-decision-tree</link><guid isPermaLink="false">https://blog.bosslogic.com/p/waterfall-versus-agile-decision-tree</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Tue, 24 Mar 2026 11:46:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!-lm7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-lm7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-lm7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-lm7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-lm7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-lm7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-lm7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg" width="1456" height="925" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:925,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:243988,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/195331528?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-lm7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-lm7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-lm7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-lm7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47630fda-899d-4486-a4f2-9ec17e429b78_1500x953.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@marcusdallcol?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Marcus Dall Col</a> on <a href="https://unsplash.com/photos/waterfalls-photograph-u99NDO-4Wv8?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><p>I was recently asked to critique a new decision tree that helps teams decide between waterfall and agile when starting a new project. The intended outcome is to improve long-term results in the organization by giving teams the ability to make critical decisions quickly and accurately.</p><p>Overall, &#8220;good shift-left stuff&#8221; in my book. Anyhow, here&#8217;s the diagram I was asked to comment on:</p>
      <p>
          <a href="https://blog.bosslogic.com/p/waterfall-versus-agile-decision-tree">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Observability as architecture: why you can’t bolt it on later]]></title><description><![CDATA[Most teams treat observability like a nice-to-have. They&#8217;re building blind &#8212; and paying for it in ways they can&#8217;t even see.]]></description><link>https://blog.bosslogic.com/p/observability-as-architecture-why</link><guid isPermaLink="false">https://blog.bosslogic.com/p/observability-as-architecture-why</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Fri, 13 Mar 2026 21:25:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!3tAI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3tAI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3tAI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg 424w, https://substackcdn.com/image/fetch/$s_!3tAI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg 848w, https://substackcdn.com/image/fetch/$s_!3tAI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!3tAI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3tAI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg" width="1456" height="970" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:970,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:298690,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/194076785?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3tAI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg 424w, https://substackcdn.com/image/fetch/$s_!3tAI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg 848w, https://substackcdn.com/image/fetch/$s_!3tAI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!3tAI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4467c5c5-d788-44cd-9096-cd2ebdc216b9_2150x1433.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@supernov?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Edi Libedinsky</a> on <a href="https://unsplash.com/photos/girl-making-hand-gesture-on-her-face-1bhp9zBPHVE?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><p>I once joined a team that had been struggling with delivery for the better part of two years. Demos kept failing. Deployments kept crashing production. Rollbacks were so routine that the ops team had gotten eerily efficient at them. (I&#8217;ll refer back to the team later &#8212; let&#8217;s call the company &#8220;Acme&#8221;).</p><p>I remember one in particular. The team was demoing a reactive search feature &#8212; the kind of thing where you start typing a product name and suggestions appear in real time. Same idea as typing &#8220;penguins&#8221; into Google and getting &#8220;Penguins of Madagascar&#8221; as a suggestion.</p><p>The demo cratered. Someone typed a product name, and nothing happened. Twenty minutes of poking around later, the demo was cancelled. What struck me wasn&#8217;t the failure itself &#8212; it was the reaction. Nobody was surprised. Nobody expected it to work. &#8220;Maybe next time.&#8221;<sup><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></sup></p><p>Later that afternoon, a planned deployment seemed to have crashed a key service. All hands on deck for a rollback. The team executed quickly. Rollback done. They&#8217;d had a lot of practice.</p><p>Here&#8217;s what immediately jumped out at me: in both cases the team had zero operational intelligence. No telemetry. No metrics. No centralized logs. No traceability. No way to quickly zero in on a root cause. They were flying blind &#8212; and they&#8217;d been flying blind so long they&#8217;d forgotten what visibility even looked like.</p><p>And that&#8217;s why the reaction was the same each time. Abort. Rollback. &#8220;Afterward, we&#8217;ll figure out what&#8217;s wrong.&#8221;</p><p>The irony is that both failures had quick fixes. Each time, queries weren&#8217;t reaching a service because the wrong port was configured. Instead of changing the port and continuing, the team burned hours &#8212; even days &#8212; backtracking, diagnosing and trying again.</p><p>That experience crystallized something I&#8217;d been <em>feeling</em> for decades: observability isn&#8217;t a tool you add. It&#8217;s an architectural decision you make &#8212; or don&#8217;t. And the cost of not making it compounds in ways that are genuinely difficult to measure, precisely because you don&#8217;t have the instrumentation to measure them.</p><div class="pullquote"><p><em>If you&#8217;re new, welcome to Customer Obsessed Engineering! Every week I publish a new article, direct to your mailbox if you&#8217;re a subscriber. As a free subscriber you can read about half of every article, plus all of my free articles.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/subscribe?"><span>Subscribe now</span></a></p><p><em>Anytime you&#8217;d like to read more, you can upgrade to a paid subscription.</em></p></div><h2>The &#8220;flying blind penalty&#8221;</h2><p>In the old days &#8212; before cloud, before microservices, before systems became truly distributed &#8212; opacity was tolerable. You had a monolith on a few servers. If something broke, you SSH&#8217;d in, looked at logs, poked around. It might take hours, but there wasn&#8217;t that much territory to cover.</p><p>Modern systems don&#8217;t afford that luxury. A single user request could traverse dozens of services, touching databases, message queues, caches and external APIs along the way. Just today I participated in a sprint review discussing a database architecture that was <em>29 views deep.</em> A latency spike could originate in any one of those &#8212; or in the invisible interplay between the services that call them.</p><p>Without observability, you&#8217;re operating on instinct and prayer.</p><p>Here&#8217;s what that looks like in practice. A bug ships. It doesn&#8217;t manifest right away &#8212; it surfaces under load, or in a specific user segment, or under certain timing conditions. By the time anyone notices, users are already suffering. Now the team has to diagnose the problem. If they&#8217;re lucky, someone complains and provides enough detail to be helpful. They narrow down which service is involved, reproduce the issue, trace the flow of data through the system, find the root cause, fix it, deploy and verify.</p><p>The whole time, sweating over how many more customers are running into the problem.</p><p>Every single step without observability compounds in difficulty. You&#8217;re not just debugging &#8212; you&#8217;re doing archaeology at midnight, piecing together behavior from scattered artifacts across dozens of services.</p><p>With observability designed in from the start, you proactively see which service is degraded. You can drill into specific request traces. You can correlate logs across service boundaries. Mean time to detect and repair drops from hours to minutes &#8212; even becoming predictive.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a></p><p>DORA.dev research bears this out. Elite-performing teams &#8212; the ones deploying multiple times per day with sub-hour recovery times &#8212; aren&#8217;t elite because they have better engineers. They&#8217;re elite because visibility closes a critical gap: it&#8217;s a prerequisite for every other capability DORA measures. They can detect and diagnose problems before those problems cascade. Their systems are instrumented to answer questions the team hasn&#8217;t even thought to ask yet.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a></p><h2>What matters is how you think about the problem</h2><p>Monitoring and observability are not the same thing.</p><p><em>Monitoring</em> answers questions you anticipated. You watch CPU utilization, disk space, error rates. You set thresholds and alert when they&#8217;re exceeded. &#8220;Is the database up? Is the error rate spiking?&#8221; These are <em>known</em> questions about <em>known </em>conditions.</p><p><em>Observability</em> answers questions you haven&#8217;t thought of yet. It&#8217;s the ability to interrogate your system&#8217;s behavior without adding new instrumentation every time you have a new question. &#8220;Why is this specific user&#8217;s checkout so slow today when it was fine yesterday? What changed in the request path between those two deployments?&#8221;</p><p>Charity Majors &#8212; co-founder of Honeycomb and one of the sharpest voices on this topic &#8212; frames it as the difference between known-unknowns and unknown-unknowns. Monitoring handles the known-unknowns: the things you anticipated might go wrong. Observability handles the unknown-unknowns: the things you couldn&#8217;t have predicted. It empowers you to follow the breadcrumbs wherever they lead.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a></p><p>Monitoring is reactive. Observability is generative &#8212; it creates the conditions for discovery.</p><p>Daniela Miao, CTO of Momento, put it well in a Dev Interrupted episode: &#8220;By giving more visibility into what&#8217;s happening with your software, your application, you actually do enable development to be faster as well. It&#8217;s not just insurance for when something goes wrong.&#8221;<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a></p><p>That&#8217;s critical. Most teams think of observability as insurance &#8212; you invest in it to cushion the blow when things break. But the real dividend is velocity. Teams with strong observability ship faster because they can <em>see</em> the impact of their changes in real time. They don&#8217;t have to guess whether a deployment worked or a tweak to a query ran faster. They know.</p><h2>Why we don&#8217;t instrument on day one</h2><p><em>Early stage.</em> You&#8217;re shipping fast. Three or four services, maybe. Errors go to a text file. You&#8217;re small enough that you can hold the whole system in your head. Observability feels like overkill. &#8220;It&#8217;s in the logs, just read &#8216;em.&#8221;</p><p><em>Growth.</em> Suddenly there are ten services, and logs are scattered across different servers. You can&#8217;t correlate them anymore. Someone says &#8220;we should get a logging tool.&#8221; You pick one &#8212; Datadog, Splunk, whatever &#8212; and bolt it on. The instrumentation is inconsistent. Some services are covered, others aren&#8217;t. Metrics are sparse and don&#8217;t tell a coherent story. You&#8217;re reading fragmented logs from disparate systems and trying to correlate events in your head. It&#8217;s starting to fall apart.</p><p><em>Pain.</em> Now you have fifty services. Traffic has increased tenfold. Something breaks, and you&#8217;re still flying blind &#8212; not because you lack tools, but because the observability layer wasn&#8217;t <em>designed</em>. It was stitched on, piecemeal, after the fact. Different teams instrumented different things using different conventions. Tracing is incomplete. Metrics don&#8217;t correlate with logs. You&#8217;re paying more and more for tools that don&#8217;t give you the insight you need.</p><p>Here&#8217;s what&#8217;s easy to miss: that team <em>invested</em> in observability. They bought the tools. They checked the box. But because every investment was reactive &#8212; a logging platform when logs got painful, a metrics dashboard when someone asked for one, a tracing system when debugging got unbearable &#8212; they ended up with three separate systems that don&#8217;t talk to each other. Logs in one silo, metrics in another, traces in a third. Every decision about what to capture was made at write time, under pressure, for a specific fire they were fighting that week.</p><p>Charity Majors, co-founder of Honeycomb, calls this Observability 1.0: many pillars, many sources of truth, many tools. It&#8217;s what you get by default when you bolt observability on after the fact. The fragmentation isn&#8217;t a failure of effort &#8212; it&#8217;s a consequence of timing. You can&#8217;t design a unified telemetry model when you&#8217;re patching gaps reactively.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a></p><p>And it matters &#8212; because a fragmented model can answer the questions you anticipated (is the database up? is the error rate spiking?) but collapses when you need to ask something new. &#8220;Why are checkouts slow today when they were fine yesterday? What changed between those two deployments?&#8221; Those questions require slicing across dimensions you didn&#8217;t pre-define. They require the kind of open-ended interrogation that siloed tools simply can&#8217;t support.</p><p><em>Insight</em> requires <em>design.</em> That&#8217;s the part teams miss.</p><p>Why does this happen? Because observability isn&#8217;t a feature. It&#8217;s not something you built first, it&#8217;s what got built <em>last.</em> It doesn&#8217;t generate revenue &#8212; at least not visibly. It feels expensive up front. And teams, under pressure to deliver, don&#8217;t demand the time they need for planning a solid foundation.</p><p>I&#8217;ve written about the same false economy with <a href="https://blog.bosslogic.com/p/when-should-you-think-about-security">security</a> and <a href="https://blog.bosslogic.com/p/delivering-customer-value-with-bdd">testing</a>. The things that feel expensive to build at the start turn out to be astronomically more expensive to retrofit.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-7" href="#footnote-7" target="_self">7</a></p><h2>Why it has to be architectural</h2><p>You can&#8217;t add observability with a library import. You <em>can</em> add logging and metrics &#8212; that&#8217;s the easy part. But genuine observability, the kind that lets you answer arbitrary questions about system behavior, requires architectural forethought.</p><p>Consider what&#8217;s involved:</p><ol><li><p><strong>How do requests get identified as they flow across boundaries?</strong> Trace IDs need to propagate through HTTP headers, message queue metadata, database session context &#8212; everywhere a request touches. If you don&#8217;t design this in, you can&#8217;t correlate activity across services.</p></li><li><p><strong>What events merit recording?</strong> Not every line of code should produce a log. That&#8217;s noise. But the meaningful transitions &#8212; state changes, boundary crossings between services, external calls and their response characteristics &#8212; these are the signals that matter.</p></li><li><p><strong>What metrics actually reflect system health?</strong> Not just CPU and memory, but application-level indicators. How long do payment transactions take? What&#8217;s the cache hit ratio? What&#8217;s the queue depth trend? These are the metrics that tell you whether your system is <em>behaving</em> &#8212; or trending toward overload.</p></li><li><p><strong>How does context propagate?</strong> When a request carries metadata &#8212; a customer ID, a feature flag, a request source &#8212; how does that context flow through the system in a way that key transitions are captured seamlessly?</p></li></ol><p>This is the shape of how you structure services, how you handle requests, how you organize code. And capturing it after the fact is brutally hard.</p><p>For example: if you decide later that you want end-to-end tracing, you need to add trace ID generation at your entry points, thread those IDs through every service-to-service call, correlate logs using those IDs, and store traces in a specialized backend. That means touching every API, every RPC, every async boundary. If you&#8217;d built it in from the start, it&#8217;s a few lines of middleware.</p><p>Consider structured logging: if you&#8217;ve been writing freeform string logs for two years, migrating to structured JSON events means auditing every logging statement, retrofitting context and rewriting every query your team depends on. If you start with structured logs, it&#8217;s just how things work from day one.</p><p>It&#8217;s not expensive when you build it in. It&#8217;s a handful of decisions, many of which improve things by introducing consistency. OpenTelemetry standardizes the plumbing &#8212; trace propagation, metric collection, structured logging &#8212; across languages and frameworks. You focus on <em>what</em> to instrument, not <em>how</em> to propagate context.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-8" href="#footnote-8" target="_self">8</a></p><p>But retrofitting: that&#8217;s an ordeal. Orders of magnitude more expensive &#8212; in engineering time, in tool sprawl and in the debugging sessions that never needed to happen.</p><h2>What to actually build</h2><p>Here&#8217;s how to do it right &#8212; whether you&#8217;re making the investment in an old project or starting fresh. The key is to think in events, not pillars.</p><h3>Start with events, not tools</h3><p>The most consequential decision you&#8217;ll make is how you model your telemetry. Do you emit three separate streams &#8212; logs here, metrics there, traces somewhere else &#8212; and try to correlate them after the fact? Or do you start with a single primitive: one structured event per unit of work?</p><p>The event-first approach works like this: when a request enters your system, you begin composing a structured event &#8212; a wide, context-rich record that accumulates everything meaningful about that request as it flows through your services. By the time the request completes, the event carries the trace ID, service name, duration, user ID, feature flags, error state, dependency latencies, cache hits, queue depths &#8212; whatever context matters.</p><p>You store that event once. From that single store, you can <em>derive</em> everything else: aggregate events over time and you get metrics; filter and read individual events and you get logs; stitch events together by trace ID and you get traces. One source of truth, many views.</p><p>This is what Charity Majors calls Observability 2.0 &#8212; and it&#8217;s the architecture that actually delivers on the promise of answering questions you haven&#8217;t thought of yet. Because the events are wide (carrying dozens or hundreds of fields), you can slice by any dimension after the fact. You didn&#8217;t have to anticipate the question at write time. You just ask it: &#8220;show me all events where <code>cache_hit=false</code> and <code>region=eu-west</code> and <code>latency_p99 &gt; 2s</code>.&#8221; If those fields are in the event, you get your answer.</p><p>Compare that to the three-pillars approach, where you'd need to have predefined that specific metric, logged that specific combination, and hoped your tracing tool captured the right spans. Three tools, three queries, three partial answers &#8212; if you&#8217;re lucky.</p><p>The event model is the architectural decision. Everything else follows from it.</p><div class="pullquote"><p><em>This newsletter grows by word of mouth&#8230; I&#8217;d really, truly appreciate it if you could refer a friend. Your referrals make it worthwhile. And this button earns you free access!</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p></div><h3>Establish a trace ID convention</h3><p>Every request gets a unique identifier the moment it enters your system. That ID propagates through every downstream call &#8212; HTTP headers, message metadata, database session context. Every event includes it.</p><p>This is foundational. Without it, you cannot correlate activity across service boundaries. With it, a single ID connects every event across every service for a given request. It&#8217;s what lets you stitch individual events into a complete trace &#8212; the full journey of a request through your system.</p><p>OpenTelemetry handles those mechanics gracefully. Use it. It&#8217;s language-agnostic, framework-aware and it solves the propagation problem so you don&#8217;t have to.</p><h3>Enrich your events at every boundary</h3><p>Not every line of code should produce telemetry. That&#8217;s noise. The moments that matter are the boundaries and transitions &#8212; the points where a request crosses from one domain to another or where state changes meaningfully:</p><ol><li><p><strong>Request entry</strong> &#8212; what arrived, who initiated it, what context it carried.</p></li><li><p><strong>External calls</strong> &#8212; what you called, what came back, how long it took.</p></li><li><p><strong>State changes</strong> &#8212; meaningful transitions: a payment processed, a queue depth shifted, a circuit breaker tripped.</p></li><li><p><strong>Errors</strong> &#8212; always, with full context. Stack traces, request metadata, the works.</p></li></ol><p>At each of these boundaries, you&#8217;re not firing off a disconnected log line &#8212; you&#8217;re enriching the event that represents this unit of work. Add fields: <code>payment_gateway_latency_ms=302</code>, <code>cache_hit=false</code>, <code>feature_flag_new_checkout=true</code>. The event gets wider and richer as the request progresses. When the request completes, it captures the full story.</p><p>Make every field structured and discrete. Not a freeform string like &#8220;User 12345 logged in from 192.168.1.1&#8221; &#8212; but named fields: <code>user_id=12345</code>, <code>source_ip=192.168.1.1</code>, <code>session_id=abc</code>, <code>duration_ms=47</code>. Structured fields are queryable. &#8220;Show me all login failures for user 12345 in the last hour&#8221; becomes a single query instead of a regex excavation.</p><h3>Derive your metrics from the same data</h3><p>Once you have rich, structured events flowing through a single store, metrics become a view &#8212; not a separate system. You aggregate events to spot trends:</p>
      <p>
          <a href="https://blog.bosslogic.com/p/observability-as-architecture-why">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[How waterfall is wrong for software]]></title><description><![CDATA[We've known for decades waterfall and software don't mix; why do we keep doing it?]]></description><link>https://blog.bosslogic.com/p/how-waterfall-is-wrong-for-software</link><guid isPermaLink="false">https://blog.bosslogic.com/p/how-waterfall-is-wrong-for-software</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Sun, 08 Mar 2026 12:23:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!uzY8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uzY8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uzY8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg 424w, https://substackcdn.com/image/fetch/$s_!uzY8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg 848w, https://substackcdn.com/image/fetch/$s_!uzY8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!uzY8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uzY8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg" width="1456" height="972" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:972,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:288740,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/193494434?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uzY8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg 424w, https://substackcdn.com/image/fetch/$s_!uzY8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg 848w, https://substackcdn.com/image/fetch/$s_!uzY8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!uzY8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b69733e-60ee-463c-b7aa-f42a2b3075d5_1500x1001.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://www.pexels.com/photo/iguazu-falls-1203565/">Rodolfo Clix</a></figcaption></figure></div><p>You&#8217;re working on an automotive assembly line. Your job is to install the steering column assembly and steering wheel. The next car rolls down the line. You grab the parts and lean in, tools in hand and try to fit the column. It won&#8217;t fit. Something&#8217;s off.</p><p>You look closely and realize the mounting point isn&#8217;t where it should be &#8212; it&#8217;s offset by a few inches. You figure, you&#8217;ll try anyway. No good. Worse, the chassis is aluminum and your steel column will cause galvanic corrosion on contact. You think to yourself &#8212; maybe this car is supposed to have something else entirely &#8212; a joystick, perhaps? You&#8217;re going to need time to research the platform and figure out what belongs here. But you&#8217;re out of time. The line grinds to a halt. Delivery stops. Something unforeseen has surfaced, and you need time to research the right solution.</p><p>That&#8217;s not how automotive assembly lines work. But it <em>is</em> how software works. Building software is about research, discovery and development.</p><div class="pullquote"><p><em>I&#8230;</em></p></div>
      <p>
          <a href="https://blog.bosslogic.com/p/how-waterfall-is-wrong-for-software">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[What happens when the next developer has to understand your AI code?]]></title><description><![CDATA[This study into the long-term cost of AI-driven development reveals some surprising findings. Most other studies only examine short-term outcomes. But what's the long-term impact of AI coding?]]></description><link>https://blog.bosslogic.com/p/when-the-next-developer-gets-your-ai-code</link><guid isPermaLink="false">https://blog.bosslogic.com/p/when-the-next-developer-gets-your-ai-code</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Fri, 30 Jan 2026 13:57:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/b9EbCb5A408" length="0" type="image/jpeg"/><content:encoded><![CDATA[
      <p>
          <a href="https://blog.bosslogic.com/p/when-the-next-developer-gets-your-ai-code">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[3.6 Specification]]></title><description><![CDATA[Before coding we need to make sure our design has enough fidelity. Specification is about adding those details, the happy paths as well as the failure scenarios, so we're confident moving into coding.]]></description><link>https://blog.bosslogic.com/p/36-specification</link><guid isPermaLink="false">https://blog.bosslogic.com/p/36-specification</guid><pubDate>Wed, 28 Jan 2026 13:06:36 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Z2qZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Z2qZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Z2qZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Z2qZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Z2qZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Z2qZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Z2qZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg" width="1456" height="1008" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1008,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:661819,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/185831127?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Z2qZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Z2qZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Z2qZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Z2qZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc64a983-67e4-4412-8a52-1f52629a6750_2104x1457.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="pullquote"><p>Behavior Driven Development (BDD) is an important part of refining our specifications. Take a look at this <a href="https://blog.bosslogic.com/p/delivering-customer-value-with-bdd">short companion article</a> to learn <em>why BDD is so important and how it fills gaps that other quality and test practices don&#8217;t.</em></p></div><h1>Introduction</h1><p>This activity is about making sure we&#8217;ve taken the time to think about happy paths as well as failure scenarios. It&#8217;s about adding fidelity to our use cases so that our finished product is a <em>quality</em> product &#8212; one that our customers will enjoy using.</p><p>As part of that process, we&#8217;ll explore variations on the <em>scenarios</em> in our design. For example, we&#8217;ve defined a scenario to make a purchase &#8212; but what about when the credit authorization fails? Or the product isn&#8217;t available in the warehouse? Or our customer adds a duplicate product to the shopping cart? What should we do if the customer abandons their shopping cart?</p><p>Working with your team to think through these scenarios &#8212; poking each scenario, prodding to see if it stands up under pressure, adding new paths if it doesn&#8217;t &#8212; will help ensure our design is solid.</p><div class="pullquote"><p><em>Writing good material is hard work &#8212; that&#8217;s why referrals are so important. Referrals let me know you like my work and keep me writing. Please share this article with a friend!</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;referrer_token=2xiufs&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://blog.bosslogic.com/leaderboard?&amp;referrer_token=2xiufs&amp;utm_source=post"><span>Refer a friend</span></a></p></div><h2>Building better specifications</h2><p>This activity isn&#8217;t just about testing our assumptions &#8212; it&#8217;s about creating better designs. We want to be sure we&#8217;ve thought about how code will be used <em>before</em> we build it. This outside-in pressure tends to produce interfaces that are cleaner, more focused and easier to consume, as well as code that is more reliable.</p>
      <p>
          <a href="https://blog.bosslogic.com/p/36-specification">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[How to fix a $25 bug before it becomes a $37,500 problem]]></title><description><![CDATA[Stop debugging and start designing by "shifting left" with BDD. It's not about testing. It's about feedback loops and thinking clearly about intent before diving into implementation.]]></description><link>https://blog.bosslogic.com/p/delivering-customer-value-with-bdd</link><guid isPermaLink="false">https://blog.bosslogic.com/p/delivering-customer-value-with-bdd</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Sat, 24 Jan 2026 10:11:32 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!FFyU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faddf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FFyU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faddf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FFyU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faddf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg 424w, https://substackcdn.com/image/fetch/$s_!FFyU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faddf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg 848w, https://substackcdn.com/image/fetch/$s_!FFyU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faddf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!FFyU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faddf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FFyU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faddf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg" width="1456" height="1010" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/addf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1010,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:377269,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/185074351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faddf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!FFyU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faddf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg 424w, https://substackcdn.com/image/fetch/$s_!FFyU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faddf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg 848w, https://substackcdn.com/image/fetch/$s_!FFyU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faddf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!FFyU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faddf5f48-7f99-4363-b1c9-6fa145aec39b_2104x1460.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="pullquote"><p>As I wrote Chapter 3.6 of the <a href="https://blog.bosslogic.com/s/delivery-playbook">Delivery Playbook</a> (and it started getting too big), I realized the outsize importance of Behavior Driven Development. It&#8217;s fundamental to the playbook. I<em>t protects product and customer value throughout the software lifecycle. So I decided to split this out as a companion article. I hope you find it as essential a practice as I do.</em></p></div><h1>The incident</h1><p>On June 4, 1996, the maiden flight of the European Space Agency's Ariane 5 rocket ended in catastrophic failure. About 40 seconds into its flight sequence, at an altitude of about 3,700 meters, the launcher veered off its flight path, broke up and exploded.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><p>The cost for this failure was estimated to be $370 million. The rocket was carrying four satellites intended to study the earth&#8217;s magnetosphere. Because of the payload&#8217;s destruction, building new satellites delayed scientific research into the magnetosphere for four more years.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a></p><p>An elaborate and careful investigation into the cause of the failure was conducted.</p><p>While several factors led to a cascade of events, it came down to a data conversion error &#8212; an error that would have been caught in testing.</p><p>Unfortunately, the internal SRI software exception that caused the problem <em>was never tested</em>. Or, more specifically, it wasn&#8217;t tested in the Ariane 5 configuration. The failure resulted because Ariane 4-era software that used 16-bit signed integers had been plugged into a more modern system &#8212; a system that used 64-bit floating point data. The older Ariane 4 SRI software couldn&#8217;t cope with the new data format.</p><p>That&#8217;s the <em>technical</em> reason.</p><p>There&#8217;s a more important lesson here. The <em>real</em> reason for the failure was <em>human error</em>. Somewhere along the line, a decision was made: the decision that the Ariane 4 SRI module didn&#8217;t need to be retested in the new Ariane 5 configuration.</p><p>The investigatory board pointed to an underlying theme in Ariane 5 development as a root cause, that theme being, &#8220;that software should be considered correct until it is shown to be at fault.&#8221; The board took another view. Their belief was, &#8220;that software should be assumed to be faulty until applying the currently accepted best practice methods can demonstrate that it is correct.&#8221;</p><p>Systems <em>must be tested</em> to prove correct behavior. We cannot simply <em>assume</em> they are correct.</p><div class="pullquote"><p><em>If you&#8217;re new, welcome to Customer Obsessed Engineering! Every week I publish a new article, direct to your mailbox if you&#8217;re a subscriber. As a free subscriber you can read about half of every article, plus all of my free articles.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/subscribe?"><span>Subscribe now</span></a></p><p><em>Anytime you&#8217;d like to read more, you can upgrade to a paid subscription.</em></p></div><h2>Preventable failure</h2><p>The key takeaways from the Ariane 5 disaster are:</p><ol><li><p>We cannot rely on software to be reliable <em>unless currently accepted best practices demonstrate that it is correct</em>.</p></li><li><p>Continuous integration and testing for correctness is necessary &#8212; <em>even when correctness has previously been proven</em>.</p></li></ol><p>The Ariane 5 case is widely taught in software engineering courses as the canonical example of how a simple, preventable defect &#8212; discovered late in the lifecycle (during operation) &#8212; can have catastrophic and costly consequences.</p><p>In fact, we know that the longer we wait to discover a defect, the more costly it is to fix. Research dating back to the 1970&#8217;s says we can fix a defect in design for nearly zero additional cost &#8212; or we can wait until production and spend north of <em>100 times the cost</em> to fix it later (Boehm, 1979).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qzTw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44be23db-e741-4aba-88b3-f816108d384f_1567x1212.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qzTw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44be23db-e741-4aba-88b3-f816108d384f_1567x1212.png 424w, https://substackcdn.com/image/fetch/$s_!qzTw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44be23db-e741-4aba-88b3-f816108d384f_1567x1212.png 848w, https://substackcdn.com/image/fetch/$s_!qzTw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44be23db-e741-4aba-88b3-f816108d384f_1567x1212.png 1272w, https://substackcdn.com/image/fetch/$s_!qzTw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44be23db-e741-4aba-88b3-f816108d384f_1567x1212.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qzTw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44be23db-e741-4aba-88b3-f816108d384f_1567x1212.png" width="610" height="471.7445054945055" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/44be23db-e741-4aba-88b3-f816108d384f_1567x1212.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1126,&quot;width&quot;:1456,&quot;resizeWidth&quot;:610,&quot;bytes&quot;:320044,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/185074351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44be23db-e741-4aba-88b3-f816108d384f_1567x1212.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qzTw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44be23db-e741-4aba-88b3-f816108d384f_1567x1212.png 424w, https://substackcdn.com/image/fetch/$s_!qzTw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44be23db-e741-4aba-88b3-f816108d384f_1567x1212.png 848w, https://substackcdn.com/image/fetch/$s_!qzTw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44be23db-e741-4aba-88b3-f816108d384f_1567x1212.png 1272w, https://substackcdn.com/image/fetch/$s_!qzTw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44be23db-e741-4aba-88b3-f816108d384f_1567x1212.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This exponential curve isn&#8217;t arbitrary. It reflects the reality that as software progresses through development stages, each defect becomes increasingly entangled with other code. Downstream systems begin to depend on it.</p><p>A requirements misunderstanding caught in design costs a conversation to fix. The same misunderstanding caught after integration means code rework, integration testing, release cycles, product updates and coordination across downstream dependencies. It can cascade into updating <em>multiple </em>products.</p><p>In concrete terms, that $25 defect can be fixed early, &#8220;for free,&#8221; or we can wait until later and spend $2,500 <em>or more</em>.</p><p>And there&#8217;s evidence that a 100X cost factor is by no means the upper limit. More recent research, in some cases, point to a factor of 1,500X cost to correct defects in operations. That $25 design defect just turned into a $37,500 cost to correct. There&#8217;s no upper limit &#8212; as the Ariane 5 team learned. (If you&#8217;re interested in reviewing more recent data there are references to NIST, NASA and Westland research in the footnotes).<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a></p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/kAo3E/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f7e1b101-0e1b-4f7f-ac7b-fc59308742eb_1220x504.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b43083a8-9fba-435d-be05-764bcd26b63e_1220x504.png&quot;,&quot;height&quot;:226,&quot;title&quot;:&quot;Cost to Correct&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/kAo3E/1/" width="730" height="226" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><p>But there&#8217;s good news. We know how to prevent failures: By applying software quality assurance policies and practices &#8212; and pairing them with rigorous software testing.</p><h1>Applying best practices</h1><p>Test Driven Development (TDD) and Behavior Driven Development (BDD) are fundamental strategies to move defect detection left on the graph &#8212; ideally all the way to the design phase where cost is lowest.</p><p>Both practices create proofs that prevent defects. What&#8217;s more, they rely on executable specifications that <em>prevent regression</em>. Even after initial development, the test suite continues to catch defects early. A change that inadvertently breaks existing behavior is caught in seconds during the next test run &#8212; not discovered in production by users.</p><p>This ongoing protection is particularly valuable as systems age and original developers move on &#8212; the tests preserve institutional knowledge about intended behavior. Imagine how powerful it would have been if the Ariane 4 SRI module had included a continuously run regression test sequence.</p><p>The fundamental promise isn&#8217;t about testing &#8212; it&#8217;s about creating better designs. Both practices demand writing tests first. That forces thinking about how code will be used <em>before</em> thinking about how it will be built. This outside-in pressure tends to produce interfaces that are cleaner, more focused, and easier to consume, as well as code that is more reliable.</p><h2>The deeper point</h2><p>TDD and BDD aren&#8217;t really about testing at all. They&#8217;re about feedback loops and thinking clearly about intent before implementation. The tests are a byproduct &#8212; valuable, but secondary to the discipline of thoroughly articulating what you want <em>before</em> you build it.</p><p>Critics often attack the testing artifacts while missing this point entirely. It&#8217;s not always about going faster or whether every scenario needs to be test-driven. It&#8217;s whether your development process includes mechanisms that force clarity of thought and protect against regression. Both TDD and BDD are proven ways to achieve that.</p><div class="pullquote"><p>I&#8217;d really, truly appreciate it if you could refer a friend. Writing takes a lot of time and effort. Your referrals make it worthwhile. And this button earns you free access!</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p></div><h2>TDD or BDD?</h2><p>TDD catches implementation errors immediately. When you write a failing test before writing code, you discover mismatches between intent and implementation within minutes, not days or weeks.</p><p>The feedback loop is so tight that &#8220;debugging&#8221; often becomes unnecessary. When a test fails you know exactly what change caused it.</p><p>Compare this to traditional development where bugs lurk undetected until integration, verification or even user experience &#8212; by which point the original context has faded. Investigation becomes archaeological, time consuming and costly.</p><p>What TDD does well is clarify the boundaries of your system. Code that&#8217;s hard to test is often code with unclear responsibilities or excessive coupling. Even if you don&#8217;t achieve full coverage, attempting TDD reveals where your architecture needs attention.</p><p>But TDD has a limitation: it doesn&#8217;t &#8220;shift left&#8221; <em>enough</em> on our error discovery graph.</p><p>TDD is largely a <em>technical</em> exercise, focused on functional specification. As such it can get deep into the weeds of a feature &#8212; but may fail to rise to the level of <em>product behavior</em>. In other words, we might be applying our test-driven thinking to a conceptual design that is <em>already defective</em>.</p><p>That&#8217;s why I prefer BDD.</p><h1>Behavior Driven Development</h1><p>Behavior Driven Development is a collaborative approach that evolved from Test Driven Development. It bridges the gap between technical and business team members by expressing specifications as concrete examples, written in plain language everyone can understand (the &#8220;Given-When-Then&#8221; style, or Gherkin format).</p>
      <p>
          <a href="https://blog.bosslogic.com/p/delivering-customer-value-with-bdd">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Transform your standups and retros: intention matters more than status updates]]></title><description><![CDATA[Do you try to skip your standup? Or feel like retros are a waste of time? Then your team isn&#8217;t doing it right. Here's my formula for giving your team agency and getting real value from both.]]></description><link>https://blog.bosslogic.com/p/the-secret-to-effective-standups-and-retros</link><guid isPermaLink="false">https://blog.bosslogic.com/p/the-secret-to-effective-standups-and-retros</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Wed, 14 Jan 2026 17:33:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!3JD0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3JD0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3JD0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg 424w, https://substackcdn.com/image/fetch/$s_!3JD0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg 848w, https://substackcdn.com/image/fetch/$s_!3JD0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!3JD0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3JD0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg" width="1456" height="917" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:917,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:441088,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/184429434?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3JD0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg 424w, https://substackcdn.com/image/fetch/$s_!3JD0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg 848w, https://substackcdn.com/image/fetch/$s_!3JD0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!3JD0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F175db0be-1ad9-4c79-ae6c-584e19f4313c_2781x1752.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>A daily standup is a great idea &#8212; <em>provided it&#8217;s done right.</em></p><p>A well-run standup:</p><ol><li><p>Is a place to foster collaboration and mindshare.</p></li><li><p>Provides a forum to get help.</p></li><li><p>Makes sure the team doesn&#8217;t spiral.</p></li></ol><p>Unfortunately, most standups that I join don&#8217;t do any of these things. Quite the opposite. These standups impede productive work, acting as a needless interruption that offers almost no value.</p><p>More often than not what I see is a team forced to stand together while each team member robotically itemizes their work since the last sprint. In some miserable cases, the &#8220;PM&#8221; and one or two team members hold the entire team hostage while a specific problem is diagnosed.</p><p>The standup stretches to 30 or 40 minutes. Your eight person team takes a cumulative <em>five hour hit</em> to their productivity.</p><h2>Create value in your standups</h2><p>If you Google &#8220;questions to ask at a standup&#8221; you&#8217;ll find the worst culprit sitting right at the top of the list: &#8220;what did you do since yesterday?&#8221;</p><p><em>Ban this question.</em></p><p>Almost just as bad is, &#8220;wha&#8230;</p>
      <p>
          <a href="https://blog.bosslogic.com/p/the-secret-to-effective-standups-and-retros">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Part 3: Refining our data pipeline architecture to solve a few hidden challenges]]></title><description><![CDATA[Ensuring scalability, reliability and responsiveness pose interesting problems in distributed architecture. Here&#8217;s how to build a forward-looking foundation.]]></description><link>https://blog.bosslogic.com/p/part-3-solving-hidden-pipeline-architecture-challenges</link><guid isPermaLink="false">https://blog.bosslogic.com/p/part-3-solving-hidden-pipeline-architecture-challenges</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Thu, 08 Jan 2026 18:09:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!_eQy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_eQy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_eQy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!_eQy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!_eQy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!_eQy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_eQy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg" width="1200" height="800" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:800,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:303905,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/183379913?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_eQy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!_eQy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!_eQy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!_eQy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bfb7c25-5f38-4a4d-9e91-77861669350e_1200x800.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://www.rawpixel.com/image/11991758">Image</a> by <a href="https://www.rawpixel.com/">rawpixel.com</a></figcaption></figure></div><div class="pullquote"><p>In this third article on data pipelines, we&#8217;ll firm up our architecture before coding. We&#8217;ll make sure all of our requirements have been adequately addressed (there are still a few missing pieces). We&#8217;ll also review our design to make sure all goals have been met. The finished architecture needs to provide a responsive, scalable and reliable foundation.</p></div><p>In the <a href="https://blog.bosslogic.com/p/part-2-a-practical-data-pipeline-architecture">previous article</a> I introduced a foundational architecture for our <em>data pipeline</em>, checking off several of our requirements. Here&#8217;s a quick recap:</p><ol><li><p>We leveraged an internal cache for <em>isolation</em> to break our dependency on external data sources, improving our resiliency and scalability options.</p></li><li><p>We introduced the idea of an <em>asynchronous</em> message architecture, so we aren&#8217;t bound by lengthy, sequential processes.</p></li><li><p>We keep our annotations long-term with <em>internal persistence</em> so we don&#8217;t reprocess data when unnecessarily.</p></li><li><p>Source data as treated as an <em>immutable source,</em> thus protecting our data integrity.</p></li><li><p>Our visualization layer is responsive, running off our internal cache so that it&#8217;s independent from other components.</p></li></ol><p>Here&#8217;s a sketch of the architecture as it stands now:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_gty!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03197c57-3741-4942-b657-e86624ade27a_988x326.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_gty!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03197c57-3741-4942-b657-e86624ade27a_988x326.png 424w, https://substackcdn.com/image/fetch/$s_!_gty!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03197c57-3741-4942-b657-e86624ade27a_988x326.png 848w, https://substackcdn.com/image/fetch/$s_!_gty!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03197c57-3741-4942-b657-e86624ade27a_988x326.png 1272w, https://substackcdn.com/image/fetch/$s_!_gty!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03197c57-3741-4942-b657-e86624ade27a_988x326.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_gty!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03197c57-3741-4942-b657-e86624ade27a_988x326.png" width="988" height="326" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/03197c57-3741-4942-b657-e86624ade27a_988x326.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:326,&quot;width&quot;:988,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:50364,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/183379913?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03197c57-3741-4942-b657-e86624ade27a_988x326.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_gty!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03197c57-3741-4942-b657-e86624ade27a_988x326.png 424w, https://substackcdn.com/image/fetch/$s_!_gty!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03197c57-3741-4942-b657-e86624ade27a_988x326.png 848w, https://substackcdn.com/image/fetch/$s_!_gty!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03197c57-3741-4942-b657-e86624ade27a_988x326.png 1272w, https://substackcdn.com/image/fetch/$s_!_gty!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03197c57-3741-4942-b657-e86624ade27a_988x326.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>It&#8217;s a good start, but we aren&#8217;t finished.</p><p>There are still two requirements that don&#8217;t have a clear solution:</p><ol><li><p>We want to be able to reprocess data, effectively &#8220;rewinding history&#8221; and applying new analytics. For instance, if we add a new analysis and insight to our pipeline, how are we going to go back and view that new analysis on old data?</p></li><li><p>Finally, we want to be able to model our insights &#8212; that is, visualize it in a presentation layer. But we haven&#8217;t talked about <em>how</em> that&#8217;s going to happen.</p></li></ol><p>Once we tackle those last few requirements, we&#8217;ll fill in some details &#8212; such as, deciding on a cache technology to use. We&#8217;ll also take an end-to-end look at what we&#8217;ve designed to see if we missed something important. </p><div class="pullquote"><p>If you&#8217;re new, welcome to Customer Obsessed Engineering! Every week I publish a new article, direct to your mailbox if you&#8217;re a subscriber. As a free subscriber you can read about half of every article, plus all of my free articles.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/subscribe?"><span>Subscribe now</span></a></p><p>Anytime you&#8217;d like to read more, you can upgrade to a paid subscription.</p></div><h1>Finishing our foundation</h1><p>One of the most powerful and underused capabilities in data analytics is the ability to reprocess historical data with new logic. When you fix a bug in your analysis or refine a calculation, you often want to know: &#8220;what would the last three months have looked like with this new logic?&#8221;</p><p>Fortunately, our design thus far aligns pretty well with this goal.</p><p>Essentially, all we are saying we need to do is throw out information that is no longer accurate and then reprocess the source data and rebuild a new and improved picture of the world. We might do this for a couple of reasons:</p><ol><li><p>We changed our analytics. Consequently, we need to throw out all of our old findings and recalculate our insights.</p></li><li><p>The source data changed. Perhaps there was a historical data update, invalidating our findings. Again, we want to throw out our findings and reprocess.</p></li></ol><p>Looking at the problem from that perspective, the architectural answer is simple: we need a way to delete our annotations.</p><p>Once we wipe our annotations, we&#8217;ll need to make sure they are recalculated. There are different strategies we could use, but for the most part our options are:</p><ol><li><p>Rebuild our annotations on-demand. This is fine if we&#8217;re OK with a bit of a delay while we wait for analytics to run. Depending on our visualization strategy we might be able to break the work up and trade one big delay for a few small delays.</p></li><li><p>Alternatively, rebuild our annotations preemptively. We might do it as soon as we realize there&#8217;s data to analyze, or perhaps we have some kind of schedule or external trigger. The point here is, we run the analysis <em>before</em> we think a user will want to visualize it.</p></li></ol><p>We&#8217;ll add these capabilities to our architecture diagram. That means responding to both <em>external</em> data changes as well as <em>internally</em> sourced changes.</p><h2>Rewinding history</h2><p>To &#8220;rewind and reprocess,&#8221; we&#8217;ll just delete our annotations and then make sure there&#8217;s a mechanism to rebuild them. Here&#8217;s an example chain of events we&#8217;ll model in our architecture:</p><ol><li><p><em>Administrative user</em> invalidates some (or all) of the annotations we&#8217;ve stored in our cache:</p><ol><li><p>Optionally, if the data was invalidated because source data changed, the system loads fresh data from the external data source.</p></li><li><p>The system deletes or otherwise invalidates the annotations in our cache.</p></li><li><p>An event such as &#8220;analysis invalidated&#8221; (with some metadata, perhaps a date range) is emitted.</p></li></ol></li><li><p>The <em>analytics service</em> is listening for events, and receives the &#8220;analysis invalidated&#8221; event:</p><ol><li><p>The event includes the date range of deleted data. The service checks the date range to see if annotations are missing from the cache.</p></li><li><p>If the data is still missing, it runs the analysis and rebuilds the missing annotations.</p></li><li><p>As annotations are rebuilt, they are written to the cache.</p></li><li><p>An event such as &#8220;analysis completed&#8221; (with some metadata) is emitted.</p></li></ol></li><li><p>Separately, a <em>visualization</em> service might be running where a user asks to display the visualization for some missing data:</p><ol><li><p>The system checks the cache, realizes annotations are still missing, and sends a &#8220;run analysis&#8221; message directly to the <em>analytics service</em>.</p><ol><li><p>The <em>analytics service</em> is already working on analyzing the data so it can ignore the message, or respond with an &#8220;analytics in process&#8221; message.</p></li></ol></li><li><p>The visualization presents some kind of &#8220;waiting for analysis&#8221; display while it listens for the &#8220;analysis completed&#8221; message. When it receives the message, it loads the annotations and displays them.</p></li></ol></li></ol><p>This is one way to handle a specific chain of events. We&#8217;ll need to handle other events and commands as well &#8212; such as an event to tell us external data has changed.</p><p>Since we&#8217;re talking about <em>responding to events that happen</em>, it makes sense to use <a href="https://blog.bosslogic.com/p/34-tactical-event-storming">event storming</a> to model those events and commands. We can model &#8220;things that have happened&#8221; (the events) as yellow cards, and &#8220;what we want to happen&#8221; (the commands) as blue cards.</p><p>If you need a refresher, <a href="https://blog.bosslogic.com/p/23-strategic-event-storming">Chapter 2.3 Strategic event storming</a> and <a href="https://blog.bosslogic.com/p/34-tactical-event-storming">Chapter 3.4 Tactical event storming</a> provide in-depth explanations on modeling event driven architectures.</p><p>Here&#8217;s an updated architectural drawing showing how our events and commands interact with the system:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LpRE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98606045-feed-451c-a057-0cb9d769266d_1291x659.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LpRE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98606045-feed-451c-a057-0cb9d769266d_1291x659.png 424w, https://substackcdn.com/image/fetch/$s_!LpRE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98606045-feed-451c-a057-0cb9d769266d_1291x659.png 848w, https://substackcdn.com/image/fetch/$s_!LpRE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98606045-feed-451c-a057-0cb9d769266d_1291x659.png 1272w, https://substackcdn.com/image/fetch/$s_!LpRE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98606045-feed-451c-a057-0cb9d769266d_1291x659.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LpRE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98606045-feed-451c-a057-0cb9d769266d_1291x659.png" width="1291" height="659" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/98606045-feed-451c-a057-0cb9d769266d_1291x659.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:659,&quot;width&quot;:1291,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:126204,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/183379913?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98606045-feed-451c-a057-0cb9d769266d_1291x659.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!LpRE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98606045-feed-451c-a057-0cb9d769266d_1291x659.png 424w, https://substackcdn.com/image/fetch/$s_!LpRE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98606045-feed-451c-a057-0cb9d769266d_1291x659.png 848w, https://substackcdn.com/image/fetch/$s_!LpRE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98606045-feed-451c-a057-0cb9d769266d_1291x659.png 1272w, https://substackcdn.com/image/fetch/$s_!LpRE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98606045-feed-451c-a057-0cb9d769266d_1291x659.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Using event storming to model behaviors that occur in our architecture.</figcaption></figure></div><div class="pullquote"><p><em>Can I ask a favor? Do you know someone that would like this article? Please send it to them. Referrals keep this publication alive and growing. (And you&#8217;ll earn free access, too).</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p></div><h2>Persistent annotation cache</h2><p>One of the things we haven&#8217;t decided yet is exactly <em>how</em> we&#8217;ll store our annotation data. There are quite a few options, and certainly more than one strategy that will work well.</p><p>In <a href="https://blog.bosslogic.com/p/part-2-a-practical-data-pipeline-architecture">part two</a> I hinted at using a relational database to store a copy of the external source data. This makes a lot of sense, but it isn&#8217;t the only option.</p><p>We could store all of our data in a persistent data store such as <a href="https://www.mongodb.com/">MongoDB</a>, a noSQL document-oriented database. Document databases offer some fantastic search capabilities and, perhaps most interesting, don&#8217;t force us into a predefined schema &#8212; we can, essentially, attach <em>anything</em> as our annotations.</p><p>That&#8217;s a nifty idea, because we want flexibility to change our data analysis and come up with new data sets to store, freely associating them with source data.</p><p>We could also stick with a purely event-driven architecture. In this kind of system, we would emit annotations as events into a persistent queue (such as <a href="https://kafka.apache.org/">Kafka</a>). The persistent queue becomes our source of truth &#8212; and annotations are just messages on the queue, like, &#8220;sprint X: total out-of-sprint hours: 500.&#8221;</p><p>With many options, it&#8217;s probably a good idea to decide on our business requirements:</p><ol><li><p>Obviously, we want to cache the original source data, so we aren&#8217;t tightly coupled to an external system. (We know the external system is a relational database).</p></li><li><p>We want to easily create new annotation data sets. If we dream up a new calculation (maybe, &#8220;number of activities completed after hours on Fridays&#8221;), we want to be able to store it easily.</p></li><li><p>We know we&#8217;re using DataFrames for analysis. Storing our DataFrames without translating them into something else would be convenient (but not necessary).</p></li><li><p>Our annotation data should be persistent (to avoid unnecessary delays rerunning an analysis) &#8212; but, once a particular report or visualization is no longer being used, we probably don&#8217;t need to keep it around.</p></li><li><p>Finally, we&#8217;ll want to think about performance and wait times. We definitely don&#8217;t want users to experience a slow system.</p></li></ol><p>The relational cache for source data still makes a lot of sense.</p><p>For our internal annotation data, something more flexible is desirable. We don&#8217;t want to be constrained by a relational schema, forced to update the schema every time we think up a new report or annotation.</p><p>While a noSQL solution seems like a good fit, it may be an unnecessary complication. It would afford long-term persistence, but unless we run into performance problems that long-term persistence may be pointless.</p><p>Designing for flexibility makes sense.</p><p>We&#8217;ll implement our internal annotation cache as a service. The service will:</p><ol><li><p>Allow us to store annotations (data structures) in a persistent fashion (but, not necessarily permanently).</p></li><li><p>Provide a shared data service (allowing other services to leverage the shared data).</p></li><li><p>Give us scalability (we can boost processing power or memory, start up multiple copies, or upgrade to a more powerful data store technology).</p></li><li><p>Allow us to start simple, just storing annotation data in memory. A long-running service might give us all we need (after all, we&#8217;d only rebuild our annotations if we restart the server).</p></li></ol><p>Let&#8217;s update our architecture diagram one more time:</p>
      <p>
          <a href="https://blog.bosslogic.com/p/part-3-solving-hidden-pipeline-architecture-challenges">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[3.5 Modeling]]></title><description><![CDATA[Engineering models eliminate mistakes & complexity, ensure better testing & reliability, and improve collaboration & understanding.]]></description><link>https://blog.bosslogic.com/p/35-modeling</link><guid isPermaLink="false">https://blog.bosslogic.com/p/35-modeling</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Mon, 29 Dec 2025 21:18:21 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!BQC2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BQC2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BQC2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg 424w, https://substackcdn.com/image/fetch/$s_!BQC2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg 848w, https://substackcdn.com/image/fetch/$s_!BQC2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!BQC2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BQC2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg" width="1456" height="926" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:926,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:992020,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/182565880?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!BQC2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg 424w, https://substackcdn.com/image/fetch/$s_!BQC2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg 848w, https://substackcdn.com/image/fetch/$s_!BQC2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!BQC2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb538905-5d89-4cc4-b560-6a2ca5f81aad_2759x1755.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@nypl?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">The New York Public Library</a> on <a href="https://unsplash.com/photos/68NORlOLXUc?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure></div><div class="pullquote"><p>Your modeling style is a complex topic. Accordingly, I recommend you read these two companion articles before diving in: <a href="https://blog.bosslogic.com/p/technical-drawings-that-work">Applying marble &amp; sequence diagrams</a> and <a href="https://blog.bosslogic.com/p/why-being-declarative-is-your-competitive-advantage">Using &#8220;declarative thinking&#8221; to establish stronger controls</a>.</p></div><h2>Introduction</h2><p>This activity creates fidelity in our <em>engineering models</em> &#8212; the diagrams and specifications that give us enough technical depth so we can proceed to coding.</p><p>Everything we&#8217;re going to build should be modeled. That might sound like of lot of work, but with the right drawings and specification style, it&#8217;s not &#8212; plus, our models should be <em>reusable.</em> For instance, once I&#8217;ve modeled my implementation of a circuit breaker, I don&#8217;t have to model it again. I can just use that circuit breaker design everywhere I need it.</p><p>The approach I&#8217;ll introduce here increases the fidelity of your technical designs using data inputs and outputs, paired with very clear and specific functional results. It builds on your existing engineering artifacts and further validates your value stream, making sure alignment with business objectives is maintained. We capture our control processes and at the same time enhance communication among those designing the solution.</p><div class="pullquote"><p><em>Hey, can I ask a favor? Writing good material is an investment &#8212; and referrals keep this publication alive. Please take a moment to send this article to a friend.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p></div><p>One of the challenges with modeling is deciding on what&#8217;s effective yet not overly constraining or complex. We want to define some clear standards of practice and make sure the engineered product is fit for purpose. At the same time, teams should have the flexibility to take a different path <em>if that different path is more fit for purpose</em>.</p><p>The modeling approach we use in the Delivery Playbook meets those goals:</p><ul><li><p>We define engineering artifacts using two specific diagram types, neither of which are difficult to understand or use.</p></li><li><p>Clear objectives are defined while giving teams enough freedom to follow a different path &#8212; <em>so long as those objectives are met</em> using whatever approach they choose to follow.</p></li></ul>
      <p>
          <a href="https://blog.bosslogic.com/p/35-modeling">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Part 2: Steel thread first: a practical data pipeline architecture]]></title><description><![CDATA[Learn how to build a sound data pipeline architecture, from the ground up, using an iterative approach that ships fast and scales.]]></description><link>https://blog.bosslogic.com/p/part-2-a-practical-data-pipeline-architecture</link><guid isPermaLink="false">https://blog.bosslogic.com/p/part-2-a-practical-data-pipeline-architecture</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Mon, 22 Dec 2025 16:59:15 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!YefJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YefJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YefJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg 424w, https://substackcdn.com/image/fetch/$s_!YefJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg 848w, https://substackcdn.com/image/fetch/$s_!YefJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!YefJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YefJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg" width="1456" height="945" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:945,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:430731,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/182280551?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YefJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg 424w, https://substackcdn.com/image/fetch/$s_!YefJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg 848w, https://substackcdn.com/image/fetch/$s_!YefJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!YefJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The Trans-Alaska Pipeline, one of the world&#8217;s largest pipeline systems.</figcaption></figure></div><div class="pullquote"><p>In this second article on data pipelines I&#8217;ll show you how to build a foundational data pipeline architecture that stays true to requirements. At the same time, we&#8217;ll keep the architecture sound and simple; something we can scale, but also something we can build quickly. This aligns with the idea of launching a <a href="https://blog.bosslogic.com/p/solve-delivery-with-a-steel-thread">steel thread</a> &#8212; rapidly delivering an architecturally complete system.</p></div><p>In the <a href="https://blog.bosslogic.com/p/data-pipelines-are-really-cool">previous article</a> I introduced <em>data pipelines</em>, highlighting their ubiquity and a few of the challenges you&#8217;ll face architecting a good data pipeline. Here&#8217;s a quick recap of those requirements:</p><ol><li><p><em>Moving data efficiently.</em> Pipelines are all about making sure the right data gets to the right place at the right time, in the right format. For many applications, like air traffic control or the stock market, timing is everything. The architecture has to scale, meeting demand without degrading &#8212; often with life-saving implications.</p></li><li><p><em>Data integrity.</em> This is about ensuring the source data is what we think it is &#8212; incorruptible, unchanged as it moves through the pipeline. We have to make sure there&#8217;s no data loss, no translation errors, no dropped information. Yet, at the same time, pipelines are fundamentally about <em>processing</em> that data, deriving new insights from it.</p></li><li><p><em>Non-destructive annotation.</em> Being able to <em>add</em> to the data in the pipeline efficiently and flexibly is key. This makes it possible to create new insights from the source data &#8212; but it implies a schema that can grow in unpredictable ways.</p></li><li><p><em>Rewinding history.</em> Pipelines evolve, refining their algorithms and adding new processing steps. When we fix a bug or refine a calculation, we need to know, &#8220;what would the last three months have looked like with this new logic?&#8221; If we can&#8217;t reprocess the data we&#8217;ll never know if an inflection point in our analysis was due to a different calculation or new business conditions.</p></li><li><p><em>Surfacing discoveries and creating actionable insight.</em> All of these steps need to culminate in <em>actionable intelligence.</em> Getting those pieces to work together, then correlating all that disparate data and presenting it clearly, logically, can present its own challenges. Does the data processing sequence matter? How does one element depend on another? What happens when your analysis depends on external data or fundamentally different data structures?</p></li></ol><p>In this article, we&#8217;ll develop a foundational data pipeline architecture. I&#8217;ll approach the architecture iteratively &#8212; beginning with something simple, exploring whether it fits our purpose, and refining it. Our final architecture will provide a foundation that can grow into a scalable, powerful data pipeline platform.</p><p>For our use case, we&#8217;ll design an application that tracks team activity across projects in an organization. Our goal in tracking all this information is to deliver new <em>business intelligence</em> that gives useful, actionable insights into team efficiency across the organization. That&#8217;s intelligence we can use to remove bottlenecks, improve team productivity and velocity, eliminate wasteful process and more.</p><div class="pullquote"><p><em>If you&#8217;re new, welcome to Customer Obsessed Engineering! Every week I publish a new article, direct to your mailbox if you&#8217;re a subscriber. As a free subscriber you can read about half of every article, plus all of my free articles.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/subscribe?"><span>Subscribe now</span></a></p><p><em>Anytime you&#8217;d like to read more, you can upgrade to a paid subscription.</em></p></div><h1>What are we measuring?</h1><p>Before we get started, it&#8217;s a good idea to know what we&#8217;re trying to influence. We want to surface insights, not just tables and charts. The difference between data and intelligence is <em>whether it impacts our decisions</em>.</p><p><em>Actionable intelligence</em> changes what you do next.</p><p>For our test case we want to develop a better understanding of team efficiency. There&#8217;s an existing body of work that covers <a href="https://blog.bosslogic.com/p/context-switching-is-killing-your-gains-part-2-85be456e6d92">this topic</a>, and we&#8217;ll leverage it.</p><p>Our plan is pretty simple. Following the principles of a <em>waste walk,</em> we&#8217;ll have team members tell us whether their day-to-day activities are creating bottlenecks or inefficiencies or draining their effectiveness. They&#8217;ll do this by capturing activities and marking them as &#8220;in sprint&#8221; or &#8220;out of sprint.&#8221; (If you aren&#8217;t familiar with those terms, take a look at <a href="https://blog.bosslogic.com/p/data-pipelines-are-really-cool">part one</a> of this series).</p><p>We&#8217;re going to assume this data is available &#8212; perhaps coming from a JIRA dashboard or other time tracking application. I&#8217;ve actually built a mobile-friendly application that does this. It&#8217;s part of a waste walk analytics platform in use today. For our purposes, what matters is the data &#8212; not the mobile app.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><p>The data schema is straight-forward. Team members are <code>Users</code>, they track their individual <code>Activities</code>, and each <code>Activity</code> belongs to a <code>Sprint</code>.</p><p>If we diagram out the basic data model, it would look like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!a8GE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0770fbc9-a710-47c2-b442-d9a3260cd665_1550x2562.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!a8GE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0770fbc9-a710-47c2-b442-d9a3260cd665_1550x2562.png 424w, https://substackcdn.com/image/fetch/$s_!a8GE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0770fbc9-a710-47c2-b442-d9a3260cd665_1550x2562.png 848w, https://substackcdn.com/image/fetch/$s_!a8GE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0770fbc9-a710-47c2-b442-d9a3260cd665_1550x2562.png 1272w, https://substackcdn.com/image/fetch/$s_!a8GE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0770fbc9-a710-47c2-b442-d9a3260cd665_1550x2562.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!a8GE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0770fbc9-a710-47c2-b442-d9a3260cd665_1550x2562.png" width="372" height="614.9752747252747" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0770fbc9-a710-47c2-b442-d9a3260cd665_1550x2562.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:2407,&quot;width&quot;:1456,&quot;resizeWidth&quot;:372,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;activity-model.png&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="activity-model.png" title="activity-model.png" srcset="https://substackcdn.com/image/fetch/$s_!a8GE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0770fbc9-a710-47c2-b442-d9a3260cd665_1550x2562.png 424w, https://substackcdn.com/image/fetch/$s_!a8GE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0770fbc9-a710-47c2-b442-d9a3260cd665_1550x2562.png 848w, https://substackcdn.com/image/fetch/$s_!a8GE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0770fbc9-a710-47c2-b442-d9a3260cd665_1550x2562.png 1272w, https://substackcdn.com/image/fetch/$s_!a8GE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0770fbc9-a710-47c2-b442-d9a3260cd665_1550x2562.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The <em>activity</em> data schema we&#8217;ll be using in our pipeline.</figcaption></figure></div><p>As you can see, <code>Teams</code> are also modeled (so we can manage sprints and their team members as a group), and every activity has an <code>Activity Stereotype</code>. These stereotypes are basically the <em>kinds</em> of activities team members can track in the system. They can&#8217;t just record a random event; instead, they pick an activity from a list of &#8220;stereotypes&#8221; like &#8220;meeting,&#8221; &#8220;writing code&#8221; or &#8220;story refinement.&#8221;</p><p>We&#8217;ll take a look at the specific fields in a little while. For now, we have a conceptual understanding of the data &#8212; that&#8217;s what we need to move forward.</p><h2>Data versus insight</h2><p>Given the data we have available, we need to ask ourselves: what kind of insights can we derive from the source data? How might those insights change our behavior?</p><p>Here are a few ideas:</p><ol><li><p>If team members spend too much time doing activities that could be automated, we&#8217;d want to prioritize automation &#8212; letting those team members get back to more important work.</p></li><li><p>If a lot of time goes into investigating defects, we would probably want to know about it so we could investigate <em>why</em> we have so many defects (and fix the root cause).</p></li><li><p>It would also be informative to know <em>when</em> the team works on fixing defects; is it after the product ships, early in design, or somewhere in-between? Early defect correction is much better than late defect correction.</p></li><li><p>A lot of planning late in the product lifecycle &#8212; for instance, planning <em>after</em> a sprint has started &#8212; might indicate opportunities to improve coordination or design process. Late-stage planning often creates bottlenecks for team members.</p></li><li><p>If individuals feel their time in sprint ceremonies and meetings is not productive, we should probably investigate why they feel that way &#8212; especially if it&#8217;s a lot of time.</p></li><li><p>If we knew how many different things team members had to juggle, it might influence how we prioritize work and <em>focus time</em> for the team.</p></li><li><p>Probably most important: we want to know, across the organization, exactly how much time is going into inefficient or wasteful activity. A small amount is fine, but in aggregate, the time and effort <em>lost</em> could be costing us more than we realize.</p></li></ol><p>I&#8217;ve done these kinds of analyses for many teams &#8212; and the insights are almost always transformative. Just one example: one team found they were spending close to 23% of their time on activities that could be entirely automated. The effort was spread out, of course &#8212; an hour here, another there. At an individual level, it was about a day&#8217;s effort each week, tweaking manual deployments, doing environment tuning, &#8220;sanity testing&#8221; in staging and production.</p><p>Now scale it up. For a team of eight, that&#8217;s 150 hours <em>per sprint</em>. Stated another way, by investing in automation, <em>the team would get back 150 productive hours every single sprint and their quality of life would be improved at the same time.</em> Knowing those numbers, prioritizing Infrastructure as Code (&#8220;IaC&#8221;) for deployments, automating those repetitive &#8220;sanity tests&#8221; &#8212; suddenly makes a lot of sense.</p><h2>Transforming raw data into insight</h2><p>We know what data is available to us. But how do we transform it into actionable intelligence we can use to create better outcomes?</p><p>The raw data doesn&#8217;t really get us there. That&#8217;s where the data pipeline comes in &#8212; by transforming that data into something we can use:</p><ol><li><p>First we need to &#8220;intake&#8221; our source data. Once we can access it, we can analyze it, of course.</p></li><li><p>Then, we transform the data into what we need. We aren&#8217;t planning anything overly complicated (at least, not yet). Here&#8217;s the gist of what we need to do:</p><ol><li><p>Separate &#8220;in sprint&#8221; versus &#8220;out of sprint&#8221; activity. We&#8217;ll be focusing on the out of sprint activities or, in Lean Engineering terms, the &#8220;non-value add&#8221; effort. This &#8220;non-value add&#8221; work is where we&#8217;ll find our biggest gains.</p></li><li><p>Summarize data about activities. For example, we&#8217;ll need a way to add up all the activities that could be automated. That tells us how much effort is spent here.</p></li><li><p>We also want to be able to count up and somehow tally the <em>time between activities</em> (the &#8220;context switching time&#8221;) for each team member &#8212; probably as some kind of aggregate or average number.</p></li></ol></li><li><p>Of course, we&#8217;ll want to visualize the results.</p></li></ol><p>That all seems very straight forward. The first logical step is to think about how we&#8217;re getting our source data.</p><div class="pullquote"><p><em>Hey, can I ask a favor? Writing good material is an investment &#8212; and referrals keep this publication alive. Please take a moment to send this article to a friend.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p></div><h2>Start with the source data</h2><p>The first thing we need is our source data. Fortunately for us, it&#8217;s readily available and easy to access.</p><p>Our tracking application stores all this activity data in a SQL database, using a traditional relational format. That makes a lot of sense &#8212; it&#8217;s a relatively static data structure, and the relationships between teams, users, sprints, and activities are clearly hierarchical.</p><p>One approach is to just <em>read the data directly from the SQL database.</em> This would be the easiest solution. Once we read the data, we can perform our calculations, add in the context switching data, and display it:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!opBV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33abeb9-808d-4589-8cec-4ed181c5ef59_836x298.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!opBV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33abeb9-808d-4589-8cec-4ed181c5ef59_836x298.png 424w, https://substackcdn.com/image/fetch/$s_!opBV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33abeb9-808d-4589-8cec-4ed181c5ef59_836x298.png 848w, https://substackcdn.com/image/fetch/$s_!opBV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33abeb9-808d-4589-8cec-4ed181c5ef59_836x298.png 1272w, https://substackcdn.com/image/fetch/$s_!opBV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33abeb9-808d-4589-8cec-4ed181c5ef59_836x298.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!opBV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33abeb9-808d-4589-8cec-4ed181c5ef59_836x298.png" width="836" height="298" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a33abeb9-808d-4589-8cec-4ed181c5ef59_836x298.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:298,&quot;width&quot;:836,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:28396,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/182280551?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33abeb9-808d-4589-8cec-4ed181c5ef59_836x298.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!opBV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33abeb9-808d-4589-8cec-4ed181c5ef59_836x298.png 424w, https://substackcdn.com/image/fetch/$s_!opBV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33abeb9-808d-4589-8cec-4ed181c5ef59_836x298.png 848w, https://substackcdn.com/image/fetch/$s_!opBV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33abeb9-808d-4589-8cec-4ed181c5ef59_836x298.png 1272w, https://substackcdn.com/image/fetch/$s_!opBV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33abeb9-808d-4589-8cec-4ed181c5ef59_836x298.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Our business objectives create the start of our architecture.</figcaption></figure></div><p>This does raise a few interesting questions, though:</p><ol><li><p>What happens if the source data changes in some way or if we can&#8217;t access the SQL database when we want to display our data?</p></li><li><p>How, exactly, are we going to store the <em>results</em> of the calculations and annotations?</p></li><li><p>Does this mean that every time we display the results we have to run through the entire pipeline, reading the data, performing calculations and then displaying our findings?</p></li><li><p>How does constantly accessing an external database impact our performance?</p></li></ol><h2>Data integrity and availability</h2><p>We want our application to be highly available and reliable.</p><p>The problem is, we&#8217;ve created a dependency on an external system &#8212; the SQL database. If the external system changes or just isn&#8217;t available when we need it, we&#8217;ve got a problem. It would break our data pipeline. We need a solution that ensures both the integrity of the data as well as its availability.</p><p>The simplest solution is to just <em>copy the data</em> and keep a local cache of it. Whenever the source data is updated, we can update our local cache. If something goes wrong &#8212; for example, the data format changes or we can&#8217;t contact the SQL database &#8212; we can keep using our local cache until we fix the problem. That gives us high availability.</p><p>This also gives us a degree of certainty about the data format.</p><p>While the external SQL database might change, our internal cache can potentially remain constant. For example, let&#8217;s say the external database is using an <code>Integer</code> data type for activity duration, but at some point they decide to change it and start using a <code>Time</code> type instead. Since our local cache is under our own control, we have a few options:</p><ol><li><p>Update our local cache to use <code>Time</code> as well, and change our pipeline code accordingly.</p></li><li><p>Convert the incoming data from <code>Time</code> to an <code>Integer</code> and store that. Leave our code as-is.</p></li><li><p>Decide to use a completely different type, like <code>Duration</code>, in our internal cache and make similar changes to our code.</p></li></ol><p>Our strategy would depend on the situation &#8212; but we have options. We&#8217;ll examine a few different ones in a bit, but for now we&#8217;ll just note the internal cache in our architecture.</p><p>Adding a cache to the architecture might look something like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Tk46!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96aa5a42-916c-478f-9c34-9e4bb889465a_988x301.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Tk46!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96aa5a42-916c-478f-9c34-9e4bb889465a_988x301.png 424w, https://substackcdn.com/image/fetch/$s_!Tk46!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96aa5a42-916c-478f-9c34-9e4bb889465a_988x301.png 848w, https://substackcdn.com/image/fetch/$s_!Tk46!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96aa5a42-916c-478f-9c34-9e4bb889465a_988x301.png 1272w, https://substackcdn.com/image/fetch/$s_!Tk46!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96aa5a42-916c-478f-9c34-9e4bb889465a_988x301.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Tk46!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96aa5a42-916c-478f-9c34-9e4bb889465a_988x301.png" width="988" height="301" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/96aa5a42-916c-478f-9c34-9e4bb889465a_988x301.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:301,&quot;width&quot;:988,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:34260,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/182280551?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96aa5a42-916c-478f-9c34-9e4bb889465a_988x301.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Tk46!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96aa5a42-916c-478f-9c34-9e4bb889465a_988x301.png 424w, https://substackcdn.com/image/fetch/$s_!Tk46!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96aa5a42-916c-478f-9c34-9e4bb889465a_988x301.png 848w, https://substackcdn.com/image/fetch/$s_!Tk46!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96aa5a42-916c-478f-9c34-9e4bb889465a_988x301.png 1272w, https://substackcdn.com/image/fetch/$s_!Tk46!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96aa5a42-916c-478f-9c34-9e4bb889465a_988x301.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Maintaining an internal cache gives us isolation and resiliency by breaking our dependency on external resources.</figcaption></figure></div><p>I&#8217;ve added an &#8220;ACL,&#8221; or &#8220;Anti-Corruption Layer,&#8221; to the intake process. ACLs are used to protect the data integrity of our domain &#8212; in other words, we don&#8217;t control the external SQL database but we <em>do</em> control our internal cache. That cache can, for instance, use a <code>Duration</code> to represent the passage of time <em>regardless</em> of how the SQL database represents time. The ACL is where we translate from the external format to our internal, domain-specific format.</p><p>It gives us a nice layer of <em>isolation</em> from external change. Generally speaking, creating isolation between services is a great strategy for improving reliability (as well as scalability &#8212; more on that later).</p><h2>Benefits of isolation</h2><p>I pointed out that by <em>copying</em> external data into our own system we are creating <em>isolation.</em> This is an important architecture topic for a few reasons:</p><ol><li><p>Isolation means we are not inexorably dependent on an external system. If that external SQL database goes down, or the data changes, we can still function.</p></li><li><p>We also get architectural independence. If we decide to change the structure of our internal data cache, we can. It&#8217;s under our own control.</p></li><li><p>Being in control of our own data architecture also means we&#8217;re in control of our <em>scalability.</em> If our data analysis product becomes the hottest thing since sliced bread, we can scale up. We might add more servers to our cache, or we might evolve our architecture toward CQRS patterns &#8212; we&#8217;re in control, and it&#8217;s all hidden behind our product API.</p></li></ol><p>From this perspective, <em>copying data is a good idea.</em> We need to remember there&#8217;s an external <em>source of truth.</em> But we remain in control of when we run data intake, how we change the data on the way in, and how our own data is structured.</p><h2>Powerful, non-destructive annotation</h2><p>Our original requirements include making sure that we maintain our source data integrity. The best possible approach in that regard requires two things.</p><p>First, we have to capture every record, in its entirety. That ensures we won&#8217;t miss anything important (including the possibility that something <em>becomes</em> important later, even though we thought it wasn&#8217;t important at first).</p><p>Second, we can&#8217;t change what we capture &#8212; we can only <em>add to it.</em> This means our analysis and data annotation can&#8217;t alter the source data &#8212; it&#8217;s immutable. We have to find a way to piggy-back or pair our new data with the raw source data.</p><p>We&#8217;ll leverage that in our code. Let&#8217;s say, for instance, you wanted to find out how many seconds of &#8220;out of sprint&#8221; work each user tracked in a sprint and you also want to make sure paid time off is not included in that number. Here&#8217;s a very simple example, using a snippet of Explorer code:</p><pre><code><code>data
|&gt; DF.group_by([&#8220;user_id&#8221;])
|&gt; DF.filter(stereotype_code != "pto")
|&gt; DF.summarise(out_of_seconds_sum: sum(out_of_sprint_seconds))</code></code></pre><p><code>Data</code> is just an array of raw data records. The <code>group_by</code> line groups all records with their respective team member. Then, with <code>filter</code> we make sure paid time off is not being included. And finally, we sum up all the <code>out_of_sprint_seconds</code> and put the result in a new variable, <code>out_of_seconds_sum</code>.</p><p>Two important things to note here: first, we haven&#8217;t altered the source data in any way. Second, we&#8217;ve annotated our data set by associating that new variable, <code>out_of_sprint_sum</code>, with our DataFrame.</p><p>We&#8217;ll explore this in depth soon. For now, I just wanted to give a quick taste of what we can do and explain why it&#8217;s valuable.</p><h2>Tackling data analysis</h2><p>We&#8217;ve decided how we&#8217;ll get the data, but there&#8217;s more work to do. How are we going to perform our calculations and store the results?</p>
      <p>
          <a href="https://blog.bosslogic.com/p/part-2-a-practical-data-pipeline-architecture">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Happy holidays, good luck, don't work too hard]]></title><description><![CDATA[Burnout is a thing. Don't forget to recharge.]]></description><link>https://blog.bosslogic.com/p/happy-holidays-good-luck-dont-work</link><guid isPermaLink="false">https://blog.bosslogic.com/p/happy-holidays-good-luck-dont-work</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Sun, 14 Dec 2025 13:54:40 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ZLs3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZLs3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZLs3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ZLs3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ZLs3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ZLs3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZLs3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg" width="1280" height="721" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:721,&quot;width&quot;:1280,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:923426,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/180643356?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ZLs3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ZLs3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ZLs3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ZLs3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7eee8de-5c08-46cd-aade-0c17cd367bfa_1280x721.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="pullquote"><p>I just saw the <a href="https://www.youtube.com/watch?v=btCzowgIh9U">Good Luck, Have Fun, Don&#8217;t Die</a> trailer. I really wanted to use the title for a post, alas&#8230; it wouldn&#8217;t work. But it reminded me how important it is to take care of ourselves.</p></div><p>These past few months were <em>very</em> busy. I had two projects compounded on top of each other &#8212; one, a client modernization effort; the other, a new release of an analytics tool we use with our customers. It was more than I like to take on at one time and, yes, I got a bit burned out.</p><p>Which is a good reminder &#8212; prioritize your well being!</p><p>Work will always be there. Life will pass you by.</p><h2>Recharge in Malaga</h2><p>After getting all the work out of the way, we took some time to recharge: a few weeks off in Malaga.</p>
      <p>
          <a href="https://blog.bosslogic.com/p/happy-holidays-good-luck-dont-work">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Data pipelines are really cool. But also, really hard to build.]]></title><description><![CDATA[Data pipelines pose challenges we should all master. They push the limits on design, architecture, performance and even predicting the future.]]></description><link>https://blog.bosslogic.com/p/data-pipelines-are-really-cool</link><guid isPermaLink="false">https://blog.bosslogic.com/p/data-pipelines-are-really-cool</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Wed, 03 Dec 2025 20:15:01 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!_Wdx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52cae73-4cc6-4357-92da-d59417b55902_2880x1920.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_Wdx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52cae73-4cc6-4357-92da-d59417b55902_2880x1920.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_Wdx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52cae73-4cc6-4357-92da-d59417b55902_2880x1920.png 424w, https://substackcdn.com/image/fetch/$s_!_Wdx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52cae73-4cc6-4357-92da-d59417b55902_2880x1920.png 848w, https://substackcdn.com/image/fetch/$s_!_Wdx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52cae73-4cc6-4357-92da-d59417b55902_2880x1920.png 1272w, https://substackcdn.com/image/fetch/$s_!_Wdx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52cae73-4cc6-4357-92da-d59417b55902_2880x1920.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_Wdx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52cae73-4cc6-4357-92da-d59417b55902_2880x1920.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f52cae73-4cc6-4357-92da-d59417b55902_2880x1920.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;mike-benna-X-NAMq6uP3Q-unsplash@0.5x.jpg&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="mike-benna-X-NAMq6uP3Q-unsplash@0.5x.jpg" title="mike-benna-X-NAMq6uP3Q-unsplash@0.5x.jpg" srcset="https://substackcdn.com/image/fetch/$s_!_Wdx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52cae73-4cc6-4357-92da-d59417b55902_2880x1920.png 424w, https://substackcdn.com/image/fetch/$s_!_Wdx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52cae73-4cc6-4357-92da-d59417b55902_2880x1920.png 848w, https://substackcdn.com/image/fetch/$s_!_Wdx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52cae73-4cc6-4357-92da-d59417b55902_2880x1920.png 1272w, https://substackcdn.com/image/fetch/$s_!_Wdx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52cae73-4cc6-4357-92da-d59417b55902_2880x1920.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@mbenna?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Mike Benna</a> on <a href="https://unsplash.com/photos/gray-pipe-on-green-grass-X-NAMq6uP3Q?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><div class="pullquote"><p>In this multi-part article, we&#8217;ll explore what it takes to build an effective data pipeline, from concept to code. As a case study, we&#8217;ll use one of my own applications that captures data across an organization, ultimately creating visual, actionable business intelligence.</p></div><h1>Why data pipelines are interesting</h1><p>A data pipeline moves data to a destination, transforming it along the way, turning it into something useful.</p><p>It&#8217;s like a factory assembly line. But, imagine you&#8217;re assembling data. Raw data is your source material entering at one end. It goes through various processes and comes out the other end as finished product (clean, structured data ready to use).</p><p>For instance, air traffic control systems process data from multiple radar stations, transponders, weather sensors, and flight plan databases to build a real-time picture of airspace. A picture humans can interpret in a split second. An air traffic control system:</p><ul><li><p>Ingests position data from hundreds of aircraft every few seconds.</p></li><li><p>Correlates radar returns with flight plans and transponder signals.</p></li><li><p>Filters out noise, birds and ground clutter.</p></li><li><p>Predicts flight paths and potential conflicts.</p></li><li><p>Integrates weather data to route around storms.</p></li><li><p>Handles sensor failures gracefully &#8212; if one source goes down, seamlessly switching to backup sources.</p></li></ul><p>Controllers need accurate data within seconds, and failures can have catastrophic consequences. They need real-time data, rather than batches, with real-time redundancy and validation.</p><p>Data pipelines are fundamental to modern data infrastructure. A good pipeline makes sure the right data gets to the right place at the right time, in the right format.</p><p>If you think about it &#8212; that&#8217;s the foundation of just about everything in our data-driven modern society.</p><p>When it comes to projects that will evolve your mastery over data management, building a data pipeline is one of the most challenging and rewarding. That&#8217;s why, in this multi-part series, I wanted to do a deep dive into a data pipeline &#8212; including design, architecture and code. In this series, we&#8217;ll get hands-on and explore how to build an app that analyzes complex streams of data.</p><div class="pullquote"><p><em>If you&#8217;re new, welcome to Customer Obsessed Engineering! Every week I publish a new article, direct to your mailbox if you&#8217;re a subscriber. As a free subscriber you can read about half of every article, plus all of my free articles.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/subscribe?"><span>Subscribe now</span></a></p><p><em>Anytime you&#8217;d like to read more, you can upgrade to a paid subscription.</em></p></div><h1>Creating actionable intelligence from data</h1><p>Data pipelines start with the raw, source data &#8212; from wearables, instrumentation, monitors, databases, mobile devices. An Airbus A380 is fitted with up to 25,000 individual sensors. Each one of those is sending <em>raw data</em> that may need to be acted upon quickly. That raw data goes through different processes &#8212; cleaning, filtering, combining, reformatting &#8212; before landing in its final destination, which might be an instrument, display, data warehouse, analytics tool, or application.</p><p>Clearly, copying and interpreting all that data by hand is impossible. Instead, the data pipeline does it automatically, often as a real-time feed that transforms information on the fly. It ensures data moves reliably and consistently. </p><p>Raw data is often messy or in the wrong format. The pipeline transforms it into something useful &#8212; removing duplicates, standardizing formats, calculating metrics, or joining information from multiple sources, as with the air traffic control example.</p><p>Often, data pipelines are <em>event driven</em>. This just means they consume a sequence of events from the real world &#8212; some fact that already happened &#8212; then turn it into actionable intelligence.</p><p>&#8220;Actionable intelligence&#8221; just means some kind of information you can use. For instance, the <em>fact</em> that a stock price dropped could be turned into an automated <em>buy</em> order for that stock. An e-commerce company might have a pipeline that pulls daily sales data from its sales database, combines it with inventory data, calculates key metrics like revenue per product, and loads everything into a dashboard where executives can see performance at a glance.</p><p>There are a lot of moving pieces. Getting those pieces to work together, then correlating all that disparate data and presenting it clearly, logically, is hard. There are challenges to doing it well, which I&#8217;ll talk about below.</p><h2>Preserving data integrity</h2><p>One of the most important things a good data analysis tool &#8212; and data pipeline &#8212; needs is a guarantee of <em>data integrity</em>. In this case, data integrity means <em>the data is exactly the data we think we are analyzing.</em> This sounds obvious, but it&#8217;s surprisingly easy to get wrong.</p><p>Here are some common pitfalls, all of which we need to design against:</p><ul><li><p><strong>Silent data loss</strong>: Information dropped during joins, filtering, or transformations without warning. For example, only capturing summary data or a subset of available data instead of recording (and keeping) everything.</p></li><li><p><strong>Type coercion errors</strong>: Numbers becoming strings, dates and time zones handled incorrectly, or precision lost in conversions.</p></li><li><p><strong>Encoding issues</strong>: Data corruption caused when moving between systems &#8212; something as simple as assuming an input field uses Latin characters instead of Unicode.</p></li><li><p><strong>Partial updates</strong>: Only processing some records, possibly ignoring &#8220;uninteresting data,&#8221; or failing to capture records that don&#8217;t process correctly.</p></li><li><p><strong>Implicit assumptions</strong>: Null handling, unexpected data volume, unexpected inputs or missing parameters, duplicate treatment, or sort order that changes behavior unexpectedly.</p></li></ul><p>Good data pipelines preserve integrity.</p><p>In the second article in this series we&#8217;ll dive deep into <em>data pipeline architecture</em> and address each of these potential pitfalls.</p><h2>Annotating data</h2><p>We also need a way to <em>evolve</em> our data over time &#8212; that is, add to it in a way that we don&#8217;t end up breaking our data integrity rules.</p><p>Raw data rarely speaks for itself. A transaction table tells you what happened, but not why. A spike in errors shows something broke, but not what you were doing at the time. Good data tools let you add <em>context</em> and turn numbers into understanding.</p><p>Annotations work at multiple levels. At the record or event level, they document what the data represents, adding fidelity. A data analyst might add a &#8220;review&#8221; tag to what looks like an accidental double-entry, or a prescription drug regulatory pipeline might link together other drugs that treat similar symptoms.</p><p>At the macro level, annotation can build on a core data set, adding new information. Data from multiple sources can be combined to create a more complete picture. Hard-to-perform calculations can be run and attached to existing data, making it easy to extract more meaning later. Later, in our example use case, we&#8217;ll do this by annotating our data set for further exploration.</p><p>Annotations compound over time. Six months later, when someone investigates why something looks unusual, annotations lead to new institutional knowledge. Without them, context can be lost and every new analyst has to rediscover what happened.</p><h2>Surfacing insight</h2><p>Data analysis tools should surface insights, not just tables and charts. The difference between data and intelligence is <em>whether it changes what you do next</em>.</p><p>We need the right level of aggregation and annotation: too granular and patterns disappear in noise; too macro and you can&#8217;t identify root causes.</p><p>Start by focusing on decisions. Before building a dashboard, a report or a graph, ask what decision it will inform. If the answer is vague or simply, &#8220;it&#8217;s good to know,&#8221; it&#8217;s not actionable. Every result should express some clear, specific action.</p><div class="pullquote"><p>Actionable intelligence changes what you do next.</p></div><p>Make the analysis do the work, not the reader. Instead of showing a table of conversion rates by channel, highlight which channels are underperforming, by how much <em>and why</em>. Instead of a trend line, show whether or not execution is deviating from planned goals and exactly <em>how it changes your delivery plan</em>.</p><p>Focus on metrics that lead to human action. Also, tune thresholds to minimize false positives. For example, it may be useful to &#8220;clean&#8221; a data set by removing anomalies and peculiar outliers. We&#8217;ll do that in our example app, effectively removing data that is suspicious and likely just &#8220;noise.&#8221;</p><p>The goal is to inform clear action. If it requires tribal knowledge, domain expertise, further exploration or twenty minutes of interpretation, it&#8217;s not yet actionable.</p><h2>&#8220;Rewinding&#8221; history</h2><p>One of the most powerful and underused capabilities in data analytics is the ability to reprocess historical data with new logic. When you fix a bug in your analysis or refine a calculation, you often want to know: &#8220;what would the last three months have looked like with this new logic?&#8221;</p><p>This is harder than it sounds. If your pipeline only processes new data, historical numbers are frozen with old limitations or bugs. You end up with charts where the methodology changes partway through, making trends impossible to interpret. &#8220;Revenue increased 20% in March,&#8221; but we&#8217;ll never know if it was growth or if it was due to a changed calculation.</p><p><em>Point-in-time correctness</em> makes this possible: storing raw events or source data permanently, without changing it or pre-processing it. When you need to revise analysis, <em>reprocess the historical data</em> through the updated pipeline. The results of that processing becomes <em>annotation</em> to the data &#8212; ultimately, annotations that we can throw out and do again using a new approach. We look at data as an entire time series, a record of <em>facts</em> that happened in the past &#8212; and are, therefore, immutable.</p><p>But this means treating our analysis and transformation logic as <em>code</em>, not ad-hoc formulas or manual actions. The source data must never be altered &#8212; only our code, and the annotations and analysis it produces. That gives us a documented data model, not tribal knowledge about which column means what. The goal is reproducibility: given raw data from any date and a specific version of your data pipeline, you can create an exact analysis for any timeframe.</p><h1>Building a data pipeline</h1><p>I promised a deep dive into the design, architecture and code of a data pipeline. There are a lot of use cases &#8212; stock trade analysis, weather data, genomic research, geologic tremor research, the list is probably endless.</p><p>For this deep dive, we&#8217;ll explore an application that tracks team activity across all the projects an organization is working on. Our goal in tracking all this information is to deliver new <em>business intelligence</em> that gives useful, actionable insights into team  efficiency across an entire organization.</p><p>We&#8217;ll build the application in stages, showing its evolution and developing a solid foundation for a data pipeline.</p><p>Using the app, team members will track their activities across various tasks, but unlike most &#8220;time trackers&#8221; they&#8217;ll be able to annotate their time as &#8220;in sprint&#8221; or &#8220;out of sprint.&#8221; These are defined as:</p><ol><li><p><strong>In sprint</strong> &#8212; essentially, &#8220;this is work that contributed direct value to my sprint goals.&#8221;</p></li><li><p><strong>Out of sprint</strong> &#8212; this represents everything else, essentially, &#8220;this is work that I had to do, but it didn&#8217;t contribute value directly to my goals &#8212; it may have even slowed me down.&#8221;</p></li></ol><p>We&#8217;ll scale this up across an entire organization. For a large organization, that means hundreds of teams, thousands of team members and tens of thousands of individual tasks. It&#8217;s a sizeable volume of data to work with, but in terms of what data pipelines are capable of it&#8217;s still pretty small (think about the volume of data flowing through the stock market, in comparison).</p><p>We&#8217;ll need a way for team members to capture day-to-day work, quickly and easily. This will become our data source, pushing data into the pipeline in real-time:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VQjk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2c6e8bb-1561-430f-a051-52d9496680c4_534x952.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VQjk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2c6e8bb-1561-430f-a051-52d9496680c4_534x952.png 424w, https://substackcdn.com/image/fetch/$s_!VQjk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2c6e8bb-1561-430f-a051-52d9496680c4_534x952.png 848w, https://substackcdn.com/image/fetch/$s_!VQjk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2c6e8bb-1561-430f-a051-52d9496680c4_534x952.png 1272w, https://substackcdn.com/image/fetch/$s_!VQjk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2c6e8bb-1561-430f-a051-52d9496680c4_534x952.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VQjk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2c6e8bb-1561-430f-a051-52d9496680c4_534x952.png" width="268" height="477.78277153558054" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c2c6e8bb-1561-430f-a051-52d9496680c4_534x952.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:952,&quot;width&quot;:534,&quot;resizeWidth&quot;:268,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;app 1.png&quot;,&quot;title&quot;:&quot;app 1.png&quot;,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="app 1.png" title="app 1.png" srcset="https://substackcdn.com/image/fetch/$s_!VQjk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2c6e8bb-1561-430f-a051-52d9496680c4_534x952.png 424w, https://substackcdn.com/image/fetch/$s_!VQjk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2c6e8bb-1561-430f-a051-52d9496680c4_534x952.png 848w, https://substackcdn.com/image/fetch/$s_!VQjk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2c6e8bb-1561-430f-a051-52d9496680c4_534x952.png 1272w, https://substackcdn.com/image/fetch/$s_!VQjk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2c6e8bb-1561-430f-a051-52d9496680c4_534x952.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The activity tracking app team members will use to tag activities as &#8220;in sprint&#8221; and &#8220;out of sprint&#8221; &#8212; or, &#8220;value add&#8221; and &#8220;non-value add&#8221; in Lean Engineering terms.</figcaption></figure></div><p>All the activities will flow into our data pipeline. We&#8217;ll capture those individual activities, but we need to look at the data in aggregate &#8212; from an organizational point of view. This means being able to annotate and analyze the data from different perspectives.</p><p>Looking at the data as a stream of events over time, we can &#8220;slice and dice&#8221; it. We can also compose the data with other analyses, all to produce actionable intelligence. That means being able to aggregate the data and run on-the-fly analysis across different segments of data (for example, being able to take a &#8220;slice&#8221; of data across four teams out of the entire organization):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Y67V!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80569ed7-3fac-444d-8f4e-674084d00e24_2420x1470.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Y67V!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80569ed7-3fac-444d-8f4e-674084d00e24_2420x1470.png 424w, https://substackcdn.com/image/fetch/$s_!Y67V!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80569ed7-3fac-444d-8f4e-674084d00e24_2420x1470.png 848w, https://substackcdn.com/image/fetch/$s_!Y67V!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80569ed7-3fac-444d-8f4e-674084d00e24_2420x1470.png 1272w, https://substackcdn.com/image/fetch/$s_!Y67V!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80569ed7-3fac-444d-8f4e-674084d00e24_2420x1470.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Y67V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80569ed7-3fac-444d-8f4e-674084d00e24_2420x1470.png" width="1456" height="884" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/80569ed7-3fac-444d-8f4e-674084d00e24_2420x1470.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:884,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;3-impact.png&quot;,&quot;title&quot;:&quot;3-impact.png&quot;,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="3-impact.png" title="3-impact.png" srcset="https://substackcdn.com/image/fetch/$s_!Y67V!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80569ed7-3fac-444d-8f4e-674084d00e24_2420x1470.png 424w, https://substackcdn.com/image/fetch/$s_!Y67V!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80569ed7-3fac-444d-8f4e-674084d00e24_2420x1470.png 848w, https://substackcdn.com/image/fetch/$s_!Y67V!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80569ed7-3fac-444d-8f4e-674084d00e24_2420x1470.png 1272w, https://substackcdn.com/image/fetch/$s_!Y67V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80569ed7-3fac-444d-8f4e-674084d00e24_2420x1470.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This dashboard shows the macro-level potential return on investment by taking specific actions to improve &#8220;ways of working&#8221; and team productivity.</figcaption></figure></div><p>We also want to perform detailed analysis. In our activity tracking app, we&#8217;ll show time the team spent on manual activity that could have been completely automated &#8212; letting the humans on the team spend their brain power on more valuable tasks:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Gpxu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e29224-e11d-4cd3-b163-99235803d944_2420x1470.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Gpxu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e29224-e11d-4cd3-b163-99235803d944_2420x1470.png 424w, https://substackcdn.com/image/fetch/$s_!Gpxu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e29224-e11d-4cd3-b163-99235803d944_2420x1470.png 848w, https://substackcdn.com/image/fetch/$s_!Gpxu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e29224-e11d-4cd3-b163-99235803d944_2420x1470.png 1272w, https://substackcdn.com/image/fetch/$s_!Gpxu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e29224-e11d-4cd3-b163-99235803d944_2420x1470.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Gpxu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e29224-e11d-4cd3-b163-99235803d944_2420x1470.png" width="1456" height="884" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/15e29224-e11d-4cd3-b163-99235803d944_2420x1470.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:884,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;6-automation.png&quot;,&quot;title&quot;:&quot;6-automation.png&quot;,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="6-automation.png" title="6-automation.png" srcset="https://substackcdn.com/image/fetch/$s_!Gpxu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e29224-e11d-4cd3-b163-99235803d944_2420x1470.png 424w, https://substackcdn.com/image/fetch/$s_!Gpxu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e29224-e11d-4cd3-b163-99235803d944_2420x1470.png 848w, https://substackcdn.com/image/fetch/$s_!Gpxu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e29224-e11d-4cd3-b163-99235803d944_2420x1470.png 1272w, https://substackcdn.com/image/fetch/$s_!Gpxu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e29224-e11d-4cd3-b163-99235803d944_2420x1470.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This dashboard shows how much work a team could recover, on a per-sprint basis, by implementing improved automation in their CI/CD pipeline.</figcaption></figure></div><p>As we discussed above, a good analytics platform also supports <em>annotation</em> &#8212; that is, being able to combine new data with existing data.</p><p>In our case, we&#8217;ll calculate how much time is lost to<em> switching</em> from one task to another. We&#8217;ll combine that analysis with pre-existing data to create new insights. Here we show the impact of giving the team more focus time:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!aNhe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07dc34df-b73c-49ba-a621-d6a43d6500d0_2420x1470.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aNhe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07dc34df-b73c-49ba-a621-d6a43d6500d0_2420x1470.png 424w, https://substackcdn.com/image/fetch/$s_!aNhe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07dc34df-b73c-49ba-a621-d6a43d6500d0_2420x1470.png 848w, https://substackcdn.com/image/fetch/$s_!aNhe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07dc34df-b73c-49ba-a621-d6a43d6500d0_2420x1470.png 1272w, https://substackcdn.com/image/fetch/$s_!aNhe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07dc34df-b73c-49ba-a621-d6a43d6500d0_2420x1470.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!aNhe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07dc34df-b73c-49ba-a621-d6a43d6500d0_2420x1470.png" width="1456" height="884" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/07dc34df-b73c-49ba-a621-d6a43d6500d0_2420x1470.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:884,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;8-context.png&quot;,&quot;title&quot;:&quot;8-context.png&quot;,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="8-context.png" title="8-context.png" srcset="https://substackcdn.com/image/fetch/$s_!aNhe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07dc34df-b73c-49ba-a621-d6a43d6500d0_2420x1470.png 424w, https://substackcdn.com/image/fetch/$s_!aNhe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07dc34df-b73c-49ba-a621-d6a43d6500d0_2420x1470.png 848w, https://substackcdn.com/image/fetch/$s_!aNhe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07dc34df-b73c-49ba-a621-d6a43d6500d0_2420x1470.png 1272w, https://substackcdn.com/image/fetch/$s_!aNhe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07dc34df-b73c-49ba-a621-d6a43d6500d0_2420x1470.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">This dashboard shows how much time is lost switching between tasks, making it clear that allowing the team more focus time would be an improvement.</figcaption></figure></div><h1>Summarizing our goals</h1><p>From a business perspective what we want to achieve with the activity tracking app doesn&#8217;t seem complicated:</p><ol><li><p>Give team members a place to easily and quickly record their activities (what they did, how long it took).</p></li><li><p>Let them tag work that falls &#8220;outside&#8221; the sprint &#8212; representing work that, while potentially necessary, didn&#8217;t really contribute direct sprint value or move their goals forward.</p></li><li><p>Aggregate data across the entire organization to discover meaningful trends.</p></li><li><p>Expose action that we can take &#8212; action that will have an immediate impact on efficiency, productivity &#8212; improving &#8220;ways of working&#8221; across teams.</p></li></ol><p>This is something that most organizations are working on &#8212; in fact, most are working on efficiency and productivity goals <em>right now</em>.</p><p>But the reality is, it&#8217;s complicated. There are competing concerns, unclear cross-organizational goals, a lot of noise to filter out, activity that may <em>be</em> necessary but might not <em>seem</em> necessary. How do we accurately analyze and filter it down into clear, actionable intelligence?</p><p>There are solutions. Ideas built on decades of rich, scientific research and business process evolution. Perhaps most famously, Toyota empowered their employees to do whatever it took to streamline automotive production lines. Toyota&#8217;s concepts regarding just in time production are deeply embedded in the foundations of Lean Manufacturing. Taiichi Ohno is widely regarded as having pioneered effective techniques for eliminating &#8220;wasteful action&#8221; in day-to-day work (<a href="https://ottomotors.com/blog/tackling-7-muda-lean-materials-handling">Muda</a>, a Japanese word meaning &#8220;wasteful&#8221;).<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a></p><p>Our application will build on that, gathering <em>activity data</em> and turning it into an actionable, live stream of insight about organizational health.</p><p>We&#8217;ll need to stay true to the critical concerns outlined in this article: preserve data integrity, focus on annotation not transformation, build a system that always delivers <em>actionable intelligence</em> and, perhaps most important, make it possible to &#8220;rewind and replay.&#8221; As our algorithms evolve and mature, we&#8217;ll want those insights to be applied retroactively.</p><div class="pullquote"><p>Hey, can I ask a favor? Referrals keep this publication alive. Please take a moment to send this article to a friend.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p></div><h1>Coming next</h1><p>We&#8217;ve outlined our requirements above. Next up is defining the architecture, the <a href="https://blog.bosslogic.com/p/blueprinting-phase-2">&#8220;blueprinting&#8221;</a> phase. That&#8217;ll be the topic of the <a href="https://blog.bosslogic.com/p/part-2-a-practical-data-pipeline-architecture">next article</a> in this series. By the end of the third article, we&#8217;ll have a concrete roadmap as well as an architectural foundation &#8212; a <a href="https://blog.bosslogic.com/p/solve-delivery-with-a-steel-thread">steel thread</a> that we can build on to deliver a proof of concept in one or two sprints worth of work.</p><p>If you&#8217;re following along in the <a href="https://blog.bosslogic.com/s/delivery-playbook">Delivery Playbook</a>, we&#8217;ve just about finished our mobilization phase. We&#8217;ve got a <a href="https://arc.net/l/quote/sfntgeti">product vision</a> and we know what the product&#8217;s <a href="https://blog.bosslogic.com/p/14-business-capabilities-and-functions">capabilities and functions</a> will be.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;595062d6-04e0-4230-b0e7-1a3cce692433&quot;,&quot;caption&quot;:&quot;In this second article on data pipelines I&#8217;ll show you how to build a foundational data pipeline architecture that stays true to requirements. At the same time, we&#8217;ll keep the architecture sound and simple; something we can scale, but also something we can build quickly. This aligns with the idea of launching a&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Part 2: Steel thread first: a practical data pipeline architecture&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:177238936,&quot;name&quot;:&quot;Zac Beckman&quot;,&quot;bio&quot;:&quot;Modernizing your team &#8211; I make software fast. Programmer, technology accelerator, coach, change agent. Builder of hyper-performing teams that obsess over delivering value.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e987c873-9ed2-4766-b6b9-bf522d9e68fc_1851x1852.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-12-22T16:59:15.735Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!YefJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7ea063d-c8bd-4cc3-981a-180ce162ccd1_1931x1253.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.bosslogic.com/p/part-2-a-practical-data-pipeline-architecture&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:182280551,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:2056439,&quot;publication_name&quot;:&quot;Customer Obsessed Engineering&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!SRH_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5de8a7cd-651e-4f84-b61d-8f100b23db5a_250x250.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><p>If you find Customer Obsessed Engineering and the <em><a href="https://blog.bosslogic.com/s/delivery-playbook">Delivery Playbook</a></em> valuable, please share it with your friends and coworkers.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&quot;,&quot;text&quot;:&quot;Share Customer Obsessed Engineering&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share"><span>Share Customer Obsessed Engineering</span></a></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>Nawras Skhmot, <a href="https://theleanway.net/what-is-lean">What Is Lean?</a>, The Lean Way Blog, Aug. 5, 2007.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>See: <a href="https://blog.bosslogic.com/p/context-switching-is-killing-your-gains-part-2-85be456e6d92">Context switching is killing your gains (part 2)</a>, Jan. 30, 2023.</p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[Why only testing use cases just isn’t enough; here’s how to do it right]]></title><description><![CDATA[Traditional unit tests are setting you up for production failures. Here's a path to a better launch experience: use property-based testing to build unbreakable software.]]></description><link>https://blog.bosslogic.com/p/why-testing-use-cases-alone-fails</link><guid isPermaLink="false">https://blog.bosslogic.com/p/why-testing-use-cases-alone-fails</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Mon, 22 Sep 2025 09:25:43 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!a3lt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!a3lt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!a3lt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg 424w, https://substackcdn.com/image/fetch/$s_!a3lt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg 848w, https://substackcdn.com/image/fetch/$s_!a3lt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!a3lt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!a3lt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg" width="1456" height="823" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:823,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:733293,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.bosslogic.com/i/174022707?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!a3lt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg 424w, https://substackcdn.com/image/fetch/$s_!a3lt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg 848w, https://substackcdn.com/image/fetch/$s_!a3lt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!a3lt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ef52468-b8c2-4f14-b832-d13895fca9fe_2310x1306.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Iceland has some of the most stunning mountain landscapes.</figcaption></figure></div><p>Most teams are building on quicksand and calling it solid ground.</p><p>You&#8217;ve got 95% test coverage. Your CI pipeline is green. Your unit tests pass every time. You ship with confidence, and then &#8212; <em>crash</em> &#8212; production burns down because of an edge case nobody thought to test. The user entered a 37-character string instead of 35. Someone sent a negative timestamp. A list came back empty when your code expected at least one item.</p><p>Sound familiar? Here&#8217;s an uncomfortable truth: <em>traditional unit testing is fundamentally inadequate for building reliable software.</em></p><p>Unit tests are like taking a single photograph of a mountain and claiming you understand the entire landscape. They capture one specific moment, one exact scenario, but they miss the infinite variations that real users will throw at your system. They&#8217;re missing the crevasses, caves, and sudden unexpected features. They&#8217;re necessary, but they&#8217;re not sufficient.</p><p>After decades of building and shipping software &#8212; from startup MVPs to mission-critical systems handling millions of transactions &#8212; I&#8217;ve learned that the teams who ship bulletproof software have one thing in common: They know that testing specific use cases is inadequate. </p><p>They don&#8217;t buy into the illusion of safety that unit testing offers. They use property-based testing.</p><p>Property-based testing doesn&#8217;t just find bugs. It finds entire categories of bugs you never knew existed. It&#8217;s the difference between checking that your bridge can hold one specific car versus proving it can fulfill its design parameters by handling a constant, unpredictable flow of traffic.</p><div class="pullquote"><p><em>If you&#8217;re new, welcome to Customer Obsessed Engineering! Every week I publish a new article, direct to your mailbox if you&#8217;re a subscriber. As a free subscriber you can read about half of every article, plus all of my free articles.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/subscribe?"><span>Subscribe now</span></a></p><p><em>Anytime you&#8217;d like to read more, you can upgrade to a paid subscription.</em></p></div><h2>The fundamental flaw in how we think about testing</h2><p>Let me paint you a picture. You&#8217;re building a user activity tracking system (let&#8217;s call it Tracky). Your traditional testing approach might look something like this:</p><pre><code><code>test "creates activity with valid data" do
  user = insert(:user)
  sprint = insert(:sprint)
  
  assert {:ok, activity} = Activities.new_activity(
    sprint.id, 
    user.id, 
    ~D[2024-01-15], 
    ~T[02:30:00], 
    "Working on feature X"
  )
  
  assert activity.duration == ~T[02:30:00]
  assert activity.description != nil
end</code></code></pre><p>This test passes. You ship. Then production explodes because:</p><ul><li><p>Someone enters a duration of 25 hours</p></li><li><p>A date falls outside the sprint boundaries</p></li><li><p>The description is 500 characters long and breaks your UI</p></li><li><p>Someone passes a <code>nil</code> sprint_id</p></li><li><p>The timestamp has microseconds that cause floating-point precision issues</p></li></ul><p>Your unit test checked <em>one path through the code</em>. But software doesn&#8217;t operate in the controlled environment of your test suite. It operates in the chaos of production, where users do unexpected things, data comes in unexpected formats, and Murphy&#8217;s Law reigns supreme.</p><p><em>Instead of testing specific examples, we should be testing universal properties that must always hold true.</em></p><p>Property-based testing builds a foundation for quality by exercising <em>all</em> the behavioral boundaries of your code. This is exactly how we approach development using a &#8220;steel thread.&#8221; A <a href="https://blog.bosslogic.com/p/solve-delivery-with-a-steel-thread">steel thread</a> creates an architecturally complete foundation by touching all the major components of a system.</p><h2>The truth about test coverage</h2><p>Here&#8217;s something that might challenge a few of your assumptions: <em>high unit test coverage can actually make your software less reliable.</em></p><p>I&#8217;ve seen teams with 98% test coverage ship catastrophic bugs because they confused <em>coverage</em> with <em>correctness.</em> They tested their happy paths thoroughly but ignored the vast space of possible inputs that could break their system.</p><p>Property-based testing breaks through this limitation. Instead of measuring how much of your code is exercised, you&#8217;re measuring how much of your input space is validated. Instead of asking, &#8220;did we test this line of code?&#8221; you&#8217;re asking, &#8220;did we prove this business rule is always true?&#8221;</p><p>A single property test might only exercise 20% of your codebase but validate behavior across millions of potential inputs &#8212; including edge cases. Which approach gives you more confidence in production?</p><p>The takeaway here: coverage metrics optimize for the wrong thing. They optimize for testing <em>effort</em> rather than testing <em>effectiveness</em>.</p><h2>What <em>is</em> a &#8220;property?&#8221;</h2><p>A &#8220;property&#8221; is a universal law or attribute. Gravity is a property that dictates how objects are attracted to each other. Fluid dynamics define a set of properties about how fluids flow and interact. And, our Tracky application has certain properties, too:</p><ol><li><p>Activities must fall inside the date boundary of a sprint.</p></li><li><p>An activity is limited in time (for our purposes, it&#8217;s a business rule that &#8220;activities must be less than 8 hours in duration).</p></li><li><p>Activities must be owned by a user, and that user can view, update, and delete only their own activities (<em>not</em> someone else&#8217;s activities).</p></li><li><p>Activities can, optionally, have a description.</p></li></ol><p>Of course there&#8217;s more, but this is sufficient for the examples we&#8217;ll look at in this article.</p><p>These <em>properties</em> define how Tracky behaves; what you are allowed to do with it, and what you are not allowed to do. They are universal laws &#8212; in all conditions, an activity <em>must</em> fulfill each of these laws &#8212; and, very importantly, the system must <em>gracefully</em> prevent the violation of these laws.</p><h2>What property-based testing actually does</h2><p>We&#8217;re all familiar with unit testing and testing very specific &#8220;success criteria,&#8221; like I described above. The problem with that approach is the inherent limitation of testing <em>a single path at a time.</em> It&#8217;s an impossible burden to test every edge case using that approach.</p><p>Property based testing expands our test horizon. Instead of writing specific test cases, you define properties &#8212; universal truths about your system &#8212; and let the testing framework try to break them using hundreds or thousands of generated test cases.</p><p>In short, you write <em>one</em> generalized test scenario, and the system uses it to create thousands of potential test paths for you.</p><p>Let&#8217;s start with a simple example.</p><p>In this example I use a &#8220;generator&#8221; to seed my test with test data &#8212; if you aren&#8217;t familiar with generators, don&#8217;t worry, we&#8217;ll come back to them. For now, just understand that a <em>generator creates an infinite, essentially random stream of test data.</em> They are the powerhouse behind property based testing.</p><p>Let&#8217;s start by replacing my naive <code>creates activity with valid data</code> with a property-based test. Here&#8217;s how it might look:</p><pre><code><code>property "activities must have reasonable durations and valid dates within sprint bounds" do
  check all sprint &lt;- sprint_generator(),
            user &lt;- user_generator(),
            duration &lt;- valid_activity_duration_generator(),
            date &lt;- member_of(Date.range(sprint.start, sprint.end)),
            description &lt;- lorem_style_phrase_generator_or_empty() do

    result = Activities.new_activity(
      sprint.id,
      user.id,
      date,
      duration,
      description
    )

    # Property 1: Valid inputs should always succeed
    assert {:ok, activity} = result
    
    # Property 2: Output duration should match input duration
    assert activity.duration == duration
    
    # Property 3: Activity date must be within sprint bounds
    assert Date.compare(activity.date, sprint.start_date) != :lt
    assert Date.compare(activity.date, sprint.end_date) != :gt
    
    # Property 4: Description, sprint, and user must all match
    assert activity.description == description
    assert activity.sprint == sprint
    assert activity.user == user
  end
end</code></code></pre><p>I&#8217;m using <a href="https://elixir-lang.org/">Elixir</a> here, but that doesn&#8217;t matter. There are property-based test frameworks available for <a href="https://github.com/jmid/pbt-frameworks">just about every language</a>.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><p>At first glance, this might not seem to be much different. I&#8217;m still creating activities, and comparing the properties <em>of</em> those created activities with expected values.</p><p>But, this single property test does the work of thousands of individual unit tests. It generates valid sprints with random date ranges, creates users with different roles, generates durations up to 8 hours, picks dates within the sprint bounds, and creates descriptions of varying lengths. It does this many times, creating a myriad of combinations and edge cases that we would never think to code up by hand.</p><p>This means you&#8217;ll see a lot of combinations:</p><ol><li><p>An administrator creating an activity with a minute-long duration.</p></li><li><p>Another user creating a 5-hour activity, mid-sprint, with a long description filled with emoji and Unicode characters.</p></li><li><p>Activities with <code>nil</code>, empty, very short, and very long descriptions with a variety of punctuation.</p></li><li><p>Activities that belong to sprints far in the future, or that started (and ended) a month ago.</p></li></ol><p>And on it goes, with many, many combinations of users, sprints, dates, durations and descriptions.</p><p>And, it gets more powerful: With property testing we also test the boundaries. What happens when the duration is exactly 8 hours? What about when it&#8217;s one second over? What about when the date is exactly on the sprint start date? Or the end date? It&#8217;s easy to write <em>negative</em> scenario tests as well, just by introducing a generator that creates bad inputs.</p><p>The testing framework explores the entire input space systematically, looking for the edge cases and <em>combinations of edge cases</em> that will break your system in production.</p><div class="pullquote"><p><em>Please consider referring a friend&#8230; it really helps keep the blog going! And, you earn rewards.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.bosslogic.com/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.bosslogic.com/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p></div><h2>The architecture of unbreakable software</h2><p>Property-based testing forces you to think architecturally about your code. When you write properties, you&#8217;re not thinking about specific scenarios &#8212; you&#8217;re thinking about the fundamental invariants that must hold true regardless of input.</p><p>Thinking in terms of property-based testing makes architecture easier. We&#8217;re shifting away from, &#8220;let&#8217;s make this one specific test case succeed&#8221; and toward, &#8220;let&#8217;s define conditions that prove these fundamental truths are always true, no matter what we throw at it.&#8221;</p><p>Here are some of those &#8220;fundamental truths&#8221; property-based testing helps to verify:</p><ol><li><p>Data integrity properties.</p><ol><li><p>Entities must always maintain appropriate relationships.</p></li><li><p>Temporal properties (time and dates) must fall within suitable boundaries.</p></li><li><p>Access and ownership must be part of the system.</p></li></ol></li></ol>
      <p>
          <a href="https://blog.bosslogic.com/p/why-testing-use-cases-alone-fails">
              Read more
          </a>
      </p>
   ]]></content:encoded></item></channel></rss>