<?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>Mon, 04 May 2026 11:53:26 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[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><item><title><![CDATA[If you’re not using “declarative teams," you have only an illusion of control]]></title><description><![CDATA[Shifting from "how to do it" to "what&#8217;s the outcome" transforms your productivity, reduces complexity, and makes your systems reliable.]]></description><link>https://blog.bosslogic.com/p/why-being-declarative-is-your-competitive-advantage</link><guid isPermaLink="false">https://blog.bosslogic.com/p/why-being-declarative-is-your-competitive-advantage</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Sun, 31 Aug 2025 20:32:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Revr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0aa8f716-934f-42dd-823b-600149a27873_2016x1386.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_!Revr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0aa8f716-934f-42dd-823b-600149a27873_2016x1386.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Revr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0aa8f716-934f-42dd-823b-600149a27873_2016x1386.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Revr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0aa8f716-934f-42dd-823b-600149a27873_2016x1386.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Revr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0aa8f716-934f-42dd-823b-600149a27873_2016x1386.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Revr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0aa8f716-934f-42dd-823b-600149a27873_2016x1386.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Revr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0aa8f716-934f-42dd-823b-600149a27873_2016x1386.jpeg" width="1456" height="1001" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0aa8f716-934f-42dd-823b-600149a27873_2016x1386.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1001,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:435683,&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/172389484?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0aa8f716-934f-42dd-823b-600149a27873_2016x1386.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_!Revr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0aa8f716-934f-42dd-823b-600149a27873_2016x1386.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Revr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0aa8f716-934f-42dd-823b-600149a27873_2016x1386.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Revr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0aa8f716-934f-42dd-823b-600149a27873_2016x1386.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Revr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0aa8f716-934f-42dd-823b-600149a27873_2016x1386.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/@picsbyjameslee?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">James Lee</a> on <a href="https://unsplash.com/photos/green-leafed-tree-in-the-center-on-green-bushes-GBaNRILH-DM?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure></div><p>The most productive teams I&#8217;ve worked with never argue about implementation details.</p><p>That&#8217;s probably surprising if you&#8217;ve spent years in rooms with engineers propounding about the merits of different algorithms, frameworks, or architectural patterns. What I&#8217;ve learned is that the teams who spend their time arguing about <em>how</em> to build something are the same teams that consistently miss deadlines, accumulate technical debt, and burn out their best people.</p><p>The highest-performing teams focus on <em>what</em> they want to achieve, then let declarative systems handle the how.</p><p>This isn&#8217;t just about programming paradigm or tool selection. It&#8217;s a fundamental change in how we <em>think</em> about building software, managing teams, and delivering customer value.</p><p>It&#8217;s the difference between organizations that scale effortlessly and those that collapse under their own complexity.</p><h2>The hidden cost of procedural thinking</h2><p>Most of us were trained to think procedurally. We write step-by-step instructions. &#8220;First, do this, then do that, and if this happens, handle it this way.&#8221; It feels natural because that&#8217;s how we&#8217;ve been taught to solve problems since childhood.</p><p>But procedural thinking carries a hidden tax on everything we build.</p><p>Here&#8217;s an example I bet sounds familiar: your team finds themselves inheriting deployment tooling for a complex product. I ran into this recently, to the tune of well over 1,000 lines of disparate scripts, loosely tied together across different systems. It handled environment setup, dependency installation, configuration management, and service startup. The scripts had been lovingly maintained by just one or two engineers for years. And it worked really well &#8212; most of the time.</p><p>The problem wasn&#8217;t that the script failed (it did, in spectacular ways, often completely derailing a new product release). The problem was what that script represented: <em>years</em> of institutional knowledge understood by one or two people, and requiring constant maintenance as the underlying infrastructure evolved (which was pretty often).</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><p>After those two people left the company, deployment became a bottleneck. When AWS updated their base images, someone had to trace through the script line by line to figure out what broke. When the team wanted to deploy to a different region, they discovered hardcoded assumptions baked into dozens of conditional statements. Little incompatibilities or unforeseen eventualities that the script just couldn&#8217;t handle. Sometimes it took <em>days</em> to reverse engineer a fix.</p><p>Here&#8217;s my key insight about this: <em>every procedural system</em> you build becomes a maintenance burden that grows exponentially with complexity.</p><p>Declarative systems are simple. They describe a clear end-state, not a series of complex instructions that <em>hopefully</em> get you there. Consequently, they become more valuable as they scale.</p><p>This is the fundamental difference between telling a system <em>how</em> to do something versus telling it <em>what</em> you want accomplished.</p><h2>What &#8220;declarative&#8221; really means</h2><p>Declarative programming isn&#8217;t just about using Infrastructure as Code (&#8220;IaC&#8221;) instead of writing for-loops and if-then statements (though that&#8217;s part of it). It&#8217;s about expressing <em>intent</em> rather than <em>implementation</em>.</p><p>When I tell Kubernetes &#8220;I want three replicas of this service running with these resource constraints,&#8221; I&#8217;m being declarative. The system figures out how to make that happen, how to recover when nodes fail, how to scale when load increases. I describe the desired state, the &#8220;what I want,&#8221; not the &#8220;how.&#8221; The system maintains it, figuring out the &#8220;how&#8221; for me.</p><p>CSS is declarative: &#8220;I want this text to be bold, pulsing dark blue on a midnight background.&#8221; It describes <em>what</em> I want to appear on my web page. The browser handles the complex rendering pipeline, layout algorithms, and cross-platform compatibility.</p><p>But &#8220;being declarative&#8221; is also about <em>thinking</em> intentionally, a way to reason about systems so they mirror my intention. By &#8220;systems,&#8221; I don&#8217;t mean <em>code</em>, I mean <em>organizational</em> systems. How your team operates. How you <em>design</em> your architecture, your product, your business.</p><p>That&#8217;s what most people miss: <em>declarative thinking applies far beyond code</em>.</p><p>When I create a <a href="https://blog.bosslogic.com/p/a-definition-of-done-is-only-half-the-story?r=2xiufs&amp;utm_campaign=post&amp;utm_medium=web&amp;showWelcomeOnShare=false">Definition of Done</a> that specifies the characteristics of completed work, I&#8217;m being declarative about quality standards. When I establish <a href="https://blog.bosslogic.com/p/value-stream-engineering-in-a-nutshell?r=2xiufs&amp;utm_campaign=post&amp;utm_medium=web&amp;showWelcomeOnShare=false">value stream maps</a> that define customer outcomes, I&#8217;m being declarative about business objectives. When I build a playbook that specifies artifacts and quality gates for each delivery phase, I&#8217;m being declarative about process.</p><p>The teams that master this distinction operate at a fundamentally different level than their peers.</p><p>In using <a href="https://blog.bosslogic.com/p/solve-delivery-with-a-steel-thread?r=2xiufs&amp;utm_campaign=post&amp;utm_medium=web&amp;showWelcomeOnShare=false">steel threads</a>, I discovered that successful teams naturally gravitate toward declarative approaches. They don&#8217;t argue about <em>how</em> to implement the &#8220;right to be forgotten&#8221; for GDPR compliance &#8212; they declare what needs to happen and let the architecture emerge from that constraint.</p><p>Those declarations became architectural constraints guiding every decision. Teams stop bikeshedding about microservice boundaries and started building systems that provably meet requirements.</p><h2>How procedural programming fails at scale</h2><p>Procedural systems fail for the same reason that manually managing server configurations fail: they don&#8217;t account for the complexity explosion from system growth.</p><p>Every time you write a procedure, you&#8217;re making assumptions about the environment, the inputs, the available resources and the desired outcomes. You rely on expected side effects, assumptions about what&#8217;s happening outside the procedure. Those assumptions become technical debt the moment any condition changes.</p><p>I&#8217;ve seen this pattern repeatedly:</p><ol><li><p>In DevOps: you start with simple deployment scripts, but as requirements evolve, scripts grow more complex. Eventually, it&#8217;s an unmanageable forest of conditional logic that nobody wants to touch.</p></li><li><p>With code complexity: systems designed procedurally become tightly coupled. When one piece changes, ripple effects cascade. What should be a simple update becomes a multi-team coordination effort.</p></li><li><p>During testing: procedural code demands testing every possible execution path, every external dependency. Side effects cause complications. Teams must choose between inadequate tests or spending too much time maintaining those tests.</p></li><li><p>With knowledge bottlenecks: procedural systems distill complex knowledge into internal implementation detail. When the code author departs so does the knowledge. It takes months to reverse-engineer implicit, complex logic.</p></li></ol><h2>The declarative alternative</h2><p>Declarative systems solve these problems. Instead of encoding <em>how</em> something should happen (which brings with it all the fragility of a procedural approach), you specify <em>what</em> should be true, then rely on the system to maintain those conditions.</p><p>There are a few arguments against declarative code that I hear now and then. In my experience these are based on misinformation:</p><blockquote><p>&#8220;Declarative code is hard to think about.&#8221;</p></blockquote><p>I couldn&#8217;t disagree more. Declarative systems are concise, clear, and consolidate all of your logic in a single place. It&#8217;s easier to comprehend, and far easier to test. This is really about comfort and changing how we were taught to solve problems &#8212; we&#8217;re more <em>comfortable</em> thinking procedurally.</p><blockquote><p>&#8220;You lose control with declarative approaches.&#8221;</p></blockquote><p>You gain control. Instead of controlling implementation details, you control outcomes. When you declare &#8220;this service should always have three healthy replicas,&#8221; the system ensures that&#8217;s true even when nodes fail, traffic spikes, or deployments occur.</p><blockquote><p>&#8220;Declarative systems are harder to debug.&#8221;</p></blockquote><p>Procedural systems require tracing through execution paths to understand what went wrong. Declarative systems let you compare current state to desired state. <em>The difference between current and desired state is the bug.</em></p><p>When a Kubernetes deployment fails, you don&#8217;t debug the container orchestration logic. You check if your declared resources can be satisfied and fix the mismatch.</p><p>Remember that deployment script example above? 1,000-line deployment script that sometimes failed spectacularly and required days of diagnosis?</p><p>We replaced it with IaC in Terraform, declaring the desired infrastructure state. The declarative specification is just a few hundred lines long. More importantly, we now deploy to any region. We change environment settings with a few variables, not by rewrite procedures. Deployments that previously took days (or, just outright failed) are now done with a click, via a dashboard, and it&#8217;s utterly reliable.</p><p>I mentioned that <em>declarative thinking applies far beyond code</em>. So how do we &#8220;scale up&#8221; from declarative code to declarative thinking?</p><div class="pullquote"><p><em>I&#8217;d really appreciate it you could refer a friend. Plus, three referrals and you earn a free month!</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>Building declarative teams</h2><p>The most profound realization is that <em>declarative thinking</em> extends beyond code to how we structure teams and processes.</p><p>Traditional project management is procedural: detailed project plans with dependencies, specific task assignments, and rigid timelines. When requirements change (and they always do), the entire plan requires revision.</p><p>Declarative project management focuses on <em>outcomes</em>: &#8220;We need a user authentication system that handles 100,000 concurrent users with 99.9% uptime.&#8221; The team figures out how to deliver that outcome, adapting their approach as they learn more about the problem space.</p><p>Goals and emphasis for the team shift <em>away</em> from activities and <em>toward</em> specific, measurable, provable outcomes.</p><p>This is exactly what the <a href="https://blog.bosslogic.com/s/delivery-playbook">Delivery Playbook</a> enables. Instead of prescriptive methodologies that tell teams <em>how</em> to work, the playbook declares <em>what</em> good delivery <em>looks like,</em> providing a framework to achieve it reliably.</p><p>Here&#8217;s a practical framework for moving your team toward declarative thinking:</p><ol><li><p><strong>Start with outcomes, not activities.</strong> Instead of &#8220;implement user authentication,&#8221; declare &#8220;users can securely access their data from any device.&#8221; The first focuses on building something; the second focuses on enabling something. This is the shift away from procedural thinking. It takes time, but with practice you&#8217;ll get there.</p></li><li><p><strong>Express constraints, not solutions.</strong> Instead of &#8220;use microservices with REST APIs,&#8221; declare &#8220;components must be independently deployable and testable.&#8221; Let the architecture emerge from the constraints.</p></li><li><p><strong>Define interfaces, not implementations.</strong> Instead of detailed API documentation explaining how to use your service, create OpenAPI specifications that declare what your service provides. <a href="https://blog.bosslogic.com/p/automate-all-the-things-with-live-documents-43267dc7bd4d?r=2xiufs&amp;utm_campaign=post&amp;utm_medium=web&amp;showWelcomeOnShare=false">Generate the documentation</a>, client APIs, and validation <em>from the specifications and code</em>.</p></li><li><p><strong>Build systems that maintain state.</strong> Instead of scripts that perform actions, build systems that ensure conditions remain true. Think about Kubernetes&#8217; declarative nature: &#8220;there must always be 3 healthy replicas running.&#8221; Use Terraform, Kubernetes and frameworks like <a href="https://ash-hq.org/">Ash Framework</a>.</p></li><li><p><strong>Test behaviors, not code paths.</strong> Instead of unit testing internal implementation details, write tests that assert <a href="https://blog.bosslogic.com/p/22-roadmaps-and-okrs?r=2xiufs&amp;utm_campaign=post&amp;utm_medium=web&amp;showWelcomeOnShare=false">observable behaviors and outcomes</a>. Focus on policies, for instance, &#8220;forbid non-administrators from creating a new account.&#8221;</p></li><li><p><strong>Use design thinking. </strong>Build organization processes that model your declarative &#8220;way of working.&#8221; Adopt inputs and specific outputs for project phases, relying on statements about target state (not focusing on &#8220;what activities everyone should be doing&#8221;). The <a href="https://blog.bosslogic.com/s/delivery-playbook">playbook</a> is a great example to use as a model.</p></li><li><p><strong>Only measure progress. </strong>Focus on evidence-based delivery. What matters is achieving the declared target state. Progress is measured <em>only</em> by validating that your target state &#8212; your feature &#8212; is working and deployed.</p></li></ol><h3>Deep dive: a declarative security API by contract</h3><p>I&#8217;ve written a lot about declarative thinking in abstract. An example will be helpful to crystalize what it really means. Let&#8217;s say we&#8217;re building a project tracking system for our agile team. We want to manage sprints and their activities.</p><p>One thing we&#8217;ll need is a way to track those sprints. Here&#8217;s one approach &#8212; a fairly traditional, procedural one:</p>
      <p>
          <a href="https://blog.bosslogic.com/p/why-being-declarative-is-your-competitive-advantage">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[8 ways you'll distinguish yourself and achieve more]]></title><description><![CDATA[8 tips for outperforming and excelling in everything you do &#8212; learned from a lifetime of working in tech, living, and being human.]]></description><link>https://blog.bosslogic.com/p/8-ways-to-distinguish-yourself</link><guid isPermaLink="false">https://blog.bosslogic.com/p/8-ways-to-distinguish-yourself</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Tue, 26 Aug 2025 16:22:01 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!VJRI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.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_!VJRI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VJRI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.jpeg 424w, https://substackcdn.com/image/fetch/$s_!VJRI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.jpeg 848w, https://substackcdn.com/image/fetch/$s_!VJRI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!VJRI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VJRI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.jpeg" width="1456" height="895" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/efeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:895,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:283417,&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/167752305?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.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_!VJRI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.jpeg 424w, https://substackcdn.com/image/fetch/$s_!VJRI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.jpeg 848w, https://substackcdn.com/image/fetch/$s_!VJRI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!VJRI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefeeb488-9e1e-43e8-a294-1576dbd6c2dc_2591x1593.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">Statue of Alexander the Great (photo by <a href="https://unsplash.com/@nikos_vlachos?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Nikos Vlachos</a> on <a href="https://unsplash.com/photos/a-statue-of-a-man-riding-a-horse-nfSsyAkYgcs?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a>)</figcaption></figure></div><div class="pullquote"><p>Here&#8217;s a collection of 8 short ideas and actions that, in a nutshell, sum up some of my key strategies for achieving more and standing out. Each one connects to a more in-depth article that I&#8217;ve written during the past year.</p></div><h2>Be uncompromising about your craft</h2><p>Steve Jobs was notorious for rejecting products that were nearly complete if they didn't meet his exacting standards. He would send teams back to redesign products multiple times, sometimes scrapping months or years of work.</p><p>The iPhone launched without a physical keyboard when BlackBerry dominated with keyboards. Jobs believed in making hard choices about what to leave out, saying &#8220;innovation is saying no to 1,000 things.&#8221;</p><p>He believed that true craftsmanship meant caring about every aspect of a product, not just what was visible. </p><div class="pullquote"><p><em><strong>&#8220;If you are working on something that you are excited about, you don&#8217;t have to be pushed. The Vision pulls you.&#8221; &#8212; Steve Jobs</strong></em></p></div><p><em>Caring</em> about your craft matters. It gives you passion. It drives exceptionalism.</p><p>Your customers care about what you build, too. They want to be delighted. Delighted customers become evangelists (just like Apple customers and the &#8220;cult of Mac&#8221;). This is your &#8220;<a href="https://blog.bosslogic.com/p/value-stream-engineering-in-a-nutshell?r=2xiufs&amp;showWelcomeOnShare=false">value stream</a>.&#8221; Understanding what really matters, and sticking to it.</p><p>Making compromises won&#8217;t lead to delight. Compromise leads to mediocrity.</p><p>Instead, be uncompromising. Seek excellence, say &#8220;no&#8221; to 1,000 things. Choose the best possible path forward &#8212; even if it takes longer, even if it&#8217;s the harder path.</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;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://blog.bosslogic.com/subscribe?"><span>Subscribe now</span></a></p><p><em>Anytime you'd like to read more, you can upgrade to a paid subscription.</em></p></div><h2>Have really deep conversations with people that matter</h2><p>It&#8217;s hard to build a shared understanding of a tough problem. But, only in-depth mutual understanding makes <em>learning and joint decision-making</em> possible. It how we discover better paths forward.</p><p>Where many teams go wrong is not understanding how important this is. They lose patience, try to explain a technical necessity with hand-wavy jargon, or tell their customer it&#8217;s &#8220;best practice.&#8221;</p><p>That creates opaque dependencies where your customer, your boss, your coworkers have no power. The only way forward would be blind trust. It&#8217;s just not realistic to believe <em>anyone</em> enjoys those conditions.</p><p>Plus, what if they know something you don&#8217;t?</p><p>No matter how experienced I <em>think</em> I am, I always have enough self-doubt to ask, &#8220;wait, am I missing something here?&#8221;</p><p>Have those deep conversations. Explain the tough problems. See if there&#8217;s a better way forward.</p><p>It means <a href="https://blog.bosslogic.com/p/stakeholder-management-101?r=2xiufs&amp;showWelcomeOnShare=false">sharing decision making</a>, because you&#8217;re opening yourself up. Admitting that maybe, there&#8217;s a better solution. At first it feels like you&#8217;re giving up control &#8212; but you&#8217;re not. You are <em>sharing control</em> by having those important conversations.</p><h2>Test your assumptions</h2><p>It&#8217;s not always easy to know if we made the right decisions, <em>especially</em> when we casually make assumptions. We make assumptions all the time. <em>This</em> feature will be great. <em>That</em> security policy is good enough.</p><p>Fortunately, in software, it&#8217;s pretty straight-forward to test those assumptions: establish your key results, and then measure them.</p><p>Pick the results you care about. Choose a metric to measure, like number of failures, latency to reply, or anything else that proves your feature does what it&#8217;s supposed to do.</p><p>Then, measure. That just means test the results. In software, I love <a href="https://blog.bosslogic.com/p/the-balanced-power-of-tdd?r=2xiufs&amp;showWelcomeOnShare=false">Test Driven Development</a> (TDD). I wouldn&#8217;t code any other way.</p><p>But what if we&#8217;re talking about doing what&#8217;s right? Cutting through the nonsense and deciding if <em>this</em> or <em>that</em> will leave our planet or our society in a better place, or a worse place?</p><p>The same strategy applies. Choose your key results and measure. Check the facts.</p><p>Maybe you&#8217;ve heard the argument, &#8220;we&#8217;re in a cooling period, the earth is actually cooler now than any time in 485 million years!&#8221; That sounds great. But don&#8217;t assume it is. Being cooler now than ever before could be a sign of fragility, a statistical anomaly. Outliers become normalized &#8212; plus, if you look closely, you&#8217;ll see other patterns. The sudden, rapid uptick in temperature that&#8217;s been happening for about 100 years? It happened once before, almost 250 million years ago &#8212; just before a mass extinction event that wiped out about 90% of life.</p><p>In the real world, don&#8217;t blindly accept some numbers you hear, instead check to see if they add up. <em>Measure your results, and see if you were right.</em></p><p>It can be hard though. We&#8217;re basically trying to catch ourselves in making a mistake. Nobody likes to make mistakes &#8212; but at least this way, you catch it first.</p><h2>Anticipate mistakes</h2><p>I assume I&#8217;m going to make mistakes.</p><p>In fact, I assume I&#8217;ll make <em>more</em> mistakes when I feel more comfortable, more knowledgeable about something. Because it&#8217;s easy to get lazy.</p><p>But I don&#8217;t <em>actually</em> make that many mistakes. Why?</p><p>Because I&#8217;ve put systems in place to protect against them.</p><div class="pullquote"><p><em>I&#8217;d really appreciate it you could refer a friend. Plus, three referrals and you earn a free month!</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><p>Those systems are my secret weapon. My personal edge that makes sure I don&#8217;t make mistakes &#8212; while sometimes, it seems like everyone else is figuring it out as they go along.</p><p>All it takes is stopping yourself from charging blindly ahead:</p>
      <p>
          <a href="https://blog.bosslogic.com/p/8-ways-to-distinguish-yourself">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Technical drawings that actually work]]></title><description><![CDATA[The right kind of technical drawings should make your engineering work easier, eradicate coding mistakes, create a linkage to your acceptance criteria and be understandable by your customer.]]></description><link>https://blog.bosslogic.com/p/technical-drawings-that-work</link><guid isPermaLink="false">https://blog.bosslogic.com/p/technical-drawings-that-work</guid><dc:creator><![CDATA[Zac Beckman]]></dc:creator><pubDate>Wed, 20 Aug 2025 07:49:48 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!cILc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.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_!cILc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cILc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.jpeg 424w, https://substackcdn.com/image/fetch/$s_!cILc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.jpeg 848w, https://substackcdn.com/image/fetch/$s_!cILc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!cILc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cILc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.jpeg" width="1456" height="928" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/da1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:928,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:429957,&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/171125033?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.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_!cILc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.jpeg 424w, https://substackcdn.com/image/fetch/$s_!cILc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.jpeg 848w, https://substackcdn.com/image/fetch/$s_!cILc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!cILc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda1ec0bf-0284-4700-87a8-49cb9c5d234c_2000x1275.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/@resourcedatabase?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Resource Database</a> on <a href="https://unsplash.com/photos/diagram-engineering-drawing-rkQdROHIwFk?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure></div><h1>Being intentional about your drawings</h1><p>I&#8217;ve seen a <em>lot</em> of technical drawings. I&#8217;ve been witness to religious wars about one style over another. I&#8217;ve seen engineering teams melt down over which arrow directionality means &#8220;input&#8221; versus &#8220;output.&#8221;</p><p>It can be a contentious topic &#8212; perhaps understandably so.</p><p>Adopting one kind of drawing style over another imposes a particular style on our <em>architecture</em> as well. Our drawings influence our architecture. If we use an object oriented notation, we&#8217;ll likely design a system based on objects. A style that&#8217;s heavily relational, we&#8217;ll probably put business logic in the database.</p><p>Our drawing style shouldn&#8217;t lock us into a predetermined technical approach.</p><p>That&#8217;s why we need to be <em>really careful</em> about our technical drawings.</p><p>I like technical drawings that are unambiguous, easy to read and easy to maintain. The drawings need to be understandable by everyone, including your customer. That&#8217;s <em>essential</em> &#8212; because the moment part of your team can&#8217;t follow along, it&#8217;s useless.</p><p>What&#8217;s more, the right style is going to add value to your project by:</p><ol><li><p>Adding fidelity to business processes, in a way that the customer, product owner, and business can validate. It can&#8217;t be indecipherable technical jargon.</p></li><li><p>Being compatible with how we model <em>business events</em>, extending ideas about event modeling and contextual boundaries.</p></li><li><p>Extending validation criteria; in other words, it should model the acceptance criteria that proves we delivered the right thing.</p></li><li><p>Working well with all of our engineering requirements (not creating an impedance mismatch as we try to translate into a different domain or technology).</p></li></ol><p>For the past decade or so, I&#8217;ve been using two specific types of diagrams. This is all I&#8217;ve needed across many domains and many project sizes.</p><p>I&#8217;ve chosen these two drawing types to meet two specific needs:</p><ol><li><p>The first adds functional detail to complex business processes, so we can see exactly how these processes will be implemented and tested.</p></li><li><p>The second makes it easier to reason about complex interaction sequences between disparate components in complex systems.</p></li></ol><h2>#1. Architectural marble diagrams</h2><p>Marble diagrams are a visual way to represent behavior. They align well with event modeling because they model <em>streams of information</em> using a timeline-based format. They use symbols to depict the emission of values, completions, and errors. A marble diagram represents an &#8220;observable source&#8221; with a timeline and demonstrates how information is transformed and ultimately emitted.</p><p>Marble diagrams are <em>event oriented,</em> so they fit well with event streaming architecture. Here&#8217;s a quick synopsis of terminology that&#8217;s frequently used in marble diagrams:</p><ol><li><p>&#8220;Observable.&#8221; A thing that can be observed to be true or false; basically, something we can validate as correct. An &#8220;observable source&#8221; is just where an observable thing comes from.</p></li><li><p>&#8220;Operation.&#8221; Some kind of a process or function that we can apply.</p></li><li><p>&#8220;Value&#8221; and &#8220;event&#8221; are, respectively, discrete properties and some concrete thing that has happened and can be recorded.</p></li></ol><p>It sounds a lot like an event driven architecture, making marble diagrams a great way to model a business process. It essentially takes an <em>input</em>, shows how the input <em>changes</em> over time, and what is ultimately <em>output</em>. If you&#8217;re following my <a href="https://blog.bosslogic.com/s/delivery-playbook">playbook</a> that formula should sound familiar.</p><p>A marble diagram, in a nutshell, looks 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_!JhoJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2631b1cb-0bff-48d1-abac-f78fceabf315_3082x1297.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JhoJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2631b1cb-0bff-48d1-abac-f78fceabf315_3082x1297.png 424w, https://substackcdn.com/image/fetch/$s_!JhoJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2631b1cb-0bff-48d1-abac-f78fceabf315_3082x1297.png 848w, https://substackcdn.com/image/fetch/$s_!JhoJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2631b1cb-0bff-48d1-abac-f78fceabf315_3082x1297.png 1272w, https://substackcdn.com/image/fetch/$s_!JhoJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2631b1cb-0bff-48d1-abac-f78fceabf315_3082x1297.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JhoJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2631b1cb-0bff-48d1-abac-f78fceabf315_3082x1297.png" width="1456" height="613" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2631b1cb-0bff-48d1-abac-f78fceabf315_3082x1297.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:613,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:217143,&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/171125033?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2631b1cb-0bff-48d1-abac-f78fceabf315_3082x1297.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_!JhoJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2631b1cb-0bff-48d1-abac-f78fceabf315_3082x1297.png 424w, https://substackcdn.com/image/fetch/$s_!JhoJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2631b1cb-0bff-48d1-abac-f78fceabf315_3082x1297.png 848w, https://substackcdn.com/image/fetch/$s_!JhoJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2631b1cb-0bff-48d1-abac-f78fceabf315_3082x1297.png 1272w, https://substackcdn.com/image/fetch/$s_!JhoJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2631b1cb-0bff-48d1-abac-f78fceabf315_3082x1297.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">Marble diagrams are functional and simple &#8212; but model complexity easily.</figcaption></figure></div><p>Here&#8217;s a quick explanation. Each of the numbered post-its in the diagram correspond to the explanation below:</p><ol><li><p>A business event from your <a href="https://blog.bosslogic.com/p/34-tactical-event-storming?r=2xiufs">tactical event map</a>. If your diagraming tool supports it (<a href="https://miro.com/">Miro</a> does), create a bidirectional link &#8212; allowing you to navigate between your tactical map and marble diagram with a click.</p></li><li><p>The input to a function is identified with a letter. In this case, the data set &#8220;A&#8221; is an input to the &#8220;4.0 Exploded Event&#8221; function.</p></li><li><p>Each function is represented as a sequence of &#8220;marbles&#8221; along a timeline. Individual marbles represent values, functions or &#8220;observables,&#8221; and emitted values. An emitted value could be a result, a signal or an error.</p></li><li><p>We can add another layer to explode further complexity &#8212; it&#8217;s &#8220;marbles all the way down.&#8221; You can think of each layer like another layer in the call stack. But, not necessarily literally; you model added complexity as you need by increasing depth.</p></li><li><p>Once the input has been transformed to a result, it&#8217;s no longer an &#8220;A&#8221; data type. It becomes a new type, here noted with a &#8220;B.&#8221; The &#8220;B&#8221; simply represents a new data set, in this case output from the &#8220;4.0 Exploded Event&#8221; function.</p></li><li><p>One of the things I <em>love</em> about marble diagrams is the representation of the <em>result</em> in your diagram. The output value, &#8220;B,&#8221; <em>is your acceptance criteria.</em> It connects your technical drawings directly to the specifications.</p></li></ol><p>As you can see marble diagrams fit very well into an event driven architectural model.</p><div class="pullquote"><p>I&#8217;d really appreciate it you could refer a friend. Plus, three referrals and you earn a free month!</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>The drawing style is easy to adapt and expand upon. You can add annotations and, of course, other shapes and icons to add specific meanings to your design.</p><p>And the value of point number 6 cannot be understated: the representation of your <em>data</em> in your design specifications is <em>powerful.</em> We&#8217;ve clearly carried our requirements forward, showing business inputs, how we will transform those inputs and then showing the output. The output, then, is <em>your acceptance criteria</em> &#8212; it effectively shows us exactly what we must <em>test</em> to validate our work.</p><p>Let&#8217;s walk through a real-world example. Here&#8217;s a simple event map that I&#8217;ve annotated by numbering the events &#8212; a better alternative would be to use clickable links, which would make numbering unnecessary:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ToVf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdebb6c69-4070-41c0-bfa9-c8fab29744c8_3251x1085.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ToVf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdebb6c69-4070-41c0-bfa9-c8fab29744c8_3251x1085.png 424w, https://substackcdn.com/image/fetch/$s_!ToVf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdebb6c69-4070-41c0-bfa9-c8fab29744c8_3251x1085.png 848w, https://substackcdn.com/image/fetch/$s_!ToVf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdebb6c69-4070-41c0-bfa9-c8fab29744c8_3251x1085.png 1272w, https://substackcdn.com/image/fetch/$s_!ToVf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdebb6c69-4070-41c0-bfa9-c8fab29744c8_3251x1085.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ToVf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdebb6c69-4070-41c0-bfa9-c8fab29744c8_3251x1085.png" width="1456" height="486" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/debb6c69-4070-41c0-bfa9-c8fab29744c8_3251x1085.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:486,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:336332,&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/171125033?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdebb6c69-4070-41c0-bfa9-c8fab29744c8_3251x1085.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_!ToVf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdebb6c69-4070-41c0-bfa9-c8fab29744c8_3251x1085.png 424w, https://substackcdn.com/image/fetch/$s_!ToVf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdebb6c69-4070-41c0-bfa9-c8fab29744c8_3251x1085.png 848w, https://substackcdn.com/image/fetch/$s_!ToVf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdebb6c69-4070-41c0-bfa9-c8fab29744c8_3251x1085.png 1272w, https://substackcdn.com/image/fetch/$s_!ToVf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdebb6c69-4070-41c0-bfa9-c8fab29744c8_3251x1085.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">Simple event map that includes a &#8220;4.0 Loan prequalified&#8221; event.</figcaption></figure></div><p>What we want to do is explode the &#8220;4.0 Loan prequalified&#8221; event, adding more fidelity to that specific card.</p><p>I&#8217;ve added some annotations to help explain the example diagram below, along with a legend:</p><ol><li><p>The marbles now have two styles. The bold style indicates an event has been emitted, for instance, writing the output value to a Kafka event queue.</p></li><li><p>Notations for logging, blocking function calls and retries have been added.</p></li><li><p>Other shapes are shown in the legend. Marble diagrams are flexible; you should feel free to add annotations whenever it adds clarity to your designs.</p></li></ol><p>This example shows the specific steps performed in prequalification:</p>
      <p>
          <a href="https://blog.bosslogic.com/p/technical-drawings-that-work">
              Read more
          </a>
      </p>
   ]]></content:encoded></item></channel></rss>