<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Sendoa Moronta]]></title><description><![CDATA[I write about data architecture, artificial intelligence, and how to design scalable solutions that bridge business and technology. I share practical insights, trends, and real-world lessons from the field.]]></description><link>https://sendoamoronta.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!CsRs!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d7ea72d-3fc8-4366-93ab-0d0d3fa49d4e_1350x1350.jpeg</url><title>Sendoa Moronta</title><link>https://sendoamoronta.substack.com</link></image><generator>Substack</generator><lastBuildDate>Mon, 10 Aug 2026 17:30:00 GMT</lastBuildDate><atom:link href="https://sendoamoronta.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Sendoa Moronta]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[sendoamoronta@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[sendoamoronta@substack.com]]></itunes:email><itunes:name><![CDATA[Sendoa Moronta]]></itunes:name></itunes:owner><itunes:author><![CDATA[Sendoa Moronta]]></itunes:author><googleplay:owner><![CDATA[sendoamoronta@substack.com]]></googleplay:owner><googleplay:email><![CDATA[sendoamoronta@substack.com]]></googleplay:email><googleplay:author><![CDATA[Sendoa Moronta]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Snowflake is Becoming an AI Platform (Not Just a Data Warehouse)]]></title><description><![CDATA[Why the most important shift in data isn&#8217;t about storage anymore&#8212;but about where intelligence lives]]></description><link>https://sendoamoronta.substack.com/p/snowflake-is-becoming-an-ai-platform</link><guid isPermaLink="false">https://sendoamoronta.substack.com/p/snowflake-is-becoming-an-ai-platform</guid><dc:creator><![CDATA[Sendoa Moronta]]></dc:creator><pubDate>Wed, 01 Apr 2026 10:58:25 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!YtF4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For years, the pitch around Snowflake was simple:</p><blockquote><p>&#8220;A better data warehouse. Scalable, decoupled storage and compute, easy to use.&#8221;</p></blockquote><p>And it worked.</p><p>Companies migrated from legacy systems, centralized their data, and built modern data stacks around it. Snowflake became the <strong>source of truth</strong>.</p><p>But something interesting is happening now&#8212;quietly, but fast.</p><p>Snowflake is no longer just where data lives.</p><p>It&#8217;s becoming where <strong>AI runs</strong>.</p><div><hr></div><h2>The Old Mental Model: Data Warehouse as Storage</h2><p>Traditionally, the architecture looked like this:</p><blockquote><p>Data &#8594; Warehouse &#8594; Export &#8594; ML / AI systems &#8594; Results</p></blockquote><p>The warehouse was:</p><ul><li><p>Passive</p></li><li><p>Centralized</p></li><li><p>Structured</p></li></ul><p>If you wanted to do anything &#8220;intelligent&#8221;:</p><ul><li><p>You exported data</p></li><li><p>Moved it into another system</p></li><li><p>Ran models externally</p></li></ul><p>This made sense when:</p><ul><li><p>Data was mostly structured</p></li><li><p>ML workflows were separate</p></li><li><p>Latency wasn&#8217;t critical</p></li></ul><p>But this model is starting to break.</p><div><hr></div><h2>The Problem: Moving Data is the Real Bottleneck</h2><p>In modern AI systems, especially LLM-based ones, the biggest friction isn&#8217;t compute.</p><p>It&#8217;s <strong>data movement</strong>.</p><p>Every time you:</p><ul><li><p>Export data to a vector database</p></li><li><p>Sync to a feature store</p></li><li><p>Move it into an ML pipeline</p></li></ul><p>You introduce:</p><ul><li><p>Latency</p></li><li><p>Complexity</p></li><li><p>Cost</p></li><li><p>Data duplication</p></li><li><p>Governance headaches</p></li></ul><p>Ironically, the more &#8220;modern&#8221; your stack becomes, the more fragmented it gets.</p><div><hr></div><h2>The Shift: Bringing AI to the Data</h2><p>Instead of moving data to AI systems, we&#8217;re starting to move <strong>AI to the data</strong>.</p><p>And this is where Snowflake is making a strategic move.</p><p>With things like:</p><ul><li><p>Cortex (LLMs inside Snowflake)</p></li><li><p>Snowpark (Python execution within the warehouse)</p></li><li><p>Native support for embeddings and vector search</p></li></ul><p>Snowflake is turning into something very different:</p><blockquote><p>A platform where data is stored, processed, and <em>understood</em>&#8212;in the same place.</p></blockquote><div><hr></div><h2>Cortex Changes the Game</h2><p>The introduction of Cortex is not just another feature.</p><p>It&#8217;s a signal.</p><p>You can now:</p><ul><li><p>Generate embeddings directly in Snowflake</p></li><li><p>Run LLM-powered transformations</p></li><li><p>Build AI-powered queries without leaving the platform</p></li></ul><p>This removes an entire layer of architecture.</p><p>Before:</p><blockquote><p>Warehouse &#8594; API calls &#8594; LLM &#8594; back to system</p></blockquote><p>Now:</p><blockquote><p>Warehouse &#8594; LLM &#8594; result</p></blockquote><p>No movement. No duplication.</p><div><hr></div><h2>Snowpark: Compute Meets Flexibility</h2><p>With Snowpark, you can run Python code directly where your data lives.</p><p>That means:</p><ul><li><p>Feature engineering happens in-place</p></li><li><p>ML models can run without exporting data</p></li><li><p>Pipelines become simpler and more unified</p></li></ul><p>It blurs the line between:</p><ul><li><p>Data engineering</p></li><li><p>Machine learning</p></li><li><p>Application logic</p></li></ul><p>And that&#8217;s a big deal.</p><div><hr></div><h2>The Emergence of the &#8220;AI Warehouse&#8221;</h2><p>We&#8217;re moving toward a new concept:</p><blockquote><p>The <strong>AI-native data platform</strong></p></blockquote><p>Where:</p><ul><li><p>Storage</p></li><li><p>Compute</p></li><li><p>Retrieval</p></li><li><p>AI inference</p></li></ul><p>All happen in the same environment.</p><p>This has a few important consequences:</p><h3>1. <strong>Fewer Systems, More Leverage</strong></h3><p>Instead of stitching together:</p><ul><li><p>Warehouse</p></li><li><p>Vector DB</p></li><li><p>Feature store</p></li><li><p>ML infra</p></li></ul><p>You centralize more capabilities in one place.</p><div><hr></div><h3>2. <strong>Better Governance</strong></h3><p>Data doesn&#8217;t leave the warehouse.</p><p>That means:</p><ul><li><p>Security policies remain intact</p></li><li><p>Compliance is easier</p></li><li><p>No shadow pipelines</p></li></ul><div><hr></div><h3>3. <strong>Lower Latency</strong></h3><p>No external calls, no data movement.</p><p>AI applications become:</p><ul><li><p>Faster</p></li><li><p>More interactive</p></li><li><p>More reliable</p></li></ul><div><hr></div><h3>4. <strong>Simpler Architectures</strong></h3><p>Fewer moving parts = fewer failure points.</p><p>This is underrated.</p><p>Most production AI systems fail not because of models&#8212;but because of <strong>architecture complexity</strong>.</p><div><hr></div><h2>But There&#8217;s a Tradeoff</h2><p>This shift isn&#8217;t free.</p><p>By consolidating everything into Snowflake, you also:</p><ul><li><p>Increase vendor dependency</p></li><li><p>Limit flexibility compared to specialized tools</p></li><li><p>Risk overloading a single platform</p></li></ul><p>There&#8217;s a real architectural question emerging:</p><blockquote><p>Do you build a composable AI stack&#8212;or an integrated one?</p></blockquote><p>Snowflake is clearly betting on the latter.</p><div><hr></div><h2>The Real Question: Where Should Intelligence Live?</h2><p>This is the deeper shift behind everything.</p><p>For years, intelligence lived:</p><ul><li><p>In BI tools (dashboards)</p></li><li><p>In ML systems (separate pipelines)</p></li></ul><p>Now, it&#8217;s moving closer to the data layer.</p><p>The question is no longer:</p><blockquote><p>&#8220;Where do we store data?&#8221;</p></blockquote><p>It&#8217;s:</p><blockquote><p><strong>&#8220;Where do we run reasoning?&#8221;</strong></p></blockquote><div><hr></div><h2>What This Means for Data Engineers</h2><p>If you&#8217;re working in data, this changes your role more than you might expect.</p><p>You&#8217;re no longer just:</p><ul><li><p>Building pipelines</p></li><li><p>Modeling tables</p></li><li><p>Optimizing queries</p></li></ul><p>You&#8217;re starting to:</p><ul><li><p>Design retrieval systems</p></li><li><p>Think about embeddings</p></li><li><p>Manage AI execution environments</p></li><li><p>Control how context is constructed</p></li></ul><p>The warehouse is no longer just infrastructure.</p><p>It&#8217;s becoming part of the <strong>application layer</strong>.</p><div><hr></div><h2>What Still Doesn&#8217;t Change</h2><p>Despite all this, some fundamentals remain:</p><ul><li><p>Data quality still matters</p></li><li><p>Modeling still matters</p></li><li><p>Governance still matters</p></li></ul><p>If anything, they matter more.</p><p>Because now:</p><ul><li><p>Bad data doesn&#8217;t just break dashboards</p></li><li><p>It breaks AI systems</p></li></ul><p>And those fail in less predictable ways.</p><div><hr></div><h2>Final Thought</h2><p>It&#8217;s tempting to think of Snowflake&#8217;s evolution as just &#8220;adding AI features.&#8221;</p><p>It&#8217;s not.</p><p>It&#8217;s a shift in where computation&#8212;and ultimately intelligence&#8212;happens.</p><p>From:</p><blockquote><p>Distributed systems stitched together</p></blockquote><p>To:</p><blockquote><p>Centralized platforms that combine data + reasoning</p></blockquote><p>Whether this becomes the dominant model or not is still an open question.</p><p>But one thing is already clear:</p><blockquote><p>The data warehouse is no longer just a place to store data.</p></blockquote><p>It&#8217;s becoming a place to <strong>think</strong>.</p><div><hr></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://sendoamoronta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://sendoamoronta.substack.com/subscribe?"><span>Subscribe now</span></a></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YtF4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YtF4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!YtF4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!YtF4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!YtF4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YtF4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:637316,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://sendoamoronta.substack.com/i/192833515?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YtF4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!YtF4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!YtF4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!YtF4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3119f03-b997-4e6c-9c4a-25395f73a374_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div>]]></content:encoded></item><item><title><![CDATA[Serving Data to Humans vs Serving Data to Models]]></title><description><![CDATA[Why designing for AI is nothing like designing for dashboards]]></description><link>https://sendoamoronta.substack.com/p/serving-data-to-humans-vs-serving</link><guid isPermaLink="false">https://sendoamoronta.substack.com/p/serving-data-to-humans-vs-serving</guid><dc:creator><![CDATA[Sendoa Moronta]]></dc:creator><pubDate>Mon, 30 Mar 2026 14:03:12 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!-H7e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you&#8217;ve ever built a data platform, you know the drill:</p><ul><li><p>Ingest raw data</p></li><li><p>Clean it</p></li><li><p>Transform it</p></li><li><p>Load it into a warehouse</p></li><li><p>Build dashboards and reports</p></li></ul><p>Everything is designed around <strong>human consumption</strong>. Analysts, product managers, and executives expect clean tables, aggregates, and charts.</p><p>And that works&#8212;really well&#8212;for humans.</p><p>But here&#8217;s the problem: <strong>models don&#8217;t consume data the same way humans do</strong>.</p><p>When you start feeding LLMs, retrieval agents, or AI copilots the same pipelines built for dashboards, you quickly hit walls.</p><div><hr></div><h2>Humans vs Models: What Actually Changes</h2><p>Let&#8217;s break down the differences:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;e3970ebf-79c4-4548-a6c1-2ec3eac888cb&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">| Aspect                   | Humans                                | Models                                                                                                  |
| ------------------------ | ------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| **Data format**          | Structured tables, readable reports   | Raw, unstructured, semantically rich chunks                                                             |
| **Query style**          | Deterministic, predictable            | Ambiguous, multi-step, context-dependent                                                                |
| **Tolerance for noise**  | Low (humans hate messy data)          | High (models can infer patterns, but misinterpretation can be catastrophic)                             |
| **Latency expectations** | Seconds, minutes acceptable           | Milliseconds to sub-second preferred for interactive systems                                            |
| **Context window**       | Humans hold limited context naturally | Models have artificial context windows and need careful chunking                                        |
| **Evaluation**           | Humans detect errors intuitively      | Must build explicit evaluation pipelines (retrieval relevance, hallucination checks, alignment metrics) |
</code></pre></div><div><hr></div><h2>Why Traditional Data Pipelines Fail for Models</h2><h3>1. <strong>Flat Tables Are Not Enough</strong></h3><p>Traditional warehouses organize data as flat tables. Great for queries like &#8220;total sales by region,&#8221; but models often need <strong>hierarchical, relational, or semantic context</strong>.</p><ul><li><p>Example: An LLM trying to answer &#8220;Why did churn spike last quarter?&#8221; needs connections between customer complaints, usage logs, and support tickets&#8212;<strong>not a simple aggregation</strong>.</p></li></ul><h3>2. <strong>Latency Is Critical</strong></h3><p>Batch ETL works for dashboards refreshed daily. But AI applications&#8212;copilots, agents, real-time assistants&#8212;require <strong>fast, dynamic retrieval</strong>. A slow query pipeline breaks the experience instantly.</p><h3>3. <strong>Meaning, Not Format, Is the Contract</strong></h3><p>Humans read schemas; models read <strong>semantics</strong>.</p><ul><li><p>Two tables with identical columns may be interpreted completely differently by an LLM if metadata, embeddings, or chunking are missing.</p></li><li><p>AI-ready pipelines must <strong>preserve meaning and relationships</strong>, not just raw data.</p></li></ul><h3>4. <strong>Determinism vs Probabilistic Reasoning</strong></h3><p>SQL queries return deterministic results. LLMs reason probabilistically.</p><ul><li><p>If your architecture assumes deterministic outputs, it will fail when feeding probabilistic models.</p></li><li><p>This requires <strong>new layers for evaluation, ranking, and filtering</strong>.</p></li></ul><div><hr></div><h2>Designing Data Pipelines for AI</h2><p>To serve models effectively, your architecture must evolve:</p><h3>1. <strong>Retrieval Layer</strong></h3><ul><li><p>Vector databases for semantic search</p></li><li><p>Hybrid retrieval: combine keyword + embedding search</p></li><li><p>Dynamic filtering and re-ranking</p></li></ul><h3>2. <strong>Context Construction Layer</strong></h3><ul><li><p>Chunking strategies (documents, paragraphs, sentences)</p></li><li><p>Metadata enrichment for relevance</p></li><li><p>Summarization/compression for long contexts</p></li></ul><h3>3. <strong>Memory Layer</strong></h3><ul><li><p>Short-term (conversation state)</p></li><li><p>Long-term (persistent knowledge)</p></li><li><p>Episodic (historical interactions)</p></li></ul><h3>4. <strong>Evaluation Layer</strong></h3><ul><li><p>Retrieval accuracy metrics</p></li><li><p>Hallucination detection</p></li><li><p>Model output quality monitoring</p></li></ul><p>These layers <strong>don&#8217;t replace your warehouse</strong>, but they make it <strong>AI-compatible</strong>.</p><div><hr></div><h2>Mental Model: Humans vs Models</h2><p>When designing for humans, think in <strong>static reports</strong>.</p><p>When designing for models, think in <strong>dynamic knowledge flows</strong>:</p><blockquote><p>Raw Data &#8594; Processing &#8594; Retrieval &#8594; Context &#8594; Reasoning &#8594; Evaluation &#8594; Output</p></blockquote><p>Each step is <strong>active</strong>, <strong>dynamic</strong>, and <strong>interdependent</strong>.</p><div><hr></div><h2>When the Old Stack Still Matters</h2><p>Your existing data lake, ETL pipelines, and warehouse still have value:</p><ul><li><p>They store raw, trusted data</p></li><li><p>They support BI and analytics</p></li><li><p>They feed AI layers with upstream content</p></li></ul><p>But they <strong>no longer sit at the center of your system</strong>. They are <strong>providers, not consumers</strong>.</p><div><hr></div><h2>The Big Takeaway</h2><p>Serving data to models is fundamentally different from serving data to humans.</p><ul><li><p>Format isn&#8217;t enough; semantics matter</p></li><li><p>Deterministic pipelines aren&#8217;t enough; dynamic retrieval and reasoning are needed</p></li><li><p>Dashboards aren&#8217;t enough; context and memory are critical</p></li></ul><p>If you try to run AI applications on a human-centric data stack, you&#8217;ll end up with <strong>fragile, inconsistent, and slow systems</strong>.</p><p>The teams that succeed won&#8217;t just build better models&#8212;they&#8217;ll build <strong>data architectures for reasoning</strong>.</p><div><hr></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://sendoamoronta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://sendoamoronta.substack.com/subscribe?"><span>Subscribe now</span></a></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-H7e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-H7e!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!-H7e!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!-H7e!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!-H7e!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-H7e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:637316,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://sendoamoronta.substack.com/i/192613563?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-H7e!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!-H7e!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!-H7e!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!-H7e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1de4f571-49d9-4007-9ab7-81f82a362a89_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p>]]></content:encoded></item><item><title><![CDATA[Data Architecture for LLM Applications: What Actually Changes]]></title><description><![CDATA[Why your existing data stack isn&#8217;t enough and what a real AI-ready architecture looks like]]></description><link>https://sendoamoronta.substack.com/p/data-architecture-for-llm-applications</link><guid isPermaLink="false">https://sendoamoronta.substack.com/p/data-architecture-for-llm-applications</guid><dc:creator><![CDATA[Sendoa Moronta]]></dc:creator><pubDate>Wed, 25 Mar 2026 14:13:41 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!4azd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There&#8217;s a quiet assumption many teams make when they start building LLM applications:</p><blockquote><p><em>&#8220;We already have a solid data platform. We can just plug AI into it.&#8221;</em></p></blockquote><p>On paper, that sounds reasonable.</p><p>You have a data lake. Maybe a warehouse. ETL pipelines. Governance. Monitoring. Everything looks mature.</p><p>And yet, the moment you try to build something beyond a demo&#8212;say a production-grade AI assistant, a copiloted workflow, or a knowledge system&#8212;you hit friction almost immediately.</p><p>Not because your data platform is broken.</p><p>But because it was never designed for this.</p><div><hr></div><h2>The Mismatch No One Talks About</h2><p>Traditional data architectures are built to serve <strong>humans</strong>.</p><p>Dashboards. Reports. Aggregations. Historical analysis.</p><p>LLM applications are different. They serve <strong>models</strong>.</p><p>That shift sounds subtle, but it changes everything.</p><p>Humans want:</p><ul><li><p>Clean tables</p></li><li><p>Aggregated metrics</p></li><li><p>Structured schemas</p></li></ul><p>Models need:</p><ul><li><p>Raw and messy context</p></li><li><p>Semantically rich information</p></li><li><p>Flexible, dynamic retrieval</p></li></ul><p>Your warehouse answers questions like:</p><blockquote><p>&#8220;What were sales last quarter?&#8221;</p></blockquote><p>Your LLM application needs to answer:</p><blockquote><p>&#8220;Why did enterprise churn spike in EMEA after the pricing change?&#8221;</p></blockquote><p>That&#8217;s not a query.</p><p>That&#8217;s a <strong>reasoning problem over distributed context</strong>.</p><div><hr></div><h2>The Old Stack (And Why It Breaks)</h2><p>A typical modern data stack looks like this:</p><ul><li><p>Ingestion &#8594; ETL/ELT &#8594; Data Lake &#8594; Warehouse &#8594; BI</p></li></ul><p>This works because:</p><ul><li><p>Data is structured</p></li><li><p>Queries are predictable</p></li><li><p>Use cases are well-defined</p></li></ul><p>But LLM applications introduce new constraints:</p><h3>1. <strong>Unstructured Data Becomes First-Class</strong></h3><p>Your most valuable data is suddenly:</p><ul><li><p>PDFs</p></li><li><p>Notion docs</p></li><li><p>Slack messages</p></li><li><p>Logs</p></li><li><p>Emails</p></li></ul><p>None of this fits cleanly into tables.</p><div><hr></div><h3>2. <strong>Latency Expectations Change</strong></h3><p>Batch pipelines are fine for dashboards.</p><p>They break for:</p><ul><li><p>AI copilots</p></li><li><p>Real-time assistants</p></li><li><p>Interactive systems</p></li></ul><p>You now need <strong>low-latency retrieval + reasoning</strong>.</p><div><hr></div><h3>3. <strong>Schema Stops Being the Interface</strong></h3><p>In traditional systems:</p><ul><li><p>Schema = contract</p></li></ul><p>In LLM systems:</p><ul><li><p><strong>Semantics = contract</strong></p></li></ul><p>The model doesn&#8217;t care about your table structure.</p><p>It cares about meaning.</p><div><hr></div><h3>4. <strong>Determinism is Gone</strong></h3><p>SQL gives deterministic answers.</p><p>LLMs don&#8217;t.</p><p>So the architecture must compensate with:</p><ul><li><p>Retrieval quality</p></li><li><p>Context control</p></li><li><p>Evaluation layers</p></li></ul><div><hr></div><h2>The New Layers You Actually Need</h2><p>To support LLM applications, your architecture needs to evolve.</p><p>Not by replacing everything&#8212;but by <strong>adding new layers on top of your existing stack</strong>.</p><div><hr></div><h3>1. The Retrieval Layer (Not Just Storage)</h3><p>This is the most obvious addition&#8212;and the most misunderstood.</p><p>Yes, this includes vector databases.</p><p>But more importantly, it includes:</p><ul><li><p>Chunking strategies</p></li><li><p>Metadata enrichment</p></li><li><p>Hybrid search (keyword + semantic)</p></li><li><p>Re-ranking</p></li></ul><p>The key idea:</p><blockquote><p>You&#8217;re no longer storing data. You&#8217;re designing <strong>how data is retrieved for reasoning</strong>.</p></blockquote><p>Bad retrieval = broken system.</p><div><hr></div><h3>2. The Embedding Pipeline</h3><p>Embeddings are often treated as a one-time step.</p><p>In reality, they are a <strong>core data pipeline</strong>.</p><p>You need to think about:</p><ul><li><p>Versioning embeddings</p></li><li><p>Recomputing on model changes</p></li><li><p>Handling schema evolution</p></li><li><p>Updating incrementally</p></li></ul><p>This is closer to feature engineering than indexing.</p><div><hr></div><h3>3. The Context Construction Layer</h3><p>This is where most architectures fall apart.</p><p>Retrieving documents is not enough.</p><p>You need to:</p><ul><li><p>Filter irrelevant information</p></li><li><p>Merge sources</p></li><li><p>Compress context</p></li><li><p>Structure prompts dynamically</p></li></ul><p>This layer transforms:</p><blockquote><p>raw data &#8594; usable context</p></blockquote><p>It&#8217;s effectively a <strong>query planner for LLMs</strong>.</p><div><hr></div><h3>4. The Memory Layer</h3><p>Unlike traditional systems, LLM applications are stateful.</p><p>You need to manage:</p><ul><li><p>Conversation history</p></li><li><p>User-specific context</p></li><li><p>Long-term knowledge</p></li></ul><p>This introduces:</p><ul><li><p>New storage patterns</p></li><li><p>New privacy concerns</p></li><li><p>New consistency challenges</p></li></ul><p>Memory is not just storage&#8212;it&#8217;s <strong>evolving context</strong>.</p><div><hr></div><h3>5. The Evaluation Layer (The Missing Piece)</h3><p>This is the layer almost everyone skips.</p><p>In traditional data systems, we validate:</p><ul><li><p>Data quality</p></li><li><p>Pipeline correctness</p></li></ul><p>In LLM systems, you must evaluate:</p><ul><li><p>Retrieval relevance</p></li><li><p>Response quality</p></li><li><p>Hallucinations</p></li><li><p>Drift over time</p></li></ul><p>Without this layer, you don&#8217;t have a system.</p><p>You have a demo.</p><div><hr></div><h2>A New Mental Model</h2><p>Instead of thinking in terms of pipelines, think in terms of <strong>flows of context</strong>:</p><blockquote><p>Data &#8594; Processing &#8594; Retrieval &#8594; Context &#8594; Reasoning &#8594; Evaluation</p></blockquote><p>Each step is dynamic.</p><p>Each step affects the final output.</p><p>And none of them are fully deterministic.</p><div><hr></div><h2>What Doesn&#8217;t Change (Important)</h2><p>Not everything is new.</p><p>Your existing stack still matters:</p><ul><li><p>Data lakes still store raw data</p></li><li><p>Warehouses still power analytics</p></li><li><p>ETL pipelines still prepare structured datasets</p></li></ul><p>But they are no longer the <strong>center of gravity</strong>.</p><p>They become <strong>upstream providers</strong> to AI systems.</p><div><hr></div><h2>The Real Shift</h2><p>The biggest change isn&#8217;t technical.</p><p>It&#8217;s conceptual.</p><p>You&#8217;re no longer building systems that:</p><blockquote><p>store and query data</p></blockquote><p>You&#8217;re building systems that:</p><blockquote><p><strong>assemble knowledge at runtime for reasoning</strong></p></blockquote><p>That&#8217;s a fundamentally different problem.</p><div><hr></div><h2>Final Thought</h2><p>If you&#8217;re trying to build LLM applications on top of your existing data architecture without changing anything, you&#8217;ll likely end up with:</p><ul><li><p>Fragile systems</p></li><li><p>Inconsistent outputs</p></li><li><p>Endless prompt tweaking</p></li></ul><p>Not because LLMs are unreliable&#8212;</p><p>but because your architecture isn&#8217;t designed for how they work.</p><p>The teams that will win in this space won&#8217;t just have better models.</p><p>They&#8217;ll have better <strong>data architectures for reasoning</strong>.</p><div><hr></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://sendoamoronta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://sendoamoronta.substack.com/subscribe?"><span>Subscribe now</span></a></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4azd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4azd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!4azd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!4azd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!4azd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4azd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:637316,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://sendoamoronta.substack.com/i/192098960?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4azd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!4azd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!4azd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!4azd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32b2e066-f7f7-4671-a288-2450ea704a72_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p>]]></content:encoded></item><item><title><![CDATA[Beyond RAG: The Next Generation of Retrieval Architectures]]></title><description><![CDATA[Why simple retrieval pipelines are breaking and what comes next]]></description><link>https://sendoamoronta.substack.com/p/beyond-rag-the-next-generation-of</link><guid isPermaLink="false">https://sendoamoronta.substack.com/p/beyond-rag-the-next-generation-of</guid><dc:creator><![CDATA[Sendoa Moronta]]></dc:creator><pubDate>Mon, 23 Mar 2026 16:19:10 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!RcHr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For the past year, Retrieval-Augmented Generation (RAG) has become the default pattern for building LLM-powered applications. It&#8217;s simple, intuitive, and (at first glance) remarkably effective.</p><p>You take a query, retrieve relevant documents, stuff them into a prompt, and let the model do the rest.</p><p>And yet, if you&#8217;ve tried to deploy RAG systems in production, you&#8217;ve probably felt it:</p><p><strong>Something doesn&#8217;t quite hold up.</strong></p><p>Results degrade under complexity. Context becomes noisy. Retrieval misses critical information. And suddenly, your &#8220;intelligent system&#8221; starts behaving like a confident but unreliable intern.</p><p>This isn&#8217;t a tooling issue. It&#8217;s architectural.</p><p>RAG, as commonly implemented, is already hitting its limits.</p><div><hr></div><h2>The Hidden Assumption Behind RAG</h2><p>At its core, RAG relies on a deceptively strong assumption:</p><blockquote><p><em>The answer to a question can be found in a small, retrievable subset of documents.</em></p></blockquote><p>This works well for:</p><ul><li><p>FAQ-style queries</p></li><li><p>Knowledge base lookups</p></li><li><p>Isolated facts</p></li></ul><p>But it starts to break when:</p><ul><li><p>Information is <strong>distributed across multiple sources</strong></p></li><li><p>The query requires <strong>multi-step reasoning</strong></p></li><li><p>Context must be <strong>constructed, not retrieved</strong></p></li></ul><p>In other words, RAG assumes retrieval is enough.</p><p>It often isn&#8217;t.</p><div><hr></div><h2>Where Traditional RAG Fails</h2><p>Let&#8217;s break down the failure modes you&#8217;ve likely encountered:</p><h3>1. <strong>Retrieval &#8800; Understanding</strong></h3><p>Vector similarity retrieves <em>related</em> chunks, not <em>relevant</em> ones.</p><p>Semantic search struggles with:</p><ul><li><p>Ambiguous queries</p></li><li><p>Implicit intent</p></li><li><p>Cross-document relationships</p></li></ul><p>You don&#8217;t get <em>the answer</em>. You get <em>pieces of something adjacent to the answer</em>.</p><div><hr></div><h3>2. <strong>Context Window Saturation</strong></h3><p>Even with large context windows, more data &#8800; better answers.</p><ul><li><p>Irrelevant chunks dilute signal</p></li><li><p>Important details get buried</p></li><li><p>Models hallucinate to &#8220;connect&#8221; incomplete context</p></li></ul><p>RAG pipelines often degrade as you add more data&#8212;ironically the opposite of what you want.</p><div><hr></div><h3>3. <strong>No Iterative Reasoning</strong></h3><p>Standard RAG is a <strong>single-shot process</strong>:</p><ol><li><p>Retrieve</p></li><li><p>Generate</p></li></ol><p>But many problems require:</p><ul><li><p>Refining the query</p></li><li><p>Exploring intermediate steps</p></li><li><p>Revisiting missing information</p></li></ul><p>Without iteration, the system gets one chance&#8212;and often misses.</p><div><hr></div><h3>4. <strong>Flat Retrieval Space</strong></h3><p>Most RAG systems treat knowledge as a flat collection of chunks.</p><p>Reality is not flat.</p><ul><li><p>Documents have structure</p></li><li><p>Concepts have relationships</p></li><li><p>Knowledge is hierarchical and interconnected</p></li></ul><p>Flattening everything into embeddings loses that structure.</p><div><hr></div><h2>The Shift: From Retrieval to Reasoning Systems</h2><p>What&#8217;s emerging now is not &#8220;better RAG.&#8221;</p><p>It&#8217;s a shift toward <strong>retrieval as part of a broader reasoning loop</strong>.</p><p>Instead of:</p><blockquote><p>retrieve &#8594; generate</p></blockquote><p>We&#8217;re moving to:</p><blockquote><p><strong>reason &#8594; retrieve &#8594; refine &#8594; retrieve &#8594; synthesize</strong></p></blockquote><p>This is the foundation of next-generation architectures.</p><div><hr></div><h2>1. Iterative Retrieval (Agentic RAG)</h2><p>The first evolution is straightforward but powerful:</p><p>Make retrieval <strong>iterative and adaptive</strong>.</p><p>Instead of one query:</p><ul><li><p>The model generates sub-queries</p></li><li><p>Retrieves incrementally</p></li><li><p>Updates its understanding</p></li><li><p>Continues until it has enough context</p></li></ul><p>This pattern is often implemented using agents.</p><p>Key properties:</p><ul><li><p>Dynamic query planning</p></li><li><p>Tool usage (search, DBs, APIs)</p></li><li><p>Intermediate reasoning steps</p></li></ul><p>This turns retrieval into a <strong>process</strong>, not a step.</p><div><hr></div><h2>2. Graph-Based Retrieval (Graph RAG)</h2><p>If flat embeddings are the problem, structure is the solution.</p><p>Graph-based approaches model:</p><ul><li><p>Entities</p></li><li><p>Relationships</p></li><li><p>Dependencies</p></li></ul><p>Instead of retrieving chunks, you traverse a graph.</p><p>Benefits:</p><ul><li><p>Better multi-hop reasoning</p></li><li><p>Explicit relationships between concepts</p></li><li><p>More controllable context construction</p></li></ul><p>This is particularly powerful for:</p><ul><li><p>Enterprise knowledge systems</p></li><li><p>Scientific domains</p></li><li><p>Complex documentation</p></li></ul><p>Graph RAG doesn&#8217;t just retrieve data&#8212;it retrieves <strong>connected meaning</strong>.</p><div><hr></div><h2>3. Retrieval with Re-ranking and Compression</h2><p>Another key evolution is what happens <em>after</em> retrieval.</p><p>Instead of blindly passing chunks to the model:</p><ul><li><p>Re-rank results using cross-encoders or LLMs</p></li><li><p>Filter noise</p></li><li><p>Compress information into dense summaries</p></li></ul><p>This creates:</p><ul><li><p>Higher signal-to-noise ratio</p></li><li><p>Better use of context windows</p></li><li><p>More deterministic outputs</p></li></ul><p>Think of it as moving from:</p><blockquote><p>&#8220;dump everything into the prompt&#8221;</p></blockquote><p>to:</p><blockquote><p>&#8220;curate the exact knowledge the model needs&#8221;</p></blockquote><div><hr></div><h2>4. Memory-Augmented Systems</h2><p>RAG is stateless by design.</p><p>But real applications aren&#8217;t.</p><p>Next-gen systems introduce <strong>memory layers</strong>:</p><ul><li><p>Short-term (conversation state)</p></li><li><p>Long-term (persistent knowledge)</p></li><li><p>Episodic (past interactions)</p></li></ul><p>This allows systems to:</p><ul><li><p>Accumulate knowledge over time</p></li><li><p>Personalize responses</p></li><li><p>Avoid repeated retrieval</p></li></ul><p>Memory transforms retrieval from:</p><blockquote><p>&#8220;find external knowledge&#8221;</p></blockquote><p>to:</p><blockquote><p>&#8220;combine external + internal knowledge&#8221;</p></blockquote><div><hr></div><h2>5. Retrieval as a Tool, Not the Core</h2><p>The most important shift is conceptual:</p><p><strong>Retrieval is no longer the architecture. It&#8217;s just one capability.</strong></p><p>Modern systems combine:</p><ul><li><p>Retrieval</p></li><li><p>Reasoning</p></li><li><p>Tool usage</p></li><li><p>Planning</p></li><li><p>Memory</p></li></ul><p>In these systems, retrieval is invoked <strong>when needed</strong>, not by default.</p><p>This leads to:</p><ul><li><p>More efficient execution</p></li><li><p>Better answers</p></li><li><p>Greater robustness</p></li></ul><div><hr></div><h2>When RAG Still Makes Sense</h2><p>To be clear, RAG isn&#8217;t obsolete.</p><p>It&#8217;s still the right choice when:</p><ul><li><p>Queries are simple and well-defined</p></li><li><p>Latency must be minimal</p></li><li><p>Data is relatively small and clean</p></li></ul><p>But as soon as your system needs:</p><ul><li><p>Reasoning</p></li><li><p>Adaptability</p></li><li><p>Depth</p></li></ul><p>You&#8217;ll hit its limits.</p><div><hr></div><h2>The Real Takeaway</h2><p>The industry isn&#8217;t moving from &#8220;bad RAG&#8221; to &#8220;good RAG.&#8221;</p><p>It&#8217;s moving from:</p><blockquote><p><strong>retrieval pipelines</strong></p></blockquote><p>to:</p><blockquote><p><strong>reasoning systems with retrieval capabilities</strong></p></blockquote><p>That&#8217;s a fundamental shift.</p><p>And it changes how we design everything:</p><ul><li><p>APIs</p></li><li><p>data layers</p></li><li><p>evaluation</p></li><li><p>system architecture</p></li></ul><div><hr></div><h2>Final Thought</h2><p>If your current system looks like this:</p><blockquote><p>query &#8594; embedding &#8594; top-k &#8594; prompt &#8594; answer</p></blockquote><p>It&#8217;s not wrong.</p><p>It&#8217;s just&#8230; incomplete.</p><p>The next generation of AI systems won&#8217;t be defined by how well they retrieve information&#8212;</p><p>but by how effectively they <strong>decide what information to retrieve, when, and why</strong>.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://sendoamoronta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://sendoamoronta.substack.com/subscribe?"><span>Subscribe now</span></a></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!RcHr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!RcHr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!RcHr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!RcHr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!RcHr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!RcHr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:637316,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://sendoamoronta.substack.com/i/191882664?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!RcHr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!RcHr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!RcHr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!RcHr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6547199-b80e-42bd-a33a-c53fae0e0afb_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div>]]></content:encoded></item><item><title><![CDATA[Google ADK and Agentic Design Patterns (Part 4): Building a Production-Grade Multi-Agent System (End-to-End Architecture)]]></title><description><![CDATA[An end-to-end blueprint for building production-grade multi-agent systems with Google ADK, from orchestration design to real-world deployment.]]></description><link>https://sendoamoronta.substack.com/p/google-adk-and-agentic-design-patterns-6de</link><guid isPermaLink="false">https://sendoamoronta.substack.com/p/google-adk-and-agentic-design-patterns-6de</guid><dc:creator><![CDATA[Sendoa Moronta]]></dc:creator><pubDate>Thu, 19 Mar 2026 07:09:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Ge0N!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the previous parts, we covered:</p><ul><li><p><strong>Part 1:</strong> primitives and multi-agent patterns</p></li><li><p><strong>Part 2:</strong> memory, evaluation, and guardrails</p></li><li><p><strong>Part 3:</strong> advanced orchestration and system economics</p></li></ul><p>In this final part, we bring everything together:</p><ul><li><p>a full <strong>production-ready architecture</strong></p></li><li><p>how components interact in practice</p></li><li><p>design decisions and tradeoffs</p></li><li><p>a realistic system you could actually deploy</p></li></ul><p>The goal is simple:</p><blockquote><p>Move from concepts to a concrete, buildable multi-agent system.</p></blockquote><div><hr></div><h1>1. The Use Case: A Production Research Agent</h1><p>To ground the architecture, we define a realistic system:</p><h3>A Deep Research Agent that can:</h3><ul><li><p>take an open-ended query</p></li><li><p>plan a research strategy</p></li><li><p>retrieve and analyze multiple sources</p></li><li><p>synthesize insights</p></li><li><p>produce a structured report</p></li></ul><p>This is one of the most common and useful real-world agent workloads.</p><div><hr></div><h1>2. High-Level Architecture</h1><p>At a high level, the system is composed of five layers:</p><div><hr></div><h2>2.1 API Layer</h2><p>Entry point for user requests.</p><p>Responsibilities:</p><ul><li><p>request validation</p></li><li><p>authentication</p></li><li><p>rate limiting</p></li></ul><div><hr></div><h2>2.2 Orchestration Layer</h2><p>Core of the system.</p><p>Components:</p><ul><li><p>planner agent</p></li><li><p>task manager</p></li><li><p>workflow controller</p></li></ul><p>This layer decides <strong>what to do and in what order</strong>.</p><div><hr></div><h2>2.3 Agent Layer</h2><p>Specialized agents:</p><ul><li><p>Research agent (retrieval)</p></li><li><p>Analysis agent (processing)</p></li><li><p>Synthesis agent (generation)</p></li><li><p>Critic agent (evaluation)</p></li></ul><p>Each agent has a narrow, well-defined responsibility.</p><div><hr></div><h2>2.4 Tool Layer</h2><p>External capabilities:</p><ul><li><p>search APIs</p></li><li><p>databases</p></li><li><p>document parsers</p></li></ul><p>Tools should remain <strong>stateless and deterministic</strong>.</p><div><hr></div><h2>2.5 Memory Layer</h2><p>Handles all state:</p><ul><li><p>session memory</p></li><li><p>vector store</p></li><li><p>structured storage</p></li></ul><p>This layer is critical for consistency across steps.</p><div><hr></div><h1>3. Execution Flow (End-to-End)</h1><p>Let&#8217;s walk through a real request:</p><div><hr></div><h2>Step 1: Request intake</h2><p>User submits:</p><blockquote><p>&#8220;Analyze the impact of AI agents on enterprise software.&#8221;</p></blockquote><p>API layer validates and forwards the request.</p><div><hr></div><h2>Step 2: Planning</h2><p>Planner agent:</p><ul><li><p>decomposes the task</p></li><li><p>creates a research plan</p></li><li><p>defines subtasks</p></li></ul><p>Example plan:</p><ul><li><p>gather sources</p></li><li><p>extract key themes</p></li><li><p>compare perspectives</p></li><li><p>generate report</p></li></ul><div><hr></div><h2>Step 3: Task orchestration</h2><p>Task manager converts plan into execution graph:</p><ul><li><p>parallel research tasks</p></li><li><p>sequential synthesis</p></li><li><p>optional critique loop</p></li></ul><div><hr></div><h2>Step 4: Parallel research</h2><p>Research agents:</p><ul><li><p>query multiple sources</p></li><li><p>retrieve documents</p></li><li><p>store results in memory</p></li></ul><p>This stage benefits heavily from parallelization.</p><div><hr></div><h2>Step 5: Analysis</h2><p>Analysis agents:</p><ul><li><p>extract structured insights</p></li><li><p>cluster information</p></li><li><p>remove redundancy</p></li></ul><div><hr></div><h2>Step 6: Synthesis</h2><p>Synthesis agent:</p><ul><li><p>generates coherent output</p></li><li><p>structures findings</p></li><li><p>adapts tone and format</p></li></ul><div><hr></div><h2>Step 7: Critique (optional but recommended)</h2><p>Critic agent:</p><ul><li><p>evaluates quality</p></li><li><p>identifies gaps</p></li><li><p>triggers revisions if needed</p></li></ul><div><hr></div><h2>Step 8: Final output</h2><p>System returns:</p><ul><li><p>structured report</p></li><li><p>citations</p></li><li><p>summary</p></li></ul><div><hr></div><h1>4. ADK-Oriented Implementation Mapping</h1><p>Mapping this architecture to ADK primitives:</p><div><hr></div><h3>Planner &#8594; LLM Agent</h3><p>Handles:</p><ul><li><p>task decomposition</p></li><li><p>reasoning</p></li></ul><div><hr></div><h3>Task Manager &#8594; Workflow Agent</h3><p>Implements:</p><ul><li><p>sequential flows</p></li><li><p>parallel execution</p></li><li><p>loops</p></li></ul><div><hr></div><h3>Workers &#8594; Sub-agents</h3><p>Each specialized agent becomes a sub-agent.</p><div><hr></div><h3>Tools &#8594; Tool interfaces</h3><p>External integrations exposed as tools.</p><div><hr></div><h3>Memory &#8594; Shared session + external stores</h3><p>Combines:</p><ul><li><p>in-session state</p></li><li><p>persistent storage</p></li></ul><div><hr></div><h1>5. Key Design Decisions</h1><div><hr></div><h2>5.1 Why multi-agent instead of single agent?</h2><p>Because:</p><ul><li><p>better modularity</p></li><li><p>easier evaluation</p></li><li><p>improved scalability</p></li></ul><p>But:</p><ul><li><p>higher complexity</p></li><li><p>more orchestration overhead</p></li></ul><div><hr></div><h2>5.2 Where to use LLM reasoning?</h2><p>Only at:</p><ul><li><p>planning boundaries</p></li><li><p>synthesis steps</p></li><li><p>evaluation</p></li></ul><p>Everything else should be deterministic when possible.</p><div><hr></div><h2>5.3 Where to introduce parallelism?</h2><p>Parallelize:</p><ul><li><p>retrieval</p></li><li><p>independent analysis tasks</p></li></ul><p>Avoid parallelizing:</p><ul><li><p>dependent reasoning steps</p></li></ul><div><hr></div><h1>6. Production Considerations</h1><div><hr></div><h2>6.1 Observability</h2><p>Must include:</p><ul><li><p>per-agent logs</p></li><li><p>execution traces</p></li><li><p>latency tracking</p></li></ul><p>Without this, debugging is nearly impossible.</p><div><hr></div><h2>6.2 Cost Control</h2><p>Key strategies:</p><ul><li><p>limit planning loops</p></li><li><p>reduce context size</p></li><li><p>use smaller models where possible</p></li></ul><div><hr></div><h2>6.3 Reliability</h2><p>Implement:</p><ul><li><p>retries</p></li><li><p>fallbacks</p></li><li><p>timeout policies</p></li></ul><div><hr></div><h2>6.4 Guardrails</h2><p>Add controls at:</p><ul><li><p>input validation</p></li><li><p>tool usage</p></li><li><p>output filtering</p></li></ul><div><hr></div><h1>7. Scaling the System</h1><div><hr></div><h2>7.1 Horizontal scaling</h2><p>Scale:</p><ul><li><p>agent workers</p></li><li><p>tool services</p></li></ul><div><hr></div><h2>7.2 Caching</h2><p>Cache:</p><ul><li><p>retrieval results</p></li><li><p>intermediate summaries</p></li></ul><div><hr></div><h2>7.3 Model routing</h2><p>Use:</p><ul><li><p>large models for reasoning</p></li><li><p>small models for simple tasks</p></li></ul><div><hr></div><h1>8. Common Failure Modes</h1><div><hr></div><h3>Over-orchestration</h3><p>Too many agents &#8594; unnecessary complexity.</p><div><hr></div><h3>Context explosion</h3><p>Memory grows uncontrollably &#8594; degraded performance.</p><div><hr></div><h3>Planner errors</h3><p>Bad plans propagate through the system.</p><div><hr></div><h3>Lack of observability</h3><p>Impossible to debug failures.</p><div><hr></div><h1>9. Minimal Viable Version (MVP)</h1><p>If you had to build this fast:</p><div><hr></div><p>Start with:</p><ul><li><p>1 planner</p></li><li><p>2 worker agents (research + synthesis)</p></li><li><p>simple sequential flow</p></li><li><p>basic memory</p></li></ul><p>Then evolve toward:</p><ul><li><p>parallelization</p></li><li><p>critique loops</p></li><li><p>advanced orchestration</p></li></ul><div><hr></div><h1>10. Final Insight</h1><p>After building multiple agent systems, one pattern becomes clear:</p><blockquote><p>The hardest part is not building agents &#8212; it is designing the system around them.</p></blockquote><div><hr></div><h1>Series Conclusion</h1><p>Across these four parts, we moved from:</p><p><strong>Part 1 &#8594;</strong> Patterns<br><strong>Part 2 &#8594;</strong> Production layers<br><strong>Part 3 &#8594;</strong> Advanced systems<br><strong>Part 4 &#8594;</strong> Real architecture</p><p>This reflects the real journey of building agent systems:</p><blockquote><p>From demos &#8594; to systems &#8594; to infrastructure.</p></blockquote><div><hr></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://sendoamoronta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://sendoamoronta.substack.com/subscribe?"><span>Subscribe now</span></a></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ge0N!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ge0N!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Ge0N!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Ge0N!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Ge0N!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ge0N!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:637316,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://sendoamoronta.substack.com/i/191450634?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ge0N!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Ge0N!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Ge0N!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Ge0N!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f2326d9-036e-47b4-88c4-c71824c007a9_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Google ADK and Agentic Design Patterns (Part 3): Advanced Orchestration, Long-Horizon Agents, and the Economics of Agent Systems]]></title><description><![CDATA[The future of agentic systems is not about smarter models, it is about smarter orchestration.]]></description><link>https://sendoamoronta.substack.com/p/google-adk-and-agentic-design-patterns-9d1</link><guid isPermaLink="false">https://sendoamoronta.substack.com/p/google-adk-and-agentic-design-patterns-9d1</guid><dc:creator><![CDATA[Sendoa Moronta]]></dc:creator><pubDate>Mon, 16 Mar 2026 16:29:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!RJEk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05212248-2d83-4c85-9245-551823abe726_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In Part 1 we explored the architectural primitives and multi-agent patterns behind Google&#8217;s Agent Development Kit (ADK).</p><p>In Part 2 we focused on the layers that determine production reliability: memory, evaluation, guardrails, and observability.</p><p>In Part 3 we step into the frontier of agent engineering:</p><ul><li><p>advanced orchestration strategies</p></li><li><p>long-horizon autonomous workflows</p></li><li><p>economic optimization of reasoning systems</p></li><li><p>real-world architecture patterns emerging in production</p></li></ul><p>The key idea is simple but profound:</p><blockquote><p>The future of agentic systems is not about smarter models, it is about smarter orchestration.</p></blockquote><div><hr></div><h1>1. The Limits of Simple Agent Architectures</h1><p>Most early agent systems rely on relatively simple orchestration structures:</p><ul><li><p>sequential pipelines</p></li><li><p>hierarchical planners</p></li><li><p>router-based dispatch</p></li></ul><p>These patterns work well for short workflows. But they struggle when tasks become:</p><ul><li><p>long-running</p></li><li><p>open-ended</p></li><li><p>exploratory</p></li><li><p>multi-domain</p></li></ul><p>In these environments, systems need <strong>adaptive orchestration</strong>, not fixed execution graphs.</p><p>This is where more advanced strategies begin to emerge.</p><div><hr></div><h1>2. Advanced Orchestration Strategies</h1><p>Beyond the basic patterns covered earlier, production systems increasingly rely on more dynamic orchestration mechanisms.</p><div><hr></div><h2>2.1 Planning-Execution Loops</h2><p>One of the most effective structures for complex workflows is the <strong>plan-execute-revise loop</strong>.</p><p>Typical structure:</p><ol><li><p>Planner generates task graph</p></li><li><p>Workers execute subtasks</p></li><li><p>Critic evaluates progress</p></li><li><p>Planner updates plan</p></li></ol><p>This allows systems to operate under uncertainty.</p><p>Key advantage:</p><p>The system can recover from incomplete or incorrect plans.</p><p>Key risk:</p><p>Planning loops can easily become <strong>cost explosions</strong> without strict iteration limits.</p><div><hr></div><h2>2.2 Dynamic Task Graphs</h2><p>Instead of static workflows, agents generate execution graphs dynamically.</p><p>Example:</p><p>A research agent might dynamically decide to:</p><ul><li><p>search sources</p></li><li><p>retrieve documents</p></li><li><p>summarize insights</p></li><li><p>spawn new research threads</p></li></ul><p>Each step creates new nodes in a task graph.</p><p>These graphs can resemble distributed computation frameworks such as DAG schedulers.</p><p>The difference is that <strong>the graph itself is generated by reasoning</strong>.</p><div><hr></div><h2>2.3 Reflection Architectures</h2><p>Reflection introduces a meta-layer where agents critique their own outputs.</p><p>Common structures:</p><p><strong>Critic&#8211;Generator loop</strong></p><p>Writer produces output<br>Critic evaluates quality<br>Writer revises</p><p><strong>Committee models</strong></p><p>Multiple agents independently solve a problem and consensus emerges.</p><p>Reflection improves quality but introduces two problems:</p><ul><li><p>latency</p></li><li><p>model cost</p></li></ul><p>As a result, reflection should be used selectively.</p><div><hr></div><h2>2.4 Multi-Agent Negotiation</h2><p>More advanced systems allow agents to interact collaboratively rather than through strict hierarchies.</p><p>Examples include:</p><ul><li><p>debate-based reasoning</p></li><li><p>cooperative planning</p></li><li><p>competitive evaluation</p></li></ul><p>These systems can produce stronger reasoning but require careful governance.</p><p>Without constraints, they may drift into unproductive loops.</p><div><hr></div><h1>3. Long-Horizon Agents</h1><p>Long-horizon agents operate over extended time periods and multi-step goals.</p><p>Unlike short workflows, these systems must handle:</p><ul><li><p>uncertainty</p></li><li><p>partial progress</p></li><li><p>changing environments</p></li></ul><p>In practice, this introduces a new category of challenges.</p><div><hr></div><h2>3.1 Persistence of Goals</h2><p>A long-horizon agent must maintain a consistent objective over many iterations.</p><p>This requires:</p><ul><li><p>stable memory representations</p></li><li><p>task tracking systems</p></li><li><p>progress evaluation mechanisms</p></li></ul><p>Without these structures, agents lose coherence quickly.</p><div><hr></div><h2>3.2 Task Decomposition at Scale</h2><p>Complex goals often decompose into dozens or hundreds of subtasks.</p><p>Effective systems therefore need:</p><ul><li><p>hierarchical planners</p></li><li><p>dependency tracking</p></li><li><p>prioritization heuristics</p></li></ul><p>This begins to resemble project management systems &#8212; but powered by reasoning engines.</p><div><hr></div><h2>3.3 Recovery and Self-Correction</h2><p>Failures are inevitable in long-horizon workflows.</p><p>Robust systems incorporate recovery strategies such as:</p><ul><li><p>retry loops</p></li><li><p>alternative tool selection</p></li><li><p>plan restructuring</p></li></ul><p>This is another area where reflection architectures prove valuable.</p><div><hr></div><h1>4. The Economics of Agent Systems</h1><p>One of the most overlooked topics in agent design is <strong>economic optimization</strong>.</p><p>Large agent systems can become extremely expensive if not designed carefully.</p><div><hr></div><h2>4.1 Cost Drivers</h2><p>The main cost drivers in agent systems are:</p><ul><li><p>model inference calls</p></li><li><p>context window size</p></li><li><p>tool invocation frequency</p></li><li><p>reflection loops</p></li></ul><p>As orchestration complexity increases, these costs can scale nonlinearly.</p><div><hr></div><h2>4.2 Cost-Aware Orchestration</h2><p>Production systems increasingly include cost awareness in their decision logic.</p><p>Examples include:</p><p>Dynamic model routing:</p><ul><li><p>large models for planning</p></li><li><p>smaller models for execution</p></li></ul><p>Selective reflection:</p><ul><li><p>critique only high-risk outputs</p></li></ul><p>Adaptive reasoning depth:</p><ul><li><p>simple tasks use shallow reasoning</p></li><li><p>complex tasks trigger deeper workflows</p></li></ul><p>These strategies dramatically reduce operating costs.</p><div><hr></div><h2>4.3 Latency vs Quality Tradeoffs</h2><p>Agent architectures must constantly balance three competing objectives:</p><ul><li><p>quality</p></li><li><p>cost</p></li><li><p>latency</p></li></ul><p>There is no universal optimum.</p><p>Systems must tune these parameters according to application requirements.</p><div><hr></div><h1>5. Emerging Production Architectures</h1><p>Across organizations experimenting with ADK-style systems, several architecture patterns are becoming common.</p><div><hr></div><h2>5.1 The Agent Platform Model</h2><p>Instead of building individual agents, organizations build <strong>internal agent platforms</strong>.</p><p>These platforms provide:</p><ul><li><p>orchestration frameworks</p></li><li><p>shared memory systems</p></li><li><p>evaluation infrastructure</p></li><li><p>tool registries</p></li></ul><p>Agents become applications on top of this platform.</p><div><hr></div><h2>5.2 Agent Capability Networks</h2><p>Another emerging pattern is the <strong>capability network</strong>.</p><p>In this architecture:</p><ul><li><p>each agent exposes specialized capabilities</p></li><li><p>other agents discover and use them dynamically</p></li></ul><p>This creates a loosely coupled ecosystem of cognitive services.</p><div><hr></div><h2>5.3 Human-AI Hybrid Systems</h2><p>Fully autonomous agents remain rare in production.</p><p>Most successful deployments integrate humans into the loop for:</p><ul><li><p>approvals</p></li><li><p>oversight</p></li><li><p>exception handling</p></li></ul><p>These hybrid architectures often outperform purely automated systems.</p><div><hr></div><h1>6. Reliability Engineering for Agents</h1><p>Traditional reliability engineering principles apply directly to agent systems.</p><p>Key mechanisms include:</p><p>Retry strategies<br>Timeout enforcement<br>Fallback models<br>Graceful degradation</p><p>One critical principle is:</p><blockquote><p>Always assume that reasoning will fail.</p></blockquote><p>Systems must therefore be designed to contain and recover from failures.</p><div><hr></div><h1>7. Design Lessons from Early Deployments</h1><p>Across early agent deployments, several consistent lessons appear.</p><div><hr></div><h3>Simpler architectures outperform complex ones</h3><p>Multi-agent systems introduce coordination overhead.</p><p>Many problems can still be solved with a single well-structured agent.</p><div><hr></div><h3>Deterministic control improves reliability</h3><p>Let LLMs handle reasoning, not orchestration.</p><p>Workflow control should remain explicit whenever possible.</p><div><hr></div><h3>Observability is non-negotiable</h3><p>Without detailed tracing, debugging multi-agent systems becomes nearly impossible.</p><div><hr></div><h3>Memory design determines scalability</h3><p>Poor memory architectures cause runaway context growth and unpredictable reasoning.</p><div><hr></div><h1>Conclusion</h1><p>The evolution of agent systems mirrors the early history of distributed computing.</p><p>At first, systems appear magical.</p><p>Then the hard engineering problems emerge.</p><p>Google ADK represents an important step in bringing discipline and architectural clarity to this space.</p><p>But the real transformation will come from engineers who treat agents not as demos but as <strong>production infrastructure</strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!RJEk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05212248-2d83-4c85-9245-551823abe726_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!RJEk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05212248-2d83-4c85-9245-551823abe726_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!RJEk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05212248-2d83-4c85-9245-551823abe726_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!RJEk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05212248-2d83-4c85-9245-551823abe726_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!RJEk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05212248-2d83-4c85-9245-551823abe726_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!RJEk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05212248-2d83-4c85-9245-551823abe726_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/05212248-2d83-4c85-9245-551823abe726_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:637316,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://sendoamoronta.substack.com/i/191147876?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05212248-2d83-4c85-9245-551823abe726_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!RJEk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05212248-2d83-4c85-9245-551823abe726_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!RJEk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05212248-2d83-4c85-9245-551823abe726_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!RJEk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05212248-2d83-4c85-9245-551823abe726_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!RJEk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05212248-2d83-4c85-9245-551823abe726_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://sendoamoronta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://sendoamoronta.substack.com/subscribe?"><span>Subscribe now</span></a></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Google ADK and Agentic Design Patterns (Part 2): Memory, Evaluation, Guardrails and Production Systems]]></title><description><![CDATA[A production-focused deep dive into memory architectures, evaluation strategies, guardrails, and the operational realities of building large-scale agentic systems with ADK]]></description><link>https://sendoamoronta.substack.com/p/google-adk-and-agentic-design-patterns-116</link><guid isPermaLink="false">https://sendoamoronta.substack.com/p/google-adk-and-agentic-design-patterns-116</guid><dc:creator><![CDATA[Sendoa Moronta]]></dc:creator><pubDate>Wed, 11 Mar 2026 08:36:25 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!CPIv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In Part 1, we framed Google ADK as a systems-oriented approach to building multi-agent architectures and covered its primitives and execution patterns.</p><p>In Part 2, we go deeper into the layers that determine whether an agentic system actually survives production:</p><ul><li><p>memory and state design patterns</p></li><li><p>evaluation and observability frameworks</p></li><li><p>guardrails and policy enforcement</p></li><li><p>MCP and A2A interoperability</p></li><li><p>deployment and scaling architectures</p></li></ul><p>The central thesis: <strong>most agent failures in production are not reasoning failures &#8212; they are systems design failures.</strong></p><div><hr></div><h2>1. Memory and State: The Hardest Layer of Agentic Systems</h2><p>If orchestration defines structure, memory defines behavior. Most real-world issues in ADK systems stem from poorly designed state boundaries rather than poor prompts.</p><p>ADK supports flexible state management via shared session context, but that flexibility requires discipline. Without clear memory design, systems drift into:</p><ul><li><p>hallucination amplification</p></li><li><p>uncontrolled context growth</p></li><li><p>inconsistent reasoning across agents</p></li></ul><p>A useful framing:</p><blockquote><p>Memory in agentic systems should be engineered like storage architecture &#8212; not like chat history.</p></blockquote><div><hr></div><h3>1.1 A taxonomy of memory in ADK systems</h3><p>In practice, ADK deployments converge toward four memory layers:</p><div><hr></div><h4>Ephemeral execution memory</h4><p>Short-lived reasoning context within a single run.</p><p>Typical uses:</p><ul><li><p>tool outputs</p></li><li><p>intermediate reasoning</p></li><li><p>temporary constraints</p></li></ul><p>Best practice:</p><ul><li><p>aggressively prune</p></li><li><p>summarize frequently</p></li><li><p>avoid cascading growth across loops</p></li></ul><div><hr></div><h4>Session memory</h4><p>State shared across agents within a workflow execution.</p><p>Strengths:</p><ul><li><p>enables coordination</p></li><li><p>reduces redundant reasoning</p></li></ul><p>Risks:</p><ul><li><p>unclear ownership</p></li><li><p>accidental coupling between agents</p></li></ul><p>Production systems often enforce <strong>state contracts</strong> to mitigate this.</p><div><hr></div><h4>Persistent structured memory</h4><p>External storage systems:</p><ul><li><p>vector stores</p></li><li><p>relational stores</p></li><li><p>knowledge graphs</p></li></ul><p>Best suited for:</p><ul><li><p>long-term learning</p></li><li><p>personalization</p></li><li><p>domain knowledge grounding</p></li></ul><p>Crucially, structured memory should remain queryable and inspectable by humans.</p><div><hr></div><h4>Procedural memory</h4><p>Often overlooked: encoded workflows and policies learned over time.</p><p>Examples:</p><ul><li><p>routing heuristics</p></li><li><p>agent selection strategies</p></li><li><p>tool usage rules</p></li></ul><p>In mature systems, this becomes a critical optimization layer.</p><div><hr></div><h3>1.2 Key memory design patterns</h3><div><hr></div><h4>Summarization cascades</h4><p>Instead of growing context indefinitely, systems compress reasoning into layered summaries.</p><p>Works best for:</p><ul><li><p>long-running research workflows</p></li><li><p>multi-stage planning systems</p></li></ul><div><hr></div><h4>State checkpointing</h4><p>Capture stable intermediate states for rollback and debugging.</p><p>Essential for:</p><ul><li><p>iterative loops</p></li><li><p>high-cost pipelines</p></li></ul><div><hr></div><h4>Retrieval-bounded reasoning</h4><p>Agents operate within scoped retrieval windows rather than full histories.</p><p>Reduces hallucinations and latency simultaneously.</p><div><hr></div><h3>1.3 Anti-patterns</h3><p>Common production failures:</p><ul><li><p>dumping full transcripts into context</p></li><li><p>mixing structured + unstructured memory carelessly</p></li><li><p>allowing uncontrolled tool-output accumulation</p></li></ul><div><hr></div><h2>2. Evaluation: From Prompt Tests to Systems Engineering</h2><p>Evaluation remains the least mature layer in agentic systems.</p><p>Traditional approaches fail because:</p><ul><li><p>agent outputs are stochastic</p></li><li><p>workflows are multi-stage</p></li><li><p>failures are often emergent</p></li></ul><p>The solution: treat evaluation as a distributed systems problem.</p><div><hr></div><h3>2.1 Levels of evaluation</h3><div><hr></div><h4>Component-level evaluation</h4><p>Evaluate individual agents:</p><ul><li><p>reasoning correctness</p></li><li><p>tool selection accuracy</p></li><li><p>output formatting</p></li></ul><p>Useful but insufficient.</p><div><hr></div><h4>Workflow-level evaluation</h4><p>Tests entire pipelines:</p><ul><li><p>task completion success</p></li><li><p>latency distribution</p></li><li><p>cost efficiency</p></li></ul><p>Reveals integration failures.</p><div><hr></div><h4>System-level evaluation</h4><p>Captures emergent behavior:</p><ul><li><p>stability under load</p></li><li><p>consistency across runs</p></li><li><p>long-tail failures</p></li></ul><p>This level often uncovers the most serious issues.</p><div><hr></div><h3>2.2 Evaluation methodologies</h3><div><hr></div><h4>Reference-based evaluation</h4><p>Compare outputs against ground truth.</p><p>Works well for:</p><ul><li><p>structured tasks</p></li><li><p>code generation</p></li><li><p>analytics workflows</p></li></ul><div><hr></div><h4>Model-as-judge evaluation</h4><p>LLMs evaluate other LLM outputs.</p><p>Best suited for:</p><ul><li><p>subjective outputs</p></li><li><p>qualitative tasks</p></li></ul><p>But requires calibration to avoid drift.</p><div><hr></div><h4>Simulation-based evaluation</h4><p>Synthetic workloads stress-test systems at scale.</p><p>Essential for:</p><ul><li><p>enterprise deployments</p></li><li><p>reliability engineering</p></li></ul><div><hr></div><h3>2.3 Observability requirements</h3><p>Agent systems demand deeper observability than traditional apps:</p><p>You need:</p><ul><li><p>per-agent tracing</p></li><li><p>state snapshots</p></li><li><p>tool-call visibility</p></li><li><p>structured logs</p></li></ul><p>Without this, debugging becomes guesswork.</p><div><hr></div><h2>3. Guardrails and Policy Enforcement</h2><p>Guardrails in ADK systems operate across multiple layers.</p><p>The mistake many teams make is treating guardrails as prompt constraints rather than architectural controls.</p><div><hr></div><h3>3.1 Guardrail layers</h3><div><hr></div><h4>Input guardrails</h4><p>Sanitize and validate inputs before agents see them.</p><p>Examples:</p><ul><li><p>schema validation</p></li><li><p>policy filters</p></li><li><p>injection detection</p></li></ul><div><hr></div><h4>Reasoning guardrails</h4><p>Constrain decision boundaries during execution.</p><p>Examples:</p><ul><li><p>tool whitelisting</p></li><li><p>role constraints</p></li><li><p>bounded planning horizons</p></li></ul><div><hr></div><h4>Output guardrails</h4><p>Post-process outputs:</p><ul><li><p>factual verification</p></li><li><p>compliance checks</p></li><li><p>formatting enforcement</p></li></ul><div><hr></div><h3>3.2 Runtime governance patterns</h3><div><hr></div><h4>Approval gates (HITL)</h4><p>Introduce human review for:</p><ul><li><p>irreversible actions</p></li><li><p>high-risk outputs</p></li><li><p>legal domains</p></li></ul><div><hr></div><h4>Policy-as-code</h4><p>Formalize constraints as executable logic.</p><p>Becomes essential at scale.</p><div><hr></div><h4>Fallback orchestration</h4><p>When agents fail:</p><ul><li><p>degrade gracefully</p></li><li><p>revert to deterministic flows</p></li><li><p>escalate to humans</p></li></ul><div><hr></div><h2>4. Interoperability: MCP and A2A ecosystems</h2><p>As agent ecosystems mature, interoperability becomes unavoidable.</p><p>Two emerging standards matter:</p><div><hr></div><h3>MCP (Model Context Protocol)</h3><p>Defines standardized interaction between models, tools, and memory layers.</p><p>Key benefit:</p><ul><li><p>portability across ecosystems</p></li><li><p>reduced vendor lock-in</p></li></ul><div><hr></div><h3>A2A (Agent-to-Agent communication)</h3><p>Enables structured communication across independent agents.</p><p>Future systems will likely resemble:</p><blockquote><p>loosely coupled networks of specialized cognitive services.</p></blockquote><div><hr></div><h2>5. Production Architectures for ADK Systems</h2><p>Production agent systems look very different from prototypes.</p><div><hr></div><h3>5.1 Execution topologies</h3><p>Common deployment patterns:</p><div><hr></div><h4>Centralized orchestration</h4><p>Single orchestrator service manages workflows.</p><p>Pros:</p><ul><li><p>simplicity</p></li><li><p>control</p></li></ul><p>Cons:</p><ul><li><p>scaling limits</p></li></ul><div><hr></div><h4>Distributed orchestration</h4><p>Agents run as independent services.</p><p>Pros:</p><ul><li><p>scalability</p></li><li><p>resilience</p></li></ul><p>Cons:</p><ul><li><p>coordination complexity</p></li></ul><div><hr></div><h4>Hybrid architectures</h4><p>Most real systems blend both approaches.</p><div><hr></div><h3>5.2 Scaling strategies</h3><p>Scaling requires balancing:</p><ul><li><p>concurrency</p></li><li><p>cost</p></li><li><p>latency</p></li></ul><p>Key techniques:</p><ul><li><p>batching tool calls</p></li><li><p>caching reasoning steps</p></li><li><p>dynamic model routing</p></li></ul><div><hr></div><h3>5.3 Reliability engineering</h3><p>Production systems need:</p><ul><li><p>retry strategies</p></li><li><p>timeout policies</p></li><li><p>circuit breakers</p></li></ul><p>Classic distributed systems patterns apply directly.</p><div><hr></div><h2>6. Design heuristics from production</h2><p>Lessons repeated across deployments:</p><div><hr></div><p><strong>1. Start simpler than you think.</strong><br>Multi-agent complexity compounds quickly.</p><div><hr></div><p><strong>2. Determinism beats cleverness.</strong><br>Prefer structured orchestration over emergent behavior.</p><div><hr></div><p><strong>3. Measure everything.</strong><br>Unobserved agents fail silently.</p><div><hr></div><p><strong>4. Optimize memory early.</strong><br>Context inefficiency kills scalability.</p><div><hr></div><p><strong>5. Design for failure first.</strong><br>Agent systems fail frequently and unpredictably.</p><div><hr></div><h2>Conclusion</h2><p>If Part 1 was about structure, Part 2 is about survival.</p><p>The hardest problems in agentic systems are not reasoning problems &#8212; they are:</p><ul><li><p>memory problems</p></li><li><p>evaluation problems</p></li><li><p>governance problems</p></li><li><p>systems engineering problems</p></li></ul><p>Google ADK provides a strong foundation, but success ultimately depends on adopting production-grade design discipline.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CPIv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CPIv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!CPIv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!CPIv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!CPIv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CPIv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:637316,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://sendoamoronta.substack.com/i/190595887?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CPIv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!CPIv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!CPIv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!CPIv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4cc3540-02b5-4257-b6c5-e40ce649b2b0_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://sendoamoronta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://sendoamoronta.substack.com/subscribe?"><span>Subscribe now</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Google ADK and Agentic Design Patterns (Part 1): Architecture, Primitives and Multi-Agent Systems]]></title><description><![CDATA[A systems-level deep dive into Google&#8217;s Agent Development Kit and the architectural patterns shaping production-grade multi-agent systems.]]></description><link>https://sendoamoronta.substack.com/p/google-adk-and-agentic-design-patterns</link><guid isPermaLink="false">https://sendoamoronta.substack.com/p/google-adk-and-agentic-design-patterns</guid><dc:creator><![CDATA[Sendoa Moronta]]></dc:creator><pubDate>Mon, 09 Mar 2026 07:37:02 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!m1G5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article introduces a systems-level mental model for designing agentic applications using Google&#8217;s Agent Development Kit (ADK). Rather than treating agents as glorified LLM wrappers, ADK frames them as composable, distributed cognitive services.</p><p>In Part 1, we focus on:</p><ul><li><p>ADK&#8217;s architectural primitives</p></li><li><p>hierarchical composition and execution semantics</p></li><li><p>the multi-agent patterns emerging from Google&#8217;s guidance</p></li><li><p>design tradeoffs observed in real systems</p></li></ul><p>Part 2 will cover memory, evaluation, guardrails, observability, and production architecture.</p><div><hr></div><h2>1. From LLM wrappers to distributed cognitive systems</h2><p>The shift toward agentic architectures is less about &#8220;agents&#8221; themselves and more about a deeper transformation in how we design software systems around reasoning engines. Early LLM applications followed a predictable trajectory: prompt templates, retrieval augmentation, tool calls.</p><p>But as soon as tasks became open-ended, multi-step, and domain-spanning, single-agent approaches began collapsing under their own ambiguity. Prompt-level orchestration does not scale.</p><p>Google&#8217;s ADK represents a decisive move away from prompt-centric thinking toward <strong>structured orchestration of reasoning systems</strong>. The key shift is conceptual:</p><blockquote><p>Agentic systems should be designed like distributed systems &#8212; not like prompts.</p></blockquote><p>ADK&#8217;s contribution is not primarily its SDK surface, but its formalization of reusable architectural patterns for cognitive workflows.</p><div><hr></div><h2>2. A mental model for ADK multi-agent systems</h2><p>ADK defines a multi-agent system as a hierarchy of specialized agents coordinating toward a shared objective. That definition embeds three foundational assumptions.</p><h3>Specialization over generalization</h3><p>Large monolithic agents degrade quickly when handling heterogeneous tasks. Splitting responsibilities across specialized agents improves:</p><ul><li><p>controllability</p></li><li><p>interpretability</p></li><li><p>evaluation granularity</p></li><li><p>cost predictability</p></li></ul><p>This mirrors microservice decomposition &#8212; but with reasoning responsibilities instead of compute ones.</p><div><hr></div><h3>Emergent behavior as a feature</h3><p>Multi-agent architectures often exhibit useful emergent properties:</p><ul><li><p>implicit consensus formation</p></li><li><p>error correction loops</p></li><li><p>dynamic task routing</p></li></ul><p>Rather than eliminating these dynamics, ADK encourages shaping them via structured orchestration.</p><div><hr></div><h3>Explicit orchestration over implicit reasoning</h3><p>A key philosophical difference between ADK and earlier agent frameworks is its emphasis on <strong>deterministic workflow control</strong>.</p><p>Instead of relying on an LLM to infer process structure, ADK lets engineers define execution topology explicitly and then insert reasoning only where needed.</p><p>This separation of concerns is arguably the most important design insight behind the framework.</p><div><hr></div><h2>3. ADK primitives: the compositional toolkit</h2><p>Nearly all ADK systems emerge from three primitive agent types plus hierarchical composition semantics.</p><div><hr></div><h3>3.1 LLM Agents: cognitive execution units</h3><p>LLM agents perform:</p><ul><li><p>interpretation</p></li><li><p>reasoning</p></li><li><p>planning</p></li><li><p>decision-making</p></li></ul><p>They sit at decision boundaries and should be used sparingly. Overusing LLM agents for orchestration often leads to fragile systems with poor reproducibility.</p><p>A useful heuristic:</p><blockquote><p>If logic can be deterministic, don&#8217;t delegate it to an LLM.</p></blockquote><div><hr></div><h3>3.2 Workflow Agents: execution topology</h3><p>Workflow agents structure execution flows without reasoning overhead.</p><p>Core variants:</p><p><strong>SequentialAgent</strong><br>Deterministic pipelines with predictable semantics.</p><p><strong>ParallelAgent</strong><br>Concurrent decomposition with join semantics.</p><p><strong>LoopAgent</strong><br>Iterative refinement with termination criteria.</p><p>These constructs function similarly to DAG orchestration frameworks but embed naturally into agent hierarchies.</p><div><hr></div><h3>3.3 Custom Agents: deterministic integration layers</h3><p>Custom agents typically encapsulate:</p><ul><li><p>external system integration</p></li><li><p>rule-based transformations</p></li><li><p>heavy compute steps</p></li></ul><p>In practice, production systems rely heavily on custom agents for reliability and cost efficiency.</p><div><hr></div><h2>4. Hierarchical composition and execution semantics</h2><p>ADK systems typically resemble execution trees:</p><ul><li><p>root orchestrator defines intent</p></li><li><p>intermediate agents transform state</p></li><li><p>leaf agents execute specialized tasks</p></li></ul><h3>Shared session state</h3><p>A defining feature of ADK systems is shared session state across sub-agents. This enables implicit coordination without heavy message passing but introduces design challenges:</p><ul><li><p>state bloat</p></li><li><p>race conditions in parallel execution</p></li><li><p>unclear ownership boundaries</p></li></ul><p>In complex systems, explicit state contracts often outperform implicit sharing.</p><div><hr></div><h3>Tools vs sub-agents</h3><p>One recurring design decision:</p><p><strong>Tools</strong><br>Stateless, atomic capabilities.</p><p><strong>Sub-agents</strong><br>Stateful, multi-step reasoning workflows.</p><p>A practical rule:</p><blockquote><p>If the capability needs reasoning or iteration, it should likely be a sub-agent.</p></blockquote><div><hr></div><h2>5. The emerging multi-agent pattern taxonomy</h2><p>Google&#8217;s guidance implicitly converges on a set of recurring patterns. These are not rigid templates but composable execution motifs.</p><div><hr></div><h3>5.1 Sequential pipelines</h3><p>The simplest structure: deterministic stepwise processing.</p><p>Strong fit for:</p><ul><li><p>ETL-like reasoning workflows</p></li><li><p>structured analysis pipelines</p></li><li><p>compliance transformations</p></li></ul><p>Tradeoff: limited adaptability to uncertainty.</p><div><hr></div><h3>5.2 Hierarchical orchestrator-worker systems</h3><p>Perhaps the dominant real-world pattern.</p><p>Structure:</p><ul><li><p>planner agent decomposes goals</p></li><li><p>workers execute specialized subtasks</p></li><li><p>synthesizer aggregates results</p></li></ul><p>Works well for:</p><ul><li><p>research agents</p></li><li><p>analytics workflows</p></li><li><p>enterprise copilots</p></li></ul><p>Main risk: cascading failure from planner errors.</p><div><hr></div><h3>5.3 Router architectures</h3><p>A routing agent dispatches requests to specialized workers.</p><p>Strong fit for:</p><ul><li><p>multi-domain copilots</p></li><li><p>service desks</p></li><li><p>modular enterprise platforms</p></li></ul><p>Key challenge: misrouting due to ambiguity.</p><div><hr></div><h3>5.4 Parallel decomposition</h3><p>Tasks split into independent subtasks executed concurrently.</p><p>Best suited for:</p><ul><li><p>large-scale research</p></li><li><p>ensemble reasoning</p></li><li><p>consensus workflows</p></li></ul><p>Primary tradeoff: reconciliation complexity.</p><div><hr></div><h3>5.5 Iterative refinement loops</h3><p>Critic-generator loops and self-improvement cycles.</p><p>Ideal for:</p><ul><li><p>long-form writing</p></li><li><p>code generation</p></li><li><p>design optimization</p></li></ul><p>But expensive and latency-heavy.</p><div><hr></div><h3>5.6 Agent-as-tool ecosystems</h3><p>Agents exposed as reusable internal services.</p><p>This pattern becomes critical in large organizations where agent capabilities must be discoverable and composable.</p><div><hr></div><h3>5.7 Human-in-the-loop governance</h3><p>In regulated domains, humans serve as supervisory agents enforcing:</p><ul><li><p>safety constraints</p></li><li><p>accountability boundaries</p></li><li><p>subjective judgment</p></li></ul><p>Hybrid systems often outperform fully autonomous ones in production.</p><div><hr></div><h3>5.8 Hybrid compositions</h3><p>Most real systems combine patterns dynamically:</p><ul><li><p>hierarchical + parallel</p></li><li><p>router + loop</p></li><li><p>sequential + HITL</p></li></ul><p>The art lies in knowing where to introduce structure and where to allow flexibility.</p><div><hr></div><h2>6. Real-world tradeoffs</h2><h3>Latency and cost explosion</h3><p>Each additional agent multiplies model calls. Parallelization reduces latency but increases spend.</p><div><hr></div><h3>Orchestration brittleness</h3><p>LLM-driven planners introduce unpredictability. Deterministic fallbacks are essential.</p><div><hr></div><h3>Observability complexity</h3><p>Multi-agent systems require:</p><ul><li><p>structured tracing</p></li><li><p>per-agent evaluation</p></li><li><p>state introspection</p></li></ul><p>Traditional logging is insufficient.</p><div><hr></div><h3>Evaluation challenges</h3><p>Testing agents individually does not guarantee system reliability. Emergent failures often occur only in integrated runs.</p><div><hr></div><h2>7. Design heuristics</h2><p>Based on production experience and evolving guidance:</p><ul><li><p>Structured workflows &#8594; sequential pipelines</p></li><li><p>Open-ended tasks &#8594; hierarchical orchestration</p></li><li><p>Multi-domain systems &#8594; routing patterns</p></li><li><p>High-throughput systems &#8594; parallel decomposition</p></li><li><p>High-risk domains &#8594; HITL</p></li></ul><p>But more importantly:</p><blockquote><p>Prefer simpler systems until complexity is justified by measurable gains.</p></blockquote><div><hr></div><h2>Conclusion</h2><p>Google ADK does not introduce fundamentally new capabilities. Its significance lies in crystallizing a shared vocabulary for designing agentic systems as structured, composable architectures.</p><p>The real lesson is not about tools, it is about adopting a systems engineering mindset for reasoning infrastructure.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!m1G5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!m1G5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!m1G5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!m1G5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!m1G5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!m1G5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:637316,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://sendoamoronta.substack.com/i/190362612?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!m1G5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!m1G5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!m1G5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!m1G5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d465a13-fe74-4717-b1f7-ee72d00e724f_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://sendoamoronta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://sendoamoronta.substack.com/subscribe?"><span>Subscribe now</span></a></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Designing a Real-Time Fraud Detection Platform with Apache Flink and Serverless AWS]]></title><description><![CDATA[How to detect coordinated fraud patterns in milliseconds using Apache Flink, Kafka and fully managed AWS infrastructure.]]></description><link>https://sendoamoronta.substack.com/p/designing-a-real-time-fraud-detection</link><guid isPermaLink="false">https://sendoamoronta.substack.com/p/designing-a-real-time-fraud-detection</guid><dc:creator><![CDATA[Sendoa Moronta]]></dc:creator><pubDate>Wed, 04 Mar 2026 08:58:46 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!6xr1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It happens in milliseconds.</p><p>A malicious actor can execute hundreds of micro-transactions in seconds, rotating IPs, devices and payment methods. By the time a traditional analytics pipeline flags the activity, the damage is already done.</p><p>Legacy fraud systems were built around <strong>batch analytics</strong> and <strong>delayed risk scoring</strong>. Modern digital platforms (fintech, e-commerce, marketplaces) require something very different:</p><p><strong>streaming intelligence capable of making decisions as events happen.</strong></p><p>In this article we&#8217;ll design a <strong>serverless, real-time fraud detection platform on AWS</strong> using:</p><ul><li><p>Apache Flink</p></li><li><p>Amazon MSK Serverless (Kafka)</p></li><li><p>DynamoDB for contextual enrichment</p></li><li><p>EventBridge and SNS for alerting</p></li><li><p>Fully managed, autoscaling infrastructure</p></li></ul><p>The goal is simple:</p><p><strong>detect coordinated fraud patterns in real time with sub-second latency.</strong></p><div><hr></div><h1>The Problem with Traditional Fraud Detection</h1><p>Most legacy systems rely on pipelines like this:</p><pre><code><code>Transactions &#8594; Data Warehouse &#8594; Batch Jobs &#8594; Fraud Alerts
</code></code></pre><p>These pipelines typically run every <strong>15 minutes to several hours</strong>.</p><p>This creates three fundamental problems.</p><h3>1. Detection Happens Too Late</h3><p>Fraudsters exploit latency.</p><p>If an attacker can perform 200 transactions in 30 seconds, a batch job running every 10 minutes is useless.</p><div><hr></div><h3>2. Systems Lack Sequential Awareness</h3><p>Fraud often manifests as <strong>patterns of events</strong>, not single anomalies.</p><p>Example:</p><ol><li><p>Login from foreign IP</p></li><li><p>New device registration</p></li><li><p>Multiple failed payment attempts</p></li><li><p>Large successful transaction</p></li></ol><p>Each event alone may look harmless.</p><p>Together, they form a clear attack pattern.</p><div><hr></div><h3>3. Lack of Real-Time Context</h3><p>Fraud decisions require context:</p><ul><li><p>known devices</p></li><li><p>previous IP addresses</p></li><li><p>risk score</p></li><li><p>recent activity</p></li></ul><p>Batch systems struggle to access this information <strong>at event time</strong>.</p><div><hr></div><h1>Design Principles for Modern Fraud Detection</h1><p>A modern fraud detection architecture should support:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;markdown&quot;,&quot;nodeId&quot;:&quot;875b8141-aa28-4489-966b-9a6e14f132dc&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-markdown">| Requirement                  | Technical Implication     |
| ---------------------------- | ------------------------- |
| Sub-second decisioning       | Stream processing         |
| Behavioral pattern detection | Stateful analytics        |
| Context-aware scoring        | Real-time enrichment      |
| Elastic scalability          | Serverless infrastructure |
| Fault tolerance              | Checkpointed state        |
</code></pre></div><p>These requirements naturally lead to <strong>stream processing architectures</strong>.</p><div><hr></div><h1>Architecture Overview</h1><p>The system processes every transaction as a <strong>streaming event</strong>.</p><p>High level architecture:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6xr1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6xr1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp 424w, https://substackcdn.com/image/fetch/$s_!6xr1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp 848w, https://substackcdn.com/image/fetch/$s_!6xr1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp 1272w, https://substackcdn.com/image/fetch/$s_!6xr1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6xr1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp" width="1009" height="411" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:411,&quot;width&quot;:1009,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:14660,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://sendoamoronta.substack.com/i/189857430?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6xr1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp 424w, https://substackcdn.com/image/fetch/$s_!6xr1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp 848w, https://substackcdn.com/image/fetch/$s_!6xr1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp 1272w, https://substackcdn.com/image/fetch/$s_!6xr1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67b01525-90ed-4ff2-bd01-af651d8dafad_1009x411.webp 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Key characteristics:</p><ul><li><p><strong>event-driven</strong></p></li><li><p><strong>stateful processing</strong></p></li><li><p><strong>horizontal scaling</strong></p></li><li><p><strong>fully managed infrastructure</strong></p></li></ul><p>No servers to operate.</p><div><hr></div><h1>Why Apache Flink for Fraud Detection</h1><p>Fraud detection is fundamentally a <strong>stateful streaming problem</strong>.</p><p>Apache Flink is particularly well suited because it provides:</p><h3>Event Time Processing</h3><p>Transactions can arrive <strong>out of order</strong>. Flink allows processing based on the <strong>true event timestamp</strong>, not arrival time.</p><div><hr></div><h3>Stateful Operators</h3><p>Fraud detection requires remembering previous behavior.</p><p>Examples:</p><ul><li><p>previous login attempts</p></li><li><p>device history</p></li><li><p>transaction velocity</p></li></ul><p>Flink maintains this state efficiently across distributed nodes.</p><div><hr></div><h3>Exactly-Once Processing</h3><p>Financial pipelines cannot tolerate duplicated alerts or inconsistent state.</p><p>Flink achieves <strong>exactly-once guarantees</strong> via checkpointing.</p><div><hr></div><h3>Complex Event Processing (CEP)</h3><p>Fraud patterns are often <strong>sequences of events</strong>.</p><p>Flink&#8217;s CEP library enables pattern detection directly on streams.</p><div><hr></div><h1>Event Flow Deep Dive</h1><p>Let&#8217;s walk through what happens when a transaction arrives.</p><h3>Step 1: Event Ingestion</h3><p>Applications publish transaction events to Kafka.</p><p>Example event:</p><pre><code><code>{
  "userId": "1234-5678",
  "amount": 4200,
  "ipAddress": "91.18.22.10",
  "deviceId": "mobile-9832",
  "timestamp": 171123123
}</code></code></pre><p>Kafka (via <strong>MSK Serverless</strong>) provides:</p><ul><li><p>high throughput ingestion</p></li><li><p>partitioned ordering</p></li><li><p>durable event storage</p></li></ul><div><hr></div><h3>Step 2: Stream Processing with Flink</h3><p>A Flink job consumes events directly from Kafka.</p><pre><code><code>StreamExecutionEnvironment env =
    StreamExecutionEnvironment.getExecutionEnvironment();

DataStream&lt;TransactionEvent&gt; transactions =
    env.addSource(new FlinkKafkaConsumer&lt;&gt;(...));</code></code></pre><p>Events are processed continuously with millisecond latency.</p><div><hr></div><h1>Real-Time Context Enrichment</h1><p>Fraud scoring requires user context.</p><p>Example user profile stored in DynamoDB:</p><pre><code><code>{
  "userId": "1234-5678",
  "riskScore": 0.82,
  "lastKnownIp": "10.3.55.1",
  "knownDevices": ["dev123", "dev456"]
}</code></code></pre><p>We enrich transactions using <strong>asynchronous DynamoDB lookups</strong>.</p><p>This avoids blocking the processing pipeline.</p><h3>Async Enrichment Function</h3><pre><code><code>public class EnrichWithUserProfile
  extends AsyncFunction&lt;TransactionEvent, EnrichedTransactionEvent&gt; {

    private transient DynamoDbAsyncClient dynamoClient;

    @Override
    public void open(Configuration parameters) {
        dynamoClient = DynamoDbAsyncClient.create();
    }

    @Override
    public void asyncInvoke(
        TransactionEvent input,
        ResultFuture&lt;EnrichedTransactionEvent&gt; resultFuture) {

        GetItemRequest request = GetItemRequest.builder()
            .tableName("UserProfile")
            .key(Map.of("userId", AttributeValue.fromS(input.userId)))
            .build();

        dynamoClient.getItem(request)
            .thenAccept(response -&gt; {

                Map&lt;String, AttributeValue&gt; item = response.item();

                double risk =
                    Double.parseDouble(item.get("riskScore").n());

                String ip = item.get("lastKnownIp").s();

                List&lt;String&gt; devices =
                    item.get("knownDevices").l().stream()
                        .map(AttributeValue::s)
                        .toList();

                resultFuture.complete(
                    List.of(new EnrichedTransactionEvent(
                        input, risk, ip, devices)));
            });
    }
}</code></code></pre><p>We integrate it into the pipeline:</p><pre><code><code>DataStream&lt;EnrichedTransactionEvent&gt; enriched =
    AsyncDataStream.unorderedWait(
        transactions,
        new EnrichWithUserProfile(),
        2,
        TimeUnit.SECONDS
    );</code></code></pre><p>This allows <strong>thousands of concurrent lookups without blocking</strong>.</p><div><hr></div><h1>Stateful Fraud Detection</h1><p>Once enriched, we can evaluate fraud conditions.</p><p>Simple example:</p><pre><code><code>public class FraudScoringFunction
  implements MapFunction&lt;EnrichedTransactionEvent, FraudAlert&gt; {

    @Override
    public FraudAlert map(EnrichedTransactionEvent event) {

        boolean ipChanged =
            !event.lastKnownIp.equals(event.transaction.ipAddress);

        boolean unknownDevice =
            !event.knownDevices.contains(event.transaction.deviceId);

        boolean largeAmount =
            event.transaction.amount &gt; 3000;

        boolean highRisk =
            event.riskScore &gt; 0.8;

        if (highRisk &amp;&amp; ipChanged &amp;&amp; unknownDevice &amp;&amp; largeAmount) {

            return new FraudAlert(
                event.transaction.userId,
                "High-confidence fraud",
                event.transaction.timestamp
            );
        }

        return null;
    }
}</code></code></pre><p>Alerts are filtered and published:</p><pre><code><code>alerts
    .filter(Objects::nonNull)
    .addSink(new FlinkKafkaProducer&lt;&gt;("fraud-alerts", ...));</code></code></pre><div><hr></div><h1>Detecting Fraud Patterns with CEP</h1><p>Rule-based detection is useful, but fraud often involves <strong>multi-step behavior</strong>.</p><p>Example pattern:</p><ol><li><p>Login from foreign IP</p></li><li><p>Unknown device</p></li><li><p>Large transaction</p></li></ol><p>Using Flink CEP:</p><pre><code><code>Pattern&lt;EnrichedTransactionEvent, ?&gt; fraudPattern =
    Pattern.&lt;EnrichedTransactionEvent&gt;begin("foreign-ip")
        .where(event -&gt;
            !event.lastKnownIp.equals(event.transaction.ipAddress))
    .next("unknown-device")
        .where(event -&gt;
            !event.knownDevices.contains(event.transaction.deviceId))
    .next("large-transaction")
        .where(event -&gt;
            event.transaction.amount &gt; 3000)
    .within(Time.minutes(5));</code></code></pre><p>This detects <strong>coordinated fraud behavior across multiple events</strong>.</p><div><hr></div><h1>Handling Backpressure and Failures</h1><p>Real streaming systems must handle operational challenges.</p><h3>DynamoDB Latency</h3><p>Async enrichment prevents blocking when DynamoDB experiences spikes.</p><div><hr></div><h3>Kafka Partition Skew</h3><p>Fraud workloads often concentrate on a few users.</p><p>Partitioning by <code>userId</code> ensures event order.</p><pre><code><code>keyBy(event -&gt; event.userId)</code></code></pre><div><hr></div><h3>Backpressure Monitoring</h3><p>Flink exposes metrics like:</p><pre><code><code>task.backPressuredTimeMs</code></code></pre><p>These can be exported to <strong>CloudWatch or Prometheus</strong>.</p><div><hr></div><h1>Observability</h1><p>Streaming systems require deep observability.</p><p>Key tools:</p><p><strong>CloudWatch Logs</strong></p><p>Flink job execution logs.</p><div><hr></div><p><strong>CloudWatch Metrics</strong></p><p>Important metrics:</p><ul><li><p>checkpoint duration</p></li><li><p>event lag</p></li><li><p>throughput</p></li><li><p>backpressure</p></li></ul><div><hr></div><p><strong>OpenSearch Dashboards</strong></p><p>Suspicious events can be indexed for live investigation.</p><div><hr></div><p><strong>Amazon Managed Grafana</strong></p><p>Used for real-time operational dashboards.</p><div><hr></div><h1>Scaling the System</h1><p>The architecture scales horizontally.</p><h3>Kafka</h3><p>MSK Serverless automatically scales partitions and throughput.</p><div><hr></div><h3>Flink</h3><p>Flink jobs scale via <strong>parallelism</strong>.</p><p>Example:</p><pre><code><code>env.setParallelism(8);</code></code></pre><p>Each subtask processes a subset of partitions.</p><div><hr></div><h3>DynamoDB</h3><p>DynamoDB provides <strong>millisecond read latency</strong> at virtually unlimited scale.</p><div><hr></div><p>Typical throughput:</p><p>ComponentCapacityMSK Serverless500K+ events/secFlink enrichment~2K&#8211;5K events/sec per taskFull pipeline50K+ events/sec</p><div><hr></div><h1>Cost Considerations</h1><p>One advantage of serverless architectures is predictable cost.</p><p>Example monthly estimate (50K EPS workload):</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;markdown&quot;,&quot;nodeId&quot;:&quot;e40ca363-f691-4dae-8a11-574925b0ccc4&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-markdown">| Service                        | Estimated Cost |
| ------------------------------ | -------------- |
| MSK Serverless                 | ~$800          |
| Kinesis Data Analytics (Flink) | ~$1200         |
| DynamoDB                       | ~$300          |
| CloudWatch + Grafana           | ~$100          |</code></pre></div><p>Total:</p><p><strong>~$2400/month</strong></p><p>Operating equivalent self-managed infrastructure would require significantly more operational effort.</p><div><hr></div><h1>Production Hardening</h1><p>Before running in production, several safeguards should be implemented.</p><h3>IAM Least Privilege</h3><p>Flink role should only allow:</p><pre><code><code>dynamodb:GetItem</code></code></pre><div><hr></div><h3>Network Isolation</h3><p>Flink runs inside a <strong>VPC</strong>.</p><p>DynamoDB accessed via <strong>VPC Gateway Endpoint</strong>.</p><div><hr></div><h3>Encryption</h3><ul><li><p>TLS for all network traffic</p></li><li><p>KMS for data at rest</p></li></ul><div><hr></div><h3>Checkpointing</h3><p>Flink checkpoints state to durable storage.</p><p>This allows <strong>exactly-once recovery after failures</strong>.</p><div><hr></div><h1>Conclusion</h1><p>Modern fraud detection systems must operate at the <strong>speed of transactions</strong>.</p><p>Batch analytics alone cannot keep up with modern attack patterns.</p><p>By combining:</p><ul><li><p>Kafka for event streaming</p></li><li><p>Apache Flink for stateful processing</p></li><li><p>DynamoDB for real-time enrichment</p></li><li><p>Serverless AWS infrastructure</p></li></ul><p>we can build a <strong>scalable, fault-tolerant fraud detection platform capable of making </strong></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://sendoamoronta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Why Most Data Mesh Initiatives Fail (And How to Make Yours Actually Work)]]></title><description><![CDATA[Data Mesh promises autonomy, scalability, and faster value delivery. But most implementations quietly collapse before delivering real impact.]]></description><link>https://sendoamoronta.substack.com/p/why-most-data-mesh-initiatives-fail</link><guid isPermaLink="false">https://sendoamoronta.substack.com/p/why-most-data-mesh-initiatives-fail</guid><dc:creator><![CDATA[Sendoa Moronta]]></dc:creator><pubDate>Thu, 26 Feb 2026 16:02:20 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!pEwF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After observing multiple Data Mesh transformations across organizations of different sizes, I&#8217;ve noticed something uncomfortable:</p><blockquote><p>The failure rarely comes from technology.<br>It comes from misunderstanding what Data Mesh really is.</p></blockquote><p>Data Mesh is not a new data architecture pattern.<br>It&#8217;s a socio-technical transformation.</p><p>And that changes everything.</p><p>In this article, I&#8217;ll break down:</p><ul><li><p>The most common Data Mesh mistakes</p></li><li><p>Why they happen (organizationally and technically)</p></li><li><p>Their hidden consequences</p></li><li><p>Practical strategies to avoid them</p></li></ul><p>If you&#8217;re leading a Data Mesh initiative, this might save you months, or even years of frustration.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pEwF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pEwF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp 424w, https://substackcdn.com/image/fetch/$s_!pEwF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp 848w, https://substackcdn.com/image/fetch/$s_!pEwF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp 1272w, https://substackcdn.com/image/fetch/$s_!pEwF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pEwF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:85830,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://sendoamoronta.substack.com/i/189263838?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pEwF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp 424w, https://substackcdn.com/image/fetch/$s_!pEwF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp 848w, https://substackcdn.com/image/fetch/$s_!pEwF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp 1272w, https://substackcdn.com/image/fetch/$s_!pEwF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e075519-c9fb-446f-b12d-d2ff82d87c45_1800x1800.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h2>1&#65039;&#8419; Over-Centralizing &#8220;For Governance&#8221;</h2><p>One of the biggest contradictions in Data Mesh transformations is this:</p><p>Companies say they want domain autonomy&#8230;<br>But they keep centralized control mechanisms in place.</p><p>They call it &#8220;governance.&#8221;<br>In practice, it&#8217;s fear.</p><h3>Why It Happens</h3><ul><li><p>Fear of losing control over data quality</p></li><li><p>Compliance concerns</p></li><li><p>Legacy mindset from centralized data warehouses</p></li><li><p>Lack of trust in domain teams</p></li></ul><p>So what happens?</p><p>The ingestion pipelines are still owned by a central platform team.<br>Schema approvals require manual review.<br>Deployments need centralized validation.</p><p>The result?</p><p>You&#8217;ve built a distributed architecture with centralized power.</p><h3>The Technical Anti-Pattern</h3><p>You often see:</p><ul><li><p>A single monolithic ingestion DAG (e.g., one Airflow pipeline for all domains)</p></li><li><p>Manual schema approval workflows</p></li><li><p>Centralized deployment gates</p></li><li><p>Shared production environments with strict access bottlenecks</p></li></ul><p>This creates:</p><ul><li><p>Single points of failure</p></li><li><p>Slow release cycles</p></li><li><p>Frustrated domain teams</p></li><li><p>Shadow data practices</p></li></ul><h3>The Better Approach</h3><p>Governance in Data Mesh must be:</p><blockquote><p>Automated and policy-driven &#8212; not approval-driven.</p></blockquote><p>That means:</p><ul><li><p>Event-driven ingestion (Kafka / PubSub style)</p></li><li><p>Infrastructure as code for domain pipelines</p></li><li><p>Automated data contract validation (JSON Schema, Avro, Protobuf)</p></li><li><p>Fine-grained IAM policies</p></li><li><p>Self-service deployment capabilities</p></li></ul><p>Governance should scale with autonomy &#8212; not restrict it.</p><div><hr></div><h2>2&#65039;&#8419; Vague Domain Boundaries and Ownership</h2><p>Data Mesh relies on domain-oriented data ownership.</p><p>But in many organizations, domain definitions are&#8230; fuzzy.</p><p>When no one is clearly accountable, everyone assumes someone else is.</p><h3>Why This Happens</h3><ul><li><p>Poor alignment between business and data architecture</p></li><li><p>Frequent organizational restructurings</p></li><li><p>Data teams defining domains without business context</p></li><li><p>&#8220;Platform-first&#8221; thinking instead of &#8220;domain-first&#8221; thinking</p></li></ul><h3>What It Looks Like Technically</h3><ul><li><p>Multiple datasets representing the same business concept</p></li><li><p>Inconsistent naming conventions</p></li><li><p>No clear data owner metadata</p></li><li><p>Broken lineage across pipelines</p></li></ul><p>Consumers don&#8217;t know:</p><ul><li><p>Which dataset is authoritative</p></li><li><p>Who to contact</p></li><li><p>What SLAs apply</p></li></ul><p>Trust erodes.</p><h3>How to Avoid It</h3><ol><li><p>Run domain mapping workshops with business and technical stakeholders.</p></li><li><p>Define domain boundaries aligned to business capabilities.</p></li><li><p>Assign explicit data product owners.</p></li><li><p>Document ownership in your data catalog.</p></li><li><p>Implement lineage tracking to visualize dependencies.</p></li></ol><p>Domain ownership is not a suggestion in Data Mesh.</p><p>It is the foundation.</p><div><hr></div><h2>3&#65039;&#8419; Treating Data Mesh as a Purely Technical Initiative</h2><p>This might be the most dangerous mistake of all.</p><p>Data Mesh is often introduced by the data engineering team.<br>But its success depends heavily on organizational culture.</p><h3>The Illusion</h3><p>&#8220;If we implement the right tooling, Data Mesh will work.&#8221;</p><p>Reality:</p><p>Without training, mindset shift, and leadership support, teams revert to centralized habits.</p><h3>What Happens</h3><ul><li><p>Domain teams feel unprepared to own data pipelines.</p></li><li><p>Platform teams keep stepping in &#8220;to help.&#8221;</p></li><li><p>Autonomy becomes theoretical.</p></li><li><p>Cultural resistance increases.</p></li></ul><p>Technology evolves quickly.<br>If platform provisioning is slow, domain teams remain dependent.</p><h3>What Actually Works</h3><ul><li><p>Hands-on training (CI/CD for data, testing frameworks, observability)</p></li><li><p>Coaching and pairing between platform and domain engineers</p></li><li><p>Sandbox environments for experimentation</p></li><li><p>Internal documentation and reusable templates</p></li><li><p>Celebrating small wins</p></li></ul><p>Data Mesh requires:</p><blockquote><p>Autonomy with accountability.</p></blockquote><p>And accountability requires capability.</p><div><hr></div><h2>4&#65039;&#8419; No Minimum Standards for Data Governance</h2><p>Data Mesh promotes decentralization.</p><p>But decentralization without standards equals fragmentation.</p><h3>The Misinterpretation</h3><p>&#8220;Each domain can do whatever they want.&#8221;</p><p>That&#8217;s not Data Mesh.<br>That&#8217;s chaos.</p><h3>What Goes Wrong</h3><ul><li><p>Incompatible schemas</p></li><li><p>Inconsistent metadata</p></li><li><p>Missing SLAs</p></li><li><p>Poor discoverability</p></li><li><p>Data products that can&#8217;t interoperate</p></li></ul><p>The whole point of Data Mesh is to create <em>data products</em>.</p><p>Products need standards.</p><h3>The Balanced Approach</h3><p>Define:</p><ul><li><p>Schema standards (JSON Schema, Avro, Protobuf)</p></li><li><p>Mandatory metadata fields</p></li><li><p>Quality metrics thresholds</p></li><li><p>Versioning practices</p></li><li><p>Access control policies</p></li></ul><p>But keep standards:</p><ul><li><p>Minimal</p></li><li><p>Clear</p></li><li><p>Automated</p></li></ul><p>The platform should enforce standards through tooling &#8212; not bureaucracy.</p><div><hr></div><h2>5&#65039;&#8419; Weak or Non-Standardized Infrastructure</h2><p>Self-service is a core principle of Data Mesh.</p><p>But self-service without automation doesn&#8217;t scale.</p><h3>Common Infrastructure Gaps</h3><ul><li><p>Manual pipeline deployment</p></li><li><p>No CI/CD for data</p></li><li><p>Monitoring scattered across tools</p></li><li><p>No reusable templates</p></li><li><p>Drift between environments</p></li></ul><p>In early stages, it &#8220;works.&#8221;</p><p>At scale, it collapses.</p><h3>The Technical Foundation You Actually Need</h3><ul><li><p>Git-based workflows for pipelines</p></li><li><p>Automated CI/CD with testing</p></li><li><p>Reusable pipeline templates</p></li><li><p>Infrastructure as Code</p></li><li><p>Centralized monitoring dashboards</p></li><li><p>Automated alerts on data quality degradation</p></li></ul><p>If domain teams must rely on experts for every deployment&#8230;</p><p>You don&#8217;t have Data Mesh.</p><p>You have distributed dependency.</p><div><hr></div><h2>6&#65039;&#8419; The Hidden Root Cause: Misaligned Incentives</h2><p>Here&#8217;s something rarely discussed:</p><p>Data Mesh fails when organizational incentives don&#8217;t support it.</p><p>If:</p><ul><li><p>Teams are evaluated only on feature delivery</p></li><li><p>Data quality isn&#8217;t measured</p></li><li><p>Ownership isn&#8217;t recognized</p></li><li><p>Cross-domain collaboration isn&#8217;t rewarded</p></li></ul><p>Then autonomy becomes extra work &#8212; not a benefit.</p><p>Cultural transformation requires aligned incentives.</p><div><hr></div><h1>What Successful Data Mesh Implementations Share</h1><p>After observing successful transformations, they all share:</p><ul><li><p>Clear domain ownership</p></li><li><p>Automated governance</p></li><li><p>Strong platform foundations</p></li><li><p>Continuous training</p></li><li><p>Executive sponsorship</p></li><li><p>Patience</p></li></ul><p>And most importantly:</p><blockquote><p>They treat Data Mesh as an operating model &#8212; not a tooling decision.</p></blockquote><div><hr></div><h1>Final Thoughts</h1><p>Data Mesh is not about adopting the latest tools.</p><p>It&#8217;s about redesigning how your organization:</p><ul><li><p>Thinks about data ownership</p></li><li><p>Distributes responsibility</p></li><li><p>Automates governance</p></li><li><p>Builds internal platforms</p></li><li><p>Aligns incentives</p></li></ul><p>The architecture diagram is the easy part.</p><p>The organizational transformation is the real challenge.</p><p>If you&#8217;re starting your Data Mesh journey:</p><p>Focus less on buzzwords.<br>Focus more on autonomy, accountability, and enablement.</p><p>That&#8217;s where success actually lives.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://sendoamoronta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Runtime Security in Cloud Composer]]></title><description><![CDATA[Enforcing Per-App DAG Isolation with External Cluster Policies]]></description><link>https://sendoamoronta.substack.com/p/runtime-security-in-cloud-composer</link><guid isPermaLink="false">https://sendoamoronta.substack.com/p/runtime-security-in-cloud-composer</guid><dc:creator><![CDATA[Sendoa Moronta]]></dc:creator><pubDate>Mon, 23 Feb 2026 13:18:12 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!WsJA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Cloud Composer makes orchestration easy.</p><p>It does <strong>not</strong> make multi-tenant runtime isolation easy.</p><p>In many organizations, a single Composer environment is shared across:</p><ul><li><p>Multiple teams</p></li><li><p>Multiple business domains</p></li><li><p>Multiple service accounts</p></li><li><p>Multiple data sensitivity levels</p></li></ul><p>At first, this feels efficient.</p><p>Over time, it becomes fragile.</p><p>Because Airflow, by default, trusts DAG authors.</p><p>And trust is not a security control.</p><p>This article describes a practical approach to enforce <strong>per-application runtime isolation inside a shared Cloud Composer environment</strong> &#8212; without duplicating environments, without introducing cluster-level admission controllers, and without rewriting Airflow internals.</p><p>The enforcement happens at runtime, using:</p><ul><li><p>DAG identity tagging</p></li><li><p>Externally defined policies</p></li><li><p>Airflow&#8217;s <code>task_policy</code> hook</p></li><li><p>Centralized configuration stored outside DAG code</p></li></ul><div><hr></div><h1>The Real Problem: Logical Separation Is Not Isolation</h1><p>Most teams start with conventions:</p><ul><li><p>&#8220;This folder is owned by Team A.&#8221;</p></li><li><p>&#8220;This service account is only for marketing.&#8221;</p></li><li><p>&#8220;Please don&#8217;t use that operator.&#8221;</p></li></ul><p>These conventions work until they don&#8217;t.</p><p>The real risks in a shared Composer environment look like this:</p><h3>1&#65039;&#8419; Operator Misuse</h3><p>A team accidentally uses an operator capable of accessing datasets outside their domain.</p><h3>2&#65039;&#8419; Connection Reuse</h3><p>A powerful <code>gcp_conn_id</code> is reused across unrelated DAGs.</p><h3>3&#65039;&#8419; Privilege Creep</h3><p>Over time, connections accumulate broader IAM permissions &#8220;just in case.&#8221;</p><h3>4&#65039;&#8419; Runtime Drift</h3><p>Static checks pass, but a change in operator behavior or parameterization bypasses expectations.</p><p>Airflow will happily execute any operator you import.</p><p>There is no built-in enforcement layer that says:</p><blockquote><p><em>&#8220;This DAG is not allowed to execute this operator with this connection.&#8221;</em></p></blockquote><p>Unless you add one.</p><div><hr></div><h1>Design Goal: Enforce Policy at Task Invocation Time</h1><p>The critical insight is this:</p><p>Security enforcement must happen <strong>right before execution</strong>, not just during code review or CI.</p><p>Airflow provides a hook precisely at that moment: <code>task_policy</code>.</p><p>This hook allows you to intercept a task object before it runs and validate:</p><ul><li><p>Its operator type</p></li><li><p>Its connection IDs</p></li><li><p>Its DAG identity</p></li><li><p>Any custom metadata</p></li></ul><p>If validation fails &#8594; raise an exception &#8594; the task never executes.</p><p>That&#8217;s your runtime gate.</p><div><hr></div><h1>Step 1 - Establish a Clear Application Identity Model</h1><p>Isolation requires identity.</p><p>We encode identity at DAG level using structured tags.</p><p>Example:</p><pre><code>with DAG(
    dag_id=&#8221;marketing_daily_load&#8221;,
    tags=[&#8221;app:marketing&#8221;],
    ...
) as dag:
    ...</code></pre><p>Rules:</p><ul><li><p>Exactly one <code>app:*</code> tag per DAG</p></li><li><p>No implicit ownership</p></li><li><p>No fallback defaults</p></li></ul><p>If a DAG does not declare its application identity, it should not run.</p><p>Identity is not inferred.<br><br>Identity is declared.</p><div><hr></div><h1>Step 2 - Move Authorization Out of DAG Code</h1><p>The policy must not live in DAG files.</p><p>If policy is inside DAG code, developers can modify it.</p><p>Instead, define policies in a centralized JSON file stored externally (e.g., in GCS):</p><pre><code>{
  &#8220;app:marketing&#8221;: {
    &#8220;allowed_operators&#8221;: [
      &#8220;PubSubPublishMessageOperator&#8221;,
      &#8220;BigQueryInsertJobOperator&#8221;
    ],
    &#8220;allowed_connections&#8221;: [
      &#8220;google_cloud_marketing&#8221;
    ]
  },
  &#8220;app:finance&#8221;: {
    &#8220;allowed_operators&#8221;: [
      &#8220;GCSToBigQueryOperator&#8221;
    ],
    &#8220;allowed_connections&#8221;: [
      &#8220;google_cloud_finance&#8221;
    ]
  }
}</code></pre><p>This file becomes:</p><ul><li><p>Version-controlled</p></li><li><p>Reviewed</p></li><li><p>Managed by platform/security</p></li><li><p>Independent from DAG authors</p></li></ul><p>We separate <strong>orchestration logic</strong> from <strong>security policy</strong>.</p><div><hr></div><h1>Step 3 - Implement Runtime Enforcement via <code>task_policy</code></h1><p>Airflow loads <code>airflow_local_settings.py</code> at runtime.</p><p>Inside it, you can define:</p><pre><code>def task_policy(task):
    ...</code></pre><p>This function runs before task execution.</p><p>Expanded version:</p><pre><code>def task_policy(task):
    # Validate DAG identity
    app_tag = next((t for t in task.dag.tags if t.startswith(&#8221;app:&#8221;)), None)
    if not app_tag:
        raise ValueError(
            f&#8221;DAG {task.dag.dag_id} missing required app:* tag&#8221;
        )

    app_config = operator_policy.get(app_tag)
    if not app_config:
        raise ValueError(
            f&#8221;No runtime policy defined for {app_tag}&#8221;
        )

    # Validate operator
    operator_name = task.__class__.__name__
    if operator_name not in app_config.get(&#8221;allowed_operators&#8221;, []):
        raise ValueError(
            f&#8221;{operator_name} not allowed for {app_tag}&#8221;
        )

    # Validate connections
    conn_id = getattr(task, &#8220;gcp_conn_id&#8221;, None)
    if conn_id and conn_id not in app_config.get(&#8221;allowed_connections&#8221;, []):
        raise ValueError(
            f&#8221;{conn_id} not allowed for {app_tag}&#8221;
        )</code></pre><p>Now the enforcement boundary is clear:</p><p>DAG author writes code<br><br>&#8595;<br><br>Scheduler loads task<br><br>&#8595;<br><br>Policy validates<br><br>&#8595;<br><br>Task runs &#8212; or fails</p><p>That is runtime isolation.</p><div><hr></div><h1>What This Model Actually Guarantees</h1><p>This approach enforces:</p><h3>&#10004; Operator Class Whitelisting</h3><p>Teams cannot import arbitrary operators.</p><h3>&#10004; Connection Scoping</h3><p>Each app can only use approved connection IDs.</p><h3>&#10004; Explicit Identity Requirement</h3><p>No untagged DAGs.</p><h3>&#10004; Centralized Policy Governance</h3><p>Security decisions are externalized.</p><p>It does <strong>not</strong> replace IAM.<br><br>It complements it.</p><div><hr></div><h1>Defense in Depth: Pair with IAM Minimization</h1><p>Runtime enforcement reduces blast radius at orchestration layer.</p><p>IAM reduces blast radius at cloud layer.</p><p>Best practice:</p><ul><li><p>One GCP service account per app</p></li><li><p>One Airflow connection per service account</p></li><li><p>Least privilege IAM roles</p></li><li><p>No shared broad-scope accounts</p></li></ul><p>If policy fails, IAM still limits damage.</p><p>If IAM fails, policy still blocks misuse.</p><p>Isolation should not rely on one layer.</p><div><hr></div><h1>Observability and Auditability</h1><p>Policy enforcement must be observable.</p><p>Add structured logging for:</p><ul><li><p>Policy violations</p></li><li><p>Missing tags</p></li><li><p>Unauthorized operator attempts</p></li><li><p>Unauthorized connection usage</p></li></ul><p>Optionally:</p><ul><li><p>Emit metrics</p></li><li><p>Alert on repeated violations</p></li><li><p>Track policy drift over time</p></li></ul><p>Security without visibility is fragile.</p><div><hr></div><h1>Operational Considerations</h1><h2>Policy Updates</h2><p>When policy JSON changes:</p><ul><li><p>Version it</p></li><li><p>Deploy it</p></li><li><p>Restart scheduler/webserver if necessary</p></li></ul><p>Treat policy as infrastructure.</p><div><hr></div><h2>Backward Compatibility</h2><p>When introducing this model into an existing environment:</p><ul><li><p>Start in audit mode (log but don&#8217;t block)</p></li><li><p>Identify violations</p></li><li><p>Gradually tighten enforcement</p></li></ul><p>Hard cutovers create outages.</p><div><hr></div><h2>Performance Impact</h2><p>The validation is lightweight:</p><ul><li><p>Dictionary lookups</p></li><li><p>Simple attribute checks</p></li></ul><p>Negligible runtime overhead compared to task execution.</p><div><hr></div><h1>Limitations of This Approach</h1><p>It&#8217;s important to be honest about boundaries.</p><p>This model:</p><ul><li><p>Does not inspect SQL queries</p></li><li><p>Does not validate operator parameters deeply</p></li><li><p>Does not enforce Kubernetes-level constraints</p></li><li><p>Does not prevent malicious Python logic inside an allowed operator</p></li></ul><p>It enforces orchestration-level constraints.</p><p>For deeper guarantees, combine with:</p><ul><li><p>IAM scoping</p></li><li><p>VPC Service Controls</p></li><li><p>Network segmentation</p></li><li><p>Separate Composer environments for high-sensitivity workloads</p></li></ul><p>Isolation is a spectrum.</p><div><hr></div><h1>Why Not Separate Composer Environments?</h1><p>You could create one environment per team.</p><p>But that introduces:</p><ul><li><p>Operational overhead</p></li><li><p>Cost increase</p></li><li><p>Upgrade complexity</p></li><li><p>Environment sprawl</p></li></ul><div><hr></div><h1>The Core Principle</h1><p>Isolation should be:</p><ul><li><p>Explicit</p></li><li><p>Enforced</p></li><li><p>Centralized</p></li><li><p>Versioned</p></li><li><p>Observable</p></li></ul><p>Not:</p><ul><li><p>Implicit</p></li><li><p>Convention-based</p></li><li><p>Folder-driven</p></li><li><p>Trust-based</p></li></ul><p>Airflow executes tasks.<br><br>It does not enforce policy.</p><p>Unless you teach it to.</p><div><hr></div><h1>Closing Thought</h1><p>Most orchestration environments fail not because of malicious actors, but because of drift:</p><ul><li><p>&#8220;We needed this permission temporarily.&#8221;</p></li><li><p>&#8220;We reused that connection.&#8221;</p></li><li><p>&#8220;It worked in staging.&#8221;</p></li></ul><p>Runtime policy enforcement introduces friction in the right place.</p><p>And friction, when intentional, is a security feature.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WsJA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WsJA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!WsJA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!WsJA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!WsJA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WsJA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:637316,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://sendoamoronta.substack.com/i/188889843?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WsJA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!WsJA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!WsJA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!WsJA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcef65adf-415c-452d-b7c2-5fe7d40a7fbc_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://sendoamoronta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item></channel></rss>