<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Roman Emreis</title>
    <subtitle>Distributed systems, developer platforms, AI infrastructure.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://romanemreis.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://romanemreis.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-05-16T00:00:00+00:00</updated>
    <id>https://romanemreis.com/atom.xml</id>
    <entry xml:lang="en">
        <title>Why this site exists</title>
        <published>2026-05-16T00:00:00+00:00</published>
        <updated>2026-05-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/notes/welcome/"/>
        <id>https://romanemreis.com/notes/welcome/</id>
        
        <content type="html" xml:base="https://romanemreis.com/notes/welcome/">&lt;p&gt;A short note on the purpose of this site.&lt;&#x2F;p&gt;
&lt;p&gt;GitHub holds the artifacts. LinkedIn carries the reach. X is where short-form thinking goes. Each works on its own, but none of them are mine in the structural sense — they shape what I can say and how it’s organized.&lt;&#x2F;p&gt;
&lt;p&gt;This site is the opposite. It’s the control room: a single narrative, structured deeply, that turns scattered output into a coherent body of work. Projects, engineering notes, guides, tricks — they all live here. Everything else is a channel.&lt;&#x2F;p&gt;
&lt;p&gt;The bar I’m holding myself to: anything published here should still be worth reading a year from now.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Organizations as Runtime Systems</title>
        <published>2026-05-13T00:00:00+00:00</published>
        <updated>2026-05-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/notes/organizations-as-runtime-systems/"/>
        <id>https://romanemreis.com/notes/organizations-as-runtime-systems/</id>
        
        <content type="html" xml:base="https://romanemreis.com/notes/organizations-as-runtime-systems/">&lt;h2 id=&quot;from-forward-deployed-engineers-to-autonomous-operations&quot;&gt;From Forward Deployed Engineers to Autonomous Operations&lt;&#x2F;h2&gt;
&lt;p&gt;For years, enterprise software promised abstraction.&lt;&#x2F;p&gt;
&lt;p&gt;Platforms, APIs, integrations, and dashboards were supposed to standardize operations and reduce organizational complexity. Yet large enterprises continued to depend on a different mechanism to make software actually work in production environments: embedded human coordination.&lt;&#x2F;p&gt;
&lt;p&gt;This is the environment in which the Forward Deployed Engineer emerged.&lt;&#x2F;p&gt;
&lt;p&gt;Companies like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.palantir.com&#x2F;&quot;&gt;Palantir&lt;&#x2F;a&gt; understood something early that much of the software industry underestimated: enterprise problems are rarely isolated technical problems. More often, they are operational coordination problems that happen to manifest through software.&lt;&#x2F;p&gt;
&lt;p&gt;The difficult part was never simply exposing APIs or shipping configurable platforms. The difficult part was translating ambiguous, constantly evolving organizational workflows into executable systems that could survive contact with reality.&lt;&#x2F;p&gt;
&lt;p&gt;FDEs became the bridge between software platforms and operational execution. More importantly, they became a coordination layer embedded directly into the organization itself.&lt;&#x2F;p&gt;
&lt;p&gt;Agentic systems are now beginning to inherit that role.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-original-role-of-the-fde&quot;&gt;The Original Role of the FDE&lt;&#x2F;h2&gt;
&lt;p&gt;The industry often describes Forward Deployed Engineers as customer-facing engineers, deployment specialists, or integration consultants. That framing misses what made the role strategically important.&lt;&#x2F;p&gt;
&lt;p&gt;FDEs existed because organizations behave less like static hierarchies and more like distributed systems operating under continuous partial inconsistency. Priorities shift, ownership changes, information arrives asynchronously, and operational workflows evolve faster than software abstractions can adapt.&lt;&#x2F;p&gt;
&lt;p&gt;Traditional enterprise platforms struggled because they assumed the organization itself was stable. In reality, most enterprise environments are defined by coordination overhead.&lt;&#x2F;p&gt;
&lt;p&gt;The real responsibility of the FDE was therefore not integration, but orchestration.&lt;&#x2F;p&gt;
&lt;p&gt;An effective FDE continuously translated fragmented workflows, conflicting operational requirements, and evolving business constraints into executable processes that software systems could reliably support. They coordinated across teams, stabilized execution under changing operational conditions, interpreted policy in operational context, and closed the gap between platform abstractions and organizational reality.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, FDEs became a runtime layer for the organization itself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-enterprise-software-needed-human-orchestration&quot;&gt;Why Enterprise Software Needed Human Orchestration&lt;&#x2F;h2&gt;
&lt;p&gt;Classical enterprise software optimized for standardization and repeatability. Organizations, however, rarely operate in such controlled conditions.&lt;&#x2F;p&gt;
&lt;p&gt;Large enterprises resemble distributed systems much more closely than traditional software diagrams suggest. Communication is asynchronous. State is inconsistent. Failures are partial. Retries are common. Decision-making is delayed. Multiple actors operate with incomplete context simultaneously.&lt;&#x2F;p&gt;
&lt;p&gt;Human operators compensated for this mismatch.&lt;&#x2F;p&gt;
&lt;p&gt;Forward Deployed Engineers became operational coordinators embedded directly inside execution flows. They routed escalations, reconciled conflicting state between teams, adapted workflows under changing operational conditions, and continuously stabilized execution where platform abstractions alone were insufficient.&lt;&#x2F;p&gt;
&lt;p&gt;Humans resolve ambiguity exceptionally well because they generalize dynamically across incomplete information and shifting operational context. But human coordination scales poorly for the same reason tightly coupled distributed systems do: every additional workflow, dependency, and organizational boundary increases coordination overhead non-linearly.&lt;&#x2F;p&gt;
&lt;p&gt;Over time, enterprises accumulated growing layers of embedded operational engineering simply to maintain execution consistency across increasingly complex systems.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;agentic-systems-change-the-equation&quot;&gt;Agentic Systems Change the Equation&lt;&#x2F;h2&gt;
&lt;p&gt;Large language models introduced a fundamentally new capability into software systems: dynamic operational reasoning.&lt;&#x2F;p&gt;
&lt;p&gt;For the first time, software systems could interpret intent, navigate incomplete information, invoke tools, adapt execution paths dynamically, and coordinate actions across previously disconnected systems.&lt;&#x2F;p&gt;
&lt;p&gt;This is why agentic systems represent more than another interface layer on top of existing software.&lt;&#x2F;p&gt;
&lt;p&gt;The important shift is not conversational AI. The important shift is that execution itself is becoming programmable.&lt;&#x2F;p&gt;
&lt;p&gt;Protocols such as MCP, structured tool invocation systems, workflow runtimes, and AI-native orchestration platforms are transforming models from passive reasoning systems into operational actors capable of participating directly inside organizational workflows.&lt;&#x2F;p&gt;
&lt;p&gt;The architectural importance of protocols in this transition is difficult to overstate.&lt;&#x2F;p&gt;
&lt;p&gt;A model capable of reasoning is interesting. A model capable of participating safely inside operational workflows is transformative.&lt;&#x2F;p&gt;
&lt;p&gt;That distinction depends on protocols.&lt;&#x2F;p&gt;
&lt;p&gt;Systems like MCP matter not because they make tool invocation possible, but because they standardize execution boundaries between autonomous actors and external systems. Once tool access becomes structured, state becomes explicit, permissions become enforceable, and workflow transitions become observable, autonomous execution stops being a collection of isolated demos and starts becoming composable infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;In that sense, protocol layers for agentic systems are beginning to play a role similar to what HTTP played for distributed services: they define a common operational surface across which independently evolving systems can coordinate execution predictably.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-reliability-problem&quot;&gt;The Reliability Problem&lt;&#x2F;h2&gt;
&lt;p&gt;Most current AI systems still inherit assumptions from conversational interfaces. They rely heavily on hidden context, implicit memory, opaque reasoning, and non-repeatable execution patterns.&lt;&#x2F;p&gt;
&lt;p&gt;Those characteristics are acceptable for consumer assistants. They are dangerous for operational systems.&lt;&#x2F;p&gt;
&lt;p&gt;The moment AI systems move from suggestion into execution, reliability becomes the central engineering problem.&lt;&#x2F;p&gt;
&lt;p&gt;Operational environments require explicit workflow state, bounded permissions, resumable execution, auditability, deterministic transitions, and observable behavior under failure conditions. Organizations cannot depend on systems that behave unpredictably across identical operational scenarios.&lt;&#x2F;p&gt;
&lt;p&gt;This is where much of the current agent hype collides with reality.&lt;&#x2F;p&gt;
&lt;p&gt;Autonomous execution introduces distributed systems problems almost immediately:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;partial completion&lt;&#x2F;li&gt;
&lt;li&gt;inconsistent state&lt;&#x2F;li&gt;
&lt;li&gt;retry storms&lt;&#x2F;li&gt;
&lt;li&gt;unsafe tool invocation&lt;&#x2F;li&gt;
&lt;li&gt;conflicting workflow transitions&lt;&#x2F;li&gt;
&lt;li&gt;deadlocks between approval systems and autonomous actors&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The architecture required to solve these problems looks significantly less like chatbot design and much more like distributed systems engineering.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;operational-runtime-engineering&quot;&gt;Operational Runtime Engineering&lt;&#x2F;h2&gt;
&lt;p&gt;This transition is creating a new engineering discipline.&lt;&#x2F;p&gt;
&lt;p&gt;Not prompt engineering. Not classical integration engineering. Not simply DevOps or platform engineering.&lt;&#x2F;p&gt;
&lt;p&gt;The emerging problem space is operational runtime engineering: the design of systems capable of safely coordinating autonomous execution inside real organizations.&lt;&#x2F;p&gt;
&lt;p&gt;Where SRE focuses primarily on infrastructure reliability and platform engineering focuses on developer abstractions, operational runtime engineering focuses on execution semantics for organizational systems themselves.&lt;&#x2F;p&gt;
&lt;p&gt;The core challenge is no longer simply deploying software. It is designing operational runtimes that remain governable under conditions of dynamic autonomous execution.&lt;&#x2F;p&gt;
&lt;p&gt;That requires explicit orchestration models, durable workflow state, bounded execution permissions, role separation between autonomous actors, human approval systems, policy enforcement layers, execution observability, and deterministic recovery paths under failure conditions.&lt;&#x2F;p&gt;
&lt;p&gt;The artifacts also begin to change. Instead of isolated APIs and service boundaries, engineers increasingly design execution graphs, workflow state machines, review pipelines, policy runtimes, orchestration protocols, and human-agent coordination models.&lt;&#x2F;p&gt;
&lt;p&gt;A deployment workflow, for example, increasingly resembles a distributed execution pipeline rather than a sequence of human-operated steps:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Executor agent generates a migration plan&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;→ orchestration runtime validates policy constraints&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;→ bounded tools execute infrastructure changes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;→ reviewer agent verifies resulting state&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;→ human operator approves production rollout&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;→ workflow runtime advances execution state&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Operational runtimes coordinate autonomous actors through explicit state, bounded execution, and governable workflow transitions.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is fundamentally different from traditional automation.&lt;&#x2F;p&gt;
&lt;p&gt;Classical automation executes predefined procedures. Operational runtimes coordinate autonomous actors operating under bounded but dynamic execution conditions.&lt;&#x2F;p&gt;
&lt;p&gt;That distinction becomes increasingly important as workflows grow longer-running, more stateful, and more organizationally coupled.&lt;&#x2F;p&gt;
&lt;p&gt;Most current agentic systems remain immature in this regard. They are optimized for generating locally impressive behavior rather than supporting reliable operational execution over extended workflows.&lt;&#x2F;p&gt;
&lt;p&gt;Operational systems, however, are not judged by how intelligently they behave under ideal conditions. They are judged by how predictably they recover under imperfect ones.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;organizations-as-runtime-systems&quot;&gt;Organizations as Runtime Systems&lt;&#x2F;h2&gt;
&lt;p&gt;The deeper shift is that organizations themselves are becoming programmable execution environments.&lt;&#x2F;p&gt;
&lt;p&gt;Historically, software primarily modeled information while humans coordinated operations manually around it. Increasingly, software systems are beginning to model operational processes directly: approvals, escalations, investigations, migrations, reviews, deployments, compliance flows, coordination paths, and organizational decision-making itself.&lt;&#x2F;p&gt;
&lt;p&gt;Tasks become executable workflows. Agents become operational workers. Humans increasingly act as reviewers, governors, and escalation authorities inside larger orchestration systems.&lt;&#x2F;p&gt;
&lt;p&gt;The architecture starts looking less like traditional enterprise software and more like a distributed runtime environment operating across humans, agents, workflows, and policy systems simultaneously.&lt;&#x2F;p&gt;
&lt;p&gt;This changes the role of enterprise engineering fundamentally.&lt;&#x2F;p&gt;
&lt;p&gt;The challenge is no longer merely building platforms. The challenge is designing operational runtimes capable of coordinating autonomous execution safely under real organizational complexity.&lt;&#x2F;p&gt;
&lt;p&gt;The systems that succeed will not be the most autonomous.&lt;&#x2F;p&gt;
&lt;p&gt;They will be the most governable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Forward Deployed Engineering was never fundamentally about integrations.&lt;&#x2F;p&gt;
&lt;p&gt;It was about embedding execution into operational reality.&lt;&#x2F;p&gt;
&lt;p&gt;Agentic systems are now extending that idea further: from embedded engineers to embedded autonomy.&lt;&#x2F;p&gt;
&lt;p&gt;But autonomy without structure does not create leverage. It creates operational instability.&lt;&#x2F;p&gt;
&lt;p&gt;The next generation of enterprise AI will therefore not be defined primarily by conversational interfaces or isolated model capability. It will be defined by orchestration, governance, recoverability, and execution reliability under real operational conditions.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, the future of enterprise AI will increasingly resemble distributed systems engineering applied to organizations themselves.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Originally published on GitHub — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RomanEmreis&#x2F;engineering-notes&#x2F;blob&#x2F;main&#x2F;organizations-as-runtime-systems.md&quot;&gt;engineering-notes&#x2F;organizations-as-runtime-systems.md&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Architect Playbook</title>
        <published>2026-03-24T00:00:00+00:00</published>
        <updated>2026-03-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/notes/architect-playbook/"/>
        <id>https://romanemreis.com/notes/architect-playbook/</id>
        
        <content type="html" xml:base="https://romanemreis.com/notes/architect-playbook/">&lt;blockquote&gt;
&lt;p&gt;A practical operating system for architects to manage ownership, flow, and system clarity.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;0-role-anchor&quot;&gt;0. Role Anchor&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;I design systems, not execute tasks.&lt;&#x2F;strong&gt;
&lt;strong&gt;I create clarity, ownership, and flow.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Decision question:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Does this improve the system or just solve it once?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;1-core-principles&quot;&gt;1. Core Principles&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-1-ownership-effort&quot;&gt;1.1 Ownership &amp;gt; Effort&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;No owner → no progress&lt;&#x2F;li&gt;
&lt;li&gt;Always establish ownership&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;1-2-process-heroics&quot;&gt;1.2 Process &amp;gt; Heroics&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Avoid one-off help&lt;&#x2F;li&gt;
&lt;li&gt;No “quick fixes” that bypass system&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;1-3-enable-do&quot;&gt;1.3 Enable &amp;gt; Do&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Guide ✔&lt;&#x2F;li&gt;
&lt;li&gt;Clarify ✔&lt;&#x2F;li&gt;
&lt;li&gt;Do it yourself ❌&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;1-4-clarity-speed&quot;&gt;1.4 Clarity &amp;gt; Speed&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Especially under pressure&lt;&#x2F;li&gt;
&lt;li&gt;Especially from leadership&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;1-5-system-local-optimization&quot;&gt;1.5 System &amp;gt; Local Optimization&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Solve root causes&lt;&#x2F;li&gt;
&lt;li&gt;Avoid patching symptoms&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;2-decision-patterns&quot;&gt;2. Decision Patterns&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;status-request&quot;&gt;Status request&lt;&#x2F;h3&gt;
&lt;p&gt;→ Redirect to owner&lt;&#x2F;p&gt;
&lt;h3 id=&quot;incident-failure&quot;&gt;Incident &#x2F; failure&lt;&#x2F;h3&gt;
&lt;p&gt;→ Engage only if you are the owner&lt;&#x2F;p&gt;
&lt;h3 id=&quot;create-ticket-ask-devops&quot;&gt;“Create ticket &#x2F; ask DevOps”&lt;&#x2F;h3&gt;
&lt;p&gt;→ Route to process&lt;&#x2F;p&gt;
&lt;h3 id=&quot;blocked-work-review-dependency&quot;&gt;Blocked work (review, dependency)&lt;&#x2F;h3&gt;
&lt;p&gt;→ Highlight blocker + assign owner&lt;&#x2F;p&gt;
&lt;h3 id=&quot;vp-stakeholder-pressure&quot;&gt;VP &#x2F; stakeholder pressure&lt;&#x2F;h3&gt;
&lt;p&gt;→ Acknowledge urgency → explain risk → propose sustainable path&lt;&#x2F;p&gt;
&lt;h3 id=&quot;they-don-t-know-how&quot;&gt;“They don’t know how”&lt;&#x2F;h3&gt;
&lt;p&gt;→ Enable, don’t execute&lt;&#x2F;p&gt;
&lt;h3 id=&quot;no-show-ignored-meetings&quot;&gt;No-show &#x2F; ignored meetings&lt;&#x2F;h3&gt;
&lt;p&gt;→ Add impact → question priority&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-communication-patterns&quot;&gt;3. Communication Patterns&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;ownership-redirect&quot;&gt;Ownership redirect&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is owned by &lt;code&gt;&amp;lt;Team X&amp;gt;&lt;&#x2F;code&gt;, they can provide the latest update.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;boundary-setting&quot;&gt;Boundary setting&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;I’m not involved in &lt;code&gt;&amp;lt;area&amp;gt;&lt;&#x2F;code&gt;, but happy to support on architecture.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;process-enforcement&quot;&gt;Process enforcement&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This should go through the standard process via &lt;code&gt;&amp;lt;link&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;risk-framing-for-leadership&quot;&gt;Risk framing (for leadership)&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;If we approach it this way, it may create &lt;code&gt;&amp;lt;risk&amp;gt;&lt;&#x2F;code&gt;.
The better approach is &lt;code&gt;&amp;lt;X&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;enablement&quot;&gt;Enablement&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;I can help clarify the process so the team can handle it directly.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;blocker-escalation&quot;&gt;Blocker escalation&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is currently blocking &lt;code&gt;&amp;lt;impact&amp;gt;&lt;&#x2F;code&gt;. We need an owner to move it forward.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;priority-alignment&quot;&gt;Priority alignment&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;If this is not a priority, we can adjust timelines accordingly.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;4-anti-patterns&quot;&gt;4. Anti-Patterns&lt;&#x2F;h2&gt;
&lt;p&gt;If you see yourself doing this — stop:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Creating tickets for others&lt;&#x2F;li&gt;
&lt;li&gt;Chasing teams for updates&lt;&#x2F;li&gt;
&lt;li&gt;Tracking delivery status&lt;&#x2F;li&gt;
&lt;li&gt;Debugging runtime issues&lt;&#x2F;li&gt;
&lt;li&gt;Owning meetings without an owner&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;This is delivery management, not architecture.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;5-operating-model&quot;&gt;5. Operating Model&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;ownership&quot;&gt;Ownership&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Every system has a DRI (Directly Responsible Individual)&lt;&#x2F;li&gt;
&lt;li&gt;No owner = problem&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;flow&quot;&gt;Flow&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Where is the blocker?&lt;&#x2F;li&gt;
&lt;li&gt;Who removes it?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;architecture&quot;&gt;Architecture&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Boundaries (DDD)&lt;&#x2F;li&gt;
&lt;li&gt;Contracts between systems&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;governance&quot;&gt;Governance&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Rules&lt;&#x2F;li&gt;
&lt;li&gt;Processes&lt;&#x2F;li&gt;
&lt;li&gt;ADRs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;interaction-model&quot;&gt;Interaction Model&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Teams communicate directly&lt;&#x2F;li&gt;
&lt;li&gt;No routing through architect&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;6-mental-models&quot;&gt;6. Mental Models&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;If I do it once — I own it forever&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Short-term speed vs long-term system&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;No owner = no progress&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;People optimize for least resistance&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;If you are the easiest path — you become the system.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;7-escalation-ladder&quot;&gt;7. Escalation Ladder&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Redirect&lt;&#x2F;li&gt;
&lt;li&gt;Add impact&lt;&#x2F;li&gt;
&lt;li&gt;Question priority&lt;&#x2F;li&gt;
&lt;li&gt;Escalate to owner &#x2F; leadership&lt;&#x2F;li&gt;
&lt;li&gt;Formalize process&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;8-scaling-this&quot;&gt;8. Scaling This&lt;&#x2F;h2&gt;
&lt;p&gt;To reduce chaos long-term:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Introduce DRI &#x2F; RACI explicitly&lt;&#x2F;li&gt;
&lt;li&gt;Document processes (DevOps, APIM, support)&lt;&#x2F;li&gt;
&lt;li&gt;Remove yourself as dependency&lt;&#x2F;li&gt;
&lt;li&gt;Enforce: &lt;strong&gt;“no owner = no meeting”&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;9-signals-you-re-doing-it-right&quot;&gt;9. Signals You’re Doing It Right&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;You are pulled less into operational noise&lt;&#x2F;li&gt;
&lt;li&gt;Teams use processes instead of you&lt;&#x2F;li&gt;
&lt;li&gt;Conversations shift from status → decisions&lt;&#x2F;li&gt;
&lt;li&gt;You have time for architecture and strategy&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;final-formula&quot;&gt;Final Formula&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Architect = Clarity + Ownership + Boundaries&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;final-insight&quot;&gt;Final Insight&lt;&#x2F;h2&gt;
&lt;p&gt;You are not the person who solves problems.&lt;&#x2F;p&gt;
&lt;p&gt;You are the person who:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;builds a system where problems are solved without you&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Originally published on GitHub — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RomanEmreis&#x2F;engineering-notes&#x2F;blob&#x2F;main&#x2F;architect-playbook.md&quot;&gt;engineering-notes&#x2F;architect-playbook.md&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Memory Is Not Context in AI Systems</title>
        <published>2026-03-11T00:00:00+00:00</published>
        <updated>2026-03-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/notes/memory-is-not-context-in-ai/"/>
        <id>https://romanemreis.com/notes/memory-is-not-context-in-ai/</id>
        
        <content type="html" xml:base="https://romanemreis.com/notes/memory-is-not-context-in-ai/">&lt;p&gt;Large language models rely on a &lt;strong&gt;context window&lt;&#x2F;strong&gt; to process information.
Because the context can include prior conversation, code snippets, and instructions, it is often treated as a form of system memory.&lt;&#x2F;p&gt;
&lt;p&gt;Architecturally, however, &lt;strong&gt;context and memory are fundamentally different concepts&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Understanding this distinction becomes critical when building AI systems that go beyond simple interactions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;context-vs-memory&quot;&gt;Context vs Memory&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Context&lt;&#x2F;strong&gt; is temporary input passed to the model during a request.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Memory&lt;&#x2F;strong&gt; is persistent state that exists across requests, sessions, and system runs.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Property&lt;&#x2F;th&gt;&lt;th&gt;Context&lt;&#x2F;th&gt;&lt;th&gt;Memory&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Lifetime&lt;&#x2F;td&gt;&lt;td&gt;Single request&lt;&#x2F;td&gt;&lt;td&gt;Persistent&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Structure&lt;&#x2F;td&gt;&lt;td&gt;Unstructured text&lt;&#x2F;td&gt;&lt;td&gt;Structured data&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Access&lt;&#x2F;td&gt;&lt;td&gt;Sequential tokens&lt;&#x2F;td&gt;&lt;td&gt;Queryable&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Purpose&lt;&#x2F;td&gt;&lt;td&gt;Provide immediate input&lt;&#x2F;td&gt;&lt;td&gt;Store knowledge&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;A context window exists only for the duration of a request.
Memory persists across time and can be referenced by future operations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-architectural-misconception&quot;&gt;The Architectural Misconception&lt;&#x2F;h2&gt;
&lt;p&gt;In many AI workflows, the system attempts to emulate memory by continually expanding the prompt:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;chat history&lt;&#x2F;li&gt;
&lt;li&gt;code snippets&lt;&#x2F;li&gt;
&lt;li&gt;system instructions&lt;&#x2F;li&gt;
&lt;li&gt;past decisions&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This approach works surprisingly well at small scales.&lt;&#x2F;p&gt;
&lt;p&gt;However, as system complexity grows, several problems appear.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;failure-modes-of-context-as-memory&quot;&gt;Failure Modes of Context-as-Memory&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-context-growth&quot;&gt;1. Context Growth&lt;&#x2F;h3&gt;
&lt;p&gt;Even with large context windows, the total capacity is finite.&lt;&#x2F;p&gt;
&lt;p&gt;Engineering systems cannot rely on prompts that grow indefinitely.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-signal-dilution&quot;&gt;2. Signal Dilution&lt;&#x2F;h3&gt;
&lt;p&gt;When everything is included in the prompt, important information loses priority.&lt;&#x2F;p&gt;
&lt;p&gt;Critical details become statistically less visible among tokens.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-lack-of-structure&quot;&gt;3. Lack of Structure&lt;&#x2F;h3&gt;
&lt;p&gt;Context is fundamentally &lt;strong&gt;a stream of text&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Memory, on the other hand, requires:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;references&lt;&#x2F;li&gt;
&lt;li&gt;relationships&lt;&#x2F;li&gt;
&lt;li&gt;retrieval mechanisms&lt;&#x2F;li&gt;
&lt;li&gt;query capabilities&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Without these, the system cannot efficiently locate relevant knowledge.&lt;&#x2F;p&gt;
&lt;p&gt;At that point the system is not maintaining memory — it is simply constructing increasingly long prompts.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-role-of-indexing&quot;&gt;The Role of Indexing&lt;&#x2F;h2&gt;
&lt;p&gt;The solution is not expanding the context window.&lt;&#x2F;p&gt;
&lt;p&gt;The solution is &lt;strong&gt;introducing indexed memory&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In traditional software systems, data is not retrieved by scanning entire datasets on every request.
Instead, systems rely on indexes to locate relevant information efficiently.&lt;&#x2F;p&gt;
&lt;p&gt;AI systems benefit from the same principle.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of embedding all information into prompts, the system retrieves only what is relevant to the current request.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;indexed-knowledge&quot;&gt;Indexed Knowledge&lt;&#x2F;h2&gt;
&lt;p&gt;Examples of indexed memory structures in AI-assisted development systems include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Indexed codebases&lt;&#x2F;strong&gt;
Retrieve relevant modules instead of entire repositories.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Indexed architectural decisions&lt;&#x2F;strong&gt;
Allow models to reference prior system design choices.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Indexed artifacts&lt;&#x2F;strong&gt;
Enable reuse of generated outputs instead of regeneration.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Indexed conversations&lt;&#x2F;strong&gt;
Preserve meaningful discussions across sessions.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With indexing in place, the workflow changes fundamentally.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of reading everything, the system performs targeted retrieval.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;context-as-a-projection-of-memory&quot;&gt;Context as a Projection of Memory&lt;&#x2F;h2&gt;
&lt;p&gt;In a well-structured system:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Persistent knowledge is stored in memory.&lt;&#x2F;li&gt;
&lt;li&gt;Retrieval mechanisms query that knowledge.&lt;&#x2F;li&gt;
&lt;li&gt;Relevant fragments are projected into the model context.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Context becomes a &lt;strong&gt;temporary view of memory&lt;&#x2F;strong&gt;, not the memory itself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;architectural-model&quot;&gt;Architectural Model&lt;&#x2F;h2&gt;
&lt;p&gt;Example flow:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         Context Window                          System Memory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  +--------------------------+          +------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Prompt                   |          | Persistent Knowledge         |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  |--------------------------|          |------------------------------|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | instructions             |          | code index                   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | chat history             |          | architectural decisions      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | code snippets            |          | documentation                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | logs                     |          | artifacts                    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | ...                      |          | ...                          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  +-------------+------------+          +--------------+---------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                |                                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                v                                      v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           +----------+                        +---------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |  MODEL   |                        |   RETRIEVAL   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           +----------+                        +-------+-------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                       v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                  +---------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                  | CONTEXT |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                  +---------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;implications-for-ai-system-design&quot;&gt;Implications for AI System Design&lt;&#x2F;h2&gt;
&lt;p&gt;Once systems introduce indexed memory, the design focus shifts.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of asking:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;How large is the context window?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Architects must ask:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;How effectively can the system retrieve relevant knowledge?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This reframes the problem from &lt;strong&gt;prompt engineering&lt;&#x2F;strong&gt; to &lt;strong&gt;system architecture&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Context windows are useful mechanisms for providing temporary input to language models.&lt;&#x2F;p&gt;
&lt;p&gt;They are not a substitute for persistent knowledge systems.&lt;&#x2F;p&gt;
&lt;p&gt;As AI becomes part of real engineering workflows, systems will require:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;persistent memory&lt;&#x2F;li&gt;
&lt;li&gt;structured knowledge&lt;&#x2F;li&gt;
&lt;li&gt;indexing&lt;&#x2F;li&gt;
&lt;li&gt;retrieval mechanisms&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In other words, &lt;strong&gt;knowledge infrastructure&lt;&#x2F;strong&gt;, not just longer prompts.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Originally published on GitHub — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RomanEmreis&#x2F;engineering-notes&#x2F;blob&#x2F;main&#x2F;memory-is-not-context-in-ai.md&quot;&gt;engineering-notes&#x2F;memory-is-not-context-in-ai.md&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Fuzz Testing in Modern Systems</title>
        <published>2026-03-05T00:00:00+00:00</published>
        <updated>2026-03-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/notes/fuzz-testing/"/>
        <id>https://romanemreis.com/notes/fuzz-testing/</id>
        
        <content type="html" xml:base="https://romanemreis.com/notes/fuzz-testing/">&lt;h2 id=&quot;context&quot;&gt;Context&lt;&#x2F;h2&gt;
&lt;p&gt;Modern software systems operate in increasingly unpredictable environments.
They process untrusted inputs, integrate with external systems, and expose APIs that may receive malformed, adversarial, or unexpected data.&lt;&#x2F;p&gt;
&lt;p&gt;Traditional testing approaches — unit tests, integration tests, and even property-based testing — rely on &lt;strong&gt;explicitly defined test cases&lt;&#x2F;strong&gt;. While effective, they often fail to explore the vast input space that real systems encounter in production.&lt;&#x2F;p&gt;
&lt;p&gt;This is where &lt;strong&gt;fuzz testing&lt;&#x2F;strong&gt; becomes a powerful tool.&lt;&#x2F;p&gt;
&lt;p&gt;Fuzz testing (or &lt;em&gt;fuzzing&lt;&#x2F;em&gt;) is a technique where a program is continuously executed with &lt;strong&gt;automatically generated, semi-random inputs&lt;&#x2F;strong&gt; in order to discover crashes, panics, memory safety violations, and logic errors.&lt;&#x2F;p&gt;
&lt;p&gt;Originally popular in security research, fuzzing is now widely used in modern software engineering, particularly in systems programming.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-fuzz-testing-actually-tests&quot;&gt;What Fuzz Testing Actually Tests&lt;&#x2F;h2&gt;
&lt;p&gt;Fuzzing focuses on discovering &lt;strong&gt;unexpected behavior under invalid or extreme inputs&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Typical issues discovered via fuzzing include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Panics and crashes&lt;&#x2F;li&gt;
&lt;li&gt;Memory safety violations&lt;&#x2F;li&gt;
&lt;li&gt;Infinite loops&lt;&#x2F;li&gt;
&lt;li&gt;Unexpected error states&lt;&#x2F;li&gt;
&lt;li&gt;Parser bugs&lt;&#x2F;li&gt;
&lt;li&gt;Incorrect assumptions about input structure&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Fuzzing is particularly effective for components such as:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Parsers&lt;&#x2F;li&gt;
&lt;li&gt;Protocol implementations&lt;&#x2F;li&gt;
&lt;li&gt;Serialization&#x2F;deserialization logic&lt;&#x2F;li&gt;
&lt;li&gt;Binary formats&lt;&#x2F;li&gt;
&lt;li&gt;Compilers and interpreters&lt;&#x2F;li&gt;
&lt;li&gt;Networking layers&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Many critical vulnerabilities in widely used software (OpenSSL, browsers, kernels) have been discovered through fuzzing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-modern-fuzzers-work&quot;&gt;How Modern Fuzzers Work&lt;&#x2F;h2&gt;
&lt;p&gt;Modern fuzzers are not purely random.&lt;&#x2F;p&gt;
&lt;p&gt;Most production-grade fuzzers use &lt;strong&gt;coverage-guided fuzzing&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The idea is simple:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The program is instrumented to track code coverage.&lt;&#x2F;li&gt;
&lt;li&gt;The fuzzer generates inputs.&lt;&#x2F;li&gt;
&lt;li&gt;Inputs that explore new execution paths are kept.&lt;&#x2F;li&gt;
&lt;li&gt;The fuzzer mutates those inputs to discover more paths.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Over time, the fuzzer builds a &lt;strong&gt;corpus of interesting inputs&lt;&#x2F;strong&gt; that maximizes code coverage.&lt;&#x2F;p&gt;
&lt;p&gt;Popular fuzzing engines include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;libFuzzer&lt;&#x2F;li&gt;
&lt;li&gt;AFL&#x2F;AFL++&lt;&#x2F;li&gt;
&lt;li&gt;honggfuzz&lt;&#x2F;li&gt;
&lt;li&gt;cargo-fuzz (Rust wrapper around libFuzzer)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Coverage-guided fuzzing allows millions of test cases to be executed automatically.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fuzz-testing-in-rust&quot;&gt;Fuzz Testing in Rust&lt;&#x2F;h2&gt;
&lt;p&gt;Rust is already memory safe by design, but fuzzing is still extremely valuable.&lt;&#x2F;p&gt;
&lt;p&gt;It helps detect:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Panics caused by invalid assumptions&lt;&#x2F;li&gt;
&lt;li&gt;Logical inconsistencies&lt;&#x2F;li&gt;
&lt;li&gt;Incorrect parsing logic&lt;&#x2F;li&gt;
&lt;li&gt;Unexpected interactions between components&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The most common approach in Rust is using &lt;strong&gt;cargo-fuzz&lt;&#x2F;strong&gt;, which integrates with &lt;code&gt;libFuzzer&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cargo-fuzz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fuzz&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fuzz&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fuzz_target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A typical fuzz target might look like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;no_main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; libfuzzer_sys&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;fuzz_target&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;fuzz_target!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; my_parser&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The fuzzer then continuously mutates &lt;code&gt;data&lt;&#x2F;code&gt; to explore different execution paths.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-role-of-the-corpus&quot;&gt;The Role of the Corpus&lt;&#x2F;h2&gt;
&lt;p&gt;Fuzzers maintain a &lt;strong&gt;corpus&lt;&#x2F;strong&gt;, a collection of inputs that produce unique execution paths.&lt;&#x2F;p&gt;
&lt;p&gt;The corpus serves two important roles:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;It improves the effectiveness of the fuzzer.&lt;&#x2F;li&gt;
&lt;li&gt;It becomes a growing library of edge cases discovered during testing.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;A good practice is to seed the corpus with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Valid examples&lt;&#x2F;li&gt;
&lt;li&gt;Known edge cases&lt;&#x2F;li&gt;
&lt;li&gt;Minimal inputs&lt;&#x2F;li&gt;
&lt;li&gt;Inputs derived from production logs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Over time, the corpus evolves into a powerful regression dataset.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;integrating-fuzzing-into-ci&quot;&gt;Integrating Fuzzing into CI&lt;&#x2F;h2&gt;
&lt;p&gt;Fuzzing is computationally expensive and typically runs longer than standard test suites.&lt;&#x2F;p&gt;
&lt;p&gt;A practical strategy is:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Pull Requests&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Build fuzz targets&lt;&#x2F;li&gt;
&lt;li&gt;Ensure they compile&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Nightly CI&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Run fuzzing for a fixed time window (e.g., 10–30 minutes)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Security&#x2F;Reliability pipelines&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Run fuzzing continuously&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;When a crash is discovered, fuzzers automatically minimize the input and save it to the corpus for reproduction.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-fuzzing-delivers-the-most-value&quot;&gt;Where Fuzzing Delivers the Most Value&lt;&#x2F;h2&gt;
&lt;p&gt;Fuzz testing is most effective for:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Parsing logic&lt;&#x2F;li&gt;
&lt;li&gt;Protocol implementations&lt;&#x2F;li&gt;
&lt;li&gt;Low-level infrastructure&lt;&#x2F;li&gt;
&lt;li&gt;Serialization frameworks&lt;&#x2F;li&gt;
&lt;li&gt;Compilers and DSL interpreters&lt;&#x2F;li&gt;
&lt;li&gt;API gateways and routing layers&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For example, in a web framework, fuzzing can target:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP parsers&lt;&#x2F;li&gt;
&lt;li&gt;Routing logic&lt;&#x2F;li&gt;
&lt;li&gt;header parsing&lt;&#x2F;li&gt;
&lt;li&gt;query parsing&lt;&#x2F;li&gt;
&lt;li&gt;middleware pipelines&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These are areas where malformed inputs are common in real-world traffic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fuzzing-vs-property-based-testing&quot;&gt;Fuzzing vs Property-Based Testing&lt;&#x2F;h2&gt;
&lt;p&gt;These two techniques are often confused but serve different roles.&lt;&#x2F;p&gt;
&lt;p&gt;Property-based testing verifies &lt;strong&gt;logical properties of a system&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Example:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;For any valid input, serialization followed by deserialization should return the same value.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Fuzzing, on the other hand, is designed to discover &lt;strong&gt;unexpected failures&lt;&#x2F;strong&gt; caused by malformed inputs.&lt;&#x2F;p&gt;
&lt;p&gt;The two approaches complement each other and should often be used together.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;practical-guidelines&quot;&gt;Practical Guidelines&lt;&#x2F;h2&gt;
&lt;p&gt;Some practical lessons from applying fuzz testing in production systems:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;1. Fuzz small components first&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fuzzing is most effective when targeting isolated functions such as parsers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2. Avoid complex setup&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fuzz targets should be lightweight and deterministic.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;3. Fail loudly&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Panics and crashes should not be hidden — they are signals of potential bugs.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;4. Persist the corpus&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Corpus inputs are valuable regression tests.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;5. Run fuzzing continuously&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The longer fuzzing runs, the more paths it explores.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;Fuzz testing shifts part of the testing burden from human-designed test cases to automated exploration of input space.&lt;&#x2F;p&gt;
&lt;p&gt;As systems grow more complex and exposed to unpredictable environments, fuzzing becomes less of a security tool and more of a &lt;strong&gt;core engineering practice&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For systems that interact with external inputs — APIs, protocols, file formats — fuzzing often discovers bugs that traditional tests never reach.&lt;&#x2F;p&gt;
&lt;p&gt;In modern engineering teams, fuzz testing is increasingly becoming a &lt;strong&gt;default layer of reliability testing&lt;&#x2F;strong&gt;, particularly for infrastructure and systems-level software.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Originally published on GitHub — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RomanEmreis&#x2F;engineering-notes&#x2F;blob&#x2F;main&#x2F;fuzz-testing.md&quot;&gt;engineering-notes&#x2F;fuzz-testing.md&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>std Channels vs Tokio Channels in Rust</title>
        <published>2026-03-05T00:00:00+00:00</published>
        <updated>2026-03-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/notes/rust-channels/"/>
        <id>https://romanemreis.com/notes/rust-channels/</id>
        
        <content type="html" xml:base="https://romanemreis.com/notes/rust-channels/">&lt;h2 id=&quot;context&quot;&gt;Context&lt;&#x2F;h2&gt;
&lt;p&gt;Rust offers multiple ways to communicate between concurrent tasks:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;std::sync::mpsc&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; (and third-party variants like &lt;code&gt;crossbeam-channel&lt;&#x2F;code&gt;) for OS-thread-based concurrency.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;tokio::sync&lt;&#x2F;code&gt; channels&lt;&#x2F;strong&gt; for async tasks scheduled by Tokio.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;They look similar at the API level — send values, receive values — but they live in very different concurrency models. Mixing them casually can lead to performance problems, deadlocks, or accidental blocking inside an async runtime.&lt;&#x2F;p&gt;
&lt;p&gt;This note explains the differences, trade-offs, and how to choose.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mental-model&quot;&gt;Mental Model&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;std-channels-thread-world&quot;&gt;std channels (thread world)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;std::sync::mpsc&lt;&#x2F;code&gt; is designed for &lt;strong&gt;blocking&lt;&#x2F;strong&gt; communication between &lt;strong&gt;OS threads&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;recv()&lt;&#x2F;code&gt; blocks the current thread.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;send()&lt;&#x2F;code&gt; may block in bounded variants (std is unbounded, so mostly “doesn’t block”, but can still be expensive under contention).&lt;&#x2F;li&gt;
&lt;li&gt;Works with &lt;code&gt;std::thread&lt;&#x2F;code&gt;, CPU-bound workers, and synchronous code.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;tokio-channels-async-world&quot;&gt;tokio channels (async world)&lt;&#x2F;h3&gt;
&lt;p&gt;Tokio channels are designed for &lt;strong&gt;non-blocking&lt;&#x2F;strong&gt; coordination between &lt;strong&gt;async tasks&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;recv().await&lt;&#x2F;code&gt; yields the task to the runtime instead of blocking a thread.&lt;&#x2F;li&gt;
&lt;li&gt;Backpressure is explicit via bounded channel capacity.&lt;&#x2F;li&gt;
&lt;li&gt;Designed to work with cancellation, task scheduling, and async shutdown patterns.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-big-rule&quot;&gt;The Big Rule&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Never block a Tokio worker thread.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you call blocking &lt;code&gt;std&lt;&#x2F;code&gt; primitives (including &lt;code&gt;std::sync::mpsc::Receiver::recv&lt;&#x2F;code&gt;) directly inside an async task, you risk:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;starving the runtime (other tasks stop progressing),&lt;&#x2F;li&gt;
&lt;li&gt;latency spikes,&lt;&#x2F;li&gt;
&lt;li&gt;deadlocks in worst cases.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you must use blocking calls inside async code, move them into:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tokio::task::spawn_blocking(...)&lt;&#x2F;code&gt; (for CPU&#x2F;blocking IO), or&lt;&#x2F;li&gt;
&lt;li&gt;a dedicated thread.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;channel-types-overview&quot;&gt;Channel Types Overview&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;std-sync-mpsc&quot;&gt;&lt;code&gt;std::sync::mpsc&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multi-producer, single-consumer&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Unbounded&lt;&#x2F;strong&gt; channel in stdlib.&lt;&#x2F;li&gt;
&lt;li&gt;Receiver is not cloneable.&lt;&#x2F;li&gt;
&lt;li&gt;Blocking receive (&lt;code&gt;recv&lt;&#x2F;code&gt;, &lt;code&gt;recv_timeout&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Simple and stable, but limited and not async-friendly.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;tokio-sync-mpsc&quot;&gt;&lt;code&gt;tokio::sync::mpsc&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multi-producer, single-consumer&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Bounded channel with capacity.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Sender&lt;&#x2F;code&gt; is cloneable.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Receiver::recv().await&lt;&#x2F;code&gt; is async and cancellation-aware.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;tokio-sync-broadcast&quot;&gt;&lt;code&gt;tokio::sync::broadcast&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multi-producer, multi-consumer&lt;&#x2F;strong&gt; (each receiver gets every message).&lt;&#x2F;li&gt;
&lt;li&gt;Bounded ring-buffer semantics.&lt;&#x2F;li&gt;
&lt;li&gt;Receivers can lag and get &lt;code&gt;Lagged&lt;&#x2F;code&gt; errors (important to handle explicitly).&lt;&#x2F;li&gt;
&lt;li&gt;Great for events, notifications, “pub-sub”.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;tokio-sync-watch&quot;&gt;&lt;code&gt;tokio::sync::watch&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;“Last value wins”.&lt;&#x2F;li&gt;
&lt;li&gt;Receivers always see the latest value, not every event.&lt;&#x2F;li&gt;
&lt;li&gt;Great for config&#x2F;state propagation and shutdown flags.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;tokio-sync-oneshot&quot;&gt;&lt;code&gt;tokio::sync::oneshot&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Single send, single receive.&lt;&#x2F;li&gt;
&lt;li&gt;Great for request&#x2F;response, completion signals.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;backpressure-and-memory-behavior&quot;&gt;Backpressure and Memory Behavior&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;std-mpsc-unbounded&quot;&gt;std mpsc (unbounded)&lt;&#x2F;h3&gt;
&lt;p&gt;Because it’s unbounded, the risk is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;producers can outpace consumers,&lt;&#x2F;li&gt;
&lt;li&gt;memory usage grows without a natural limit,&lt;&#x2F;li&gt;
&lt;li&gt;latency grows because the queue grows.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is often fine for small workloads, but it becomes dangerous for bursty or untrusted input.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tokio-mpsc-bounded&quot;&gt;Tokio mpsc (bounded)&lt;&#x2F;h3&gt;
&lt;p&gt;Tokio mpsc is typically bounded and will apply backpressure:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;When the buffer is full, &lt;code&gt;send().await&lt;&#x2F;code&gt; waits until there is capacity.&lt;&#x2F;li&gt;
&lt;li&gt;This helps keep memory stable and forces the system to self-regulate.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you need “fire and forget”, Tokio also provides &lt;code&gt;try_send()&lt;&#x2F;code&gt; patterns, but you must decide what to do on overflow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;blocking-vs-async-waiting-why-it-matters&quot;&gt;Blocking vs Async Waiting: Why It Matters&lt;&#x2F;h2&gt;
&lt;p&gt;In a Tokio runtime, the runtime uses a limited number of worker threads to drive many tasks.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Blocking in a task blocks the whole worker thread.&lt;&#x2F;li&gt;
&lt;li&gt;Async waiting yields execution to other tasks.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;std channels are correct&lt;&#x2F;strong&gt; when your concurrency is “thread-per-worker”.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;tokio channels are correct&lt;&#x2F;strong&gt; when your concurrency is “many async tasks on few threads”.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;when-std-channels-are-still-a-great-choice&quot;&gt;When std Channels Are Still a Great Choice&lt;&#x2F;h2&gt;
&lt;p&gt;Use std channels (or &lt;code&gt;crossbeam-channel&lt;&#x2F;code&gt;) if:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You are building a &lt;strong&gt;synchronous&lt;&#x2F;strong&gt; library.&lt;&#x2F;li&gt;
&lt;li&gt;You are using &lt;strong&gt;std threads&lt;&#x2F;strong&gt; for CPU-bound parallelism.&lt;&#x2F;li&gt;
&lt;li&gt;You want “classic pipeline” style concurrency without async.&lt;&#x2F;li&gt;
&lt;li&gt;You are integrating with a non-async ecosystem.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In high-performance synchronous Rust, &lt;code&gt;crossbeam-channel&lt;&#x2F;code&gt; is often preferred over &lt;code&gt;std::sync::mpsc&lt;&#x2F;code&gt; due to better performance and features (bounded + select).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;when-tokio-channels-are-the-right-tool&quot;&gt;When Tokio Channels Are the Right Tool&lt;&#x2F;h2&gt;
&lt;p&gt;Use Tokio channels when:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Communication happens between Tokio tasks.&lt;&#x2F;li&gt;
&lt;li&gt;You need &lt;code&gt;.await&lt;&#x2F;code&gt;-based receiving.&lt;&#x2F;li&gt;
&lt;li&gt;You want bounded queues + backpressure.&lt;&#x2F;li&gt;
&lt;li&gt;You care about async cancellation, graceful shutdown.&lt;&#x2F;li&gt;
&lt;li&gt;You want structured patterns like request&#x2F;response, broadcast, watch.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If your code is already async, Tokio channels keep you in the same model.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bridging-between-std-and-tokio-worlds&quot;&gt;Bridging Between std and Tokio Worlds&lt;&#x2F;h2&gt;
&lt;p&gt;Sometimes you must integrate sync and async components.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pattern-a-dedicated-thread-tokio-channel&quot;&gt;Pattern A: Dedicated thread → Tokio channel&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Sync component runs in a dedicated thread.&lt;&#x2F;li&gt;
&lt;li&gt;It sends messages into &lt;code&gt;tokio::mpsc::Sender&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is common for:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;reading from blocking sources,&lt;&#x2F;li&gt;
&lt;li&gt;stdin&#x2F;stdout bridges,&lt;&#x2F;li&gt;
&lt;li&gt;legacy libraries.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;pattern-b-tokio-task-std-channel-rare&quot;&gt;Pattern B: Tokio task → std channel (rare)&lt;&#x2F;h3&gt;
&lt;p&gt;Usually avoid. If you must do it, don’t call blocking &lt;code&gt;recv()&lt;&#x2F;code&gt; in async context.
Instead:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;use &lt;code&gt;spawn_blocking&lt;&#x2F;code&gt; or a thread to receive, then forward into Tokio.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;pattern-c-use-tokio-sync-mpsc-everywhere-spawn-blocking-at-edges&quot;&gt;Pattern C: Use &lt;code&gt;tokio::sync::mpsc&lt;&#x2F;code&gt; everywhere + &lt;code&gt;spawn_blocking&lt;&#x2F;code&gt; at edges&lt;&#x2F;h3&gt;
&lt;p&gt;This is often the cleanest approach in async applications:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;async core uses Tokio channels,&lt;&#x2F;li&gt;
&lt;li&gt;blocking edges are isolated.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;shutdown-semantics&quot;&gt;Shutdown Semantics&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;std-channels&quot;&gt;std channels&lt;&#x2F;h3&gt;
&lt;p&gt;Shutdown is “implicit”:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;if all senders drop, receiver eventually gets &lt;code&gt;Err(Disconnected)&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;tokio-channels&quot;&gt;Tokio channels&lt;&#x2F;h3&gt;
&lt;p&gt;Similar principle, but more structured:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;recv().await&lt;&#x2F;code&gt; returns &lt;code&gt;None&lt;&#x2F;code&gt; when all senders are dropped.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;broadcast&lt;&#x2F;code&gt; has explicit lag handling.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;watch&lt;&#x2F;code&gt; can signal change and also detect sender drop.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Engineering tip:&lt;&#x2F;strong&gt; Use explicit shutdown signals (&lt;code&gt;watch&lt;&#x2F;code&gt; or &lt;code&gt;broadcast&lt;&#x2F;code&gt;) rather than relying solely on “drop closes channel” when you need predictable shutdown ordering.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;performance-notes-practical&quot;&gt;Performance Notes (Practical)&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Tokio channels integrate with the runtime scheduler and are tuned for async workloads.&lt;&#x2F;li&gt;
&lt;li&gt;std channels are simpler but can become bottlenecks under contention.&lt;&#x2F;li&gt;
&lt;li&gt;For high-throughput sync pipelines, consider &lt;code&gt;crossbeam-channel&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;For high-throughput async pipelines, keep channels bounded and prefer batching when possible.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Avoid designing systems where:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a single receiver becomes a “hot spot” bottleneck,&lt;&#x2F;li&gt;
&lt;li&gt;messages are extremely small and extremely frequent (consider batching or different primitives).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;quick-decision-table&quot;&gt;Quick Decision Table&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Need&lt;&#x2F;th&gt;&lt;th&gt;Best Tool&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Pure sync + threads&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;std::sync::mpsc&lt;&#x2F;code&gt; or &lt;code&gt;crossbeam-channel&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Async tasks + &lt;code&gt;.await&lt;&#x2F;code&gt; receive&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;tokio::sync::mpsc&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;1-to-many event stream&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;tokio::sync::broadcast&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Share latest state&#x2F;config&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;tokio::sync::watch&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Single response signal&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;tokio::sync::oneshot&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Bounded queue + backpressure&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;tokio::sync::mpsc&lt;&#x2F;code&gt; (bounded)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;final-takeaway&quot;&gt;Final Takeaway&lt;&#x2F;h2&gt;
&lt;p&gt;The difference isn’t “which channel is better” — it’s which concurrency model you are in:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Threads&lt;&#x2F;strong&gt; → blocking primitives (std&#x2F;crossbeam)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Async runtime&lt;&#x2F;strong&gt; → async primitives (Tokio)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The fastest way to introduce subtle production issues in async Rust is to accidentally use blocking channels in the hot path. Keep blocking at the edges, and use Tokio-native channels for the async core.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Originally published on GitHub — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RomanEmreis&#x2F;engineering-notes&#x2F;blob&#x2F;main&#x2F;rust-channels.md&quot;&gt;engineering-notes&#x2F;rust-channels.md&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>ferrus</title>
        <published>2026-03-01T00:00:00+00:00</published>
        <updated>2026-03-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/projects/ferrus/"/>
        <id>https://romanemreis.com/projects/ferrus/</id>
        
        <summary type="html">&lt;p&gt;ferrus is a deterministic orchestration system for real software execution.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of treating agents as autonomous chat participants, ferrus models them as workers in a controlled lifecycle — with explicit state, enforced transitions, and restartable execution.&lt;&#x2F;p&gt;
&lt;p&gt;Projects are registered locally and maintain isolated runtime state, task execution, and recovery metadata through a dedicated orchestration database.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>On the Evolution of Programming Languages in the Age of AI</title>
        <published>2026-02-27T00:00:00+00:00</published>
        <updated>2026-02-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/notes/evolution-of-prog-lang/"/>
        <id>https://romanemreis.com/notes/evolution-of-prog-lang/</id>
        
        <content type="html" xml:base="https://romanemreis.com/notes/evolution-of-prog-lang/">&lt;h2 id=&quot;context&quot;&gt;Context&lt;&#x2F;h2&gt;
&lt;p&gt;While building my own AI pipeline (model orchestration, structured outputs, constraint enforcement, tool chaining), I started questioning a deeper assumption about software engineering.&lt;&#x2F;p&gt;
&lt;p&gt;Programming languages were never designed for machines.
They were designed for humans.&lt;&#x2F;p&gt;
&lt;p&gt;Even assembly is an abstraction layer.
The CPU only understands machine code.&lt;&#x2F;p&gt;
&lt;p&gt;Yet today we ask LLMs to generate Rust, Go, C#, Java — languages optimized for human readability, maintainability, and collaboration.&lt;&#x2F;p&gt;
&lt;p&gt;If AI becomes a primary producer of code, are we still targeting the right abstraction layer?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;observation-from-practice&quot;&gt;Observation from Practice&lt;&#x2F;h2&gt;
&lt;p&gt;In AI-assisted workflows, the bottleneck is not syntax.&lt;&#x2F;p&gt;
&lt;p&gt;It is &lt;strong&gt;precision of intent&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The quality of AI-generated output scales with how well the following are formalized:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;System guarantees&lt;&#x2F;li&gt;
&lt;li&gt;Invariants&lt;&#x2F;li&gt;
&lt;li&gt;Concurrency constraints&lt;&#x2F;li&gt;
&lt;li&gt;Failure semantics&lt;&#x2F;li&gt;
&lt;li&gt;Performance envelopes&lt;&#x2F;li&gt;
&lt;li&gt;Data ownership boundaries&lt;&#x2F;li&gt;
&lt;li&gt;Consistency models&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;When these properties are clearly expressed, output improves dramatically — even without changing the underlying language.&lt;&#x2F;p&gt;
&lt;p&gt;This suggests something deeper:&lt;&#x2F;p&gt;
&lt;p&gt;The limiting factor is not the programming language.
It is the structure of system-level intent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hypothesis-languages-as-transitional-abstractions&quot;&gt;Hypothesis: Languages as Transitional Abstractions&lt;&#x2F;h2&gt;
&lt;p&gt;Traditional flow:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Human → Imperative code → Compiler → Machine code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Potential AI-native flow:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Human → Structured intent (constraints DSL)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      → AI-generated intermediate representation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      → Verification layer (invariants, safety, properties)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      → Optimizing compiler backend&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this model:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Rust&#x2F;Go&#x2F;C#&#x2F;Java become compilation targets&lt;&#x2F;li&gt;
&lt;li&gt;AI operates on structured intent&lt;&#x2F;li&gt;
&lt;li&gt;Verification becomes first-class&lt;&#x2F;li&gt;
&lt;li&gt;Properties replace instructions as the dominant abstraction&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;why-not-just-prompting&quot;&gt;Why Not Just “Prompting”?&lt;&#x2F;h2&gt;
&lt;p&gt;Plain prompts are insufficient for serious engineering because they are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Untyped&lt;&#x2F;li&gt;
&lt;li&gt;Non-verifiable&lt;&#x2F;li&gt;
&lt;li&gt;Hard to diff formally&lt;&#x2F;li&gt;
&lt;li&gt;Hard to compose safely&lt;&#x2F;li&gt;
&lt;li&gt;Weakly enforceable in enterprise environments&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Enterprise systems require:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Versioned representations&lt;&#x2F;li&gt;
&lt;li&gt;Reviewable structures&lt;&#x2F;li&gt;
&lt;li&gt;Static validation&lt;&#x2F;li&gt;
&lt;li&gt;Explicit guarantees&lt;&#x2F;li&gt;
&lt;li&gt;Enforceable invariants&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This strongly points toward constraint-driven DSLs rather than conversational programming.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implications-for-engineering&quot;&gt;Implications for Engineering&lt;&#x2F;h2&gt;
&lt;p&gt;If programming shifts from implementation to property declaration:&lt;&#x2F;p&gt;
&lt;p&gt;The most valuable skills become:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Architectural reasoning&lt;&#x2F;li&gt;
&lt;li&gt;Distributed systems thinking&lt;&#x2F;li&gt;
&lt;li&gt;Trade-off analysis&lt;&#x2F;li&gt;
&lt;li&gt;Invariant modeling&lt;&#x2F;li&gt;
&lt;li&gt;Failure domain design&lt;&#x2F;li&gt;
&lt;li&gt;Formal constraint specification&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Syntax fluency becomes secondary.&lt;&#x2F;p&gt;
&lt;p&gt;Engineering evolves from “writing code” to “designing enforceable intent.”&lt;&#x2F;p&gt;
&lt;h2 id=&quot;open-questions&quot;&gt;Open Questions&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Will we see AI-native DSLs for distributed systems?&lt;&#x2F;li&gt;
&lt;li&gt;Will verification layers become mandatory in AI-generated systems?&lt;&#x2F;li&gt;
&lt;li&gt;Will mainstream languages evolve to embed property modeling more deeply?&lt;&#x2F;li&gt;
&lt;li&gt;Is the future of programming closer to formal methods than to autocomplete?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;working-thesis&quot;&gt;Working Thesis&lt;&#x2F;h2&gt;
&lt;p&gt;Programming languages may not disappear.
But they may stop being the primary interface between human intent and executable systems.&lt;&#x2F;p&gt;
&lt;p&gt;They could become optimized backends.&lt;&#x2F;p&gt;
&lt;p&gt;And engineering might increasingly operate at the level of constraints, guarantees, and system properties.&lt;&#x2F;p&gt;
&lt;p&gt;If so, this is not the end of software engineering.
It is a shift toward a more formal and system-oriented discipline.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Originally published on GitHub — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RomanEmreis&#x2F;engineering-notes&#x2F;blob&#x2F;main&#x2F;evolution-of-prog-lang.md&quot;&gt;engineering-notes&#x2F;evolution-of-prog-lang.md&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>istok</title>
        <published>2026-02-14T00:00:00+00:00</published>
        <updated>2026-02-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/projects/istok/"/>
        <id>https://romanemreis.com/projects/istok/</id>
        
        <summary type="html">&lt;p&gt;istok is an experimental HTTP&#x2F;3 engine built around deterministic state machines, explicit protocol semantics, and test-first transport design.&lt;&#x2F;p&gt;
&lt;p&gt;The project focuses on making HTTP&#x2F;3 behavior easier to reason about, validate, and evolve without relying on opaque runtime behavior or implicit protocol transitions.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Asymptotic Optimality vs Real Performance</title>
        <published>2026-02-13T00:00:00+00:00</published>
        <updated>2026-02-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/notes/asymptotic-optimal-vs-real/"/>
        <id>https://romanemreis.com/notes/asymptotic-optimal-vs-real/</id>
        
        <content type="html" xml:base="https://romanemreis.com/notes/asymptotic-optimal-vs-real/">&lt;h2 id=&quot;context&quot;&gt;Context&lt;&#x2F;h2&gt;
&lt;p&gt;Sliding-window algorithm maintaining k smallest elements under a distance constraint.&lt;&#x2F;p&gt;
&lt;p&gt;Baseline implementations were already asymptotically optimal: O(n log k)&lt;&#x2F;p&gt;
&lt;p&gt;However, runtime performance varied dramatically depending on data representation and deletion strategy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;observation&quot;&gt;Observation&lt;&#x2F;h2&gt;
&lt;p&gt;The main bottlenecks were not algorithmic complexity but:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;data layout&lt;&#x2F;li&gt;
&lt;li&gt;memory access patterns&lt;&#x2F;li&gt;
&lt;li&gt;indirection level&lt;&#x2F;li&gt;
&lt;li&gt;container design&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;design-changes&quot;&gt;Design Changes&lt;&#x2F;h2&gt;
&lt;p&gt;Transition from generic abstractions to specialised representations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;value-based structures → index-based state&lt;&#x2F;li&gt;
&lt;li&gt;hash maps → compact contiguous arrays&lt;&#x2F;li&gt;
&lt;li&gt;generic containers → specialised heaps&lt;&#x2F;li&gt;
&lt;li&gt;struct pairs → packed 64-bit keys&lt;&#x2F;li&gt;
&lt;li&gt;lazy deletion via counters → index flags&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;results&quot;&gt;Results&lt;&#x2F;h2&gt;
&lt;p&gt;Same algorithmic complexity.&lt;&#x2F;p&gt;
&lt;p&gt;Different performance characteristics.&lt;&#x2F;p&gt;
&lt;p&gt;C# implementation:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;~550 ms&lt;&#x2F;li&gt;
&lt;li&gt;~75 MB RSS (actual data much smaller, but CLR overhead is real)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Initial Rust implementation:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;~110 ms&lt;&#x2F;li&gt;
&lt;li&gt;~6.8 MB RSS&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Optimised Rust implementation:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;~60 ms&lt;&#x2F;li&gt;
&lt;li&gt;~4.7 MB RSS&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;key-insight&quot;&gt;Key Insight&lt;&#x2F;h2&gt;
&lt;p&gt;Asymptotic optimality does not imply real-world efficiency.&lt;&#x2F;p&gt;
&lt;p&gt;Memory layout and indirection frequently dominate performance.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implications&quot;&gt;Implications&lt;&#x2F;h2&gt;
&lt;p&gt;Relevant beyond algorithmic problems:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;low-latency services&lt;&#x2F;li&gt;
&lt;li&gt;streaming pipelines&lt;&#x2F;li&gt;
&lt;li&gt;infrastructure-level code&lt;&#x2F;li&gt;
&lt;li&gt;performance-sensitive middleware&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Originally published on GitHub — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RomanEmreis&#x2F;engineering-notes&#x2F;blob&#x2F;main&#x2F;asymptotic-optimal-vs-real.md&quot;&gt;engineering-notes&#x2F;asymptotic-optimal-vs-real.md&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>When a Convenient API Becomes a Performance Constraint</title>
        <published>2026-02-13T00:00:00+00:00</published>
        <updated>2026-02-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/notes/when-a-convenient-api-becomes-a-perf-constraint/"/>
        <id>https://romanemreis.com/notes/when-a-convenient-api-becomes-a-perf-constraint/</id>
        
        <content type="html" xml:base="https://romanemreis.com/notes/when-a-convenient-api-becomes-a-perf-constraint/">&lt;h2 id=&quot;context&quot;&gt;Context&lt;&#x2F;h2&gt;
&lt;p&gt;Convenience-focused APIs improve developer experience.&lt;&#x2F;p&gt;
&lt;p&gt;However, in performance-sensitive systems they may introduce hidden costs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;patterns-observed&quot;&gt;Patterns Observed&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;implicit-allocations&quot;&gt;Implicit Allocations&lt;&#x2F;h3&gt;
&lt;p&gt;Small per-request allocations accumulate in hot paths, increasing latency and memory pressure.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hidden-control-flow&quot;&gt;Hidden Control Flow&lt;&#x2F;h3&gt;
&lt;p&gt;Automatic conversions and implicit defaults obscure execution paths and complicate reasoning about performance.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;error-handling-abstractions&quot;&gt;Error Handling Abstractions&lt;&#x2F;h3&gt;
&lt;p&gt;Automatic transformation layers make it unclear where cost is paid.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;deep-middleware-chains&quot;&gt;Deep Middleware Chains&lt;&#x2F;h3&gt;
&lt;p&gt;Composable layers improve modularity but may introduce:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;branching overhead&lt;&#x2F;li&gt;
&lt;li&gt;cache misses&lt;&#x2F;li&gt;
&lt;li&gt;reduced locality&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;tradeoff-model&quot;&gt;Tradeoff Model&lt;&#x2F;h2&gt;
&lt;p&gt;Convenience is beneficial in:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;business applications&lt;&#x2F;li&gt;
&lt;li&gt;productivity-oriented environments&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Explicit APIs become preferable when:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;latency is critical&lt;&#x2F;li&gt;
&lt;li&gt;throughput matters&lt;&#x2F;li&gt;
&lt;li&gt;predictable behaviour is required&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;key-insight&quot;&gt;Key Insight&lt;&#x2F;h2&gt;
&lt;p&gt;The best API for performance-critical systems often forces explicit ownership, cost visibility and execution flow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implications&quot;&gt;Implications&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;framework design&lt;&#x2F;li&gt;
&lt;li&gt;infrastructure libraries&lt;&#x2F;li&gt;
&lt;li&gt;async runtime abstractions&lt;&#x2F;li&gt;
&lt;li&gt;agent system architecture&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Originally published on GitHub — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RomanEmreis&#x2F;engineering-notes&#x2F;blob&#x2F;main&#x2F;whan-a-convenient-api-becomes-a-perf-constraint.md&quot;&gt;engineering-notes&#x2F;whan-a-convenient-api-becomes-a-perf-constraint.md&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>neva</title>
        <published>2025-03-27T00:00:00+00:00</published>
        <updated>2025-03-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/projects/neva/"/>
        <id>https://romanemreis.com/projects/neva/</id>
        
        <summary type="html">&lt;p&gt;neva is a Rust SDK for building Model Context Protocol clients and servers with ergonomic APIs, async transports, and typed primitives for tools, resources, prompts, and protocol flows.&lt;&#x2F;p&gt;
&lt;p&gt;It is designed for developers who want Rust-level performance and reliability without turning simple MCP integrations into framework-heavy boilerplate.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>volga</title>
        <published>2024-10-02T00:00:00+00:00</published>
        <updated>2024-10-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://romanemreis.com/projects/volga/"/>
        <id>https://romanemreis.com/projects/volga/</id>
        
        <summary type="html">&lt;p&gt;Modern Rust web framework built around explicit HTTP abstractions and composable middleware.&lt;&#x2F;p&gt;
&lt;p&gt;volga avoids implicit behavior and hidden execution paths, enabling systems that remain understandable under load and at scale.&lt;&#x2F;p&gt;</summary>
        
    </entry>
</feed>
