<?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[Joseph Gefroh: War Stories]]></title><description><![CDATA[Lived experiences I've had leading and managing engineering organizations.]]></description><link>https://blog.jgefroh.com/s/war-stories</link><image><url>https://substackcdn.com/image/fetch/$s_!sphd!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cef45a3-7420-4cba-95f3-46a3b5d34293_100x100.png</url><title>Joseph Gefroh: War Stories</title><link>https://blog.jgefroh.com/s/war-stories</link></image><generator>Substack</generator><lastBuildDate>Wed, 08 Apr 2026 13:17:36 GMT</lastBuildDate><atom:link href="https://blog.jgefroh.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Joseph Gefroh]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[jgefroh@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[jgefroh@substack.com]]></itunes:email><itunes:name><![CDATA[Joseph Gefroh]]></itunes:name></itunes:owner><itunes:author><![CDATA[Joseph Gefroh]]></itunes:author><googleplay:owner><![CDATA[jgefroh@substack.com]]></googleplay:owner><googleplay:email><![CDATA[jgefroh@substack.com]]></googleplay:email><googleplay:author><![CDATA[Joseph Gefroh]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[War Stories - The breach from within]]></title><description><![CDATA[Responding to security incidents can take you to completely unexpected places.]]></description><link>https://blog.jgefroh.com/p/war-stories-the-breach-from-within</link><guid isPermaLink="false">https://blog.jgefroh.com/p/war-stories-the-breach-from-within</guid><dc:creator><![CDATA[Joseph Gefroh]]></dc:creator><pubDate>Tue, 22 Jul 2025 00:21:46 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!weYM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.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_!weYM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!weYM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.jpeg 424w, https://substackcdn.com/image/fetch/$s_!weYM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.jpeg 848w, https://substackcdn.com/image/fetch/$s_!weYM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!weYM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!weYM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.jpeg" width="938" height="512" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:512,&quot;width&quot;:938,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:69216,&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://jgefroh.substack.com/i/168882306?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.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_!weYM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.jpeg 424w, https://substackcdn.com/image/fetch/$s_!weYM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.jpeg 848w, https://substackcdn.com/image/fetch/$s_!weYM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!weYM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1edcab41-ada6-4ee4-9a9d-6b2101c58e2c_938x512.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><strong>&#8220;There&#8217;s a weird error on the admin page&#8221;</strong> </p><p>One of the lead engineers for a company I was helping walked over to my desk shortly before the day ended. He had been randomly checking on errors and he saw something suspicious - a series of errors on our internal admin pages for users. </p><p>We had never seen the error before - did we accidentally break internal tools relied on by our support team?</p><p>Thus started a saga that involved sprinklings that wouldn&#8217;t be out of place in a thriller: security breaches, detective work, and sudden leadership exits.</p><div><hr></div><h2>It all started with an error</h2><p>While I don&#8217;t recall the details of the error, what I remember was that it was unusual - it wasn&#8217;t the kind of error we normally saw, and it was in a location that rarely broke. </p><p>The system was usually noisy, but predictable. Hundreds of the same kinds of error would occur like clockwork- some blocking, some weren&#8217;t, but they were all expected to various degrees as the day&#8217;s activity ebbed and flowed.</p><p>New errors, though - we were alway concerned with new errors. We treated new ones as change failures, and since this was a new error, we started an incident response. </p><p>We checked deploys - we hadn&#8217;t deployed anything recently to break things. We checked feature flag toggles - nope, nothing.</p><p>So, we dug deeper. As the lead and I investigated, we started becoming more and more puzzled. </p><p>We saw logs that showed access to page numbers in the triple digits. Our first reaction was very engineer: why was someone on support accessing the user list in the internal admin in such an inefficient way? Most people just searched for who they needed.</p><p>As we dug deeper, we started seeing other things that raised our alarm bells - sequential ids were being accessed, the user account didn&#8217;t match the name of anyone we knew, even some indirect object reference.</p><p>This wasn&#8217;t normal user behavior. This was a security incident.</p><div><hr></div><h2>Houston, we have a problem</h2><p>We immediately started our incident response.</p><p>First - we wanted to identify and contain the threat, which was ongoing. After reporting it to the company leadership, we got to work.</p><p>The activity turned out to be a scraper that was scraping our internal admin pages that listed user accounts page by page by page. We saw logs with indirect object references, contiguous pagination coming from multiple sources.</p><p>We quickly got a list of IP addresses and accounts that were performing this activity. We went over account names, matching them with people we knew on the support team. We narrowed on a list of people we didn&#8217;t know or recognize.</p><p>We shut down the accounts and blocked access. After we were confident the immediate threat was contained, we moved to expand further to collect evidence and understand the extent of the attack.</p><p>We started the work of identifying who had created the accounts, what they had accessed, and when they had gained access. We poured over logs, audit trails, error alerts - anything that would give us information. We jumped back and forth from being glad we had logging in certain places to cursing our past selves for not implementing more robust observability.</p><p>Eventually, we found the smoking gun: the IP address of the creator of the accounts. We did a broader trace of activity and found <strong>something shocking.</strong></p><div class="paywall-jump" data-component-name="PaywallToDOM"></div><div><hr></div><h2>The call is coming from inside the house</h2><p>What we found was the biggest surprise: the accounts were created by IP addresses associated with one of our executives.</p><p>What? Did we accidentally copy-paste the wrong log? Was it a public internet? We double checked, then triple checked, then quadruple checked. Nope, it was accurate.</p><p>We cross-compared against everything we could think of. We checked IP addresses from Chat logins, email messages, account logins from when we knew they were in the office, going back months and even years. The IP was consistent. We even geolocated it to their house on days they were in office vs. days they weren&#8217;t.</p><p>The admin accounts used in the attack were created by the executive&#8217;s IP address many days prior, and they were created from an IP address that was associated with private, legitimate traffic. In short - it wasn&#8217;t a case of a hacked admin account.</p><p>The immediate question on our minds was - why? What was the motive?</p><p>It dawned on us - shortly before all this happened, the executive had declared they were stepping down for a new company.  It&#8217;s possible the information would&#8217;ve been useful.</p><div><hr></div><h2>Reporting to the C-Suite</h2><p>As we packaged up our findings, we notified the C-suite with the latest conclusions and gave them the evidence. The suspicion was that the executive hired contractors to write and run the scraper against our internal pages, and granted access to them to do so.</p><p>We documented everything - logs, screenshots, data fields that were accessed. </p><p>Afterwards, we secured a forensics team to dig deeper and prepare evidence. We spent a few sessions explaining what we saw, how we arrived at it, what confidence we had in the information.</p><p>After that, the rest was out of our hands.</p><div><hr></div><h2>The effects</h2><p>After this event, I never saw that executive in the office again. They were just there one day and never came back.</p><p>I don&#8217;t know what specifically happened afterwards. I imagine there was yelling, threats of lawsuits, and even serious conversations of legal exposure.</p><p>Whatever happened, it seems that everyone involved found a way forward, likely interested in not making this &#8220;a thing&#8221;. The executive moved on to a new company, and the other company continued as if nothing had happened.</p><p>I heard rumors here and there afterwards that it was done &#8220;with permission from leadership&#8221; - at least, that was the formal messaging behind why it didn&#8217;t seem to be pursued further. I can&#8217;t say whether that&#8217;s true or not, but in my experience things done with permission don&#8217;t often need to be hidden and usually aren&#8217;t a surprise to the person who gave permission.</p><div><hr></div><h3>The irony</h3><p>The ironic thing is - it could&#8217;ve been untraceable had any number of things happened. </p><p>If the engineer had headed out that evening just a minute or two earlier, we wouldn&#8217;t have noticed. The error would&#8217;ve been lost in a sea of other random errors as a result of poor error curation.</p><p>If the executive had just asked their team for a backup copy, they probably could&#8217;ve gotten the full data without any of the scraping that led to them. It wouldn&#8217;t have been out of the ordinary to give them copies of certain tables to analyze.</p><p>The whole incident was caught due to a bit of luck and overcomplicated execution.</p><div><hr></div><h2>The lessons</h2><p>This story highlights a lot of things:</p><ul><li><p>Observability and traceability are critically important, and you don&#8217;t want to wait until you need them to invest in them.</p></li><li><p>Automate anomaly detection as much as possible - don&#8217;t leave it to chance.</p></li><li><p>We only had &#8220;just enough&#8221; logging to figure out what was happening - that was pure luck, and this could&#8217;ve gone completely undetected.</p></li><li><p>Governance controls are important oversight layers especially in high trust environments - that extends to the leadership team.</p></li><li><p>Evidence and tight chain of custody is required for proof in response to security incidents - a good lawyer can argue anything.</p></li><li><p>When something strange happens, it&#8217;s valuable to really dig into it - we could&#8217;ve just chalked it up to a quirk and gone home.</p></li><li><p>Get written permission if you&#8217;re going to do something that looks remotely suspicious - arguing after the fact can get messy.</p></li><li><p>Integrity and trust are key at all layers of an organization - this includes leadership.</p></li><li><p>Rational behavior can&#8217;t always be expected when the stakes are high</p></li><li><p>Sometimes you get lucky detecting things - but that shouldn&#8217;t be a strategy you rely on</p></li></ul>]]></content:encoded></item><item><title><![CDATA[War Stories - How I turned around a paralyzed Product organization into a rapid delivery engine]]></title><description><![CDATA[How telling a product management organization "value doesn't matter" was the best possible thing I could've done for them.]]></description><link>https://blog.jgefroh.com/p/war-stories-how-i-turned-around-a</link><guid isPermaLink="false">https://blog.jgefroh.com/p/war-stories-how-i-turned-around-a</guid><dc:creator><![CDATA[Joseph Gefroh]]></dc:creator><pubDate>Sun, 11 Feb 2024 21:54:06 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!fmLc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7803ab70-2470-4578-b9ea-da8c880d19b2_1202x584.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_!fmLc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7803ab70-2470-4578-b9ea-da8c880d19b2_1202x584.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fmLc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7803ab70-2470-4578-b9ea-da8c880d19b2_1202x584.png 424w, https://substackcdn.com/image/fetch/$s_!fmLc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7803ab70-2470-4578-b9ea-da8c880d19b2_1202x584.png 848w, https://substackcdn.com/image/fetch/$s_!fmLc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7803ab70-2470-4578-b9ea-da8c880d19b2_1202x584.png 1272w, https://substackcdn.com/image/fetch/$s_!fmLc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7803ab70-2470-4578-b9ea-da8c880d19b2_1202x584.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fmLc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7803ab70-2470-4578-b9ea-da8c880d19b2_1202x584.png" width="1202" height="584" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7803ab70-2470-4578-b9ea-da8c880d19b2_1202x584.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:584,&quot;width&quot;:1202,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1510617,&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;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fmLc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7803ab70-2470-4578-b9ea-da8c880d19b2_1202x584.png 424w, https://substackcdn.com/image/fetch/$s_!fmLc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7803ab70-2470-4578-b9ea-da8c880d19b2_1202x584.png 848w, https://substackcdn.com/image/fetch/$s_!fmLc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7803ab70-2470-4578-b9ea-da8c880d19b2_1202x584.png 1272w, https://substackcdn.com/image/fetch/$s_!fmLc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7803ab70-2470-4578-b9ea-da8c880d19b2_1202x584.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></figure></div><p>A while ago I was given the responsibility of improving the Product Management organization at a startup. It was a Series B company with about 200 people, of which ~50 people were in the development organization. The group of ~10 Product Managers had their leadership recently depart, and they needed someone to step in to help guide them through that transition.</p><p>I knew some of the challenges and opportunity areas from the engineering perspective first-hand and through constant feedback from the engineering team.</p><ul><li><p><strong>There was never enough &#8220;ready&#8221; work to do.</strong> The Product Management organization had a difficult time defining and prioritizing work. As a result, engineers went underutilized for weeks at a time, working on tiny things they found themselves here and there with little value.</p></li><li><p><strong>The requirements that made it to engineering were ill-defined.</strong> The work hadn&#8217;t been done to define the boundaries of the problem space or even what the end-state was supposed to be, leaving engineers to fill in massive gaps in requirements.</p></li><li><p><strong>The &#8220;Why?&#8221; wasn&#8217;t defined or answered, let alone asked.</strong> The value, the problem it was solving, and how that item mapped to a larger vision or picture wasn&#8217;t defined for the development teams.</p></li><li><p><strong>Cross-feature interaction analysis and product capability management was non-existent.</strong> Work items were done in silos  without consideration to how they interacted with existing features, which led to duplicative functionality, or different functionality for the same capability. This lead to large numbers of gaps and quirks in the product overall that reduced quality and led to difficult defects - not due to implementation errors, but due to thought not being put into the intended change itself.</p></li><li><p><strong>Explicit functional boundaries prevented gap filling. </strong>The organization was afraid to step on toes or interfere with another function&#8217;s work, so boundaries formed, leading to decreased collaboration. Of course, because the work that did get handed off had issues, it meant an ever-increasing burden on Engineering to fill in all the gaps as the last function in the value stream capable of fixing issues.</p></li></ul><p>These challenges were at best slowing down delivery of everything, and at worst completely stalling efforts to deliver value.</p><div><hr></div><h1><strong>Identifying the issues</strong></h1><p>When I came on board to the Product organization, I had my own hypothesis and opinions of what the issues were, but I did my due diligence:</p><ul><li><p>I read through chat histories, meeting notes, and other documents to understand how decisions were being made</p></li><li><p>I had 1:1s with every product manager and adjacent functions like Marketing, Privacy, Customer Success, and Solutions that interacted with Product to better understand the issues and challenges from their perspectives.</p></li><li><p>I mapped out the relationships of all of the issues and their causes, influencers, and effects to better understand the first, second, and third effects.</p></li><li><p>I conducted surveys and other analysis of sentiment.</p></li></ul><p>From that, I saw some clear root issues that were creating a complex web of spiraling - a vicious cycle of negative feedback that reinforced itself the longer it went on.</p><ul><li><p><strong>The Product Managers didn&#8217;t have a true understanding of the product or user.</strong></p><ul><li><p>Without understanding how the product truly worked or what the user truly needed, the Product Managers were afraid to make decisions because they couldn&#8217;t figure out the effect of it. When they did make a decision, it often broke some user workflow or had some issue they didn&#8217;t consider because of their lack of comprehensive, true understanding of the user, their journey, and their work. It was like the blind leading the blind. </p></li><li><p>There wasn&#8217;t any formalized mechanisms for the organization to get and leverage feedback. Certain members occasionally did interviews, or looked at a competitor, or read an article, but very little was baked into any formal feedback loop. Whatever knowledge we did obtain was silo&#8217;d and lost in random slack messages instead of becoming a concrete learning that could be used in the future to make decisions.</p></li></ul></li></ul><ul><li><p><strong>The Product Managers wanted to be 100% correct, all the time.</strong></p><ul><li><p>Being wrong was viewed as a terrible thing. In fact, most discussions revolved around how to not be wrong, which naturally led to doing further analysis, measurement, and thinking to avoid being wrong. The quantification of the negative impact of being wrong wasn&#8217;t even being considered. Being wrong was avoided 100%, even for the smallest negative impact. Some of this was due to individual Product Manager personalities, and others were due to fear of punitive measures if something went wrong.</p></li></ul></li><li><p><strong>The Product Managers over-indexed on working on the highest value item.</strong></p><ul><li><p> Not just <em>value</em>, but specifically the <em>highest value</em>. This meant a lot of discussion, argument, and analysis to intimately understand the exact value of all items being considered to eventually be able to decide which item specifically had the most value. This, of course, increased decision-delay.</p></li></ul></li><li><p><strong>The Product Managers wanted everyone to agree before they decided anything.</strong></p><ul><li><p>The Product Management culture was one of consensus - full alignment and agreement was required before anything moved forward. Because nobody wanted to be the one that was wrong, even the smallest disagreement or concern raised derailed a plan to move forward. Few people made decisions, instead opting to have another meeting or touchpoint to get further alignment and clarity. This meeting, of course, was scheduled for a week or two after, which added wait time to even the smallest discussions.</p></li><li><p>If disagreement persisted, even by one person and even if it was an otherwise minor addressable element, it meant that the item was disregarded. While this was fine if it got replaced by another valuable item, the issue was it got replaced with nothing, which further exasperated the lack of delivery of anything.</p></li></ul></li><li><p><strong>The Product Managers cared too much about optics.</strong></p><ul><li><p>There was a massive pressure to concretely measure the specific impact on a particular metric with exacting precision. The go-to method was the A/B test. Product Managers were pushing for every single change to be A/B tested. Despite this, features lacked basic instrumentation because Product Managers generally handed off those responsibilities to the Data Science team.</p></li><li><p>This of course, meant not only the setup of the A/B test adding time to development efforts, but also monitoring and running and interpreting results. Because the Product Managers as a group weren&#8217;t particularly organized or familiar with the data side, the A/B test interpretation fell almost entirely onto the data science function. Because a proper A/B test requires a stable environment, this also meant follow-up iterations were effectively blocked until the A/B test was completed.</p></li></ul></li></ul><p><strong>In short - analysis paralysis ruled the day.</strong> All of these specific issues fed into each other like a vicious cycle. Because of a lack of understanding, product managers made mistakes. This made them more scared to make future decisions, so they tried to analyze more and measure more to prove they did a good job. Because they tried to analyze more before they made any decision, they slowed down their decision making. This increased pressure on the product managers to make sure whatever decision they did make had high value, which further led to more analysis and delays. This decreased confidence so they tried to get all of their stakeholders and peers to agree on every aspect of a change before moving forward, which meant valuable items with minor concerns got disregarded, further leading to slower decisions.</p><p><em>I knew I needed to break this cycle.</em></p><div><hr></div><h1>The Gordion Knot of Analysis Paralysis</h1><blockquote><p>The Gordion Knot is a legend about a complicated knot. </p><p>The belief was that whoever untied that knot would go on to rule all of Asia. Alexander the Great came along to untie it. Instead of painstakingly and slowly untying the knot as expected, he just cut it in into pieces with his sword.</p><p>It&#8217;s a metaphor for intractable problems and the solution spaces that are possible if you don&#8217;t make yourself beholden to perceived constraints.</p></blockquote><p>I thought hard about the situation and the culture. I spent several weeks diving deep into the problem space that the organization found itself in. </p><p>Fear was the root cause of a lot of these issues. Fear of being wrong. Fear of looking bad. Fear of having others disagree. Fear of being uncertain. Fear of making mistakes. Fear of punishment. The only way to remove the fear is to remove the disincentives.</p><p>I created a bold and, frankly, <em>insane,</em> 120-day plan. One that I kicked off at the next Product Management all-hands.</p><h2><strong>Setting the tone</strong></h2><p>That Monday, I said clearly and in no uncertain terms to every Product Manager in the company:</p><p><strong>I don&#8217;t care about the value. The value doesn&#8217;t matter. Stop considering it. Stop thinking about it.</strong></p><p>I could see the wheels turning in all the product manager&#8217;s heads. Their whole job is oriented around delivering value. If value doesn&#8217;t matter, what does that mean for them and their careers?</p><p><em>I can see the wheels turning in your heads, too.</em> I can hear the cries of &#8220;blasphemy&#8221; from all of you readers who are product managers that have been trained on the belief that the highest value is the only thing that matters. </p><p>But the fact is, it&#8217;s not.</p><p><strong>The whole point of a Product Management is to </strong><em><strong>deliver value.</strong></em> The key first word in that is to be able to <em>deliver</em>. It&#8217;s not enough to talk about value, or compare one value to another, or know what&#8217;s valuable in your head. All of the purpose of the role is predicated on the first word - that value is being <strong>delivered.</strong></p><p>The team&#8217;s problem was that in their pursuit of the value, they forgot how to deliver. The muscle of intentionally and sufficiently defining a change, crafting a narrative, influencing others, working with a development team, and putting it out into the world, and then seeing what the effect was had atrophied. Habits of fear and talking replaced it. Under that fog of fear, they went through the motions of product management without fulfilling its spirit. They got slower because they didn&#8217;t know how to act without full knowledge. They got slower because getting full knowledge required delivering, which they didn&#8217;t know how to do.</p><p>It was lik trying to turn a car into tho right direction without moving either forward or backwards. We couldn&#8217;t even get out of the parking lot to know whether we were going in the right direction.</p><p>We needed to build up the delivery muscle, and to do that, we needed to go through the reps of delivering <em>something</em> - regardless of the value.</p><h2><strong>Breaking the desire for full confidence</strong></h2><p>Some of the Product Managers still weren&#8217;t sure. They were still fearful of changes they made. It might be fine to ignore value, but what if it has a negative impact?</p><p>My response was simple : <em>who cares?</em> If it has a negative impact, we can see it on the basic instrumentation and roll it back. Changes were reversible. Software is &#8220;soft&#8221;ware for a reason.</p><p>Some weren&#8217;t convinced. </p><p><strong>&#8220;Well, that&#8217;s not precise enough&#8221;.</strong> They wanted to A/B test everything to be absolutely sure it wouldn&#8217;t harm a company outcome.</p><p>I told them that with change comes risk, and with risk comes the possibility of failure. Trying to measure every single step you take to see if it&#8217;s taking you in the right direction isn&#8217;t due diligence, it&#8217;s fear. There&#8217;s no place for fearful product management in a startup. </p><p>The fact is, at our company, A/B testing had become a crutch to hide a lack of decision-making.</p><p>So, I decided to remove that crutch. </p><p><em><strong>I banned A/B tests.</strong></em></p><h3><strong>The right tool for the wrong job</strong></h3><p>That&#8217;s not to say A/B tests aren&#8217;t useful. They are, in the right context. The situation our company in was absolutely the wrong context. The desire of the product managers to test everything was getting in the way of making progress.</p><p>There were proposals to A/B test even the smallest of changes - changing the text of a navigation bar link, adding a new filter to a dashboard list, or adding instructional text to a search bar. There was even a proposal to A/B test the error message of a donation!</p><div class="paywall-jump" data-component-name="PaywallToDOM"></div><p>Little thought was put into what the risk profile of these changes actually looked like. Nobody even considered whether that profile warranted needing the precision confidence of an A/B test to make a decision on outcome. That there were other cheaper, perfectly appropriate mechanisms to obtain outcome confidence didn&#8217;t seem to resonate.</p><p>The proponents of &#8220;A/B test everything&#8221; also didn&#8217;t put much weight into the fact we wanted to iterate rapidly on our product, and an A/B test would prevent rapid follow-up iterations to the exact areas we wanted to change as a company because we would need to wait weeks and months for an appropriately large sample size.</p><p>I stuck to my stance.</p><h2><strong>Drawing decision boundaries</strong></h2><p>The third thing I did was to ensure that the Product Managers didn&#8217;t get interfered with. One of the issues was that they got a lot of feedback from others in the company - folks that were there longer or whom were viewed as  &#8220;subject matter experts&#8221; of a particular area or system that argued about the smallest detail or approach. Many arguments ended in the same way - the Product Manager seeing all of the possible problems, challenges, and issues and simply concluding that it wasn&#8217;t worth it to continue.</p><p><strong>Every single thing we do has reasons for not doing them</strong>. Some are very good reasons. Some are bad reasons. They are all there, all the time. If we overpay attention to reasons we shouldn&#8217;t do something, we&#8217;ll just get stuck not doing anything at all. Instead, we should look for good reasons to do something, and treat all the reasons not to do something as the addressable, definable, and sometimes ignorable risks they are.</p><p>I needed to break the product managers free of the well-intentioned influence from others. </p><p>To do that, I took a page out of my autocratic dictator playbook. I told them that the only person who&#8217;s opinion mattered was my own, and that they should ignore any disagreements from anyone. If I said it was to be done, that was all that mattered. People who argued we hadn&#8217;t validated it, that it had risks, that it wasn&#8217;t aligned: none of that mattered except my opinion for them to do it.</p><h2>Listening to the users</h2><p>If the Product Managers weren&#8217;t doing analysis and discovery, then what would they work on? What would get prioritized? How would we determine what we worked on?</p><p>Simple: the users.</p><p>For years we had multiple mechanisms for collecting user feedback - annual surveys, in-product ratings, support tickets. While some analysis was done and an occasional item or two pulled from them, these sources of user feedback were almost entirely ignored.</p><p>It had gotten to the point that our users giving us feedback were answering our questions with statements like &#8220;why do we even bother answering this if you never change the things we bring up&#8221;. They were tired of making the same complaints, year over year over year and seeing nothing done.</p><p>I didn&#8217;t want the Product Organization to waste all their time trying to identify possible new problem spaces. With the surveys, we had problem spaces in front of us we could immediately address. Sure, it might not be the most valuable, but I didn&#8217;t care about the value. What use was identifying the most valuable if we had not built up the ability to act on it afterwards? That would be like hearing without listening.</p><p>I went through the thousands of answers on the survey and, with the product managers, manually created a list of feedback areas that I called &#8220;Pain Points&#8221; - the problem areas of our product that people complained about repeatedly. </p><p>Many of these were explicitly self-evident solutions, while some contained more ambiguity and nuance:</p><ul><li><p>Alphabetize the dashboard record list</p></li><li><p>Add a new filter for date</p></li><li><p>Add &lt;X&gt; information to the record</p></li><li><p>Save notes properly</p></li><li><p>Calculating totals</p></li><li><p>Ensure we get paid for our work</p></li><li><p>Improve account security</p></li></ul><p>On that list of pain points, I put a &#8220;reason for doing&#8221; column. I chose 10 pain points - problems I felt had simple solutions with outcomes that would be <em>meaningful to</em> <em>someone</em> and little risk of being <em>harmful to anyone</em>. Next to those 10, I put under &#8220;reason for doing&#8221; - &#8220;Joseph&#8221;.</p><p>I told the team if an item had my name on it, it was a &#8220;do it&#8221;, regardless of any objections they may encounter from anyone. If anyone complained, argued, or pushed back, they should redirect that person to me.</p><p>My goal was simple: I wanted to see a completely different list of problems the next time the survey was run.</p><h2>Being talked out of delivering value</h2><p>There were still extensive discussions happening in Teams and tickets as to why the product managers shouldn&#8217;t do the items on my list:</p><ul><li><p>Did we understand the problem space?</p></li><li><p>What&#8217;s the <em>real</em> problem being solved?</p></li><li><p>Why can&#8217;t they just use the information or features we already have?</p></li><li><p>Are we going to A/B test it?</p></li><li><p>What if it takes too long?</p></li><li><p>Why aren&#8217;t we going to user-test it?</p></li></ul><p>These were happening for even the smallest changes. Product Managers were being talked out of doing work based on even the most insignificant complaints. For example - adding a new label would decrease the screen real estate by 16 pixels, or that adding a specific filter in the product was duplicative because a user could just go and export their data and filter their spreadsheet in Excel. </p><p>Reasons for not moving forward. Reasons for not acting. All reasons without risk-adjusted consideration.</p><p>I needed to create a culture where people were OK with delivering something that didn&#8217;t solve the problem fully, if at all. I needed to create a culture of build-measure-learn, which mean being OK with getting it wrong the first few times. I needed people to understand that sometimes, you just have to do something to see the effects of it.</p><p>Very few of these complaints were one-way doors: that is, items that had negative consequences that were irreversible or massively damaging. Most issues were easily adjusted or minor. <em>Minor issues shouldn&#8217;t stop progress.</em></p><p>This was symptomatic of the exact problem we were having before. We would spend weeks talking about a half dozen possibilities to figure out which one to do. In that time, we could&#8217;ve successfully delivered all of them and then figured out the right one based on real results. It was all talk, no walk.</p><p>I re-iterated that they should ignore any objection and to proceed with solving the problem at hand. I explicitly told them to ignore every single person complaining or proposing alternatives.</p><p><strong>Did that reduce autonomy and collaboration from the organization?</strong> Yes, it did. But the team had shown that they couldn&#8217;t move forward with the level of autonomy that they had, and that the level of collaboration was no longer productive. </p><p>It&#8217;s perfectly fine to reduce positive elements to appropriate levels if they start having negative impacts.</p><h1><strong>Supporting rapid solutions</strong></h1><p>With these adjustments, the Product Managers were able to bypass the &#8220;discovery&#8221; and &#8220;prioritization&#8221; steps that had been plaguing their slow speed and finally moved towards &#8220;defining&#8221; and &#8220;scoping&#8221; the solution space.</p><p>It immediately became clear solution definition skillsets had weakened greatly. The initial scope for many of the proposed requirements for solutions to even the simplest pain points contained weeks or months of development effort that required extensive analysis, discovery, and feedback. The Product Manager were putting the cart before the horse - they had been trying to define massive solutions to complex problems before they had even learned how to define and solve the smallest of problems.</p><p>I told the team to think about not just solving the problem in full, but to constrain their answers to different time-boxes.</p><ul><li><p>The 1 hour solution</p></li><li><p>The 1 day solution</p></li><li><p>The 1 week solution</p></li><li><p>The 1 month solution</p></li><li><p>The 1 quarter solution</p></li></ul><p>These were solutions that could be implemented if they had a time limit to implement that solution.</p><p>I prohibited them from pursuing the 1 week solution unless they had first delivered to production the 1-hour solution. </p><p>This constraint was hard for them to think about first. They just couldn&#8217;t visualize how to solve a problem partially. I had to guide them to think about low-hanging things, and to think about solutions in stages of progressing difficulty and investment and comprehensiveness in solving the problem:</p><ul><li><p><strong>Informing the user or making it clearer</strong></p><ul><li><p>eg. adding instructional text, clarifying terminology, writing an out-of-product FAQ</p></li></ul></li><li><p><strong>Doing it manually internally</strong></p><ul><li><p>eg. taking on a request via email and having an employee do it ad-hoc, creating a meeting to do it once a week for all requestors, etc.</p></li></ul></li><li><p><strong>Providing a way for the user to do it manually</strong></p><ul><li><p>eg. adding a basic form to collect information, or giving them an action or button</p></li></ul></li><li><p><strong>Doing it automatically</strong></p><ul><li><p>eg. doing something in bulk, on schedule, or removing all the steps</p></li></ul></li><li><p><strong>Removing the need for it completely</strong></p><ul><li><p>eg. removing the business process from having to exist</p></li></ul></li></ul><p>Sure, the best solution might be to remove the need for a user to do something completely, but sometimes just telling the user how to do it correctly solves 80% of the problem. </p><h2><strong>Did we solve the pain?</strong></h2><p>The important part about all these changes was that without having a tight feedback loop with our users, we would never be able to tell what effect we were having. It would backfire if we did a bunch of stuff that did not do anything for our users or the company.</p><p>We still needed <em>feedback</em> on the decisions we were making and the actions we were taking. We just wanted to not be beholden to it for every step we took.</p><p>To do that, I worked to operationalize feedback - to bake in leveraging quantitative and qualitative insights as part of the entire organization&#8217;s work. </p><p>I worked with the Product Management group to set up:</p><ul><li><p><strong>Insights groups -</strong> groups of users we could talk to every week to get feedback, ask questions, and learn about their days</p></li><li><p><strong>Raised awareness for feedback</strong> - I had in-product feedback sent directly to a Slack channel, allowing us to discuss in real-time as comments came in and also personally amplified feedback we received by sharing it broadly with others and following up on it</p></li><li><p><strong>Mandatory relationships</strong> - I instructed all the Product Managers to directly email specific users and build feedback relationships with them</p></li><li><p><strong>User interviews</strong> - I placed more emphasis on talking to the users, incuding interviewing them, and sharing notes and learnings in a regular, organized manner</p></li><li><p><strong>Feedback intent</strong> - I created cycles of intentional times where we discussed feedback from users specifically as part of our day-to-day</p></li><li><p><strong>Instrumentation</strong> - I emphasized having product analytics and instrumentation implemented, and knowing what questions we wanted to be able to answer</p></li><li><p><strong>Relationships with support</strong> - I emphasized the need to work closely with support and meet with them regularly, monitor tickets they received, and leverage their knowledge as their front-line experience with our users was valuable</p></li></ul><p>With these, we created firehoses of feedback into the Product organization, and set the expectation that we acted on it in a timely manner. </p><p>I especially emphasized qualitative and in some cases anecdotal feedback to ensure we moved past the paralysis caused by concerns of having the maximum quantitative impact.</p><h2><strong>The changes have massive effects</strong></h2><p>It was a tremendous 180-degree turnaround. </p><p>The Product Management team had gone from taking months and quarters to do a 1-day project because they were so busy thinking about value, to being able to respond to user feedback and deliver something <strong>within that same day.</strong> We solved dozens of identified user pain points in a short time, some of which led to deeper learnings about their causes and unlocked new valuable areas to explore.</p><p>The speed of decisions, the scoping of solutions, the responsiveness to user feedback, and the intentionality of instrumentation and monitoring all worked together to give us more opportunities &#8220;at bat&#8221; - more chances to get it wrong so we can get feedback and act to get it right. </p><p>The Product Managers had successfully done the reps to build up their delivery muscle, and it was showing at the rate we were delivering working, quality solutions to our users. </p><p>We had gone from delivering nothing to becoming a fairly efficient feature factory that delivered many things, some of which had value, but with the ability to course-correct based on feedback.</p><p><strong>The effect was that we delivered more in a single month than we had in two quarters the prior year.</strong> Some of the delivered items were massive wins that saw immediate adoption and usage. Others flopped and saw no usage, but had no negative effects. All led to learnings and better understanding of the mental models and user journeys our product fit into. All were cheap bets that cost little investment, and were delivered incrementally and iteratively. </p><p>We would not have delivered on even half the wins had we been operating under the prior rules.</p><h2><strong>Knowing when to break the rules</strong></h2><p>Although unintuitive, ignoring value didn&#8217;t harm us given our context. Instead, it was the key to establishing a virtuous cycle and getting out of our death spiral. It broke through the fear of failure and opened up the possibility of learning from mistakes.</p><p>Focusing on rapid delivery meant we got better at getting real feedback and insights earlier. Rapid follow-through meant we incorporated that better into our future decisions. An operations process that tightly monitored for and fed new information into decision-making processes made it a virtuous cycle to make mistakes, get things in front of users, and learn from them. These built up capabilities and competencies we were lacking in the organization.</p><p>It resulted in faster validation of risks, and richer information than we could&#8217;ve gotten from all the interviews and analysis in the world. You can&#8217;t predict with 100% precision how users will interact and behave. Some problems you can&#8217;t analyze your way out of - not all problems are complicated: some exist in complex-adaptive systems where action is required.</p><p>The speed meant having more opportunities to have an effect. This ended up meaning we experienced more wins than if we had tried to avoid the failures. </p><p>If we made 25 attempts and failed 20 of those times, we would still be better off than if we had tried only 3 times and had all 3 win. More &#8220;at bats&#8221; meant more chances to win and learn and adjust course.</p><p>It also meant we got better at defining and shepherding solutions and delivering. There&#8217;s a study floating around about how making a thousand pots as fast as you can without regard to quality leads to you getting better at making pots than if you had focused on making high quality pots. The exact thing happened here - doing the reps let the Product Managers get better at the work.</p><p><strong>That didn&#8217;t mean we ignored outcomes completely.</strong> We still built a culture of instrumentation and measuring and making sure we could observe the effects. We still built a culture of listening to users, building relationships and feedback loops, and sharing knowledge. We still built a culture of defining and validating risks. </p><p>We just decided that value was not to be a driving factor in our decisions for a certain time frame. <em>It worked.</em></p><h2><strong>Re-orienting towards value</strong></h2><p>Ignoring value wasn&#8217;t where we wanted to be in an ideal world, but it was great progress relative to doing nothing. We don&#8217;t need a team of 50 to do nothing. </p><p>Now that we had the means to actually act on and learn from our actions, we could then shift the organization towards increasing diligence around value without losing our delivery effectiveness.</p><p>It was time to take the journey towards Value once again - this time without the baggage of analysis paralysis. </p><p>As I let go of the steering wheel, I started orienting Product Managers to think more deeply and strategically, giving back some of the autonomy I had taken away.</p><p><strong>How I did that, however, is a War Story for another time.</strong></p>]]></content:encoded></item><item><title><![CDATA[War Stories - Defusing an executive kerfuffle]]></title><description><![CDATA[Some situations you encounter as a leader are no-win scenarios. The best thing to do for your organization sometimes is to take the "L" personally.]]></description><link>https://blog.jgefroh.com/p/war-stories-defusing-an-executive</link><guid isPermaLink="false">https://blog.jgefroh.com/p/war-stories-defusing-an-executive</guid><dc:creator><![CDATA[Joseph Gefroh]]></dc:creator><pubDate>Sun, 11 Feb 2024 01:36:30 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iy-Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F883b1bc9-8702-4850-9885-78c69ee79699_1024x1024.webp" 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_!iy-Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F883b1bc9-8702-4850-9885-78c69ee79699_1024x1024.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iy-Y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F883b1bc9-8702-4850-9885-78c69ee79699_1024x1024.webp 424w, https://substackcdn.com/image/fetch/$s_!iy-Y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F883b1bc9-8702-4850-9885-78c69ee79699_1024x1024.webp 848w, https://substackcdn.com/image/fetch/$s_!iy-Y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F883b1bc9-8702-4850-9885-78c69ee79699_1024x1024.webp 1272w, https://substackcdn.com/image/fetch/$s_!iy-Y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F883b1bc9-8702-4850-9885-78c69ee79699_1024x1024.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iy-Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F883b1bc9-8702-4850-9885-78c69ee79699_1024x1024.webp" width="1024" height="1024" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/883b1bc9-8702-4850-9885-78c69ee79699_1024x1024.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:258888,&quot;alt&quot;:null,&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="" srcset="https://substackcdn.com/image/fetch/$s_!iy-Y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F883b1bc9-8702-4850-9885-78c69ee79699_1024x1024.webp 424w, https://substackcdn.com/image/fetch/$s_!iy-Y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F883b1bc9-8702-4850-9885-78c69ee79699_1024x1024.webp 848w, https://substackcdn.com/image/fetch/$s_!iy-Y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F883b1bc9-8702-4850-9885-78c69ee79699_1024x1024.webp 1272w, https://substackcdn.com/image/fetch/$s_!iy-Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F883b1bc9-8702-4850-9885-78c69ee79699_1024x1024.webp 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><strong>A sudden flurry of Slack notifications appear on the top right of my screen: three new, separate DMs, surprisingly from the President, CEO, CTO, and CMO. I knew something blew up.</strong></p><p>Given the absence of other blaring alarms, I knew the system wasn&#8217;t down.</p><p>What was?</p><h3>An unexpected crisis</h3><p>All four messages were about the exact same thing.</p><p>One of my reports, a newly minted engineering manager, had posted a message on his team channel that had suddenly ruffled a lot of executive feathers.</p><div class="paywall-jump" data-component-name="PaywallToDOM"></div><p>The message itself was simple: <em>&#8220;We have unexpectedly received new goals from leadership and will need to reprioritize.&#8221;</em></p><p>It was viewed as extremely passive aggressive given the context of the company.&nbsp;</p><p><strong>What was the context?</strong></p><p>My report had previously communicated feedback up of the difficulty caused by frequently changing goals.&nbsp;</p><p>The leadership team had listened, and had been working feverishly on implementing a new, fair, and more consistent goaling system. It would take time because such a change is always fraught with everything from board dynamics to HR considerations to projection challenges and everything in-between. It was a heavy topic with many vigorous debates behind the scenes, but it was something actively being worked on.</p><p>The problem was that my report had also communicated feedback down, around, and across&#8202;&#8212;&#8202;pretty much to anyone an everyone who would listen. He wore his heart on his sleeve, and he oozed frustration in every conversation. With coaching it had decreased some, but old habits die hard.</p><p><strong>The demands</strong></p><p>Aligned by this particular problem, the entire C-Suite had the same demand: that I immediately correct the engineering manager for this passive aggressive message.</p><p>I had one problem: I can&#8217;t just tell my report he&#8217;s the new target of the C-Suite. It would change how he viewed his relationships with others and key partners, and make him afraid of posting and communicating. It would&#8217;ve made him less likely to trust others, when it&#8217;s such a large component of his effectiveness in the role. It would also make him less likely to give feedback upwards from a team that I needed to hear it from.&nbsp;</p><p>In short&#8202;&#8212;&#8202;it would have created a cycle of destructive fear.</p><p><strong>What did I do?</strong></p><p>I took the blame.</p><p><strong>I told the C-Suite: </strong>hey, I&#8217;m working with the report on communication techniques. It&#8217;s an area that we expect to improve over time and I&#8217;ve seen good progress&#8202;&#8212;&#8202;we&#8217;ll need to expect unintended mistakes happen as we refine and hone this skill and I take responsibility for the miscommunication here.</p><p><strong>To my report&#8202;&#8212;&#8202;I coached him.</strong> as if I came up with the message and that it was me who had issue with it. I essentially gave that C-suite feedback as if it was my own.</p><p>I had a quick chat with the report:</p><p>&#8220;I read that message and I can see it being interpreted by others in a way that you may not intended. I recommend adjusting it to be more neutral or matter-of-fact that the goals changed&#8202;&#8212;&#8202;ie. without any particular charge, to avoid alienating any stakeholders. We want to cultivate a culture where change is welcome, and embraced as an opportunity to improve.&#8221;</p><p><em>I didn&#8217;t even mention the C-Suite.</em></p><p>My report took the feedback immediately as he typically did&#8202;&#8212;&#8202;&#8220;we will be reprioritizing our efforts to align with our new goals.&#8221; The C-Suite was satisfied&#8202;&#8212;&#8202;the newer message was perceived as less passive aggressive.</p><p>The crisis subsided. The C-Suite moved on to other issues and I was able to give my report some useful advice that he implemented moving forward.</p><h3>3 months&nbsp;later</h3><p>My report gave me a negative mark on the upward performance review, citing that I had &#8220;inappropriately micromanaged communication&#8221;.</p><p>My boss gave me negative remark on my own performance review, citing that I &#8220;needed to work more closely with reports on effective messaging.&#8221;</p><p>Sometimes you just have to take the &#8220;L&#8221; to do what&#8217;s best for the company.&nbsp;</p><p>I thanked them for the feedback and carried on.</p>]]></content:encoded></item><item><title><![CDATA[War Stories - How I saved a company taken hostage by a contractor]]></title><description><![CDATA[You don&#8217;t always know what you&#8217;re getting yourself into when you accept a job.]]></description><link>https://blog.jgefroh.com/p/war-stories-how-i-saved-a-company</link><guid isPermaLink="false">https://blog.jgefroh.com/p/war-stories-how-i-saved-a-company</guid><dc:creator><![CDATA[Joseph Gefroh]]></dc:creator><pubDate>Sat, 10 Feb 2024 20:52:49 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!GKwR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F668c53b2-1132-4c7e-b1b7-504274c341d5_1400x788.webp" 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_!GKwR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F668c53b2-1132-4c7e-b1b7-504274c341d5_1400x788.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GKwR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F668c53b2-1132-4c7e-b1b7-504274c341d5_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!GKwR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F668c53b2-1132-4c7e-b1b7-504274c341d5_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!GKwR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F668c53b2-1132-4c7e-b1b7-504274c341d5_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!GKwR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F668c53b2-1132-4c7e-b1b7-504274c341d5_1400x788.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GKwR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F668c53b2-1132-4c7e-b1b7-504274c341d5_1400x788.webp" width="1400" height="788" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/668c53b2-1132-4c7e-b1b7-504274c341d5_1400x788.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:788,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:101072,&quot;alt&quot;:null,&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="" srcset="https://substackcdn.com/image/fetch/$s_!GKwR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F668c53b2-1132-4c7e-b1b7-504274c341d5_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!GKwR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F668c53b2-1132-4c7e-b1b7-504274c341d5_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!GKwR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F668c53b2-1132-4c7e-b1b7-504274c341d5_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!GKwR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F668c53b2-1132-4c7e-b1b7-504274c341d5_1400x788.webp 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>You don&#8217;t always know what you&#8217;re getting yourself into when you accept a job.</p><p>This is the story of my first two months at a startup I worked with &#8212; let&#8217;s call it Transaction Software, Inc. In short, it was a brutal mess.</p><p>I&#8217;ve written my recollections here. While it&#8217;s now been some time since the events occurred, much of the story here is based on notes and logs I had kept as the situation was unfolding.</p><p>I&#8217;ve changed the names to protect everyone involved. As a disclaimer, everything I write here is from my perspective, my understanding, and entirely my opinion only. To be completely fair, I may be missing pieces of the puzzle that could change my perspective.</p><p>Ready for my nightmare? Let&#8217;s begin&#8230;</p><h1><strong>The beginning of the strange journey</strong></h1><p>Elliot, the CEO of Transaction Software, Inc., was looking for a senior front-end developer. He somehow found me on a job board and reached out to me.</p><p>During my interview with the CTO, Bob. I dug into the company and its history. I found out about the team , the technology, the problem space, etc.</p><p>The engineering team consisted of 2 junior front-end developers and Bob. There were multiple projects in the works, but Bob and the engineering team were currently focused on an effort to upgrade an existing transaction platform written in Ruby on Rails by a previous team and give it a facelift. The projects were already late and running up against some upcoming final deadlines.</p><p>The new front-end was written in Ionic 2 / Angular 2, and my first task would be to wire it to the Ruby on Rails system, which I was told had fully-functioning JSON APIs. I would be leading the front-end development efforts as a senior front-end / full-stack developer, guiding the junior developers.</p><p>I believed that I had found a good place to work: the technologies were recent, the domain was interesting, and I believed Bob would be someone who could mentor me.</p><p><em><strong>I was wrong.</strong></em></p><h1><strong>The truth hits like a freight train</strong></h1><p>From the very first day it was clear that the amount of progress had been&#8230;misrepresented. There was still quite a long ways to go. The Ionic 2 / Angular 2 application I was hired to wire up to the backend turned out to be almost entirely a mock. Much of the data was entirely hard-coded and flows through the pages scripted in a smoke-and-mirrors way. I wasn&#8217;t just going to be wiring up the apps, I was essentially going to have to redesign and develop most of the pages and flow from the ground up.</p><p>The code quality of the front-ends themselves was very poor. There were 3000 line SCSS files copy-pasted throughout the app. There were repeated functions everywhere. The naming was inconsistent. There were no patterns or libraries. It was messy and unclear.</p><h1><strong>Questioning authority</strong></h1><p>The products we were building were intended to be used almost exclusively on the desktop, but for some reason we were building them using mobile technologies. I&#8217;m not one to pass up an opportunity to learn and get a &#8220;wide lens&#8221; of a project, so I asked Bob what the business reasoning behind using Ionic 2 was. Bob replied that he was running an &#8220;Ionic 2 / Angular 2 shop&#8221;, and that he didn&#8217;t want the other engineers confused when they also had to learn how to use Angular 2.</p><p>I pressed further &#8212;Bob&#8217;s reason didn&#8217;t make sense to me. Having to learn an entirely new mobile framework on top of an entirely new JS framework is a lot harder than having to just learn just Angular 2. Even the junior developers agreed &#8212; they had been struggling with Ionic 2 for quite some time and often spent significant amounts of time trying to do basic things with the framework.</p><p>Bob stated that we were using Angular 2 / Ionic 2 was there because the users would be using it on their phones. By creating an app we could provide offline queuing capabilities for the system in case connectivity was lost and that as a hybrid app it would prevent us from having to create both an iOS and an Android version.</p><p>Aha! A legitimate business reason&#8230;or so it seemed. I thought about the audience and the kind of system we were building &#8212; the business case of making it mobile just didn&#8217;t add up.</p><p>Our system needed always-on online connectivity to verify the validity of transactions and to provide immediate feedback on the result. Ours was not the kind of transaction we could queue and wait several hours to complete. The user had to know at the time of the transaction what the result was. There was no valid business case I could think of for offline queuing capabilities.</p><p>Our audience was also not primarily mobile app users. They were users at their desks on large-screen always-online computers, infrequent users, or users visiting the site for the first time and never visiting it again after completing their transaction. A vast majority of them would not be taking the time to download a mobile app to use our system.</p><p>So why were we making a mobile app?</p><h1><strong>The mobile focus leads to technical issues</strong></h1><p>Bob&#8217;s focus on creating a mobile app also influenced the architecture. The app was designed with the intention to load every transaction record on sign-in and store it in memory for offline support &#8212; searching, querying, reporting, calculations, etc. This data, along with all the other data in the app, was stored in a singleton reference that was then scattered throughout the entire codebase.</p><p>The problem &#8212;there&#8216;s several, actually!</p><h2><strong>Problem 1 &#8212;the design was a giant ball of spaghetti</strong></h2><p>The first problem was the whole design was the question: how should we persist the transactions in an offline-queue capable way like Bob wanted? If we did pursue this direction, we would need some sort of mechanism to sync it sensibly &#8212; to keep track of changes, updates, successful and unsuccessful requests, errors, etc. To do so while dealing with a singleton modified and read from in every single file would be a nightmare.</p><div class="paywall-jump" data-component-name="PaywallToDOM"></div><p>I asked Bob what the plan was to sync and persist the data in a sensible way. He responded with the names of technologies like NoSQL and PouchDB in response without explaining anything beyond the name. I was confused &#8212; we were using Ruby on Rails and MySQL and had no intention to move away from a relational database &#8212; how did NoSQL or PouchDB factor into this at all?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Vkzx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81b87030-7fc4-4d91-b939-14360cee213a_972x1288.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Vkzx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81b87030-7fc4-4d91-b939-14360cee213a_972x1288.png 424w, https://substackcdn.com/image/fetch/$s_!Vkzx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81b87030-7fc4-4d91-b939-14360cee213a_972x1288.png 848w, https://substackcdn.com/image/fetch/$s_!Vkzx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81b87030-7fc4-4d91-b939-14360cee213a_972x1288.png 1272w, https://substackcdn.com/image/fetch/$s_!Vkzx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81b87030-7fc4-4d91-b939-14360cee213a_972x1288.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Vkzx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81b87030-7fc4-4d91-b939-14360cee213a_972x1288.png" width="972" height="1288" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/81b87030-7fc4-4d91-b939-14360cee213a_972x1288.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1288,&quot;width&quot;:972,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Vkzx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81b87030-7fc4-4d91-b939-14360cee213a_972x1288.png 424w, https://substackcdn.com/image/fetch/$s_!Vkzx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81b87030-7fc4-4d91-b939-14360cee213a_972x1288.png 848w, https://substackcdn.com/image/fetch/$s_!Vkzx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81b87030-7fc4-4d91-b939-14360cee213a_972x1288.png 1272w, https://substackcdn.com/image/fetch/$s_!Vkzx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81b87030-7fc4-4d91-b939-14360cee213a_972x1288.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">What do NoSQL and PouchDB have to do with anything?</figcaption></figure></div><h2><strong>Problem 2 &#8212; incredibly slow performance built into the design</strong></h2><p>The second problem was one of performance. Many users would easily generate over 70 megabytes of data a day! It was far too much to load even a week&#8217;s worth! Even with only a single day&#8217;s worth of test data, it took a good 10 seconds to sign-in! No sane user would wait that long.</p><p>I asked Bob about the performance issue and he responded that it &#8220;shouldn&#8217;t be a problem&#8221;. A reply like that was shocking &#8212; users nowadays barely wait 2 seconds to use a website, why would they wait 2 minutes? I even presented him with the math and actual numbers involved &#8212; he remained unconvinced. It was only later that he admitted that this was a problem, but he noted that he would solve this using Angular Universal. I couldn&#8217;t see how that was relevant &#8212; the data would still have to reach the client-side somehow.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yapA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff7c38cb-9d18-423a-b6d7-1ab5ff0ecf54_1400x103.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yapA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff7c38cb-9d18-423a-b6d7-1ab5ff0ecf54_1400x103.png 424w, https://substackcdn.com/image/fetch/$s_!yapA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff7c38cb-9d18-423a-b6d7-1ab5ff0ecf54_1400x103.png 848w, https://substackcdn.com/image/fetch/$s_!yapA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff7c38cb-9d18-423a-b6d7-1ab5ff0ecf54_1400x103.png 1272w, https://substackcdn.com/image/fetch/$s_!yapA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff7c38cb-9d18-423a-b6d7-1ab5ff0ecf54_1400x103.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yapA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff7c38cb-9d18-423a-b6d7-1ab5ff0ecf54_1400x103.png" width="1400" height="103" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ff7c38cb-9d18-423a-b6d7-1ab5ff0ecf54_1400x103.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:103,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!yapA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff7c38cb-9d18-423a-b6d7-1ab5ff0ecf54_1400x103.png 424w, https://substackcdn.com/image/fetch/$s_!yapA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff7c38cb-9d18-423a-b6d7-1ab5ff0ecf54_1400x103.png 848w, https://substackcdn.com/image/fetch/$s_!yapA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff7c38cb-9d18-423a-b6d7-1ab5ff0ecf54_1400x103.png 1272w, https://substackcdn.com/image/fetch/$s_!yapA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff7c38cb-9d18-423a-b6d7-1ab5ff0ecf54_1400x103.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">The data still has to get to the client-side somehow even with this solution.</figcaption></figure></div><h2><strong>The realization</strong></h2><p>It dawned on me that there was no business reason for using the technologies Bob chose. Even worse, our technology choice was actually going to become an issue down the line in accomplishing our business objectives &#8212; users simply wouldn&#8217;t use our system in the manner we were building it. We were designing and building a mobile app for something that was rarely, if ever, going to be used as a mobile app.</p><h1><strong>If the mobile side doesn&#8217;t work, at least the web side should, right? Wrong.</strong></h1><p>As the web side of the hybrid application, the picture was even worse. Ironically, for a project that took &#8220;mobile-first&#8221; quite literally, the web side was not responsive.</p><p>That wasn&#8217;t even the worst offender. One of our core functionality requirements was the ability for users to share their various pages across social media. However, in the SPAs this just wasn&#8217;t possible &#8212; any URL change would lead to a completely blank slate and the front-end would lose all state.</p><p>At the time, Ionic 2 didn&#8217;t support URL routing, and the Angular 2 router was undergoing frequent core changes. As a result, URL navigation didn&#8217;t route correctly. The browser navigation buttons (Back, Forward, etc.) weren&#8217;t supported &#8212; they would reload the application, as would any URL change.</p><p>Looking deeper into the codebase, I learned that all navigation was being done by programmatically and without history support. A link click would trigger a function that would crawl the DOM and look for a reference to a master Tabs element. Once found, the it would look up the current page&#8217;s tab index and add or subtract the number of tabs to move from the current tab depending on what page the link was supposed to navigate to.</p><p>In short, it was brittle, highly unclear, and not a good solution by any means.</p><h2><strong>No solutions &#8212; again</strong></h2><p>I asked Bob about a potential solution or design direction for this issue. Once again, he threw out the name of a technology without going into detail, claiming that he would use NGINX to solve it.</p><p>I didn&#8217;t understand how that would solve the client-side routing problem &#8212; having a manifest of the possible pages in NGINX was not a viable solution, and even if you made NGINX interpret the URL appropriately, the SPA would still needed to interpret the URL on the client-side and statefully keep track of it.</p><p>I asked for clarification, but Bob didn&#8217;t articulate his design approach.</p><p>He later produced a &#8220;prototype&#8221;, stating it had taken him a mere 15 minutes of development work to figure out:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1N9C!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaba2705-1b3e-4501-a2e1-708b687e2865_1400x179.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1N9C!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaba2705-1b3e-4501-a2e1-708b687e2865_1400x179.png 424w, https://substackcdn.com/image/fetch/$s_!1N9C!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaba2705-1b3e-4501-a2e1-708b687e2865_1400x179.png 848w, https://substackcdn.com/image/fetch/$s_!1N9C!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaba2705-1b3e-4501-a2e1-708b687e2865_1400x179.png 1272w, https://substackcdn.com/image/fetch/$s_!1N9C!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaba2705-1b3e-4501-a2e1-708b687e2865_1400x179.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1N9C!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaba2705-1b3e-4501-a2e1-708b687e2865_1400x179.png" width="1400" height="179" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/baba2705-1b3e-4501-a2e1-708b687e2865_1400x179.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:179,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!1N9C!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaba2705-1b3e-4501-a2e1-708b687e2865_1400x179.png 424w, https://substackcdn.com/image/fetch/$s_!1N9C!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaba2705-1b3e-4501-a2e1-708b687e2865_1400x179.png 848w, https://substackcdn.com/image/fetch/$s_!1N9C!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaba2705-1b3e-4501-a2e1-708b687e2865_1400x179.png 1272w, https://substackcdn.com/image/fetch/$s_!1N9C!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbaba2705-1b3e-4501-a2e1-708b687e2865_1400x179.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>It solved the issue of being unable to load a specific page on first load, but the client-side routing and history support remained unaddressed. To use Bob&#8217;s approach would have required us to write a custom client-side routing solution from the ground up. The resulting system would have been brittle, fragile, and highly unmaintainable &#8212; it would be re-inventing the wheel in the worst way possible. Since we were already months behind schedule, I believed it would&#8217;ve been a waste of the company&#8217;s time to do so, and certainly not a viable solution for any long-term use.</p><p>Those were just some of the technical issues that were plaguing the company. I wish I could say that the problems the company faced were purely technical, but I&#8217;d be lying if I did.</p><h1><strong>Toxicity</strong></h1><p>Bob had a way of managing and communicating that I would describe as passive-aggressive and controlling at its best. His management style didn&#8217;t go unnoticed &#8212; when he walked into the office (a less than 200 square foot closet), I noticed the junior developers would clam up and go quiet.</p><p>I spoke to both of the junior developers in private (they were very friendly and personable) and learned their true feelings towards the situation. Needless to say, it had to change quickly &#8212; everyone seemed to walk on eggshells whenever Bob was around.</p><p>I&#8217;m a stickler for effective team communication, so I set up Slack as a tool to give the team a communication outlet. This way, communication was still encouraged even if the atmosphere in the room itself proved too tense for the junior engineers to speak their minds.</p><h1><strong>Power games</strong></h1><p>Elliot gave me access to the Github repository for the backend to better acquaint myself with the product. Bob, who was in the office at the time, immediately demanded I be removed. When Elliot asked why, Bob stated that I hadn&#8217;t proven my velocity on the front-end code to be given access to the back-end code. Elliot reluctantly removed me, later asking if that reaction from Bob was a &#8220;power thing&#8221;.</p><p>No other engineer had access to any of the back-end code. All work was done by pointing our local front-ends to the URL of a shared staging environment. Bob&#8217;s reasoning was that he didn&#8217;t want &#8220;people&#8217;s PCs cluttered and confused with all the brittle legacy Rails back-end stuff&#8221;. He told me to base my attempts to communicate with the back-end on the front-end schema of the singleton object he had created (which, as I wrote previously, turned out to be wildly inaccurate on multiple levels).</p><p>This was a very strange, ineffective setup &#8212; even Elliot realized this, and he&#8217;s not even a technical person! Not having any documentation or visibility on how the APIs worked would make my job of actually integrating the front-ends and the back-end very difficult.</p><h2><strong>Making progress any way I can</strong></h2><p>Since I didn&#8217;t have much to work with, I decided working with the junior engineers would be mutually beneficial. I&#8217;d be able to help them understand better practices and the technology when I could, and they would be able to help me understand the various quirks and the general problem domain.</p><p>I was new to Angular 2, but the weekend I spent ramping up was more than enough to start contributing. Pairing helped us both, and we were even able to get past some issues they were stuck on.</p><p>During the time I was mentoring the juniors, I implemented a code review process through pull requests as a way to share knowledge and improve quality. One of my tenets of code reviews is to help guide people and teach them to arrive at the solution instead of giving the solution outright &#8212; it helps them grow as developers and ultimately leads to better decision making and improved code quality.</p><p>Bob didn&#8217;t seem to share my sentiments.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sPEW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7afec411-56f6-41ff-8ef5-cf6a151d2e62_1400x1745.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sPEW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7afec411-56f6-41ff-8ef5-cf6a151d2e62_1400x1745.png 424w, https://substackcdn.com/image/fetch/$s_!sPEW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7afec411-56f6-41ff-8ef5-cf6a151d2e62_1400x1745.png 848w, https://substackcdn.com/image/fetch/$s_!sPEW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7afec411-56f6-41ff-8ef5-cf6a151d2e62_1400x1745.png 1272w, https://substackcdn.com/image/fetch/$s_!sPEW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7afec411-56f6-41ff-8ef5-cf6a151d2e62_1400x1745.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sPEW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7afec411-56f6-41ff-8ef5-cf6a151d2e62_1400x1745.png" width="1400" height="1745" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7afec411-56f6-41ff-8ef5-cf6a151d2e62_1400x1745.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1745,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!sPEW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7afec411-56f6-41ff-8ef5-cf6a151d2e62_1400x1745.png 424w, https://substackcdn.com/image/fetch/$s_!sPEW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7afec411-56f6-41ff-8ef5-cf6a151d2e62_1400x1745.png 848w, https://substackcdn.com/image/fetch/$s_!sPEW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7afec411-56f6-41ff-8ef5-cf6a151d2e62_1400x1745.png 1272w, https://substackcdn.com/image/fetch/$s_!sPEW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7afec411-56f6-41ff-8ef5-cf6a151d2e62_1400x1745.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 discussion we had following this felt like a scolding.</figcaption></figure></div><h1><strong>Threatened</strong></h1><p>Later that day I received an email from Bob stating that while my mentorship was valuable, I was hired to code and that my continuing employment would be based on output from my desk. Bob stated that Transaction Software, Inc. was &#8220;still in the process of evaluating [my] performance as a senior-level software developer&#8221;. Read in his voice, I found it vaguely threatening.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VVxu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4057296d-d78c-4f42-9dbd-c00bf1d3b705_1400x377.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VVxu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4057296d-d78c-4f42-9dbd-c00bf1d3b705_1400x377.png 424w, https://substackcdn.com/image/fetch/$s_!VVxu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4057296d-d78c-4f42-9dbd-c00bf1d3b705_1400x377.png 848w, https://substackcdn.com/image/fetch/$s_!VVxu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4057296d-d78c-4f42-9dbd-c00bf1d3b705_1400x377.png 1272w, https://substackcdn.com/image/fetch/$s_!VVxu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4057296d-d78c-4f42-9dbd-c00bf1d3b705_1400x377.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VVxu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4057296d-d78c-4f42-9dbd-c00bf1d3b705_1400x377.png" width="1400" height="377" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4057296d-d78c-4f42-9dbd-c00bf1d3b705_1400x377.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:377,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!VVxu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4057296d-d78c-4f42-9dbd-c00bf1d3b705_1400x377.png 424w, https://substackcdn.com/image/fetch/$s_!VVxu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4057296d-d78c-4f42-9dbd-c00bf1d3b705_1400x377.png 848w, https://substackcdn.com/image/fetch/$s_!VVxu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4057296d-d78c-4f42-9dbd-c00bf1d3b705_1400x377.png 1272w, https://substackcdn.com/image/fetch/$s_!VVxu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4057296d-d78c-4f42-9dbd-c00bf1d3b705_1400x377.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 email I received from Bob.</figcaption></figure></div><p>I&#8217;ve never been threatened before with losing my job in my first three days of working. Concerned, I asked Elliot the CEO (who was CC&#8217;d on the email) about this, and he assured me my job was safe. I asked how I could possibly stay at a company if the CTO had already determined in the first few days that I&#8217;m not productive enough? Elliot finally gave me the rundown.</p><h1><strong>The org-chart is a mess</strong></h1><p>It turns out Bob was actually a contractor, and not the CTO as he had told me! Even more surprising: Transaction Software, Inc. didn&#8217;t actually have an engineering team at all! Elliot had selected the junior developers to hire, but Bob had convinced Elliot to hire them under Bob&#8217;s own consulting company, for &#8220;insurance purposes&#8221;.</p><p>Elliot paid Bob&#8217;s consulting firm extra to pay for the junior developers. In effect, Bob and the junior engineers were a consulting company working for Transaction Software. It was confusing &#8212; I was technically Transaction Software, Inc.&#8217;s first engineering hire.</p><p>Bob was previously attempting to negotiate a CTO position or an acquisition of his consulting firm by Transaction Software, Inc. I assume keeping everything in-house and under one&#8217;s control puts one in a better negotiating position for a buyout or acquisition, especially if a company relies on your firm exclusively for their technology needs.</p><p>Additional meetings with Elliot gave me a clearer understanding of what was going on. Elliot had started wondering why the projects were being delayed repeatedly. One key project in particular was already months in the making, and Bob had told Elliot time and time again that production delivery was &#8220;only two weeks away&#8221;. The front-ends had been delayed time and time again, and the clients for that project were already highly agitated and losing faith.</p><p>Elliot was paying Bob tremendous amounts of money and felt he was getting very little in return. I was hired, in part, to shine a light on what was going on &#8212; were all these problems a normal part of software development?</p><p>At the time I still felt the best course of action was to work things out with Bob to make positive changes gradually. Bob hadn&#8217;t demonstrated to me that he was experienced at leading or working with teams. He hadn&#8217;t yet shown me that he was particularly knowledgable about the principles of developing large web applications.</p><p>As time went on I continued what I was doing, replying politely and professionally to Bob&#8217;s various remarks and tried to set a good example for the team. However, I believed blindly following Bob would lead to the failure of the projects and the organization in a very short amount of time. I couldn&#8217;t do that &#8212; I had a responsibility to the company.</p><h1><strong>Turning the ship around</strong></h1><p>I spoke a lot with Elliot, explaining from my perspective the various technical, team, and cultural issues I was discovering. I proposed a new approach that would get the product up and running on a much faster and more aggressive timeline, in the hopes of meeting the deadline for a critical stakeholder demo.</p><p>I designed and diagrammed a workable architecture for the various front-ends. Instead of the giant singleton ball of spaghetti, I created a linear hierarchy of pages and components. I created a schedule that we could realistically achieve.</p><p>Elliot and I agreed to deal with Bob with &#8220;kid gloves&#8221;, tolerating any outbursts and passive-aggressive behavior until we were in a better position to make a decision regarding him.</p><h1><strong>A New Hope</strong></h1><p>I presented my plans to Bob and Elliot on Monday, explaining that with some focused engineering effort, the system could be done in less than two weeks of development effort in Angular 1 if the endpoints were in the state Bob said they were in. I also presented alternative approaches incorporating Angular 2 if needed, although I clarified that this would greatly extend the actual timeline.</p><p>Bob was visibly upset. We had a very long debate, with him making points that writing the code in Angular 1 would be generating untold amounts of technical debt because it was a deprecated technology. I agreed that Angular 1 was on its way out, but the Angular 2 / Ionic 2 combo he had built the product with just wasn&#8217;t ready for our use.</p><p>I argued that Angular 1 was stable, the problems were well-known and the solutions readily available. I greatly preferred the &#8220;devil you know&#8221; approach to risk management. I reasoned that with months of development time already wasted on the Angular 2 / Ionic 2 solution with no real progress, with more problems arising every day, and with deadlines far missed, it just made more sense to start from scratch and build it in Angular 1 in 2 weeks.</p><p>Bob argued that he had the solutions to the problems we were encountering. I begged him to tell me what the solutions were, or at the very least to point me in the right direction so that I at least knew he had a viable way across the river, metaphorically speaking. If there was a way forward, I would pursue it to the end. He didn&#8217;t articulate his direction and vision, only mentioning the names of various technologies.</p><p>Elliot stepped up and made an executive decision to go with my 2-week plan of writing the front-end in Angular 1. If we didn&#8217;t succeed, at worst we would waste 2 weeks, and what&#8217;s 2 weeks wasted when we were already months behind?</p><p>At this point Bob&#8217;s gloves were off &#8212; he was adamant I wouldn&#8217;t be able to do it and said I was living in the &#8220;land of rainbows and unicorns and fairies&#8221; and not the real world, where people had to deal with legacy code. I told him that I had dealt with monstrous legacy systems before, and that I understood the challenges and risks associated with them.</p><p>Bob said that he &#8220;washed his hands&#8221; of the project, and that it was entirely on me and that he would not be held responsible at all if anything went wrong. It wasn&#8217;t the best team-oriented attitude, but it was enough for the company to start succeeding.</p><p>I laid out the plan in detail &#8212; for the next week, we would follow my Angular 1 plan and wire it up to the endpoints needed for it. I made a list of endpoints I needed from Bob (less than 7), and we set to work.</p><h1><strong>Ace up my sleeve</strong></h1><p>I have to admit, I had a secret weapon coming in to that meeting &#8212; I had already built the entire front-end in Angular 1 over the weekend. It wasn&#8217;t smoke and mirrors, either. It had full data flow to JSON endpoint mocks and full user-interaction. Routing was fully working. The code was architected in a maintainable and extensible way. The styles were just like the design minus a few font-weights and bolds here and there. It was mobile responsive. The deployment and production scripts were built and working. Quality-wise, it was a production-ready front-end. All it needed was the URLs for the endpoints and some minor field changes in case there happened to be field naming changes from the anticipated schema.</p><h1><strong>The light reveals some dust bunnies</strong></h1><p>It turns out endpoints weren&#8217;t in the state we were led to believe. The front-end schema we were given to follow was wildly inaccurate &#8212; different field names, missing fields, different accepted schemas, and even different datatypes. I had to go back and forth many times with Bob to get the endpoints to function properly.</p><p>Some of the issues were normal synchronization issues that are a normal part of integrating with APIs. However, some were indicative of poor testing and quality assurance practices. One issue was opened and closed 5 times as various bugs kept coming up &#8212; it led me to believe that the code changes weren&#8217;t being tested thoroughly before being deployed to staging (where my UI was pointing).</p><p>Despite the difficulties we encountered, the Angular 1 plan actually worked! We managed to meet our deadline (minus some promised features due to missing / non-functional endpoints) and we presented the product to our stakeholders, who were very satisfied with the progress. They had almost written us off by this point, but the new momentum had renewed their faith in us.</p><h1><strong>Fixing the cultural problems</strong></h1><p>The sprint gave me hope that Bob would still be able to be a productive member of the team.</p><p>Although some of his actions and communication during the sprint could be interpreted as passive-aggressive (such as changing the names of our Angular 1 repositories and adding the word &#8220;temporary&#8221;), they weren&#8217;t outright antagonistic and the edge seemed to have dulled somewhat. The office didn&#8217;t feel as tense when we were working on this effort (although there were still moments), and things were actually getting done for the most part. There was actually a nice buzz of activity as we all worked together towards a common goal. It was a glimmer of hope for how the engineering team could be.</p><p>I played with the idea that Bob could be redirected and he could work exclusively on tiger projects or other lone initiatives without negatively impacting the rest of the team.</p><p>Unfortunately, it quickly became evident that this would not work out:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pBMw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39f2aa52-0770-46e0-a6fa-9f2e07e11909_1082x1522.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pBMw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39f2aa52-0770-46e0-a6fa-9f2e07e11909_1082x1522.png 424w, https://substackcdn.com/image/fetch/$s_!pBMw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39f2aa52-0770-46e0-a6fa-9f2e07e11909_1082x1522.png 848w, https://substackcdn.com/image/fetch/$s_!pBMw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39f2aa52-0770-46e0-a6fa-9f2e07e11909_1082x1522.png 1272w, https://substackcdn.com/image/fetch/$s_!pBMw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39f2aa52-0770-46e0-a6fa-9f2e07e11909_1082x1522.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pBMw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39f2aa52-0770-46e0-a6fa-9f2e07e11909_1082x1522.png" width="1082" height="1522" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/39f2aa52-0770-46e0-a6fa-9f2e07e11909_1082x1522.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1522,&quot;width&quot;:1082,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!pBMw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39f2aa52-0770-46e0-a6fa-9f2e07e11909_1082x1522.png 424w, https://substackcdn.com/image/fetch/$s_!pBMw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39f2aa52-0770-46e0-a6fa-9f2e07e11909_1082x1522.png 848w, https://substackcdn.com/image/fetch/$s_!pBMw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39f2aa52-0770-46e0-a6fa-9f2e07e11909_1082x1522.png 1272w, https://substackcdn.com/image/fetch/$s_!pBMw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39f2aa52-0770-46e0-a6fa-9f2e07e11909_1082x1522.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><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NMqY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7b3d2-a5b1-4a0c-aabd-2430fd8ec1e3_1400x1292.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NMqY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7b3d2-a5b1-4a0c-aabd-2430fd8ec1e3_1400x1292.png 424w, https://substackcdn.com/image/fetch/$s_!NMqY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7b3d2-a5b1-4a0c-aabd-2430fd8ec1e3_1400x1292.png 848w, https://substackcdn.com/image/fetch/$s_!NMqY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7b3d2-a5b1-4a0c-aabd-2430fd8ec1e3_1400x1292.png 1272w, https://substackcdn.com/image/fetch/$s_!NMqY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7b3d2-a5b1-4a0c-aabd-2430fd8ec1e3_1400x1292.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NMqY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7b3d2-a5b1-4a0c-aabd-2430fd8ec1e3_1400x1292.png" width="1400" height="1292" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8ec7b3d2-a5b1-4a0c-aabd-2430fd8ec1e3_1400x1292.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1292,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!NMqY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7b3d2-a5b1-4a0c-aabd-2430fd8ec1e3_1400x1292.png 424w, https://substackcdn.com/image/fetch/$s_!NMqY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7b3d2-a5b1-4a0c-aabd-2430fd8ec1e3_1400x1292.png 848w, https://substackcdn.com/image/fetch/$s_!NMqY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7b3d2-a5b1-4a0c-aabd-2430fd8ec1e3_1400x1292.png 1272w, https://substackcdn.com/image/fetch/$s_!NMqY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7b3d2-a5b1-4a0c-aabd-2430fd8ec1e3_1400x1292.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">Error after error, on a single issue, only to finally be told &#8220;Good luck with that.&#8221;</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jQWU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc23fc2b9-2e87-457d-b511-965d6ee7726a_1400x1752.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jQWU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc23fc2b9-2e87-457d-b511-965d6ee7726a_1400x1752.png 424w, https://substackcdn.com/image/fetch/$s_!jQWU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc23fc2b9-2e87-457d-b511-965d6ee7726a_1400x1752.png 848w, https://substackcdn.com/image/fetch/$s_!jQWU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc23fc2b9-2e87-457d-b511-965d6ee7726a_1400x1752.png 1272w, https://substackcdn.com/image/fetch/$s_!jQWU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc23fc2b9-2e87-457d-b511-965d6ee7726a_1400x1752.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jQWU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc23fc2b9-2e87-457d-b511-965d6ee7726a_1400x1752.png" width="1400" height="1752" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c23fc2b9-2e87-457d-b511-965d6ee7726a_1400x1752.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1752,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!jQWU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc23fc2b9-2e87-457d-b511-965d6ee7726a_1400x1752.png 424w, https://substackcdn.com/image/fetch/$s_!jQWU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc23fc2b9-2e87-457d-b511-965d6ee7726a_1400x1752.png 848w, https://substackcdn.com/image/fetch/$s_!jQWU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc23fc2b9-2e87-457d-b511-965d6ee7726a_1400x1752.png 1272w, https://substackcdn.com/image/fetch/$s_!jQWU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc23fc2b9-2e87-457d-b511-965d6ee7726a_1400x1752.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>That was the straw that broke the camel&#8217;s back. Bob&#8217;s apparent lack of care and his refusal to cooperate or play nice with the team led me to recommended to Elliot to end our business relationship with him.</p><h1><strong>The Bus Factor</strong></h1><p>Unfortunately, this relationship was somewhat difficult to end: Bob had the keys to the kingdom. He was the only with any knowledge of the backend or access to the various production servers, the passwords, the critical technical accounts, etc. He had admin access to most of the systems, and in some cases was the only person with admin access.</p><p>During this time, Elliot had requested multiple times for Bob to sit down with me and train/provide deployment instructions, passwords, etc. Every time, Bob refused and responded that anyone who &#8220;knew what they were doing&#8221; would be able to figure it out in a matter of minutes.</p><p>It was likely a jab at how unskilled Bob thought I was. Multiple attempts to get him to sit down with us proved futile &#8212; there was always some reason that prevented the meeting&#8212; time, money, schedule, etc. We weren&#8217;t getting anything.</p><p>Even with the bus factor of one, we decided the best thing to do was to end it.</p><h1><strong>Bob is gone</strong></h1><p>After we ended our business relationship with Bob, we were basically starting from zero. No passwords, no instructions, no diagrams, or deployment instructions. We didn&#8217;t even have the latest deployed backend source code &#8212; the earliest version we had was from a month before I joined the company. We hadn&#8217;t even received any code or deliverables from the critical, constantly delayed project Bob repeatedly said was only &#8220;weeks away&#8221;.</p><p>Luckily, I was friends with the team at a consulting firm that was highly skilled in DevOps and system administration. We set up a meet, I explained the situation, and Elliot decided to contract their services. I worked closely with the consulting firm&#8217;s lead, Charlie, to figure out our server issues and get a handle on where we were as a company.</p><h1><strong>Starting with a crawl</strong></h1><p>Our first move was to retain access to our servers. We decided to start by resetting the staging server&#8217;s root password so we could do some exploration on how everything was set up. It was the least risky course of action in our minds &#8212;we didn&#8217;t want to touch production directly because we didn&#8217;t know if we could bring it up if it when down.</p><p>Good thing we didn&#8217;t touch production! The staging server&#8217;s application and its dependencies didn&#8217;t start up after we brought it back up. We had to dig around for a while in the command history, search through various installed applications, and dig through files until we figured out which commands to run on which files and in what order. We eventually figured out the commands we needed to bring the application back up properly.</p><h1><strong>The fires start up</strong></h1><p>As Charlie and I researched the environments and learned our deployment procedures, we received panicked messages from our biggest client, saying that records were showing up twice in the production environments, messing up key reporting. We traced it back to the staging server&#8217;s job runner.</p><p>Apparently, the staging server&#8217;s job runner was being pointed to the production database, which caused it to create invalid records. We quickly stopped the staging server and simply decided to bring the whole system down, unsure of what other traps were lying in wait.</p><p>Over the next couple of weeks, we utilized Charlie and his team heavily, obtaining control of our servers and figuring out various account and network issues. We set up a secondary deployment procedure because we simply couldn&#8217;t risk changing the initial production server&#8217;s deployment. There was a month of untested code in the latest branch, the dependencies were old and hard to find &#8212; some weren&#8217;t even available online anymore.</p><h1><strong>A terrible discovery</strong></h1><p>At the same time, I was resetting the passwords for the various accounts that were being used by Bob for Transaction Software, Inc. &#8212; email accounts, 3rd-party vendor accounts, etc. We didn&#8217;t have a list of them, but there were easily several dozen.</p><p>During this process we discovered that Bob had actually deleted Transaction Software, Inc.&#8217;s Bitbucket repository! The deployment setup was partially relying on it and the latest version of the code was on it! Worse yet, this had been done this AFTER we had decided to terminate our business relationship with him!</p><p>We lost everything in that Bitbucket repository, including any wiki pages, documentation, past / existing issues, and code versions. No passwords, no recent codebase, no roadmap. The latest version of the code we had available to us on Github was from before I joined the company.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LA1o!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76fabf9-da1f-4e1e-b3e4-ee7db2e88c5c_728x143.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LA1o!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76fabf9-da1f-4e1e-b3e4-ee7db2e88c5c_728x143.png 424w, https://substackcdn.com/image/fetch/$s_!LA1o!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76fabf9-da1f-4e1e-b3e4-ee7db2e88c5c_728x143.png 848w, https://substackcdn.com/image/fetch/$s_!LA1o!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76fabf9-da1f-4e1e-b3e4-ee7db2e88c5c_728x143.png 1272w, https://substackcdn.com/image/fetch/$s_!LA1o!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76fabf9-da1f-4e1e-b3e4-ee7db2e88c5c_728x143.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LA1o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76fabf9-da1f-4e1e-b3e4-ee7db2e88c5c_728x143.png" width="728" height="143" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b76fabf9-da1f-4e1e-b3e4-ee7db2e88c5c_728x143.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:143,&quot;width&quot;:728,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!LA1o!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76fabf9-da1f-4e1e-b3e4-ee7db2e88c5c_728x143.png 424w, https://substackcdn.com/image/fetch/$s_!LA1o!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76fabf9-da1f-4e1e-b3e4-ee7db2e88c5c_728x143.png 848w, https://substackcdn.com/image/fetch/$s_!LA1o!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76fabf9-da1f-4e1e-b3e4-ee7db2e88c5c_728x143.png 1272w, https://substackcdn.com/image/fetch/$s_!LA1o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76fabf9-da1f-4e1e-b3e4-ee7db2e88c5c_728x143.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Bob deleted our repository and had removed Elliot as an administrator.</figcaption></figure></div><p>I had never heard of a contractor destroying the assets of the company he was contracting for. I guess there is a first time for everything.</p><p>In a pure stroke of luck, I had discovered that the staging server had the latest source code on it. I tarballed it, downloaded it, and then pushed it up to a branch on the company&#8217;s Github. The work was saved &#8212; or at least some of it.</p><h1><strong>Like a bad penny</strong></h1><p>I wish we could say that was the last we saw of Bob, but unfortunately it wasn&#8217;t. Bob sprang up again some time later, this time with outlandish IP claims.</p><p>He claimed that all of the code and software he wrote was his intellectual property, despite multiple references in his past invoices that it was work for hire. He demanded payment of his final invoices, despite the fact that some of the projects he was supposed to have been working on were never delivered to us at that time.</p><p>Several back and forth and multiple attempts to resolve the issue without getting lawyers involved proved futile. Both sides eventually got lawyers.</p><p>When we did finally receive the code for the missing projects, it became clear just how much we overpaid. The critical project that was &#8220;2 weeks away&#8221; for months? It consisted entirely of an automatically generated rails scaffold with a few files taken straight from easily discoverable online code samples. None of it was usable for any real world, production use. It would&#8217;ve taken anyone, even someone who didn&#8217;t know how to code, mere minutes to recreate.</p><p>This was too much. Elliot wanted to sue him into the ground, no matter how much it cost. I recommended we move on. We had already incurred significant costs trying to fix Bob&#8217;s mistakes and errors. Wasting more time, energy, and money would only serve as a distraction. It was simply easier to stop wasting time on Bob. We had a company to build, and we wanted to focus on that instead of fighting silly legal battles or dealing with Bob anymore. If Bob used or further laid claim to our IP, we would defend it. Otherwise, we would ignore him. He wasn&#8217;t worth our time or effort.</p><p>We decided to fully pay Bob&#8217;s final invoices and left it at that &#8212; a painful lesson learned.</p><p>This was a story about my first two months at Transaction Software, Inc. It was absolutely brutal, and if I had known what I was getting into I wouldn&#8217;t have shown up to the interview.</p><p>However, this story has a happy ending. Starting that low meant you could only go up from there. After the initial rocky start, we planned and successfully executed a turn-around for the company, working hard and smartly at removing the old baggage and creating a new future. I&#8217;m proud to report that the company culture turned around completely, and it actually became a fun place to work for everyone!</p><p>You don&#8217;t always know what you&#8217;re getting yourself into when you accept a job!</p>]]></content:encoded></item><item><title><![CDATA[War Stories - How I matured a chaotic startup into a professional development team]]></title><description><![CDATA[A story of a dev-ops adoption and an organization&#8217;s transformation from waterfall to agile to lean.]]></description><link>https://blog.jgefroh.com/p/war-stories-from-waterfall-to-lean</link><guid isPermaLink="false">https://blog.jgefroh.com/p/war-stories-from-waterfall-to-lean</guid><dc:creator><![CDATA[Joseph Gefroh]]></dc:creator><pubDate>Sat, 10 Feb 2024 19:56:03 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!VMm7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2008d145-fe5a-4abf-8aec-130351f61214_1400x548.webp" 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_!VMm7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2008d145-fe5a-4abf-8aec-130351f61214_1400x548.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VMm7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2008d145-fe5a-4abf-8aec-130351f61214_1400x548.webp 424w, https://substackcdn.com/image/fetch/$s_!VMm7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2008d145-fe5a-4abf-8aec-130351f61214_1400x548.webp 848w, https://substackcdn.com/image/fetch/$s_!VMm7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2008d145-fe5a-4abf-8aec-130351f61214_1400x548.webp 1272w, https://substackcdn.com/image/fetch/$s_!VMm7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2008d145-fe5a-4abf-8aec-130351f61214_1400x548.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VMm7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2008d145-fe5a-4abf-8aec-130351f61214_1400x548.webp" width="1400" height="548" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2008d145-fe5a-4abf-8aec-130351f61214_1400x548.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:548,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:70704,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&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="" srcset="https://substackcdn.com/image/fetch/$s_!VMm7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2008d145-fe5a-4abf-8aec-130351f61214_1400x548.webp 424w, https://substackcdn.com/image/fetch/$s_!VMm7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2008d145-fe5a-4abf-8aec-130351f61214_1400x548.webp 848w, https://substackcdn.com/image/fetch/$s_!VMm7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2008d145-fe5a-4abf-8aec-130351f61214_1400x548.webp 1272w, https://substackcdn.com/image/fetch/$s_!VMm7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2008d145-fe5a-4abf-8aec-130351f61214_1400x548.webp 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><h1><strong>The Beginning of the End?</strong></h1><p>Engineers were leaving by the droves. We lost seven engineers in months due to a single project. Our turnover had hit a high of a 38%.</p><p><strong>It was the beginning of an exodus </strong>and an organizational collapse was on the horizon.</p><h2><strong>What was going on?</strong></h2><p>We were supposed to be on a solid path. Product ran two-week sprints and performed all of the scrum ceremonies to the T. We had 1:1s with all of the engineers. By any organizational standard, we should have been doing well.</p><p>Our problem was that, while on paper we were agile, in spirit we were far from it. We had highly centralized, top-down command-and-control, driven by product management that told the developers exactly what to do and when to do it.</p><p><strong>Product&#8217;s initiatives weren&#8217;t at all aligned with the business</strong>. The developers ended up creating feature after feature that the business never used or even asked for.</p><p>The project that broke the camel&#8217;s back was a multi-month waterfall technology project that provided zero value, was started with little to no planning, and touched every core part of our software systems and business processes. Despite multiple warnings raised by engineers, they were overruled and the project proceeded.</p><p>It was an intense and focused effort by the organization to get it done, with the promise from Product that it would solve all of the business&#8217; problems by the end. It was an empty promise but we labored on.</p><p>On the one hand, it was great to see that level of organizational alignment. On the other, developers hate death marches. Sure, we ran it in two-week sprints, but a two-week waterfall is still a waterfall. By the end of it, the developers were burnt out.</p><p><strong>Enough was enough. </strong>The rate of departure was unsustainable and not yet over. As an engineering manager close to team, I knew that more than a few developers were actively looking for other jobs.</p><p><strong>We had to make a change.</strong></p><h1><strong>Who Are We? Product or Engineering?</strong></h1><p>The organizational structure at the company hadn&#8217;t changed much from its startup roots. While the company had scaled by nearly 600%, its processes and structures hadn&#8217;t grown to match. The structure was very much the same as its startup roots.</p><p>There was no &#8220;Engineering&#8221; department. It was simply &#8220;Product,&#8221; which included all of the product managers, designers, and engineers under a single organizational entity. Engineering didn&#8217;t have a separate budget, OKRs, KPIs, or even roadmap.</p><p>As a result, Product was the sole authority on <em>everything</em>.</p><h2><strong>This led to a few challenges</strong></h2><p><strong>It was difficult to prioritize or advocate for Engineering requirement</strong>s. Things like addressing technical debt would always lose against &#8220;the next big product idea&#8221; that would (in an ideal world) generate millions of more dollars in revenue.</p><p>As a result, the system accrued a significant amount of technical debt over the years, making the development of even basic things like changing the color of a button across all of the pages a monumental effort. We had a joke for it &#8212; we called it &#8220;load-bearing CSS&#8221; because we knew somehow, somewhere, there was critical business logic depending on the color of that button.</p><p><strong>It made resourcing and planning difficult.</strong> We shared a fungible budget with Product, which meant when an engineer left, that allocation often disappeared, going to either Design or Product, or disappearing outright.</p><p><strong>It made it hard to give people raises. </strong>Our developers had significant pay disparities as a result of ineffective hiring practices during the company&#8217;s hyper-growth phase. Many were nearly 30&#8211;50% under market, some were 50% above market. In some cases, people who shared the same level had as much as a 60% salary difference!</p><p><strong>Finally, it made engineering difficult</strong>. We were subservient to the Product organization, which meant we always had to do what the product manager said, without exceptions. We ended up with a team of ticket takers building tiny things the product manager specified, instead of leveraging our collective problem-solving skills to find a great solution to a problem.</p><h2><strong>Lacking voice</strong></h2><p>As far as the rest of the company was concerned, Product was the technology team and, as a result, the product managers were the voice of the technology, design, and engineering.</p><p>Unfortunately, the product managers simply didn&#8217;t know the technology as well as they thought they did. They had a lot of assumptions about how it was built and how it functioned &#8212; these assumptions were incorrect.</p><p><strong>Part of the issue was their skill level.</strong> Novice product managers ended up drip-feeding information or projects to engineers with no cohesive end vision. As a result, things were built as separate items or as minor add-ons to existing systems. When it was time to make the pi&#232;ce de r&#233;sistance, tying them together into a synergistic whole, it was impossible because they weren&#8217;t built to be integrated or separated from other parts of the system.</p><p><strong>Part of the challenge was the team structure. </strong>We had teams that operated at the layer level &#8212; front end, back end, and mobile teams. They weren&#8217;t cross-functional and each initiative required significant cross-over and synchronization. The result? Unnecessary hand-offs, gatekeeping, and delays on things that could have been executed rapidly with a single cross-functional team.</p><p><strong>This happened repeatedly. </strong>When product managers communicated their features to the rest of the company, they were assumed to have wildly different capabilities than what was actually built. However, because product managers were viewed as the voice of the technology, their inaccurate statements were taken as gospel by other parts of the organization, leading to significant confusion.</p><p>Engineering needed a distinct voice.</p><p></p><h2><strong>How did we get there?</strong></h2><div class="paywall-jump" data-component-name="PaywallToDOM"></div><p>Like any major organizational transformation, it took a lot of conversations and a few lucky breaks.</p><p>The first issue to solve was the layered teams. This was relatively straightforward to fix &#8212; have engineers work in full-stack teams. This meant mixing engineers of varying skills into each team, removing the layers.</p><p>Once that was proven to work better, it was time to illustrate the need for separate departments. I talked about the confusion and development issues it caused to have them combined. I talked about how it was still possible to maintain collaboration and organizational cohesion even with the departments separated, citing the success of the newly formed full-stack teams as an example.</p><p>I emphasized the need for a leadership structure that represented engineering needs and could manage engineering-related personnel and structural issues.</p><p>I came prepared. I had everything from desired org charts to career progression ladders to budgets. I talked about team structure, development processes, with anyone and everyone who would listen.</p><p>I worked directly with executive stakeholders as well as middle managers and ICs throughout the company to share this message and understand the problems it would cause or solve, and then summarized them the essential details for the executive team.</p><p>We eventually got buy-in from executive stakeholders and thus formed the PED team &#8212; Product, Engineering, and Design as separate departments working collaboratively. I became the Director of Engineering responsible for the newly formed Engineering department and all of its developers.</p><p>This meant we had our voice, our autonomy, and our budget.</p><h1><strong>First Stop: Fair Compensation</strong></h1><p>As previously stated, developer compensation was all over the place and completely divorced from actual performance, by as much as 60%.</p><p><strong>It&#8217;s not a great strategy to have that significant a pay disparity for the same quality of work. </strong>Pay disparities<strong> </strong>demotivate high performers who wonder why they should work harder to earn less and it causes low performers to become complacent. After all, if high performance isn&#8217;t necessary to achieve their desired salaries, that&#8217;s one less thing motivating them to improve and perform well.</p><p>I put a stop to that as soon as I could. One of the first things the separation enabled me to do was level pay bands across the board. Working with our finance team, I brought Engineers who were significantly under market up to market. One of the biggest gripes engineers had was about their compensation and I ensured that hygiene factors were met so we could focus on more important issues.</p><p><strong>I provided clarity and reset expectations </strong>for the engineers who were significantly over the market level. For some, I made it known that their salary expectations were simply unrealistic given our company and their skill level. For others, it was about focusing them and providing them training and professional development so that they could perform at the level that matched what they were getting paid.</p><p>In some cases, the conversations turned into performance improvement plans. Some employees improved and thrived. Others didn&#8217;t and parted ways with us. I ensured a portion of departing employee salaries was re-invested back into the current team, enabling me to level up the employees that were performing well or improving.</p><h1><strong>Names Give Power &#8212; With Power Comes Responsibility</strong></h1><p>Because we were now the engineering department, we had some responsibilities to the rest of the company. They needed visibility of how our organization was performing and whether this change was worth it.</p><h2><strong>Numbers for everyone</strong></h2><p>We were in a position where the metrics we were looking at weren&#8217;t particularly useful. We had product metrics like velocity for team-level capacity, but not much else. We couldn&#8217;t use them to see where we were on our journey of continuous improvement.</p><p>We experienced lucky timing. The <a href="https://cloudplatformonline.com/rs/248-TPC-286/images/DORA-State%20of%20DevOps.pdf">State of DevOps</a> report had come out, which provided an easy-to-adopt set of metrics we could use as the foundation for our culture of measurement. As an avid fan of the book &#8220;Accelerate,&#8221; it was a great reminder of the existence of a set of principles for engineering success.</p><p>We took the four basic ones:</p><ul><li><p>Cycle time.</p></li><li><p>Mean-time-to-restore.</p></li><li><p>Deployment frequency.</p></li><li><p>Change failure rate.</p></li></ul><p><strong>We hadn&#8217;t measured any of these in the past.</strong> I looked at some tooling to retrieve these, but they were complex, not quite what we needed, or were pricey. We simply didn&#8217;t have the resources to devote to exploring them. Besides, it wasn&#8217;t the greatest idea to suddenly increase costs by hundreds or thousands of dollars, right when the engineering department started. We first needed to prove ourselves.</p><p><strong>We took the DIY approach. </strong>I immediately wrote a bash script that took our Git commit data and calculated the deployment frequency from it. I also wrote a second script that took the same Git data and estimated a change failure rate, looking for words like &#8220;hotfix&#8221; and comparing it to the deployment frequency.</p><p>I also implemented a process to manually document every single incident or outage &#8212; including timelines, when it started, when it was detected, when it was resolved, what the root cause was, and what actions were taken subsequently. It was documented in a Github issue, which was fully available to all of the engineers. Through this, we had our mean-time-to-restore &#8212; at least manually.</p><p>I couldn&#8217;t figure out how to get cycle time from what we were already tracking, so I took a proxy measure of lead time. I created a spreadsheet that took our JIRA issues and estimated lead time based on the time an issue was created and when it was resolved. It wasn&#8217;t precise or accurate, but it was a good enough ballpark to get a picture of where we were.</p><h2><strong>The results weren&#8217;t pretty</strong></h2><p>Looking back at the data as a benchmark the result were disappointing, to say the least.</p><p><strong>Deployment Frequency was at 0.25 / day.</strong> That means we deployed, on average, once every four days. Digging deeper into the numbers, it was often small tweaks and bug fixes &#8212; feature deploys were happening a lot more rarely.</p><p><strong>Our Change Failure Rate was 25%</strong>, which meant one out of every four deploys required a hotfix. Looking into data even earlier, our change failure rate at one point had hit 400%, meaning every deploy led to four hotfixes.</p><p><strong>Our mean-time-to-restore was roughly eight hours. </strong>This was driven primarily by a database outage that we simply weren&#8217;t prepared for.</p><p><strong>Our Lead Time was 14 days &#8212;</strong> coincidentally, the same length as a sprint. I guess that work does always fill the allotted time!</p><h1><strong>Getting Lean</strong></h1><p>There&#8217;s a lot of overlap with DevOps and Lean principles. Post-agile foundations just don&#8217;t change. Reducing batch size, creating and driving feedback loops, iteration &#8212; these are all things we could do.</p><p>However, the technology didn&#8217;t enable it. If I were to tell our team &#8220;we should deploy every day,&#8221; it would be impossible to do without greatly negatively affecting our output.</p><p>Our deployment took nearly half an hour. We didn&#8217;t have a staging environment. Our tests failed regularly for random reasons.</p><p><strong>It was a chicken and egg problem</strong> &#8212; how do we improve our process, to improve our technology, to improve our process, to improve our technology&#8230;?</p><h1><strong>Starting With the Principles First &#8212; Small Batch Sizes</strong></h1><p>One of the principle practices of Lean and DevOps is risk reduction via small batch size. By reducing the risk of every deployment, we accelerate our ability to deliver by improving confidence and stability in our delivery process.</p><p>Our technology platform was not conducive to delivering anything without a big-bang release. We would have long-lived feature branches where everything would go (via the git-flow approach, which I introduced when I first started). These branches may have had several thousand lines of code be deployed all at once.</p><p>It&#8217;s because we didn&#8217;t have the capability to deliver small parts without impacting users.</p><p><strong>The solution? Create the capability.</strong></p><h1><strong>Feature Flagging to the Rescue</strong></h1><p>I set out to create a feature flagging infrastructure within the platform to enable us to toggle features off and on in a consistent way. My hope was that this would encourage the deployment of incomplete features but good code, which meant it would reduce batch sizes/deployment sizes.</p><p><strong>This wasn&#8217;t as easy as it sounded.</strong> Over the years, multiple pseudo-flagging techniques were littered throughout the system. Some things were using ENV variables, others were using hard-coded conditional checks, and more. We even had columns that represented feature flags for a given table!</p><p>Managing and integrating all these to work consistently was a challenge that took more than a few phases. It was made more difficult by the way our system was designed &#8212; we had to approach system-level feature flags and context-level feature flags in separate phases due to legacy code.</p><p><strong>We stuck to the basics. </strong>We moved all our feature checks behind an interface, built out a service class to encapsulate all of the various different kinds of flag checks we used. Once we transitioned everything to use the new service class, we created a new data model to hold the feature flags and ran both systems in parallel. After the system was proven to work, we sunset the old data model, then finally deprecated the old code. We also performed a developer training to ensure all the developers knew about the new feature flagging system and how to use it.</p><p>Once we had the service layer and data model controlling all feature flags in our platform, extending its functionality with even more power was easy. We added A/B testing, flag options, and more!</p><p>Because the interface was built in a generic way, we could easily swap it out with a more robust flagging library down the line without a problem.</p><h2><strong>Deployment != release</strong></h2><p>Feature flagging led to the separation of a <em>deploy</em><strong> </strong>from a <em>release </em>&#8212; a terminology difference that people previously didn&#8217;t even consider within the realm of possibility. A deploy was a code integration and delivery into a production environment, whereas a release was a feature becoming used by one or more users.</p><h1><strong>An Unexpected Surprise</strong></h1><p>Surprisingly, the<strong> </strong>introduction of feature flags actually improved interactions between Engineering, Product, and Design.</p><p>There was always a tension between building things right, building the right thing, and building things right away.</p><p><strong>Feature flagging made engineers happy</strong> because it helped de-risk large projects by providing a way to integrate and get things out quickly. Engineers started to deploy code earlier in the development process, which prevented code from piling up into massive, risky deployments.</p><p><strong>It made product managers happy</strong> because they could test the business impact of an idea with less risk but still control when it went out. They could release a feature when they wanted, or test it on smaller audiences to manage risk and get feedback early without drastically impacting the business. If the feature didn&#8217;t work as intended or caused issues, they could easily turn it off with the click of a button. Features could be iterated multiple times to get the kinks out before a wider release.</p><p><strong>This, in turn, made designers happy</strong> because by deploying things, but not releasing widely, they could be iterated on to eventually match design fidelity. It helped us to ensure we didn&#8217;t deliver subpar interactions and experiences to customers.</p><p><strong>It was an unexpected but welcome effect on team collaboration. </strong>I won&#8217;t say feature flagging was the silver bullet to our collaboration problems, but it sure helped us realize that we all had the same goal in mind and get over the smaller execution quibbles.</p><h1><strong>Small Batch Sizes = More Batches = More Overhead</strong></h1><p>The feature flags helped reduce risk and batch sizes somewhat but we were still deploying releases with nearly a thousand lines of code.</p><p>Why?</p><p><strong>Our deployments were painful. </strong>It took 30 to 45 minutes of a developer&#8217;s full attention, merging PRs, writing release notes, and performing smoke tests.</p><p>As a result, most developers hated to deploy. A few dedicated engineers did most of the deploys, while the rest cheered them on.</p><p><strong>The frequency of deploys was low under this model. </strong>It only happened a few times week and each of the deploys was still relatively large and risky.</p><p>We needed to reduce the overhead of producing the batch/deploy.</p><h2><strong>Automation to the rescue</strong></h2><p>I wrote a tool in bash to automate this tedious process, at least for some of our deployments. The tool, which we called <em>Patchy</em>, allowed any engineer to create a release out of a single PR, and deploy it straight to production with a single command.</p><p>Running <code>./patchy.sh 6486</code> would deploy PR #6486, for example.</p><p>It handled everything related to the deploy that was previously taking up the developer&#8217;s attention: release notes, incrementing version numbers, checking the test results, and even notifying people with the notes.</p><p>Patchy reduced the time it took a developer to deploy from 30 minutes to just one minute. While the deploy itself took roughly 15 minutes, the developer simply triggered it in a &#8220;fire and forget&#8221; manner.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bdTg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6de9f548-c495-473e-a46a-c581ca7b0100_1054x314.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bdTg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6de9f548-c495-473e-a46a-c581ca7b0100_1054x314.png 424w, https://substackcdn.com/image/fetch/$s_!bdTg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6de9f548-c495-473e-a46a-c581ca7b0100_1054x314.png 848w, https://substackcdn.com/image/fetch/$s_!bdTg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6de9f548-c495-473e-a46a-c581ca7b0100_1054x314.png 1272w, https://substackcdn.com/image/fetch/$s_!bdTg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6de9f548-c495-473e-a46a-c581ca7b0100_1054x314.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bdTg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6de9f548-c495-473e-a46a-c581ca7b0100_1054x314.png" width="1054" height="314" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6de9f548-c495-473e-a46a-c581ca7b0100_1054x314.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:314,&quot;width&quot;:1054,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!bdTg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6de9f548-c495-473e-a46a-c581ca7b0100_1054x314.png 424w, https://substackcdn.com/image/fetch/$s_!bdTg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6de9f548-c495-473e-a46a-c581ca7b0100_1054x314.png 848w, https://substackcdn.com/image/fetch/$s_!bdTg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6de9f548-c495-473e-a46a-c581ca7b0100_1054x314.png 1272w, https://substackcdn.com/image/fetch/$s_!bdTg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6de9f548-c495-473e-a46a-c581ca7b0100_1054x314.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">Patchy reduced the time it took to deploy from 30 minutes to 1 minute.</figcaption></figure></div><p><strong>The results were instantaneous.</strong> Deployment Frequency went from 0.25/day, to an average of 6.5/day. More developers were involved in the deployment process. Gone were the 15&#8211;20 PR queues. We even had some days where we hit zero PRs open without a reduction in our productivity or output.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!x0mu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9e6729b-69c0-4596-ac49-31faef21ba7d_1400x708.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!x0mu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9e6729b-69c0-4596-ac49-31faef21ba7d_1400x708.png 424w, https://substackcdn.com/image/fetch/$s_!x0mu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9e6729b-69c0-4596-ac49-31faef21ba7d_1400x708.png 848w, https://substackcdn.com/image/fetch/$s_!x0mu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9e6729b-69c0-4596-ac49-31faef21ba7d_1400x708.png 1272w, https://substackcdn.com/image/fetch/$s_!x0mu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9e6729b-69c0-4596-ac49-31faef21ba7d_1400x708.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!x0mu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9e6729b-69c0-4596-ac49-31faef21ba7d_1400x708.png" width="1400" height="708" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a9e6729b-69c0-4596-ac49-31faef21ba7d_1400x708.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:708,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!x0mu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9e6729b-69c0-4596-ac49-31faef21ba7d_1400x708.png 424w, https://substackcdn.com/image/fetch/$s_!x0mu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9e6729b-69c0-4596-ac49-31faef21ba7d_1400x708.png 848w, https://substackcdn.com/image/fetch/$s_!x0mu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9e6729b-69c0-4596-ac49-31faef21ba7d_1400x708.png 1272w, https://substackcdn.com/image/fetch/$s_!x0mu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9e6729b-69c0-4596-ac49-31faef21ba7d_1400x708.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">A beautiful site for an engineer.</figcaption></figure></div><h2><strong>Increase deployment batch size</strong></h2><p>One issue we encountered was that, while our deployment frequency was high, the smaller deployment batch sizes led to an increased overhead when deploying multiple items.</p><p>We had &#8220;deploy trains&#8221; where engineers would take turns &#8220;Patchying&#8221; their PRs. These deploy trains would sometimes run for hours &#8212; an engineer would run Patchy for their PR, sending a deploy automatically, and once it was done, another engineer would run Patchy for their PR, and so on and so forth. This led to a stream of changes that, while good on the surface, were indicative of inefficiency.</p><p>I rewrote Patchy into a Ruby script, adding the capability to specify multiple PRs to deploy.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9TJF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27a31bb7-078f-42dd-929f-de2532f7104a_1400x410.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9TJF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27a31bb7-078f-42dd-929f-de2532f7104a_1400x410.png 424w, https://substackcdn.com/image/fetch/$s_!9TJF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27a31bb7-078f-42dd-929f-de2532f7104a_1400x410.png 848w, https://substackcdn.com/image/fetch/$s_!9TJF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27a31bb7-078f-42dd-929f-de2532f7104a_1400x410.png 1272w, https://substackcdn.com/image/fetch/$s_!9TJF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27a31bb7-078f-42dd-929f-de2532f7104a_1400x410.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9TJF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27a31bb7-078f-42dd-929f-de2532f7104a_1400x410.png" width="1400" height="410" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27a31bb7-078f-42dd-929f-de2532f7104a_1400x410.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:410,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!9TJF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27a31bb7-078f-42dd-929f-de2532f7104a_1400x410.png 424w, https://substackcdn.com/image/fetch/$s_!9TJF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27a31bb7-078f-42dd-929f-de2532f7104a_1400x410.png 848w, https://substackcdn.com/image/fetch/$s_!9TJF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27a31bb7-078f-42dd-929f-de2532f7104a_1400x410.png 1272w, https://substackcdn.com/image/fetch/$s_!9TJF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27a31bb7-078f-42dd-929f-de2532f7104a_1400x410.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">Patchy V2 allowed for deploying multiple PRs at once.</figcaption></figure></div><p>By enabling Patchy to deploy multiple items in an automated way, we were able to reduce the cost of deploying multiple things by slightly increasing the deployment batch size.</p><p>The result: a drop in deployment frequency to about 3/day without an accompanying drop in the change volume. The number of items actually being released didn&#8217;t go down at all.</p><p>I carefully monitored the change failure rate and didn&#8217;t see any increase. People were still careful to keep their releases low-risk: Trusting your engineers pays off!</p><p>Patchy V2 simply removed the overhead of deploying multiple things.</p><h1><strong>Iterating on Metrics</strong></h1><p>Around this time, I was able to update our tracking capabilities. JIRA had released new project types (<em>thank you Atlassian!)</em>, which allowed me to automatically set timestamps and other items based on when items moved into certain statuses. This allowed me to automatically calculate cycle time, distinguishing it from lead time.</p><p>I also implemented automated uptime monitoring, using a combination of Pingdom and Statuspage. This allowed us to have basic server checks that ran once a minute and sent us an alert if our site returned any issues.</p><p>In the interest of transparency, we also shared the status page with the rest of the company, providing operations, sales, and other departments an inside look at our uptime to help hold us accountable.</p><h1><strong>It&#8217;s Not Just About the Technology</strong></h1><p>A lot of people equate DevOps with technologies. When they hear &#8220;DevOps&#8221;, they think of Docker, Kubernetes, etc. Some think of practices &#8212; containerization, orchestration, etc.</p><p>For me, these are just tools or methods to accomplish a cultural shift. DevOps begins in the mind and its primary focus is shifting the mindset and culture.</p><p>One of the biggest blockers to shifting towards a DevOps model on our organization was our own mindset towards change, ownership, and responsibility.</p><p>It had to change.</p><h1><strong>Ambiguity and the Unknown</strong></h1><h2><strong>&#8220;Ugh, the requirements changed.&#8221;</strong></h2><p><em>&#8220;Change&#8221; had become a bad word.</em></p><p><strong>The team was not comfortable with ambiguity</strong>, to say the least. Previously, the highly centralized work was expected to be finely planned, intricately detailed, and perfectly accurate before being handed off to engineers. This was a result of a building mistrust between Product and engineers.</p><p>Any changes or missing information led to an outcry of &#8220;incomplete requirements!!!&#8221; and many complaints and grumblings from engineers. Perfect requirements are an impossibility, of course, but that never really occurred to the team.</p><p>It was a huge shift to get engineers comfortable with being adaptable.</p><p><strong>&#8220;Change&#8221; had become a bad word.</strong> If we wanted to succeed and truly be agile, we had to embrace change. I immediately started a counter-culture that was tolerant and accepting of change, shifting the perspective to a new mindset where change was an opportunity to gain more insights into what reality represented.</p><h2><strong>Making the problem visible</strong></h2><p>Sometimes, there&#8217;s no better way of showing there&#8217;s a problem than to visually show it.</p><p>I made the lead time metric visible to <em>everyone</em> by publishing the graph on the shared TV in our office area to force the developers to visually see what the impact of demanding perfect planning and detail was. I shared it in 1:1s and meetings.</p><p><strong>It was a drastic metric. </strong>Some requests waited over sixty days in planning before they even started getting worked on. From a customer&#8217;s perspective, that was nearly two months before anything happened &#8212; no wonder people in our organization felt Product was a black hole for requests!</p><h2><strong>Solving the problem</strong></h2><p>Now that the problem was visible, I could explicitly address it.</p><p>I encouraged limits to the length of time we planned items as a forcing function to force things to not be fully fleshed out. We encountered real analysis paralysis and encouraging short lead times improved the team&#8217;s adaptability.</p><p>Short lead times, however, led to more ambiguity in the requirements. I did significant 1:1 training with the engineers, leads, and product managers to overcome the reluctance to work with less detail. I taught them the kinds of questions to ask and the problems they should look for, and the solutions they could find on their own.</p><p>I gave them strategies and tactics for dealing with ambiguity, such as making the &#8220;70% decision,&#8221; or &#8220;guessing right.&#8221; I taught them architecture and patterns to help make their code more flexible and less dependent on policy details that could change at any time.</p><p>These foundational techniques helped them to get more comfortable with the loss of explicit detail, and also pushed them to leverage more of their own problem-solving skills.</p><p>Sure, some project requirements were rushed in the short-term, but the long-term positive impact on culture was invaluable. It might have been an uncomfortable experience, but it greatly improved the team&#8217;s capability to adapt and operate with ambiguous information.</p><h1><strong>Planning for the Future vs. Planning for the Never</strong></h1><p>While we had made progress in reducing lead times, Product direction still operated in a long-term manner that wasn&#8217;t adaptive to changing business needs. Roadmaps would be planned three months to a year out.</p><p><strong>Startups change drastically in short time frames.</strong> The company&#8217;s focus might be one thing in one month, then completely different in the next. In an environment where change is the only constant, why attempt to create a 12-month roadmap?</p><p>Forecasts of the long time horizons would go out of date quickly. Worse, a month into the roadmap and we&#8217;d know better about our environment and problem, making our roadmap moot. Why stick with it when we know it won&#8217;t last? How do we change that mindset?</p><p><em>In an environment where change is the only constant, why attempt to create a 12-month roadmap?</em></p><h2><strong>Failure is an option and a darn good one</strong></h2><p>All of the changes we made in our culture and technology had a massive benefit &#8212; it made it cheap to fail.</p><p>Reducing the cost of failure allowed us to pursue opportunities that might have previously been incredibly risky or needed to be highly planned in the past. Getting it wrong doesn&#8217;t matter when the failure is easy to reverse, or the scope and impact are limited.</p><p>I formed a team with a couple of engineers with the sole intent of focusing on the opportunities the business wanted to pursue &#8212; those that had a high likelihood of failure, or that weren&#8217;t thought out that well. These were often the interruptive tasks that previously annoyed teams and took their attention away from the roadmapped items.</p><p>To execute with this team, we practiced Kanban and adopted lean principles. Other teams were running Scrum with all of its ceremony and pomp, but I felt it wasn&#8217;t the right approach for this team.</p><p><strong>We wanted to be a quick reaction force</strong> &#8212; a nimble team capable of adapting to the whims of the business. We couldn&#8217;t have a quarterly roadmap and do that at the same time. As a result, I ran the team with no roadmap, keeping a close eye on our queue size and ensuring we never planned more than the next week&#8217;s worth of work.</p><p>Some of the product managers viewed this approach as chaotic and unaligned with the roadmap. They argued it was taking valuable manpower from the planned work we had.</p><p>I disagreed. I viewed it as a supportive effort for the product roadmap. By taking on all of the interruptive projects and demands of the business, it freed up the other teams to focus on the main efforts of their planned roadmaps exclusively.</p><p><strong>You know what? It worked. </strong>The business threw problem after problem at us and the lean team adapted immediately and executed on it. We were able to protect the rest of the teams from these projects, which if we hadn&#8217;t done would&#8217;ve had to be done anyways, except on a much tighter schedule. While the other teams churned away on a predefined quarterly roadmap, our team was able to handle the business&#8217;s urgent intake requests.</p><p><strong>The business was happy.</strong> Previously they had no ability to change or influence the direction of the product development once it was set. Now, we had a collaborative relationship that allowed us as an entire product development organization to make progress on roadmapped items while still remaining adaptable to business needs.</p><p><strong>Other teams later adopted this lean execution model</strong>, although not to the extent of the quick reaction force I set up. By limiting their forecast and roadmapped projects to a month or two, they avoided doing extra work on items that would never get executed. They would also leave their roadmaps open to responding to the feedback they got from customers about their release. This meant we started listening to the customer more, which led to better feedback loops and more iterative execution.</p><p>By adhering to lean principles, such as work-in-progress limits and managing queue sizes, teams were able to build a backlog of work that was useful for executing and communicating, but adaptable and still responsive to changes found in feedback and business direction.</p><h1><strong>Promoting Decentralized Control</strong></h1><p>We were moving faster and delivering more and more, and the speed was uncomfortable for some. The speed, combined with all of these changes and the increased ambiguity, led some people to try and involve themselves in every decision and meeting in an attempt to keep abreast of all of the things that were happening. This led to slowdowns as their gatekeeping became bottlenecks in execution and delivery.</p><p>This wasn&#8217;t sustainable or effective and the lead engineers had to change their mindsets.</p><p>The question becomes, &#8220;how do you encourage lead engineers that were previously very centrally controlled to get out of their comfort zone and start making decisions?&#8221; When people have operated for a long time under a central command model, it becomes second nature for them to ask for permission and just do what they&#8217;re told.</p><p>&#8220;Learned helplessness&#8221; is contagious. It&#8217;s a culture shock to be thrust into a situation where you have full freedom with no warning.</p><h2><strong>We started small</strong></h2><p>We started small. We provided decision-making capabilities to people who had proven their competency. We limited the scope enough to ensure we didn&#8217;t go astray and that we could easily recover from bad decisions.</p><p>I personally coached lead engineers and other promising junior leadership on how to flip the mental model of leading. I talked to them about being tolerant of failure, leading with intent, asking not telling, and other foundational practices intending to build a culture of initiative. I taught them that by letting go of direct control and oversight, they would get teams able to make local decisions in a timely manner.</p><p>By providing intense clarity and alignment, you can indirectly promote autonomous decision-making that&#8217;s beneficial to the business.</p><h2><strong>The culture wasn&#8217;t for everyone</strong></h2><p><em>When you define a culture, some people are going to opt-in, and some people are going to opt-out.</em></p><p>It was a long journey. Unfortunately, not everyone followed us on that journey.</p><p>Some people just don&#8217;t operate well with ambiguity, or explicitly do not want that kind of working environment. That&#8217;s OK.</p><p>That&#8217;s the downside of defining a culture. When you define a culture, some people are going to opt-in, and some people are going to opt-out. It&#8217;s a choice every person makes.</p><p>I wish those that opted-out the best of luck!</p><h1><strong>Was It Worth It?</strong></h1><p>Did all of these efforts work? Were they useful at all? The answer is a resounding <em>yes</em>!</p><h2><strong>Organizational culture</strong></h2><p>The company used a tool called 15Five to do a quick weekly survey of the team, asking how their week went. I added additional questions from the Accelerate Westrum Organizational Culture survey in the 15Five to measure the results on the engineering team.</p><p>The idea is straightforward: If the biggest predictor of effective organizations is job satisfaction, how do you measure the factors that lead to increased job satisfaction? Westrum created a model for the factors correlated with an organization&#8217;s health. We took those factors and surveyed our team regularly over the year.</p><p>As we transitioned through our cultural shift, results went from an average of 3.1 to 4.3. It was a massive leap that signaled that we were on the right track.</p><h2><strong>Retention</strong></h2><p>Our retention numbers improved significantly as well. That year, only three developers quit &#8212; two for personal reasons and one for performance reasons.</p><p>People weren&#8217;t leaving because of our company anymore.</p><h2><strong>Delivery</strong></h2><p>Our delivery improved significantly in both speed and quality.</p><p>We were operating by every metric three to five times better than we ever were before.</p><p>Our cycle time had hit a low of three days. Our change failure rate went and stayed below 2%. Our deployment frequency hovered around 3.5 deploys / day after the introduction of batch deployment tooling. We introduced change volume as a counter metric and consistently released roughly 120&#8211;180 pull requests a month.</p><p>We released a multitude of changes that drove significant increases to retention, acquistion, and revenue. The business was happy &#8212; they were seeing tangible progress and results on a consistent basis.</p><h2><strong>Technology</strong></h2><p>On the technology front, we greatly improved the stability, performance, scalability, and security of our systems. We developed subsystems that helped us develop even faster &#8212; design systems, modular component libraries, isolated subsystems, etc.</p><p>The delivery of business value didn&#8217;t sacrifice the technical quality and the technical quality didn&#8217;t sacrifice the delivery of business value. It worked harmoniously.</p><h1><strong>Improvements</strong></h1><p>In just one short year, we had drastically transformed how the development organization operated. The changes we made proved to be effective. We were now releasing multiple times a day and had multiple experiments and tests running at any given time.</p><p>What&#8217;s more, the way we operate had led to better operations across the entire company. The company collaborated better and was more aligned than we had ever been. </p>]]></content:encoded></item></channel></rss>