<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Joel Connett — Writing</title><link>https://joelconnett.com/blog/</link><description>Articles and case studies on engineering leadership, architecture, and effective software delivery.</description><language>en</language><generator>Hugo</generator><atom:link href="https://joelconnett.com/blog/index.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Tue, 10 Nov 2026 00:00:00 +0000</lastBuildDate><item><title>Better Architecture Starts With Better Conversations</title><link>https://joelconnett.com/blog/decisions-close-to-work/</link><guid isPermaLink="true">https://joelconnett.com/blog/decisions-close-to-work/</guid><category>Article</category><pubDate>Tue, 10 Nov 2026 00:00:00 +0000</pubDate><dc:creator>Joel Connett</dc:creator><description>How collaborative, engineer-owned decisions and a lasting record of tradeoffs lead to better software architecture.</description><content:encoded><![CDATA[<p>The summer before my senior year of high school, I worked as a paid intern at the Environmental Research Institute of Michigan (ERIM). My project used ocean elevation measurements from the TOPEX/Poseidon satellite. I wrote C++ and MATLAB software to extract data from CD-ROMs, organize it into coordinate grids, and generate 3D visualizations of ocean height.</p>
<p>At the end of the summer, I presented my findings to the institute&rsquo;s president and other leaders. They asked good questions about the results and the tradeoffs I&rsquo;d made.</p>
<p>I doubt anyone ever ran that software again. But if someone had opened the code months or years later, would they have understood why I&rsquo;d made those choices? The reasoning existed in a conversation, not in a durable record alongside the code.</p>
<p>Years later, I encountered a larger version of the same problem at Control4.</p>
<p>When we were designing the OS 3.0 mobile applications, our senior engineers met regularly to evaluate UI architectures, including MVC, MVP, VIPER, and MVVM. We discussed the tradeoffs and the maturity of the available implementations. We also took meeting notes. Some of the reasoning was probably captured there, but those notes were eventually lost during a wiki migration.</p>
<p>The code survived. The context behind some of our decisions did not.</p>
<figure class="engineering-os-figure architecture-conversation-figure">
  <img class="engineering-os-illustration engineering-os-illustration--light" src="https://joelconnett.com/images/better-architecture-conversations-light.svg" alt="Light infographic showing four steps: start the conversation, seek advice and alternatives, own the decision, and preserve the reasoning near the code. The outcomes are stronger collaboration, clearer accountability, and lasting knowledge." width="1440" height="900" loading="lazy" decoding="async">
  
  <figcaption>Engineer-owned decisions work best when advice is welcomed, accountability is clear, and the reasoning remains accessible.</figcaption>
</figure>
<h2 data-hextra-search-id="the-problem-isnt-just-missing-documentation">The problem isn&rsquo;t just missing documentation<span class="hx:absolute hx:-mt-20" id="the-problem-isnt-just-missing-documentation"></span>
    <a href="#the-problem-isnt-just-missing-documentation" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Engineers make decisions every day. Most are local to a function, class, or component and don&rsquo;t need a formal process.</p>
<p>But some decisions affect other engineers, teams, or products. Those decisions need broader input and a way to preserve the reasoning. Without that, we risk revisiting the same arguments, repeating mistakes, or criticizing choices without understanding the constraints under which they were made.</p>
<p>The answer isn&rsquo;t to have every technical decision made by a committee. Committees can introduce compromises that satisfy everyone on paper while producing a worse technical solution.</p>
<p><strong>I wanted decisions to stay with the engineers closest to the work, while making sure the people affected by those decisions had a voice.</strong></p>
<h2 data-hextra-search-id="let-the-team-define-the-process">Let the team define the process<span class="hx:absolute hx:-mt-20" id="let-the-team-define-the-process"></span>
    <a href="#let-the-team-define-the-process" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I&rsquo;ve followed Martin Fowler&rsquo;s writing for much of my career and put many of the patterns he discusses into practice. Andrew Harmel-Law&rsquo;s Thoughtworks article, <a href="https://martinfowler.com/articles/scaling-architecture-conversationally.html" target="_blank" rel="noopener"><em>Scaling the Practice of Architecture, Conversationally</em></a>, gave me a useful framework for scaling technical decisions through conversation rather than centralized approval. Architecture Decision Records (ADRs) were one of the tools it described.</p>
<p>ADRs weren&rsquo;t new, but we hadn&rsquo;t established them in my organization.</p>
<p>I had a practical reason for wanting to try them. Engineers would sometimes come to my office frustrated by decisions another engineer had made. Often, the disagreement wasn&rsquo;t only about the outcome. They felt that their concerns hadn&rsquo;t been heard or that their perspective hadn&rsquo;t been considered.</p>
<p>We needed a better way to involve stakeholders without turning architecture into design by committee.</p>
<p>I also knew that engineers generally don&rsquo;t appreciate having a new process imposed on them, especially one they&rsquo;re expected to follow without helping shape it.</p>
<p>Around that time, I&rsquo;d formed a small UI-Platform team in our Belgrade office: two engineers and a manager. The team was just getting started, had several architectural decisions ahead of it, and had the capacity to try something new.</p>
<p>I introduced the concept of ADRs, and we read through several articles together. Then I asked the team to create its first ADR:</p>
<p><strong>An ADR defining how we would write and use ADRs.</strong></p>
<p>It was a small decision with an important consequence. The engineers weren&rsquo;t just adopting a process I&rsquo;d designed. They were helping define it, testing it on real work, and improving it as they learned.</p>
<h2 data-hextra-search-id="how-we-put-adrs-into-practice">How we put ADRs into practice<span class="hx:absolute hx:-mt-20" id="how-we-put-adrs-into-practice"></span>
    <a href="#how-we-put-adrs-into-practice" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>We started with a standard template. It evolved over time, but the essentials stayed consistent:</p>
<ul>
<li><strong>Context:</strong> What problem are we trying to solve, and why does it matter?</li>
<li><strong>Alternatives:</strong> What credible approaches have we considered, and what are their tradeoffs?</li>
<li><strong>Evidence:</strong> What did we learn from research, prototypes, or proofs of concept?</li>
<li><strong>Feedback:</strong> Who will be affected, what did they recommend, and how did we respond?</li>
<li><strong>Decision:</strong> What did we choose, why, and what consequences do we expect?</li>
</ul>
<p>The ADR also included metadata such as its author, creation date, status, and stakeholders.</p>
<p>I encouraged engineers to consider multiple alternatives—often three where they were genuinely plausible—rather than start with a favorite solution and work backward to justify it. A proof of concept could be valuable when the tradeoffs weren&rsquo;t clear.</p>
<p>But the document wasn&rsquo;t the main point. <strong>The conversations it prompted were.</strong></p>
<h3 data-hextra-search-id="seek-advice-not-unanimous-approval">Seek advice, not unanimous approval<span class="hx:absolute hx:-mt-20" id="seek-advice-not-unanimous-approval"></span>
    <a href="#seek-advice-not-unanimous-approval" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>For the UI-Platform team&rsquo;s initial ADRs, I identified Staff and Principal engineers and managers across my organization who should be consulted.</p>
<p>The author&rsquo;s responsibility was to seek out feedback, understand the concerns, and take them seriously. Sometimes that meant revising the proposal or finding a compromise. Sometimes stakeholders disagreed with each other, and there wasn&rsquo;t a solution that satisfied everyone.</p>
<p>We weren&rsquo;t trying to design by committee. After making a reasonable effort to resolve concerns, the author was expected to make the decision within their authority and explain the reasoning, including why some advice wasn&rsquo;t followed. Genuine blockers or decisions outside that authority still needed to be escalated.</p>
<p>That distinction matters: <strong>owning a decision doesn&rsquo;t mean ignoring advice, and seeking advice doesn&rsquo;t mean giving up ownership.</strong></p>
<h3 data-hextra-search-id="keep-the-process-visibleand-the-record-close-to-the-code">Keep the process visible—and the record close to the code<span class="hx:absolute hx:-mt-20" id="keep-the-process-visibleand-the-record-close-to-the-code"></span>
    <a href="#keep-the-process-visibleand-the-record-close-to-the-code" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Our workflow used several states.</p>
<p>An ADR began as a <strong>Draft</strong>, while the author clarified the problem, explored alternatives, gathered feedback, and ran proofs of concept. Once the proposal was ready, it moved to <strong>Proposed</strong> and was shared with the affected teams. If no blocking concerns remained, it became <strong>Ratified</strong>.</p>
<p>We also tracked ADRs that were <strong>Rejected</strong> or <strong>Abandoned</strong>, recording why they didn&rsquo;t move forward. Later decisions could <strong>Supersede</strong> earlier ones, with a reference to the replacement. The history mattered, including the paths we chose not to take.</p>
<p>During drafting and review, we used Confluence. Not every stakeholder had access to every team&rsquo;s Git repository, and sometimes product managers needed to participate. The wiki made collaboration easier.</p>
<p>Once an ADR was ratified, we converted it to Markdown and committed it to an ADR directory in the repository closest to the code. We also preserved rejected and abandoned decisions. The important thing was that future engineers could find the reasoning where they encountered the implementation.</p>
<p>We established a review committee made up of the managers in my organization. But <strong>the committee didn&rsquo;t review or approve the technical decisions</strong>. We reviewed the <em>progress</em> of ADRs, looking for proposals that had become stuck and needed help moving forward.</p>
<p>That was a deliberate separation of responsibilities. Engineering managers helped keep the process healthy; engineers retained ownership of the technical decisions.</p>
<h2 data-hextra-search-id="where-judgment-still-matters">Where judgment still matters<span class="hx:absolute hx:-mt-20" id="where-judgment-still-matters"></span>
    <a href="#where-judgment-still-matters" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Not every decision deserves an ADR. Sometimes a conversation between two engineers is enough. The process should be reserved for decisions with meaningful impact beyond the immediate work.</p>
<p>It also helps to distinguish between <strong>one-way doors</strong> and <strong>two-way doors</strong>. Some choices are expensive to reverse once implemented. Others are easy to revisit. The amount of investigation and review should reflect the consequences of getting the decision wrong.</p>
<p>The process wasn&rsquo;t perfect.</p>
<p>A small number of engineers became too attached to their proposals. They treated authorship as permission to dismiss feedback and move ahead with their preferred solution.</p>
<p>When I saw that happening, I worked with their managers to coach them through the process. Giving an engineer ownership of a decision doesn&rsquo;t remove the need for judgment, collaboration, or accountability.</p>
<p>I also saw authors criticize previous architectural choices without fully understanding why those choices had been made.</p>
<p>One principle I&rsquo;ve held for a long time is that <strong>we stand on the shoulders of giants</strong>. We often don&rsquo;t know the constraints the engineers before us faced. A past decision may look wrong with today&rsquo;s information but have been reasonable at the time.</p>
<p>An ADR won&rsquo;t prevent every disagreement, but it can preserve enough context to let the next engineer evaluate a decision fairly—and improve on it when circumstances change.</p>
<h2 data-hextra-search-id="what-i-learned">What I learned<span class="hx:absolute hx:-mt-20" id="what-i-learned"></span>
    <a href="#what-i-learned" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Over time, engineers appreciated having a consistent way to make and communicate decisions. It encouraged more discussion across the organization, made disagreements easier to surface, and preserved the reasoning that might otherwise have disappeared.</p>
<p>Having the UI-Platform team help define and trial the process made adoption easier. The managers&rsquo; review committee helped keep proposals from sitting indefinitely without taking decision-making authority away from the authors.</p>
<p>After two or three years of using ADRs in my organization, I introduced the approach to the broader organization through my VP&rsquo;s Principal Engineering Committee. Rather than simply adopting our exact process, that group developed and tried its own. The result was similar, but the ownership was theirs.</p>
<p>That&rsquo;s probably the most important part of the story.</p>
<p><strong>The goal was never to produce more documents. It was to help engineers make better decisions, involve the people affected by those decisions, and preserve the reasoning for whoever inherited the code.</strong></p>
<p>My responsibility as an engineering leader wasn&rsquo;t to make every technical decision. It was to create the environment in which engineers could make good decisions themselves.</p>
<p>That&rsquo;s a central part of my <a href="https://joelconnett.com/philosophy/engineering-operating-system/">Engineering Operating System</a>.</p>
]]></content:encoded></item><item><title>The Engineering OS in the Age of AI</title><link>https://joelconnett.com/blog/engineering-leadership-beyond-code-review/</link><guid isPermaLink="true">https://joelconnett.com/blog/engineering-leadership-beyond-code-review/</guid><category>Article</category><pubDate>Fri, 30 Oct 2026 00:00:00 +0000</pubDate><dc:creator>Joel Connett</dc:creator><description>How AI changes architectural coordination, engineering validation, and leadership responsibilities.</description><content:encoded><![CDATA[<p><em>As AI takes on more software development work, engineering leaders need to rethink how architectural decisions are communicated, enforced, and validated.</em></p>
<p><strong>A note on perspective (October 2026):</strong> These are my thoughts and opinions as of October 2026, based on my experience and understanding of AI today. The technology is evolving rapidly, and I expect my perspective to evolve along with it.</p>
<figure class="engineering-os-figure ai-leadership-figure">
  <img class="engineering-os-illustration engineering-os-illustration--light" src="https://joelconnett.com/images/ai-engineering-oversight-light.svg" alt="Light diagram showing specifications and decisions flowing through agent development into architecture review, automated quality checks, risk-based human approval, and monitored delivery, with feedback to improve the process." width="1200" height="720" loading="lazy" decoding="async">
  
  <figcaption>Agent-driven development needs context, independent checks, and feedback—not just faster implementation.</figcaption>
</figure>
<h2 data-hextra-search-id="another-layer-of-abstraction">Another Layer of Abstraction<span class="hx:absolute hx:-mt-20" id="another-layer-of-abstraction"></span>
    <a href="#another-layer-of-abstraction" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Software engineering has always evolved through abstraction.</p>
<p>Compilers eliminated the need to manage individual machine instructions. Frameworks and libraries abstracted away common functionality. AI is introducing another layer.</p>
<p>I recently encountered an observation that resonated with me: we may eventually care about AI-generated source code about as much as we care about the assembly a compiler produces.</p>
<p>There is an important difference, though. Compilers translate well-defined languages. AI agents interpret specifications that may be incomplete, ambiguous, or contradictory.</p>
<p>Historically, engineers filled in those gaps using experience, product knowledge, and architectural understanding. Agents make assumptions too, but those assumptions may conflict with existing decisions.</p>
<p>As implementation becomes less expensive, specifications, architectural constraints, and acceptance criteria become more important.</p>
<p>I expect agents to eventually become capable of making most architectural decisions as well. Whether that&rsquo;s six months or five years away, I don&rsquo;t know.</p>
<p>Architecture is a harder problem to train and evaluate. Source code is abundant, and functional correctness can often be tested. Architectural decisions involve competing constraints, undocumented reasoning, and consequences that may not become apparent for years.</p>
<p>In the meantime, agents need access to the architectural knowledge that engineers have traditionally carried in their heads.</p>
<h2 data-hextra-search-id="communication-doesnt-disappear-it-moves">Communication Doesn&rsquo;t Disappear. It Moves.<span class="hx:absolute hx:-mt-20" id="communication-doesnt-disappear-it-moves"></span>
    <a href="#communication-doesnt-disappear-it-moves" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p><a href="https://joelconnett.com/blog/conways-law-leadership/">Conway&rsquo;s Law</a> describes how software architecture reflects the communication structures of the organizations building it.</p>
<p>AI doesn&rsquo;t eliminate that relationship. It changes how communication happens.</p>
<p>Multiple agents working independently can produce individually reasonable solutions that conflict with each other. One might introduce a new service where existing infrastructure would suffice. Another might implement functionality already provided by a shared component.</p>
<p>Without coordination, those decisions accumulate into architectural complexity.</p>
<p>I&rsquo;ve invested considerable effort in documenting repositories so agents can understand the systems they&rsquo;re modifying. But documentation alone isn&rsquo;t sufficient. Relevant information needs to reach an agent when it&rsquo;s making a decision.</p>
<p>This is one reason I&rsquo;ve been studying transformer models and how LLMs, harnesses, and agents work. I think engineers should understand the technologies they&rsquo;re using to build products.</p>
<p>Those boundaries are evolving as models and agent platforms incorporate capabilities previously handled externally.</p>
<p>The harness is particularly interesting from an engineering leadership perspective. It can retrieve relevant documentation, identify architectural constraints, supply historical decisions, and initiate validation.</p>
<p>We don&rsquo;t need to provide every document in every prompt. We need to make the right information available at the right time.</p>
<p>But providing context doesn&rsquo;t guarantee an agent will follow it. We also need checks and balances.</p>
<h2 data-hextra-search-id="making-architecture-enforceable">Making Architecture Enforceable<span class="hx:absolute hx:-mt-20" id="making-architecture-enforceable"></span>
    <a href="#making-architecture-enforceable" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Our mobile and AirPlay 2 development efforts demonstrated how good engineering practices allow developers to operate independently while maintaining quality.</p>
<p>We invested in automated testing, including isolated functional tests with abstracted backend dependencies and end-to-end functional tests. A relatively small number of manual tests supplemented that coverage.</p>
<p>We also used linters, static analysis, and security analysis tools such as SonarQube.</p>
<p>Everything had to build and pass the required checks before merging into trunk.</p>
<p>These practices provided consistent expectations and immediate feedback. AI agents can benefit from the same approach.</p>
<p>Where I think we need to invest more is <strong>architectural validation</strong>.</p>
<p>Dependency analysis, interface contracts, layering rules, and architecture fitness functions can enforce many structural constraints.</p>
<p>But not every architectural concern can be expressed as a deterministic rule.</p>
<p>At a minimum, I&rsquo;d want an <strong>architecture review agent</strong> examining proposed changes before they merge.</p>
<p>It should have access to architectural documentation, relevant decisions, and the context behind the proposed change.</p>
<p>The reviewer should identify potential architectural problems, request revisions from the submitting agent or engineer, and escalate significant concerns for human review.</p>
<p>This provides another layer of architectural coordination without requiring every change to go through a human architect.</p>
<h3 data-hextra-search-id="preserve-the-reasoning">Preserve the Reasoning<span class="hx:absolute hx:-mt-20" id="preserve-the-reasoning"></span>
    <a href="#preserve-the-reasoning" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Around 2022–2023, I began introducing Architecture Decision Records (ADRs) within my organization.</p>
<p>The engineer closest to the problem authored the decision, gathered feedback, and evaluated alternatives, often through proofs of concept.</p>
<p>I&rsquo;ve found agents effective at this exploratory work. They can implement PoCs quickly and identify weaknesses in proposed designs.</p>
<p>I haven&rsquo;t yet had agents commit new ADRs, but I see value in having them propose decisions, evaluate alternatives, and document tradeoffs.</p>
<p>I&rsquo;d also expect better commit messages from agents. They should capture non-obvious decisions, assumptions, and tradeoffs rather than simply describe which files changed.</p>
<p>Both ADRs and useful commit history preserve context for future engineers and agents.</p>
<h2 data-hextra-search-id="rethinking-review-and-approval">Rethinking Review and Approval<span class="hx:absolute hx:-mt-20" id="rethinking-review-and-approval"></span>
    <a href="#rethinking-review-and-approval" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I&rsquo;m still working through how much human oversight should remain necessary for AI-generated code.</p>
<p>I&rsquo;m uncomfortable with large, complex production systems being changed without meaningful review. But agents can produce changes faster than engineers can inspect them, making traditional code review increasingly difficult to scale.</p>
<p>I think we need several complementary controls.</p>
<p><strong>Executable requirements.</strong> I&rsquo;ve been exploring behavior-driven development, where requirements are expressed as testable scenarios. These provide acceptance criteria that can be defined independently of the implementation and enforced automatically.</p>
<p><strong>Architectural review.</strong> Deterministic checks should enforce known architectural constraints. A separate architecture review agent can identify potential design problems that aren&rsquo;t easily expressed as static rules.</p>
<p><strong>Automated quality gates.</strong> Builds, functional tests, static analysis, and security checks should remain mandatory. Independent validation matters because tests written by the implementing agent may reinforce its own incorrect assumptions.</p>
<p><strong>Risk-based human approval.</strong> Changes affecting security boundaries, critical interfaces, or significant architectural decisions should receive additional scrutiny.</p>
<p><strong>Random human inspection.</strong> I like the approach of sampling changes that otherwise passed automated approval. It&rsquo;s similar to manufacturing quality control: periodically inspecting products from the line to find weaknesses in the process. Those findings should feed back into better tests, architectural rules, and agent instructions.</p>
<p><strong>Supply-chain protection.</strong> Agents can introduce dependencies without anyone explicitly requesting them. Dependency scanning, package allowlists, provenance checks, and approval requirements for new libraries should help prevent malicious or unsuitable dependencies from entering the system.</p>
<p>Finally, agents need appropriate permissions. They shouldn&rsquo;t be able to bypass required checks or deploy high-risk changes simply because they can implement them.</p>
<p>These mechanisms don&rsquo;t eliminate risk. They create multiple opportunities to detect problems and limit their consequences.</p>
<h2 data-hextra-search-id="the-engineering-operating-system">The Engineering Operating System<span class="hx:absolute hx:-mt-20" id="the-engineering-operating-system"></span>
    <a href="#the-engineering-operating-system" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I&rsquo;ve already seen the practical value of AI agents in engineering workflows.</p>
<p>Recently, I used agents to triage and resolve five issues in our AV team&rsquo;s escalation backlog. The agents identified problems and fixed the code. We validated the fixes on our own systems before deploying them to the affected customers&rsquo; systems.</p>
<p>That reduced the escalation backlog from five issues to zero.</p>
<p>The experience reinforced a principle I&rsquo;ve followed throughout my leadership career: engineering effectiveness depends on more than individual capability. It depends on the system surrounding the work.</p>
<p>I describe that system as an <a href="https://joelconnett.com/philosophy/engineering-operating-system/">Engineering Operating System</a>.</p>
<p>Engineering leadership establishes the organizational structure, development practices, decision-making processes, tooling, and feedback mechanisms that enable engineers to deliver.</p>
<p>AI extends those responsibilities to agents.</p>
<p>We need to provide the appropriate context, architectural guidance, permissions, and validation. We also need engineers who understand these tools well enough to recognize their limitations and use them effectively.</p>
<p>As agents become more capable, I expect them to take on increasing responsibility for both implementation and architecture.</p>
<p>The engineering practices surrounding them will need to evolve accordingly.</p>
<p>Producing software is becoming easier. Coordinating architectural decisions, communicating intent, and establishing confidence in the resulting systems may become the more significant challenges.</p>
<p><strong>Communication doesn&rsquo;t disappear. It moves. Our engineering practices need to move with it.</strong></p>
]]></content:encoded></item><item><title>Conway's Law Is a Leadership Problem</title><link>https://joelconnett.com/blog/conways-law-leadership/</link><guid isPermaLink="true">https://joelconnett.com/blog/conways-law-leadership/</guid><category>Article</category><pubDate>Thu, 29 Oct 2026 00:00:00 +0000</pubDate><dc:creator>Joel Connett</dc:creator><description>How team structure and communication paths shape software architecture—and what I learned from Control4's pillar model.</description><content:encoded><![CDATA[<p>Software architecture doesn&rsquo;t exist independently of the people building it. How we divide work, define ownership, and communicate across teams influences the software we produce.</p>
<p>Melvin Conway described this in his 1968 paper, <a href="https://melconway.com/Home/pdf/committees.pdf" target="_blank" rel="noopener"><em>How Do Committees Invent?</em></a>:</p>
<blockquote>
  <p>“organizations which design systems &hellip; are constrained to produce designs which are copies of the communication structures of these organizations.”</p>

</blockquote>
<p>That&rsquo;s the heart of <strong>Conway&rsquo;s Law</strong>. Organization design isn&rsquo;t just a management concern. It&rsquo;s also an architectural decision.</p>
<figure class="engineering-os-figure">
  <img class="engineering-os-illustration engineering-os-illustration--light" src="https://joelconnett.com/images/conways-law-light.webp" alt="Conway's Law infographic: the Platform, Mobile, Device, and Cloud teams correspond to the architecture's platform layer, mobile application, device software, and cloud services." loading="lazy" decoding="async">
  
  <figcaption>Conway's Law: team boundaries and communication paths influence system architecture.</figcaption>
</figure>
<h2 data-hextra-search-id="team-boundaries-become-software-boundaries">Team boundaries become software boundaries<span class="hx:absolute hx:-mt-20" id="team-boundaries-become-software-boundaries"></span>
    <a href="#team-boundaries-become-software-boundaries" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Teams naturally optimize for the work they own and the people they talk to most often. Engineers working closely together can make quick decisions, share context, and build tightly integrated software. Across teams, communication requires more deliberate coordination.</p>
<p>Neither tight nor loose coupling is inherently good. A mobile application team may benefit from owning a cohesive app experience. But if mobile and cloud engineers are organized around an individual product feature, shared cloud capabilities—like authentication—can become harder for other products to use.</p>
<p>The question isn&rsquo;t simply whether teams should be organized by platform or product. It&rsquo;s <strong>where we want strong ownership, where we need shared capabilities, and which communication paths the architecture will require</strong>.</p>
<h2 data-hextra-search-id="what-i-saw-at-control4">What I saw at Control4<span class="hx:absolute hx:-mt-20" id="what-i-saw-at-control4"></span>
    <a href="#what-i-saw-at-control4" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Control4 experimented with different organizational structures as our products and teams evolved. One of those experiments was the <strong>pillar model</strong>: teams organized around major domains of the Control4 system, each responsible for work across the software stack.</p>
<p>I was a Staff Software Engineer in the <strong>Listen and Watch</strong> pillar, primarily working on the graphical user interface.</p>
<p>Before that change, our iOS and Android applications were developed by a team we called <strong>Navigator</strong>. The applications had a cohesive architecture that made it relatively straightforward for the team to work across the app.</p>
<p>Under the pillar model, domain-specific code moved into separate modules owned by the individual pillar teams. Building the application meant bringing together the current versions of multiple modules. I recall roughly six or seven, although the exact number isn&rsquo;t important to the lesson.</p>
<p>The architecture gradually began to reflect the organization. Work that had been coordinated within one team was now divided across several teams. We saw duplicated effort and different implementations of similar capabilities.</p>
<p>Those changes didn&rsquo;t happen overnight, but they appeared quickly enough to make the relationship clear.</p>
<p>When we eventually moved away from the pillar model and reestablished a single Navigator team, we also consolidated the pillar modules over time. The code became easier for the application team to work with because its structure once again better matched how the team operated.</p>
<h2 data-hextra-search-id="the-tradeoff-isnt-one-size-fits-all">The tradeoff isn&rsquo;t one-size-fits-all<span class="hx:absolute hx:-mt-20" id="the-tradeoff-isnt-one-size-fits-all"></span>
    <a href="#the-tradeoff-isnt-one-size-fits-all" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The pillar model wasn&rsquo;t inherently a bad idea. It created clear responsibility for product domains and brought different engineering disciplines together around customer outcomes.</p>
<p>But it also introduced costs where we needed consistency across those domains. Those costs showed up in integration work, duplicated solutions, and the experience of developing the applications.</p>
<p>A platform-oriented structure has tradeoffs too. It can encourage shared capabilities and consistent interfaces, but it can also create dependencies and handoffs that slow product teams down.</p>
<p>A leader has to understand those tradeoffs instead of assuming one organization chart is universally better.</p>
<h2 data-hextra-search-id="shape-the-organization-deliberately">Shape the organization deliberately<span class="hx:absolute hx:-mt-20" id="shape-the-organization-deliberately"></span>
    <a href="#shape-the-organization-deliberately" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>When evaluating a team structure, I ask:</p>
<ul>
<li><strong>What should this team own end to end?</strong> Ownership needs clear boundaries.</li>
<li><strong>Which capabilities must be shared?</strong> Those shouldn&rsquo;t accidentally become isolated inside a product team.</li>
<li><strong>Where will teams need to coordinate?</strong> Frequent cross-team communication is a signal worth examining.</li>
<li><strong>What architecture are we trying to enable?</strong> The organization should make that architecture practical to build and maintain.</li>
</ul>
<p>It&rsquo;s not enough to draw clean boxes on an organization chart. We need to understand the communication paths between them and how those paths influence technical decisions.</p>
<h2 data-hextra-search-id="a-later-example-align-teams-with-shared-architecture">A later example: align teams with shared architecture<span class="hx:absolute hx:-mt-20" id="a-later-example-align-teams-with-shared-architecture"></span>
    <a href="#a-later-example-align-teams-with-shared-architecture" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>When I later led mobile engineering, two cross-functional Scrum teams shared one application architecture. Rather than split the architecture to match the team boundaries, I brought the teams together to make domain expertise and technical feedback accessible across the organization. I describe that decision and the broader evolution of our mobile development practices in <a href="https://joelconnett.com/experience/mobile-engineering-transformation/">Transforming Mobile Engineering</a>.</p>
<h2 data-hextra-search-id="what-ive-learned">What I&rsquo;ve learned<span class="hx:absolute hx:-mt-20" id="what-ive-learned"></span>
    <a href="#what-ive-learned" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Changing an organization can change the software, even when nobody sets out to redesign the architecture. The reverse is also true: if we want a different architecture, we may need to change ownership and communication patterns to make it possible.</p>
<p>That&rsquo;s why I think of <strong>shaping the organization</strong> as part of the engineering leader&rsquo;s job. We should build teams around the work and the technical boundaries we want to support, then be willing to evolve both as we learn.</p>
<p>Conway&rsquo;s Law doesn&rsquo;t prescribe a perfect organizational model. It reminds us that <strong>organizational decisions have technical consequences</strong>.</p>
]]></content:encoded></item><item><title>Case Study: Transforming Mobile Engineering: From Organizational Friction to Continuous Delivery</title><link>https://joelconnett.com/experience/mobile-engineering-transformation/</link><guid isPermaLink="true">https://joelconnett.com/experience/mobile-engineering-transformation/</guid><category>Case Study</category><pubDate>Thu, 29 Oct 2026 00:00:00 +0000</pubDate><dc:creator>Joel Connett</dc:creator><description>How aligning teams, changing engineering ownership, and modernizing releases helped Control4 deliver fixes to customers faster.</description><content:encoded><![CDATA[<p>One of the most meaningful outcomes of our mobile engineering transformation at Control4 was reducing the time it took to get bug fixes into customers&rsquo; hands.</p>
<p>Previously, we released our applications at most once per quarter. After the transformation, we could get a customer-reported defect fixed and released to everyone within a month, sometimes sooner for customers participating in our beta program.</p>
<p>That improvement didn&rsquo;t come from simply asking engineers to work faster. Over several years, we changed how the organization was structured, how teams collaborated, who owned quality, and how we developed, released, and supported software.</p>
<p>The changes weren&rsquo;t always popular, and we didn&rsquo;t have every piece of the solution in place when we started.</p>
<figure class="engineering-os-figure mobile-transformation-figure">
  <img class="engineering-os-illustration engineering-os-illustration--light" src="https://joelconnett.com/images/mobile-transformation-light.svg" alt="Four stages of mobile engineering transformation: align teams, own quality, deliver frequently, and operate with production feedback. Outcome: customer fixes broadly released within a month." loading="lazy" decoding="async" width="1100" height="810">
  
  <figcaption>Align the organization, build quality ownership, enable frequent releases, and close the loop with production feedback.</figcaption>
</figure>
<h2 data-hextra-search-id="aligning-the-organization-with-the-architecture">Aligning the Organization with the Architecture<span class="hx:absolute hx:-mt-20" id="aligning-the-organization-with-the-architecture"></span>
    <a href="#aligning-the-organization-with-the-architecture" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The first challenge was organizational.</p>
<p>When I took responsibility for mobile engineering, we had two Scrum teams operating somewhat independently. Each team included a mix of iOS, Android, and QA engineers, but the team boundaries didn&rsquo;t align with our shared application architecture. Decisions made by one team frequently affected the other.</p>
<p><a href="https://joelconnett.com/blog/conways-law-leadership/">Conway&rsquo;s Law</a> tells us that organizational structure influences software architecture. We could change the architecture to support the existing teams or change the organization to better support the architecture.</p>
<p>I chose the latter. Even if we redesigned the architecture, the applications would still need to deliver consistent experiences across platforms, and engineers would still need to collaborate closely.</p>
<h3 data-hextra-search-id="creating-one-cohesive-team">Creating one cohesive team<span class="hx:absolute hx:-mt-20" id="creating-one-cohesive-team"></span>
    <a href="#creating-one-cohesive-team" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>I combined the two Scrum teams into one, bringing approximately sixteen engineers together for planning, standups, retrospectives, and demos. We retained distinct platform expertise and management, but created one shared forum for delivery.</p>
<p>Sixteen people in a standup isn&rsquo;t ideal. We needed to be disciplined about using everyone&rsquo;s time. But everyone could now see what their colleagues were working on. Staff and Principal engineers could share technical feedback with the entire team rather than just half of it.</p>
<p>This was particularly important at Control4 because effective application development required both mobile platform expertise and Control4 domain knowledge. An engineer might understand iOS or Android deeply but lack experience with a particular Control4 subsystem. Someone with that domain expertise might previously have been on the other Scrum team.</p>
<p>Bringing everyone together made it easier to find expertise, collaborate on shared components, resolve technical issues, and maintain consistency across platforms. It reduced the chance of independently building redundant components or solving the same problem differently.</p>
<p><strong>The goal wasn&rsquo;t to create a larger Scrum team. It was to remove an organizational boundary that didn&rsquo;t make sense for the architecture.</strong></p>
<p>Years later, as meeting demands increased and coordination within iOS, Android, and Qt became more important, we adjusted the rhythm again: horizontal standups on Monday, Wednesday, and Friday, and combined standups on Tuesday and Thursday. That replaced some duplicated team and combined standups while preserving cross-platform visibility.</p>
<p>The communication structure evolved as the organization did.</p>
<h2 data-hextra-search-id="making-qa-an-active-part-of-development">Making QA an Active Part of Development<span class="hx:absolute hx:-mt-20" id="making-qa-an-active-part-of-development"></span>
    <a href="#making-qa-an-active-part-of-development" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Around the time of the Scrum team merger—possibly just before it—we changed who presented features during sprint demos.</p>
<p>We asked QA engineers to present the work. If QA was going to demonstrate functionality, they first needed to validate what was being shown.</p>
<p>That didn&rsquo;t require the feature to be complete. Many features took more than a two-week sprint; demos showed progress, not necessarily finished functionality. But the change encouraged QA to participate throughout development instead of waiting until the end.</p>
<p>Our QA engineers became exceptionally good at presenting. They developed consistently polished demos across mobile applications, touch panels, on-screen displays, and remotes. High-quality demos became the norm, and we eventually invited executives to attend.</p>
<p>What started as a way to encourage earlier quality involvement became an effective way to communicate engineering progress.</p>
<h2 data-hextra-search-id="establishing-a-devops-strategy">Establishing a DevOps Strategy<span class="hx:absolute hx:-mt-20" id="establishing-a-devops-strategy"></span>
    <a href="#establishing-a-devops-strategy" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>In June 2019, we released Control4 OS 3.0, including completely rewritten mobile applications. The rewrite gave us an architecture that made feature development faster, and we had practiced test-driven development from the beginning, giving us good automated test coverage.</p>
<p>But writing software faster didn&rsquo;t mean we could deliver it faster.</p>
<p>We released applications at most once per quarter. QA had thousands of regression test cases available but could execute only a portion of them in the available release window. Large releases accumulated more changes than we could comfortably validate, and we had experienced quality misses.</p>
<p>I wrote a Navigator DevOps plan, using an approach similar to <a href="https://blog.kindel.com/2011/06/14/the-5-ps-achieving-focus-in-any-endeavor/" target="_blank" rel="noopener">Tigger (Tig) Kindel&rsquo;s 5 Ps framework</a>, to establish a more modern engineering operating model. It covered faster releases, trunk-based development, feature flags, testing automation, on-call engineers, and ownership of software in production.</p>
<h3 data-hextra-search-id="define-the-outcomes-let-teams-own-the-implementation">Define the outcomes; let teams own the implementation<span class="hx:absolute hx:-mt-20" id="define-the-outcomes-let-teams-own-the-implementation"></span>
    <a href="#define-the-outcomes-let-teams-own-the-implementation" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>I established measurable goals rather than dictating every technical decision.</p>
<p>One was a faster release cadence. I offered an example of two weeks of development followed by two weeks of testing and a release—not a mandated implementation.</p>
<p>I also set a goal of approximately <strong>25 open bugs per team</strong>. We had metrics suggesting a team could review about 25 bugs in an hour. I wanted each backlog small enough that engineers could regularly understand, prioritize, and address outstanding issues. Other goals included incident response and defect resolution times.</p>
<p>Each team took the broader DevOps plan and wrote its own implementation plan.</p>
<p><strong>My job was to establish direction, provide support, and hold teams accountable for progress—not make every technical decision myself.</strong></p>
<div class="mobile-milestones" role="group" aria-label="Key milestones in the mobile engineering transformation">
  <div class="mobile-milestone"><span class="mobile-milestone-date">June 2019</span><strong>OS 3.0 rewrite released</strong><span>New mobile architecture and a foundation of automated tests</span></div>
  <div class="mobile-milestone"><span class="mobile-milestone-date">August 2019</span><strong>Quality ownership changed</strong><span>Development teams became responsible for validation and automation</span></div>
  <div class="mobile-milestone"><span class="mobile-milestone-date">January 2020</span><strong>Biweekly releases began</strong><span>Navigator took responsibility for its own application releases</span></div>
</div>
<h2 data-hextra-search-id="changing-quality-ownership">Changing Quality Ownership<span class="hx:absolute hx:-mt-20" id="changing-quality-ownership"></span>
    <a href="#changing-quality-ownership" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>In late August 2019, my manager made a broader organizational change that eliminated dedicated QA teams. I transitioned the QA engineers in my organization into engineering or management roles.</p>
<p>Manual validation responsibilities moved to the development teams. The engineers weren&rsquo;t particularly enthusiastic about repetitive manual testing.</p>
<p>My response was simple: <strong>If you don&rsquo;t like doing it manually, automate it.</strong></p>
<p>I wasn&rsquo;t trying to make developers into full-time manual testers. I wanted teams to own the quality of the software they built and invest in making validation easier.</p>
<p>Our OS 3.0 applications already had a good automated test foundation, but broader regression and release validation still needed work. Giving engineers ownership made those gaps visible and created a reason to address them.</p>
<p>Quality starts and ends with the engineer. That doesn&rsquo;t diminish specialized QA expertise; it means development teams can&rsquo;t treat validation as someone else&rsquo;s responsibility.</p>
<h2 data-hextra-search-id="moving-to-a-two-week-release-cadence">Moving to a Two-Week Release Cadence<span class="hx:absolute hx:-mt-20" id="moving-to-a-two-week-release-cadence"></span>
    <a href="#moving-to-a-two-week-release-cadence" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I also had to convince people outside engineering.</p>
<p>Program management and release management were particularly worried that faster releases would reduce quality. Their concerns weren&rsquo;t unreasonable—we&rsquo;d already had quality misses.</p>
<p>I saw a different risk. With limited regression testing capacity, accumulating months of changes into each release made validation harder.</p>
<p><strong>Less frequent releases weren&rsquo;t necessarily reducing risk. They were concentrating it into each release.</strong></p>
<h3 data-hextra-search-id="change-release-ownership">Change release ownership<span class="hx:absolute hx:-mt-20" id="change-release-ownership"></span>
    <a href="#change-release-ownership" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Rather than asking the central release management organization to manage Navigator releases every two weeks, I proposed taking responsibility for application releases within my organization. That allowed central release managers to focus on the base operating system.</p>
<p>They were reluctant, but agreed to a trial. We began the two-week Navigator release cadence in <strong>January 2020</strong>.</p>
<p>We hadn&rsquo;t completed every practice in the DevOps plan. Feature flags were just beginning to take hold, and I was advocating for trunk-based development, but it wasn&rsquo;t established yet.</p>
<p>I could have waited until all the ideal practices were in place. But sometimes engineers need to experience the limitations of the current process before they&rsquo;re persuaded to change it.</p>
<p>I think of it as ripping off the bandage and exposing the wound before people are willing to undergo the surgery. The problems were already there. The new cadence made their costs harder to ignore.</p>
<p>The teams scrambled a bit for the first month or two. The transition to trunk-based development happened fairly quickly, though, and made an enormous difference. We could produce a release from the main development branch at almost any point.</p>
<p>Unfinished work could stay hidden behind feature flags, so features didn&rsquo;t have to launch on the same schedule as application releases.</p>
<p>To the best of my recollection, we didn&rsquo;t miss a scheduled release during that first year.</p>
<h3 data-hextra-search-id="make-releases-routine">Make releases routine<span class="hx:absolute hx:-mt-20" id="make-releases-routine"></span>
    <a href="#make-releases-routine" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>We established a patching structure that made it easy to produce additional beta builds when necessary. We also changed our version scheme to combine the Control4 OS version and year into the first number, followed by the week of the year, patch number, and build number. For example, <code>426.44.0.1234</code> represents an OS 4 application build from week 44 of 2026, patch 0, build 1234.</p>
<p>We tracked feature flags on a Scrum board and established telemetry alerts to catch features being exposed prematurely. Feature flags deserve their own article, but they were an important way to separate releasing an application from launching a feature.</p>
<p>The trial eventually became the normal operating model. Navigator retained responsibility for its releases, and central release management no longer needed to oversee them or worry that the cadence would compromise quality.</p>
<p>We still coordinated app and feature launches with the broader organization when they depended on OS capabilities. The OS typically released twice a year, and at most quarterly, while Navigator could keep delivering app updates every two weeks.</p>
<p><strong>We removed unnecessary release dependencies without eliminating coordination that actually mattered.</strong></p>
<h2 data-hextra-search-id="making-engineers-responsible-for-software-in-production">Making Engineers Responsible for Software in Production<span class="hx:absolute hx:-mt-20" id="making-engineers-responsible-for-software-in-production"></span>
    <a href="#making-engineers-responsible-for-software-in-production" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The technical foundation for operational visibility came before the DevOps plan.</p>
<p>We integrated New Relic telemetry into the rewritten OS 3 applications. I personally wrote the Android telemetry API, and the iOS team adopted the same API for consistency across platforms.</p>
<p>We also followed an architectural rule: cross-cutting third-party integrations belonged behind our own API wrappers, so switching providers wouldn&rsquo;t require changing every application component. That&rsquo;s a broader architecture topic, but it helped make telemetry consistent.</p>
<p>The DevOps plan built on that early work. Collecting telemetry was useful; having engineers act on it was better.</p>
<h3 data-hextra-search-id="give-on-call-engineers-time-to-do-the-job">Give on-call engineers time to do the job<span class="hx:absolute hx:-mt-20" id="give-on-call-engineers-time-to-do-the-job"></span>
    <a href="#give-on-call-engineers-time-to-do-the-job" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>We established an on-call rotation in each engineering team. Each sprint, one engineer took the on-call role and <strong>wasn&rsquo;t assigned feature stories that sprint</strong>.</p>
<p>Their capacity was reserved for monitoring app health, triaging incoming bugs, investigating issues, and responding to customers. Responsibilities varied somewhat by team, and each team maintained an on-call checklist for the engineer to review.</p>
<p>Engineers also participated in customer outreach through forums, staying connected to how people experienced the software.</p>
<p>The rotation created clear operational ownership without expecting engineers to absorb it on top of a full sprint of feature work.</p>
<p><strong>If operational ownership was important enough to expect from engineers, it was important enough to allocate time for it.</strong></p>
<h2 data-hextra-search-id="the-results">The Results<span class="hx:absolute hx:-mt-20" id="the-results"></span>
    <a href="#the-results" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><div class="mobile-outcomes" role="group" aria-label="Outcomes from the mobile engineering transformation">
  <div class="mobile-outcome"><strong>2 weeks</strong><span>Regular application release cadence</span></div>
  <div class="mobile-outcome"><strong>~25</strong><span>Open bug target achieved per team, with fluctuations</span></div>
  <div class="mobile-outcome"><strong>Within a month</strong><span>Customer fixes broadly released, sometimes sooner via beta</span></div>
</div>
<p>The improvements reinforced one another, but they weren&rsquo;t a single overnight transformation.</p>
<p>The teams eventually reached our goal of approximately <strong>25 open bugs per team</strong>. The backlog ebbed and flowed. iOS maintained the target more consistently; Android had a broader portfolio, including touch panels and originally the on-screen display applications, alongside mobile. With roughly the same number of engineers, I expected Android&rsquo;s backlog to run somewhat higher.</p>
<p>The number wasn&rsquo;t the point. Keeping the backlog manageable meant teams could regularly review, prioritize, and address defects.</p>
<p>The result I value most was getting fixes to customers sooner.</p>
<p>Before the transformation, a customer might have to wait for the next quarterly release. Afterward, we could get a reported bug fixed and released to everyone within a month, with some beta customers receiving fixes sooner.</p>
<p>I remember the VP over QA being particularly happy about that outcome. It&rsquo;s notable because quality concerns had been a major reason for resisting the faster cadence in the first place.</p>
<p>Faster releases didn&rsquo;t eliminate defects. They made us much more responsive when defects occurred.</p>
<h2 data-hextra-search-id="what-i-learned">What I Learned<span class="hx:absolute hx:-mt-20" id="what-i-learned"></span>
    <a href="#what-i-learned" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The transformation wasn&rsquo;t about adopting a particular methodology. It was about changing the environment around engineering work.</p>
<p>When Scrum team boundaries conflicted with our architecture, we aligned the organization with the software.</p>
<p>When delivery couldn&rsquo;t keep pace with development, we changed release ownership and engineering practices.</p>
<p>When teams became responsible for manual validation, we encouraged them to automate the repetitive work.</p>
<p>When engineers became responsible for production software, we reserved capacity for that responsibility.</p>
<p>And throughout the process, I defined outcomes while leaving implementation decisions with the teams closest to the work.</p>
<p>Some changes were uncomfortable. At times we committed to a new way of working before every supporting practice was established. But that only works if engineers have the authority, time, and support to improve the system.</p>
<p>I didn&rsquo;t want a process that depended on everyone continually working harder. I wanted the right practices to make sustainable delivery possible.</p>
<p><strong>Engineering leaders shouldn&rsquo;t simply demand better outcomes. They should build the environment that makes those outcomes possible.</strong></p>
<p>That&rsquo;s a central idea behind my <a href="https://joelconnett.com/philosophy/engineering-operating-system/">Engineering Operating System</a>.</p>
<p><a href="https://joelconnett.com/experience/">Back to Experience &amp; Impact</a>.</p>
]]></content:encoded></item><item><title>Case Study: Building a Self-Sufficient Engineering Team: The Control4 Halo Turnaround</title><link>https://joelconnett.com/experience/halo-turnaround/</link><guid isPermaLink="true">https://joelconnett.com/experience/halo-turnaround/</guid><category>Case Study</category><pubDate>Thu, 29 Oct 2026 00:00:00 +0000</pubDate><dc:creator>Joel Connett</dc:creator><description>How organizational changes, technical mentoring, and incremental architecture improvements helped the Halo team ship and grow independent.</description><content:encoded><![CDATA[<p>In January 2023, Control4 released the original Halo remote. Six months later, in July 2023, Halo Touch shipped.</p>
<p>Those launches followed a challenging period for the Remote Control GUI team. By fall 2022, the project needed additional technical and organizational support, and I became more directly involved.</p>
<p>Our immediate objective was to stabilize development and deliver the first product. The longer-term goal was more important: <strong>build a team capable of developing and maintaining Halo without depending on engineers temporarily assigned from another organization.</strong></p>
<figure class="engineering-os-figure halo-turnaround-figure">
  <img class="engineering-os-illustration engineering-os-illustration--light" src="https://joelconnett.com/images/halo-turnaround-light.svg" alt="Light infographic showing the Halo team's progression from shared OSD foundations through fall 2022 stabilization, January and July 2023 Halo launches, and long-term technical independence." width="1100" height="730" loading="lazy" decoding="async">
  
  <figcaption>Two delivery milestones—and a longer-term investment in a self-sufficient engineering team.</figcaption>
</figure>
<h2 data-hextra-search-id="starting-with-a-technical-foundation">Starting with a Technical Foundation<span class="hx:absolute hx:-mt-20" id="starting-with-a-technical-foundation"></span>
    <a href="#starting-with-a-technical-foundation" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>My organization had developed a Qt-based on-screen display application, which we called OSD. When the Remote Control GUI project began, there was an opportunity to reuse much of its architecture and shared functionality.</p>
<p>Our OSD team was heavily engaged in launching the CORE controller line and didn&rsquo;t have capacity to own another major GUI project. I asked one of my Principal engineers to extend the OSD application to support different themes and views, conceptually similar to Android product flavors.</p>
<p>That gave the new Remote Control team a starting point while leaving it responsible for implementation and delivery. For the first several months, that was largely the extent of my involvement.</p>
<h2 data-hextra-search-id="bringing-experience-into-the-team">Bringing Experience into the Team<span class="hx:absolute hx:-mt-20" id="bringing-experience-into-the-team"></span>
    <a href="#bringing-experience-into-the-team" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>By fall 2022, the Remote Control project was having difficulty making progress. At the same time, our CORE controller work had largely wrapped up, giving my team capacity to help.</p>
<p>My manager brought me up to speed and asked how I thought we should address the situation. The team included a first-time engineering manager and several early-career engineers, with limited experience in the C++ and Qt technologies central to the project. It had also diverged considerably from the reusable OSD architecture, expanding the implementation work it needed to own.</p>
<p>I reassigned two experienced engineers from OSD into the existing Remote Control Scrum team. A Staff engineer became the Scrum master, helping establish a more effective development rhythm. A Principal engineer brought hands-on Qt and OSD expertise, helped resolve technical issues, and mentored the engineers.</p>
<p>The existing manager retained responsibility for the team. We weren&rsquo;t building a separate group to take over the project.</p>
<p><strong>The objective was to transfer experience into the team, not establish a permanent dependency on the people helping it.</strong></p>
<h2 data-hextra-search-id="establishing-ui-platform">Establishing UI-Platform<span class="hx:absolute hx:-mt-20" id="establishing-ui-platform"></span>
    <a href="#establishing-ui-platform" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>We also had an organizational opportunity I&rsquo;d discussed with my manager well before the Halo project needed help: a dedicated UI-Platform team.</p>
<p>Qt, iOS, and Android applications relied on shared capabilities in a common Core library. Those capabilities needed clearer ownership.</p>
<p>When we reviewed the challenges in Belgrade, my manager and I recognized that creating UI-Platform could address both a longstanding architectural need and concerns some Remote Control engineers had raised about their existing team arrangement.</p>
<p>We moved two engineers to the new UI-Platform team to focus on shared capabilities rather than the remote-specific GUI.</p>
<p>My manager and I evaluated experienced engineering managers in our Belgrade office and chose the one whose background best matched the new team&rsquo;s responsibilities. He brought substantial C++ experience and was already successfully leading another team. UI-Platform expanded his scope while giving shared functionality experienced leadership.</p>
<p>This was another practical lesson from <a href="https://joelconnett.com/blog/conways-law-leadership/">Conway&rsquo;s Law</a>: organizational ownership and software architecture need to support one another.</p>
<h2 data-hextra-search-id="addressing-management-challenges">Addressing Management Challenges<span class="hx:absolute hx:-mt-20" id="addressing-management-challenges"></span>
    <a href="#addressing-management-challenges" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I met weekly with the Remote Control engineering manager to discuss the challenges and agree on improvements. Unfortunately, those changes weren&rsquo;t consistently reflected in how the team operated. The Principal engineer embedded with the team independently observed similar difficulties.</p>
<p>Technical mentoring and improved Scrum practices were helping, but they weren&rsquo;t sufficient on their own. We also needed to revisit the management arrangement.</p>
<p>The manager wasn&rsquo;t my direct report; he reported through another manager to my boss. My responsibility was to provide observations and recommendations, while the final decision belonged to my boss.</p>
<p>Eventually, the experienced manager leading UI-Platform also assumed leadership of Remote Control. This helped create a more consistent environment for collaboration and technical decision-making.</p>
<p>The lesson wasn&rsquo;t that more senior engineers could solve every problem. <strong>Effective technical support and effective engineering management needed to work together.</strong></p>
<h2 data-hextra-search-id="stabilizing-delivery-and-shipping-halo">Stabilizing Delivery and Shipping Halo<span class="hx:absolute hx:-mt-20" id="stabilizing-delivery-and-shipping-halo"></span>
    <a href="#stabilizing-delivery-and-shipping-halo" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>By the time I became directly involved, the original Halo launch had already been reduced significantly in scope.</p>
<p>Our first priority was to stabilize development, finish the remaining functionality, and ship the remote—not attempt an architectural redesign during a difficult release.</p>
<p>The Remote Control application had diverged substantially from OSD. I believed moving toward the shared architecture was the right long-term direction, but doing that immediately would have added complexity and risk.</p>
<p>The original <strong>Halo shipped in January 2023</strong>, a few months after our more direct involvement began. The initial feature set was limited, and substantial work remained. The team continued delivering and <strong>Halo Touch shipped in July 2023</strong>.</p>
<aside class="halo-delivery-milestones" aria-label="Halo delivery milestones">
  <div><strong>January 2023</strong><span>Original Halo remote released</span></div>
  <div><strong>July 2023</strong><span>Halo Touch released</span></div>
</aside>
<p>These milestones showed that the team could move beyond the initial recovery and continue delivering product functionality. They didn&rsquo;t mean every architectural issue had been resolved—or that the team had already become fully independent.</p>
<h2 data-hextra-search-id="evolving-toward-a-shared-architecture">Evolving Toward a Shared Architecture<span class="hx:absolute hx:-mt-20" id="evolving-toward-a-shared-architecture"></span>
    <a href="#evolving-toward-a-shared-architecture" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>After the initial launch, we could begin addressing the longer-term architectural work.</p>
<p>The OSD architecture simplified GUI development substantially, but it represented a different way of thinking for the Remote Control engineers. Adoption required learning, not just copying code.</p>
<p>Because much of the original OSD code had been replaced or left behind, the migration was larger than originally anticipated. We approached it one feature at a time: <strong>new features used the shared OSD architecture</strong>, while existing features remained on the Remote Control implementation until there was a reason and opportunity to migrate them.</p>
<p>The Principal engineer helped guide that transition. The work continued over an extended period and, to the best of my knowledge, beyond my direct involvement.</p>
<p>A shared architecture is useful only if the team can understand and evolve it. We needed to build that capability along with the code.</p>
<h2 data-hextra-search-id="building-a-more-effective-team">Building a More Effective Team<span class="hx:absolute hx:-mt-20" id="building-a-more-effective-team"></span>
    <a href="#building-a-more-effective-team" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The combined changes gradually improved how the team operated.</p>
<p>We saw less conflict, more productive collaboration, and greater receptiveness to technical guidance. Recommendations were incorporated more consistently, changes happened faster, and the team&rsquo;s development velocity improved. There were fewer escalations over technical disagreements.</p>
<p>Those improvements weren&rsquo;t attributable to one intervention. Experienced engineers strengthened delivery and mentoring; UI-Platform clarified shared ownership; and the management transition improved the team&rsquo;s leadership environment.</p>
<p>Most importantly, we could gradually reduce the temporary engineering support.</p>
<p>The Staff engineer returned to other responsibilities. The Principal engineer transitioned from substantial hands-on implementation into a largely advisory role. <strong>She continued meeting with the team weekly</strong>, but the team increasingly made its own technical decisions and completed the development work.</p>
<p>That mattered more to me than keeping an expert permanently embedded.</p>
<h2 data-hextra-search-id="what-i-learned">What I Learned<span class="hx:absolute hx:-mt-20" id="what-i-learned"></span>
    <a href="#what-i-learned" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p><strong>Stabilize before optimizing.</strong> When a project is struggling, not every important issue is equally urgent. We prioritized delivery first and introduced architectural improvements incrementally.</p>
<p><strong>Address technical and organizational problems together.</strong> Technical mentoring helped, but the team also needed clear ownership and effective management. Creating UI-Platform served an architectural need while improving organizational alignment.</p>
<p><strong>Respect decision-making boundaries.</strong> I supported and coached the manager, brought observations to my boss, and worked within the management structure instead of treating the personnel decision as mine alone.</p>
<p><strong>Build capability, not dependency.</strong> Borrowed senior engineers can accelerate delivery, but the lasting outcome is a team that no longer needs them to do its work.</p>
<p>The original Halo launched in January 2023, followed by Halo Touch in July. Both were important milestones. But the more meaningful accomplishment was helping the Remote Control organization grow more capable and less dependent on outside support.</p>
<p><strong>A successful turnaround isn&rsquo;t just getting a project back on track. It&rsquo;s building a team that can stay on track without you.</strong></p>
<p>That&rsquo;s a central part of my <a href="https://joelconnett.com/philosophy/engineering-operating-system/">Engineering Operating System</a>.</p>
<p><a href="https://joelconnett.com/experience/engineering-organizations/">Explore more engineering leadership experience</a>.</p>
]]></content:encoded></item><item><title>Case Study: Enabling Edge AI Across the Product System</title><link>https://joelconnett.com/experience/edge-ai-systems/</link><guid isPermaLink="true">https://joelconnett.com/experience/edge-ai-systems/</guid><category>Case Study</category><pubDate>Mon, 26 Oct 2026 00:00:00 +0000</pubDate><dc:creator>Joel Connett</dc:creator><description>How connected hardware, edge inference, mobile experiences, and cloud processing came together to make AI capabilities practical.</description><content:encoded><![CDATA[<p>AI features are only useful when the surrounding product system makes them practical. One initiative I worked on at Control4 connected existing hardware, an edge AI accelerator, model-training data, cloud video processing, and a customer-facing mobile experience.</p>
<p>My role focused on <strong>systems engineering and cross-team leadership</strong>, not building the machine-learning models themselves.</p>
<h2 data-hextra-search-id="adapting-an-existing-controller">Adapting an existing controller<span class="hx:absolute hx:-mt-20" id="adapting-an-existing-controller"></span>
    <a href="#adapting-an-existing-controller" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I partnered with hardware engineers to explore how an existing <strong>CORE1 controller</strong> could be modified to run a <strong>Hailo edge AI accelerator</strong>. Reusing an established controller platform meant working within real hardware and software constraints rather than designing an entirely new device around inference.</p>
<h2 data-hextra-search-id="enabling-collection-of-training-data">Enabling collection of training data<span class="hx:absolute hx:-mt-20" id="enabling-collection-of-training-data"></span>
    <a href="#enabling-collection-of-training-data" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I developed a driver that <strong>employees and beta dealers could install</strong> to contribute images from their cameras for model training.</p>
<p>The training effort focused on recognizing <strong>people, cars, and animals</strong> across times of day and environmental conditions. The driver was an enabling piece of the system: it connected real-world cameras to the data needed to develop and evaluate the models.</p>
<h2 data-hextra-search-id="bringing-detections-into-the-mobile-experience">Bringing detections into the mobile experience<span class="hx:absolute hx:-mt-20" id="bringing-detections-into-the-mobile-experience"></span>
    <a href="#bringing-detections-into-the-mobile-experience" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I had the mobile teams build a <strong>History</strong> section to help customers see what had been happening around their homes. We integrated edge AI detections into that workflow so that a detection could become meaningful information in the product experience, not just an event generated by a device.</p>
<h2 data-hextra-search-id="making-video-processing-more-economical">Making video processing more economical<span class="hx:absolute hx:-mt-20" id="making-video-processing-more-economical"></span>
    <a href="#making-video-processing-more-economical" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>As the cost of converting video clips increased, I worked with the <strong>Cloud team</strong> to replace the Amazon-based video conversion approach with a custom <strong>FFmpeg processing pipeline</strong>.</p>
<p>That change <strong>dramatically reduced conversion costs</strong>. I don&rsquo;t have a verified percentage to publish, but the experience reinforced the importance of evaluating ongoing operating costs as part of system design.</p>
<h2 data-hextra-search-id="what-i-take-from-this-work">What I take from this work<span class="hx:absolute hx:-mt-20" id="what-i-take-from-this-work"></span>
    <a href="#what-i-take-from-this-work" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>This was a systems problem that crossed several disciplines:</p>
<ul>
<li><strong>Hardware and embedded software:</strong> enabling inference on an existing controller platform</li>
<li><strong>Model development support:</strong> collecting representative images from real deployments</li>
<li><strong>Mobile product development:</strong> bringing detections into an understandable History workflow</li>
<li><strong>Cloud infrastructure:</strong> finding a more economical way to process video clips</li>
</ul>
<p>The important leadership work was recognizing these dependencies, helping teams connect their pieces, and making sure the technology could fit into a useful and sustainable product experience.</p>
<p><a href="https://joelconnett.com/experience/">Back to Experience &amp; Impact</a>.</p>
]]></content:encoded></item></channel></rss>