<?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[Jagadeesh Rampam]]></title><description><![CDATA[Tech, research, field notes, BTS of our products: Parjanya v2.0, WilderhoodTV, Smriti LLM
https://phagyul.ai]]></description><link>https://blog.phagyul.ai</link><image><url>https://blog.phagyul.ai/img/substack.png</url><title>Jagadeesh Rampam</title><link>https://blog.phagyul.ai</link></image><generator>Substack</generator><lastBuildDate>Thu, 12 Nov 2026 17:33:08 GMT</lastBuildDate><atom:link href="https://blog.phagyul.ai/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Jagadeesh Rampam]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[jagadeeshrampam@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[jagadeeshrampam@substack.com]]></itunes:email><itunes:name><![CDATA[Parjanya by Phagyul AI]]></itunes:name></itunes:owner><itunes:author><![CDATA[Parjanya by Phagyul AI]]></itunes:author><googleplay:owner><![CDATA[jagadeeshrampam@substack.com]]></googleplay:owner><googleplay:email><![CDATA[jagadeeshrampam@substack.com]]></googleplay:email><googleplay:author><![CDATA[Parjanya by Phagyul AI]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[The case for TypeScript SDKs in Grove ]]></title><description><![CDATA[An evidence-led technical deep dive and a dogfooding exercise in building Grove's agent pipeline with its own research agent &#8212; Grove 0.2.0 | Finalised 7 November 2026.]]></description><link>https://blog.phagyul.ai/p/the-case-for-typescript-sdks-in-grove</link><guid isPermaLink="false">https://blog.phagyul.ai/p/the-case-for-typescript-sdks-in-grove</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Thu, 12 Nov 2026 02:10:08 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!i1Iu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><h3><strong>How this note was made.</strong> </h3><p><em><strong>Grove&#8217;s research agent (0.2.0)</strong> drafted it on using local <strong>Gemma 4 (31B Dense) model , served by Ollama on a Mac M3 Max. </strong></em></p><div class="comment" data-attrs="{&quot;url&quot;:&quot;https://open.substack.com/&quot;,&quot;commentId&quot;:381502090,&quot;comment&quot;:{&quot;id&quot;:381502090,&quot;date&quot;:&quot;2026-11-07T20:13:10.880Z&quot;,&quot;edited_at&quot;:null,&quot;body&quot;:&quot;Grove 0.2.0 is out!\n\nAnother step forward in building Grove by Parjanya &#8212; an open, extensible foundation for rooted intelligence.\n\nWe're building towards an ecosystem where agents, tools, and capabilities can work together through a thoughtfully designed architecture. Each release brings us a little closer to that vision.\n\nThis is an evolving journey, and there's much more to come.\n\nExplore the release notes: https://parjanya.phagyul.ai/release-notes#grove\n\n#Grove #AI #AgenticAI #OpenSource&quot;,&quot;body_json&quot;:{&quot;type&quot;:&quot;doc&quot;,&quot;attrs&quot;:{&quot;schemaVersion&quot;:&quot;v1&quot;,&quot;title&quot;:null},&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Grove 0.2.0 is out!&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Another step forward in building &quot;},{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;Grove by Parjanya&quot;},{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot; &#8212; an open, extensible foundation for rooted intelligence.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;We're building towards an ecosystem where agents, tools, and capabilities can work together through a thoughtfully designed architecture. Each release brings us a little closer to that vision.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;This is an evolving journey, and there's much more to come.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Explore the release notes: &quot;},{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;link&quot;,&quot;attrs&quot;:{&quot;href&quot;:&quot;https://parjanya.phagyul.ai/release-notes#grove&quot;,&quot;target&quot;:&quot;_blank&quot;,&quot;rel&quot;:&quot;nofollow ugc noopener&quot;,&quot;class&quot;:&quot;note-link&quot;,&quot;title&quot;:null}}],&quot;text&quot;:&quot;https://parjanya.phagyul.ai/release-notes#grove&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;#Grove #AI #AgenticAI #OpenSource&quot;}]}]},&quot;restacks&quot;:0,&quot;reaction_count&quot;:0,&quot;children_count&quot;:0,&quot;attachments&quot;:[{&quot;id&quot;:&quot;6c8f435c-152b-42ae-b4a1-761f7a749b14&quot;,&quot;type&quot;:&quot;image&quot;,&quot;imageUrl&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d442abcc-e57c-4213-a297-7da9ad80f06e_1672x941.png&quot;,&quot;imageWidth&quot;:1672,&quot;imageHeight&quot;:941,&quot;explicit&quot;:false},{&quot;id&quot;:&quot;0ad19f8a-2c86-4c80-a1d1-f0fb29c18785&quot;,&quot;type&quot;:&quot;link&quot;,&quot;linkMetadata&quot;:{&quot;url&quot;:&quot;https://parjanya.phagyul.ai/release-notes#grove&quot;,&quot;host&quot;:&quot;parjanya.phagyul.ai&quot;,&quot;title&quot;:&quot;What&#8217;s new &#183; Parjanya release notes&quot;,&quot;description&quot;:&quot;A short, plain-language summary of what changed in each Parjanya release, with links to the full notes and every fixed issue.&quot;,&quot;image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/275dcc0b-196b-4635-a39b-d43d278499a3_1200x630.jpeg&quot;,&quot;original_image&quot;:&quot;https://parjanya.phagyul.ai/share/static-share.jpg&quot;},&quot;explicit&quot;:false,&quot;is_saved&quot;:false}],&quot;name&quot;:&quot;Parjanya by Phagyul AI&quot;,&quot;user_id&quot;:12091074,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;user_bestseller_tier&quot;:null,&quot;userStatus&quot;:{&quot;bestsellerTier&quot;:null,&quot;subscriberTier&quot;:1,&quot;leaderboard&quot;:null,&quot;vip&quot;:false,&quot;badge&quot;:{&quot;type&quot;:&quot;subscriber&quot;,&quot;tier&quot;:1,&quot;accent_colors&quot;:null},&quot;subscriber&quot;:null}},&quot;source&quot;:null,&quot;forumChannel&quot;:null}" data-component-name="CommentPlaceholder"></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rcWg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9e1c98d-e4e8-42e7-a8d0-cbd92912f2cf_1774x887.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rcWg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9e1c98d-e4e8-42e7-a8d0-cbd92912f2cf_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!rcWg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9e1c98d-e4e8-42e7-a8d0-cbd92912f2cf_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!rcWg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9e1c98d-e4e8-42e7-a8d0-cbd92912f2cf_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!rcWg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9e1c98d-e4e8-42e7-a8d0-cbd92912f2cf_1774x887.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rcWg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9e1c98d-e4e8-42e7-a8d0-cbd92912f2cf_1774x887.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9e1c98d-e4e8-42e7-a8d0-cbd92912f2cf_1774x887.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1376328,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/224402095?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9e1c98d-e4e8-42e7-a8d0-cbd92912f2cf_1774x887.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_!rcWg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9e1c98d-e4e8-42e7-a8d0-cbd92912f2cf_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!rcWg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9e1c98d-e4e8-42e7-a8d0-cbd92912f2cf_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!rcWg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9e1c98d-e4e8-42e7-a8d0-cbd92912f2cf_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!rcWg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9e1c98d-e4e8-42e7-a8d0-cbd92912f2cf_1774x887.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h4><em>It read 40 sources: 30 web pages, the research brief and nine of Grove&#8217;s own documents. From them it kept 128 quotes, each checked word for word against a stored copy of its source. </em></h4><p><em>I have approved the draft on 7 November 2026. Claude currently acting as an orchestrator without intelligence in the absence of interface and GPT helped me format for links, tables, and graphics used in this post shared. </em></p><p><em><strong>Every factual statement below rests on one of those quotes, cited as [En] and listed under Sources at the end. Where the sources are silent, the note says so.</strong> </em></p><h5>[All web pages were retrieved on 7 November 2026]</h5></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!i1Iu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!i1Iu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!i1Iu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!i1Iu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!i1Iu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!i1Iu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1791120,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/224402095?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.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_!i1Iu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!i1Iu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!i1Iu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!i1Iu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b9fdec-e4b6-46c1-b963-68612a7d1999_1774x887.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Executive summary</h2><h4>Research Brief and Architectural Context. </h4><p>I have asked for the evidence behind &#8220;<strong>our case of leveraging TypeScript SDK</strong>&#8221; to back on my decision as well as cross verifying before final call. It was to go beyond &#8220;<strong>developer community fondness and support</strong>&#8221; and cover the current status of support, future efforts and, &#8220;<strong>most importantly current trade offs</strong>&#8221; [E12]. </p><p>Grove&#8217;s recorded position is that it is TypeScript-first, with language-neutral contracts so that parts of it can later move to Python [E13][E1].</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!X0sC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff90c1d9d-af41-4032-87a7-bd81600213c0_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!X0sC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff90c1d9d-af41-4032-87a7-bd81600213c0_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!X0sC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff90c1d9d-af41-4032-87a7-bd81600213c0_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!X0sC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff90c1d9d-af41-4032-87a7-bd81600213c0_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!X0sC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff90c1d9d-af41-4032-87a7-bd81600213c0_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!X0sC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff90c1d9d-af41-4032-87a7-bd81600213c0_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f90c1d9d-af41-4032-87a7-bd81600213c0_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;:1557474,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/224402095?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff90c1d9d-af41-4032-87a7-bd81600213c0_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_!X0sC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff90c1d9d-af41-4032-87a7-bd81600213c0_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!X0sC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff90c1d9d-af41-4032-87a7-bd81600213c0_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!X0sC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff90c1d9d-af41-4032-87a7-bd81600213c0_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!X0sC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff90c1d9d-af41-4032-87a7-bd81600213c0_1536x1024.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h3><strong>The case, beyond fondness.</strong> </h3><h4>The evidence gives four reasons:</h4><ol><li><p><strong>Types plus run-time schemas.</strong> Both Claude SDKs and four of the five other agent toolkits in the run pair TypeScript types with a schema library that also checks data at run time, usually Zod (section 2.2).</p></li><li><p><strong>Types as contracts.</strong> DeepSeek typed its harness&#8217;s wire protocol so that &#8220;<strong>server drift breaks compilation, not clients</strong>&#8221; [E70]. Grove&#8217;s plan makes bypassing its gateway, router or recorder a compile error [E3].</p></li><li><p><strong>Agent-assisted coding.</strong> GitHub links TypeScript&#8217;s rise to &#8220;<strong>agent-assisted coding</strong>&#8221; [E107]. A 2025 paper uses type systems to constrain model-generated code, and extends the method to TypeScript [E128].</p></li><li><p><strong>The SDKs exist and are actively released.</strong></p><ul><li><p>Both of Claude&#8217;s SDK layers have TypeScript editions.</p></li><li><p>Anthropic&#8217;s API SDK for TypeScript shipped at least nine releases between 15 September and 5 November 2026, including 1.0.0 on 21 October 2026 [E56].</p></li><li><p>DeepSeek&#8217;s design note of 27 July 2026 records building a TypeScript SDK for its harness [E68].</p></li><li><p>Five other agent toolkits ship for TypeScript (section 5).</p></li></ul></li></ol><h4>Future efforts</h4><p>TypeScript 7.0, a native port written in Go, reached beta on 21 April 2026. It is &#8220;<strong>often about 10 times faster than TypeScript 6.0</strong>&#8221; [E93], and it&#8217;s release was planned &#8220;within the next two months&#8221; [E94]. Whether it has shipped is not in the evidence. Node.js now runs TypeScript directly by stripping types, a feature its documentation marks as stable [E99].</p><h4>Limits of the case.</h4><ul><li><p><strong>Quality evidence is mixed.</strong> The one direct study found better code quality and understandability in TypeScript applications than in JavaScript ones, but not fewer bugs or faster fixes [E120][E121].</p></li><li><p><strong>Python leads in AI.</strong> Python &#8220;remains dominant for AI and data science workloads&#8221; [E108].</p></li><li><p><strong>Popularity measures disagree.</strong> TypeScript is first on GitHub [E110] but sixth in the 2026 Stack Overflow survey [E116].</p></li><li><p><strong>Types vanish at run time.</strong> Node.js checks no types when it runs TypeScript [E101], and running it directly rules out some syntax [E103][E104].</p></li><li><p><strong>DeepSeek&#8217;s TypeScript SDK is not an API client.</strong> It drives the DeepSeek Harness [E64]. For its model API, DeepSeek&#8217;s documentation points to OpenAI&#8217;s and Anthropic&#8217;s SDKs [E75].</p></li><li><p><strong>The SDK comparison is thin.</strong> The run&#8217;s evidence on Claude&#8217;s Python Agent SDK shows it following the TypeScript one on three points [E38][E39][E40], and holds no fuller comparison.</p></li></ul><h4>For Grove. </h4><p>The evidence supports TypeScript-first with language-neutral contracts. It contradicts nothing in Grove&#8217;s recorded position. Most of what it suggests adopting or avoiding is already settled by Grove&#8217;s decisions: one schema serving as both the type and the run-time check; a separate type check; Python only for the parts that move, behind a planned subprocess protocol with cancellation and a timeout. Five points are open or only partly settled (section 10):</p><ul><li><p>the cost of a full runtime per child process;</p></li><li><p>the syntax limits of running TypeScript directly;</p></li><li><p>how Claude&#8217;s Agent SDK would sit beside Grove&#8217;s own runtime;</p></li><li><p>whether DeepSeek&#8217;s API works through Grove&#8217;s existing OpenAI-compatible route;</p></li><li><p>keeping use of <code>any</code> low.</p></li></ul><h2>1. The Research Brief and the positions being tested</h2><p>I have noted that Claude and DeepSeek have both developed TypeScript SDKs, and asked to deep dive beyond the &#8220;obvious reason&#8221; of community fondness to establish four things:</p><ul><li><p>why it is good to use a TypeScript SDK;</p></li><li><p>the current status of support;</p></li><li><p>future efforts from the communities;</p></li><li><p>most importantly, the current trade-offs [E12].</p></li></ul><h4>Grove&#8217;s own records state the position being tested:</h4><ul><li><p>Grove&#8217;s decision record on language-neutral contracts says: &#8220;Grove is TypeScript-first.&#8221; It names the team&#8217;s machine-learning codebase as Python, and as the place where an in-house language model is planned to evolve [E13].</p></li><li><p>Grove&#8217;s implementation plan records the my own decision that some Grove modules will move into that codebase later, so Grove &#8220;stays TypeScript with language-neutral contracts&#8221; [E1]. Its decision log marks portability as decided on the same terms [E6].</p></li></ul><p>These are stated positions, not findings. Sections 2 to 8 set out what the external sources say. Section 9 tests Grove&#8217;s position against them, and section 10 draws out what Grove should adopt or avoid.</p><h2>2. Why TypeScript for agents, beyond community fondness</h2><h3>2.1 What static types are argued to buy</h3><p>The 2022 paper &#8220;<a href="https://arxiv.org/html/2203.11115">To Type or Not to Type? A Systematic Comparison of the Software Quality of JavaScript and TypeScript Applications on GitHub</a>&#8220; reports what proponents of static typing claim. They say it &#8220;allows early detection of some programming errors&#8221; and leads to &#8220;better documentation in the form of type signatures&#8221; [E119]. The paper&#8217;s own background section is more cautious. For smaller applications, dynamic typing&#8217;s flexibility &#8220;could be preferable&#8221;, while larger systems &#8220;might be more sustainable with static typing&#8221; [E125]. What the same paper measured is in section 8.1.</p><h3>2.2 Schemas: types that also check data at run time</h3><p>TypeScript&#8217;s types do not exist when the program runs (section 8.2). The sources show agent SDKs pairing them with schema libraries that validate data at run time:</p><ul><li><p>The Claude Agent SDK&#8217;s <code>tool()</code> takes a Zod schema for a tool&#8217;s input, and types the handler&#8217;s arguments from that schema [E32].</p></li><li><p>The Claude API&#8217;s TypeScript SDK describes tool inputs with &#8220;Zod schemas or JSON Schemas&#8221; [E45].</p></li><li><p>The Vercel AI SDK&#8217;s README generates structured model output against a Zod schema [E84].</p></li><li><p>The OpenAI Agents SDK&#8217;s install command adds <code>zod</code> beside the SDK [E80].</p></li><li><p>Google&#8217;s Agent Development Kit for TypeScript lists &#8220;Zod schema validation&#8221; among its features [E92].</p></li><li><p>The MCP TypeScript SDK accepts any Standard Schema library: &#8220;bring Zod v4, Valibot, ArkType, or any compatible library&#8221; [E77].</p></li><li><p>Grove&#8217;s plan uses zod for its schemas and for their JSON Schema export [E4].</p></li></ul><h3>2.3 Types as contracts between components and processes</h3><p>Three sources use compile-time types to hold a boundary:</p><ul><li><p><strong>DeepSeek&#8217;s wire protocol.</strong> DeepSeek&#8217;s design note for its TypeScript SDK, dated 27 July 2026, describes its protocol package as &#8220;the wire made shared and nominal&#8221;: one module names every payload the server speaks [E69]. Because the server&#8217;s <code>notify()</code> calls are typed against those names, &#8220;server drift breaks compilation, not clients&#8221; [E70].</p></li><li><p><strong>Grove&#8217;s dependency rule.</strong> In Grove&#8217;s plan, every library depends only on Grove&#8217;s public contracts package, and the applications are the only place implementations meet. Package dependencies and a dependency checker enforce the rule. Agents see only the contracts package, &#8220;so bypassing the gateway, router or recorder is a compile error&#8221; [E3].</p></li><li><p><strong>Typed tool results.</strong> Version 0.3.292 of the Claude Agent SDK for TypeScript added typed <code>sections</code> and <code>notes</code> to a tool&#8217;s result, &#8220;so hosts can list agents without parsing its text&#8221; [E26].</p></li></ul><h3>2.4 Types that flow from a definition to its users</h3><p>The Vercel AI SDK&#8217;s README derives an agent&#8217;s message type directly from the agent&#8217;s definition [E86]. It also types a UI component&#8217;s tool invocation from the tool&#8217;s own return type [E87]. The examples show the mechanism. No source in the run measures its benefit.</p><h3>2.5 Models writing code against types</h3><ul><li><p><strong>A 2025 paper on constrained decoding.</strong> &#8220;<a href="https://arxiv.org/abs/2504.09246">Type-Constrained Code Generation with Language Models</a>&#8220; introduces &#8220;a type-constrained decoding approach that leverages type systems to guide code generation&#8221;. The method is meant to &#8220;enforce well-typedness on LLM-generated code&#8221;. The authors formalise it on a simply-typed language, then &#8220;extend it to TypeScript to demonstrate practicality&#8221; [E128].</p></li><li><p><strong>GitHub&#8217;s 2025 reading.</strong> GitHub&#8217;s <a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/">Octoverse 2025 report</a> says TypeScript&#8217;s rise &#8220;illustrates how developers are shifting toward typed languages that make agent-assisted coding more reliable in production&#8221; [E107].</p></li><li><p><strong>GitHub&#8217;s 2026 data.</strong> <a href="https://github.blog/news-insights/octoverse/octoverse-commits-pushes-reach-new-highs-in-2026-as-developers-build-with-agents/">Octoverse 2026</a> found TypeScript to be the primary language in 35% of repositories created in 2026 that showed an agent signal, against 24% of those without one [E114]. GitHub reads this as suggesting that &#8220;developers who work with agents gravitate toward languages where agent output is easier to check&#8221; [E115]. That reading is GitHub&#8217;s interpretation of a correlation, not a measured cause.</p></li></ul><h3>2.6 Where the code runs</h3><p>Each SDK states its own runtimes. These are properties of the SDKs, not of the language.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MI7H!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccff0aa1-5d2b-4155-89ed-9ac319a15713_1240x700.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MI7H!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccff0aa1-5d2b-4155-89ed-9ac319a15713_1240x700.png 424w, https://substackcdn.com/image/fetch/$s_!MI7H!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccff0aa1-5d2b-4155-89ed-9ac319a15713_1240x700.png 848w, https://substackcdn.com/image/fetch/$s_!MI7H!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccff0aa1-5d2b-4155-89ed-9ac319a15713_1240x700.png 1272w, https://substackcdn.com/image/fetch/$s_!MI7H!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccff0aa1-5d2b-4155-89ed-9ac319a15713_1240x700.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!MI7H!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccff0aa1-5d2b-4155-89ed-9ac319a15713_1240x700.png" width="1240" height="700" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ccff0aa1-5d2b-4155-89ed-9ac319a15713_1240x700.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:700,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:119824,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/224402095?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccff0aa1-5d2b-4155-89ed-9ac319a15713_1240x700.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_!MI7H!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccff0aa1-5d2b-4155-89ed-9ac319a15713_1240x700.png 424w, https://substackcdn.com/image/fetch/$s_!MI7H!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccff0aa1-5d2b-4155-89ed-9ac319a15713_1240x700.png 848w, https://substackcdn.com/image/fetch/$s_!MI7H!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccff0aa1-5d2b-4155-89ed-9ac319a15713_1240x700.png 1272w, https://substackcdn.com/image/fetch/$s_!MI7H!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccff0aa1-5d2b-4155-89ed-9ac319a15713_1240x700.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>3. The status of Claude&#8217;s TypeScript SDKs</h2><p>Anthropic&#8217;s <a href="https://platform.claude.com/docs/en/cli-sdks-libraries/overview.md">overview of its SDKs and libraries</a> says that &#8220;Claude Code, the Claude Agent SDK, and Claude Managed Agents work at a higher level, providing the agent loop, tool execution, and runtime&#8221; [E41]. Below that level sits the Claude API&#8217;s own client SDK. Each layer has a TypeScript SDK: the Agent SDK (section 3.1) and the API SDK (section 3.2). The documentation pages are undated. The Agent SDK changelogs give version numbers without dates, and the API SDK changelog gives both.</p><h3>3.1 The Claude Agent SDK for TypeScript</h3><h4>What it offers.</h4><ul><li><p><strong>Purpose.</strong> Its <a href="https://raw.githubusercontent.com/anthropics/claude-agent-sdk-typescript/main/README.md">README</a> says it lets developers &#8220;programmatically build AI agents with Claude Code&#8217;s capabilities&#8221;: agents that can &#8220;understand codebases, edit files, run commands, and execute complex workflows&#8221; [E17].</p></li><li><p><strong>Bundled binary.</strong> It bundles a native Claude Code binary for the platform as an optional dependency, such as <code>@anthropic-ai/claude-agent-sdk-darwin-arm64</code>. &#8220;Most installs need no separate Claude Code install.&#8221; [E28]</p></li><li><p><strong>Streaming.</strong> <code>query()</code> is the primary function. It &#8220;creates an async generator that streams messages as they arrive&#8221;, and takes either a string or an async iterable of user messages as its prompt [E31].</p></li><li><p><strong>Tools and MCP.</strong> <code>tool()</code> defines a typed tool from a Zod schema [E32]. <code>createSdkMcpServer()</code> defines an MCP server from a name, a version, instructions and such tools [E35].</p></li><li><p><strong>Sessions.</strong> It provides session helpers, including <code>listSessions()</code> and <code>getSessionMessages()</code> [E36][E37].</p></li><li><p><strong>Prewarming.</strong> <code>prewarm()</code> returns a spare process [E34]. It is alpha, was added to the <code>/core</code> entry in version 0.3.314 [E18], and requires Agent SDK v0.3.282 or later [E33].</p></li><li><p><strong>Bundling.</strong> An application that bundles the SDK with its own dependencies should import the <code>/core</code> entry, which needs Agent SDK v0.3.282 or later, and TypeScript 5.0 or later for its types [E30]. The root entry inlines its own copies of <code>zod</code> and the MCP SDK. <code>/core</code> takes them from the application&#8217;s own <code>node_modules</code> instead, so a bundle does not carry a second copy [E29].</p></li></ul><p><strong>Recent changes</strong> (in the newest 720 lines of the changelog, which carries no dates):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vJQR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feee16763-1a86-42e7-92c0-19cf85d3714a_1240x1120.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vJQR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feee16763-1a86-42e7-92c0-19cf85d3714a_1240x1120.png 424w, https://substackcdn.com/image/fetch/$s_!vJQR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feee16763-1a86-42e7-92c0-19cf85d3714a_1240x1120.png 848w, https://substackcdn.com/image/fetch/$s_!vJQR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feee16763-1a86-42e7-92c0-19cf85d3714a_1240x1120.png 1272w, https://substackcdn.com/image/fetch/$s_!vJQR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feee16763-1a86-42e7-92c0-19cf85d3714a_1240x1120.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!vJQR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feee16763-1a86-42e7-92c0-19cf85d3714a_1240x1120.png" width="1240" height="1120" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eee16763-1a86-42e7-92c0-19cf85d3714a_1240x1120.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1120,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:220031,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/224402095?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feee16763-1a86-42e7-92c0-19cf85d3714a_1240x1120.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_!vJQR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feee16763-1a86-42e7-92c0-19cf85d3714a_1240x1120.png 424w, https://substackcdn.com/image/fetch/$s_!vJQR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feee16763-1a86-42e7-92c0-19cf85d3714a_1240x1120.png 848w, https://substackcdn.com/image/fetch/$s_!vJQR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feee16763-1a86-42e7-92c0-19cf85d3714a_1240x1120.png 1272w, https://substackcdn.com/image/fetch/$s_!vJQR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feee16763-1a86-42e7-92c0-19cf85d3714a_1240x1120.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>How actively it is released.</strong> The cited entries run from version 0.3.292 to 0.3.319, and the newest tracks Claude Code v2.1.319 [E21]. Because the changelog has no dates, the evidence cannot say how often these versions shipped.</p><h3>3.2 The Claude API&#8217;s TypeScript SDK</h3><h4>What it offers.</h4><ul><li><p><strong>Types.</strong> TypeScript definitions &#8220;for all request parameters and response fields&#8221; [E43].</p></li><li><p><strong>Streaming and batches.</strong> Streaming responses over Server-Sent Events [E44], and batch processing under <code>client.messages.batches</code> [E49].</p></li><li><p><strong>Tool helpers.</strong> Tools are described with Zod schemas or JSON Schemas and run with <code>client.beta.messages.toolRunner()</code>, a beta method [E45]. A tool can throw a <code>ToolError</code>, which, unlike a plain <code>Error</code>, can carry images or other structured content back to the model [E46].</p></li><li><p><strong>MCP helpers.</strong> Helpers convert MCP tools, prompts and resources to Claude API types [E47]. They throw <code>UnsupportedMCPValueError</code> for values the API does not support, such as an unsupported content or MIME type, or a non-HTTP/HTTPS resource link [E48].</p></li><li><p><strong>File uploads.</strong> Uploads accept a <code>File</code>, a <code>fetch</code> <code>Response</code>, an <code>fs.ReadStream</code> or the output of <code>toFile</code> [E50].</p></li><li><p><strong>Errors.</strong> A connection failure or a 4xx or 5xx response throws a subclass of <code>APIError</code> [E51].</p></li><li><p><strong>Runtimes.</strong> The runtimes listed in section 2.6 [E42].</p></li></ul><p><strong>How actively it is released.</strong> The changelog is dated:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MhaE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9bc30d-04fe-4ba8-a3b5-d1d5e468bc3a_1240x1430.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MhaE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9bc30d-04fe-4ba8-a3b5-d1d5e468bc3a_1240x1430.png 424w, https://substackcdn.com/image/fetch/$s_!MhaE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9bc30d-04fe-4ba8-a3b5-d1d5e468bc3a_1240x1430.png 848w, https://substackcdn.com/image/fetch/$s_!MhaE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9bc30d-04fe-4ba8-a3b5-d1d5e468bc3a_1240x1430.png 1272w, https://substackcdn.com/image/fetch/$s_!MhaE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9bc30d-04fe-4ba8-a3b5-d1d5e468bc3a_1240x1430.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!MhaE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9bc30d-04fe-4ba8-a3b5-d1d5e468bc3a_1240x1430.png" width="1240" height="1430" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4a9bc30d-04fe-4ba8-a3b5-d1d5e468bc3a_1240x1430.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1430,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:276380,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/224402095?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9bc30d-04fe-4ba8-a3b5-d1d5e468bc3a_1240x1430.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_!MhaE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9bc30d-04fe-4ba8-a3b5-d1d5e468bc3a_1240x1430.png 424w, https://substackcdn.com/image/fetch/$s_!MhaE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9bc30d-04fe-4ba8-a3b5-d1d5e468bc3a_1240x1430.png 848w, https://substackcdn.com/image/fetch/$s_!MhaE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9bc30d-04fe-4ba8-a3b5-d1d5e468bc3a_1240x1430.png 1272w, https://substackcdn.com/image/fetch/$s_!MhaE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9bc30d-04fe-4ba8-a3b5-d1d5e468bc3a_1240x1430.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The cited entries alone show nine releases in about seven weeks, and a 1.0.0 release tied to a new API version. This is the most precisely dated evidence of release activity in the run. The fetch truncated this changelog and the run read only its first 720 lines, so older history is not covered.</p><h3>3.3 Compared with the Python SDKs</h3><p>Three entries in the changelog of the Claude Agent SDK for Python describe changes made to match the TypeScript SDK:</p><ul><li><p><strong>0.2.160.</strong> The SDK now listens for the CLI&#8217;s <code>session_state_changed</code> messages and keeps stdin open until the CLI reports <code>idle</code>, &#8220;matching the TypeScript SDK&#8217;s behavior&#8221; [E38].</p></li><li><p><strong>0.2.140.</strong> A new <code>forward_subagent_text</code> option forwards a subagent&#8217;s text and thinking blocks into the stream. It &#8220;Matches the TypeScript SDK&#8217;s <code>forwardSubagentText</code>&#8220; [E39].</p></li><li><p><strong>0.2.126.</strong> <code>ResultMessage.model_usage</code> is now typed with a <code>ModelUsage</code> TypedDict that &#8220;mirrors the TypeScript SDK&#8217;s shape&#8221; [E40].</p></li></ul><p>On these three points the TypeScript SDK had the behaviour first. The Python changelog is undated.</p><p>The evidence holds no full comparison of the two languages&#8217; SDKs, and nothing on where the Python SDKs lead. The run fetched the Python Agent SDK&#8217;s README and the Claude API&#8217;s Python SDK page, but kept no quote from either (section 11).</p><h2>4. The status of DeepSeek&#8217;s TypeScript SDK</h2><h3>4.1 What DeepSeek Harness is</h3><p>DeepSeek Harness (<code>dsh</code>) is &#8220;an open-source agent harness developed by DeepSeek AI&#8221;. It is built on an &#8220;everything-is-a-plugin&#8221; architecture and powered by Cordis [E62]. Its <a href="https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/README.md">README</a>&#8216;s quick start is to install Node.js and run it with <code>npx</code> [E63]. The README is undated.</p><h3>4.2 The TypeScript SDK family</h3><p>The <a href="https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/packages/sdk/README.md">SDK</a> &#8220;lets another process drive a complete DeepSeek Harness runtime over newline-delimited JSON-RPC&#8221; [E64]:</p><ul><li><p>its protocol package defines the public messages;</p></li><li><p>the TypeScript client launches <code>dsh</code> with a named profile and ordered patches;</p></li><li><p>the server accepts SDK requests over stdio.</p></li></ul><p>It has three packages [E65]:</p><p>PackageRole<code>protocol/</code>The newline-delimited JSON-RPC transport, and the named request, result and notification types<code>client/</code>A TypeScript client that spawns a runtime subprocess and drives agent turns through high-level and protocol-level APIs<code>server/</code>A <code>jsonrpc</code> plugin that serves out-of-process SDK clients over stdio</p><p>DeepSeek&#8217;s <a href="https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/docs/architecture.md">architecture document</a> adds that the TypeScript SDK resolves a <code>dsh</code> dependency of the same version and selects the <code>sdk</code> profile. Custom plugin composition remains &#8220;a profile plus ordered patch files, not another executable or inline application tree&#8221; [E73].</p><p>DeepSeek&#8217;s TypeScript SDK is therefore not a client for DeepSeek&#8217;s model API. It drives the harness as a subprocess [E64]. For the model API, see section 4.6.</p><h3>4.3 It&#8217;s Python counterpart</h3><p>The <a href="https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/python/sdk/README.md">Python SDK</a> &#8220;speaks the same protocol and ships a bundled runtime&#8221; [E66]. It is a &#8220;Python subprocess SDK for driving DeepSeek Harness over newline-delimited JSON-RPC on stdio&#8221; [E67]. It &#8220;follows the same application architecture&#8221;: its runtime wheel packages the normal <code>dsh</code> CLI, and by default the client launches <code>dsh --profile sdk</code> with an explicit Harness home [E74].</p><h3>4.4 Why it was built</h3><p>DeepSeek&#8217;s design note, dated 27 July 2026, gives the reason. &#8220;TypeScript consumers wanting the same drive-a-harness-as-a-subprocess capability &#8212; repo tests, automation, and above all a subagent backend whose child is a <em>complete harness runtime</em> rather than a generic ACP agent &#8212; had nothing to import&#8221; [E68]. The design made the wire shared and nominal [E69], so that server drift breaks compilation rather than clients [E70].</p><h3>4.5 The limits its own documents state</h3><p>The design note lists two costs of the design:</p><ul><li><p><strong>A full runtime per child.</strong> &#8220;the SDK backend boots a complete plugin tree per child (heavier per-run than an ACP child; pooling remains future work, same as ACP)&#8221; [E71].</p></li><li><p><strong>No cancel method.</strong> &#8220;the wire still has no cancel method, so both the SDK&#8217;s <code>RequestTimeoutError</code> and the backend&#8217;s dispose settle locally while the server-side turn runs on until process teardown&#8221; [E72].</p></li></ul><p>The evidence does not say whether either cost has been addressed since. The run also fetched DeepSeek Harness&#8217;s safety notice, but kept no verified quote from it. This note therefore cannot report the limits that notice states (section 11).</p><h3>4.6 What DeepSeek&#8217;s API documentation says about client libraries</h3><p>&#8220;<a href="https://api-docs.deepseek.com/">The DeepSeek API uses an API format compatible with OpenAI/Anthropic. By modifying the configuration, you can use the OpenAI/Anthropic SDK or softwares compatible with the OpenAI/Anthropic API to access the DeepSeek API.</a>&#8220; [E75] The page is undated. The quoted passage names no DeepSeek client library.</p><h2>5. The wider TypeScript agent ecosystem</h2><p>Each project is described from its own README. The READMEs are undated, and no source in the run ranks the projects against each other.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pEfL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e78ff3a-f6f7-4d88-b4ed-385948a6ba27_1240x1700.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pEfL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e78ff3a-f6f7-4d88-b4ed-385948a6ba27_1240x1700.png 424w, https://substackcdn.com/image/fetch/$s_!pEfL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e78ff3a-f6f7-4d88-b4ed-385948a6ba27_1240x1700.png 848w, https://substackcdn.com/image/fetch/$s_!pEfL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e78ff3a-f6f7-4d88-b4ed-385948a6ba27_1240x1700.png 1272w, https://substackcdn.com/image/fetch/$s_!pEfL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e78ff3a-f6f7-4d88-b4ed-385948a6ba27_1240x1700.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!pEfL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e78ff3a-f6f7-4d88-b4ed-385948a6ba27_1240x1700.png" width="1240" height="1700" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6e78ff3a-f6f7-4d88-b4ed-385948a6ba27_1240x1700.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1700,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:418342,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/224402095?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e78ff3a-f6f7-4d88-b4ed-385948a6ba27_1240x1700.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_!pEfL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e78ff3a-f6f7-4d88-b4ed-385948a6ba27_1240x1700.png 424w, https://substackcdn.com/image/fetch/$s_!pEfL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e78ff3a-f6f7-4d88-b4ed-385948a6ba27_1240x1700.png 848w, https://substackcdn.com/image/fetch/$s_!pEfL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e78ff3a-f6f7-4d88-b4ed-385948a6ba27_1240x1700.png 1272w, https://substackcdn.com/image/fetch/$s_!pEfL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e78ff3a-f6f7-4d88-b4ed-385948a6ba27_1240x1700.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h4>Three more points from these sources:</h4><ul><li><p><strong>OpenAI states</strong>: &#8220;<em>We&#8217;re committed to building the Agents SDK as an open source framework so others in the community can expand on our approach.</em>&#8221; [E81]</p></li><li><p><strong>GitHub&#8217;s Octoverse 2025</strong> report notes that the Model Context Protocol &#8220;<em>hit 37k stars in just eight months</em>&#8221;, though it is not on the report&#8217;s ranked lists [E109].</p></li><li><p>Four of the five projects name <strong>Zod</strong>, or a schema standard that includes it. Two describe themselves as provider-agnostic [E78][E82].</p></li></ul><h2>6. Future efforts</h2><h3>6.1 TypeScript 7: the native compiler</h3><p><strong>The March 2025 plan.</strong> &#8220;<a href="https://devblogs.microsoft.com/typescript/typescript-native-port/">A 10x Faster TypeScript</a>&#8220; (11 March 2025) announced a native port of the compiler and tools. The port would &#8220;drastically improve editor startup, reduce most build times by 10x, and substantially reduce memory usage&#8221; [E96]. Its plan at the time was:</p><ul><li><p>a preview of a native <code>tsc</code> for command-line type checking by mid-2025;</p></li><li><p>a feature-complete solution for project builds and a language service by the end of 2025 [E97];</p></li><li><p>a release as TypeScript 7.0 once the native codebase &#8220;has reached sufficient parity&#8221; [E98].</p></li></ul><p>This was the plan as of March 2025, not a record of what happened.</p><p><strong>The April 2026 beta.</strong> &#8220;<a href="https://devblogs.microsoft.com/typescript/announcing-typescript-7-0-beta/">Announcing TypeScript 7.0 Beta</a>&#8220; (21 April 2026) reports that the codebase had been ported from TypeScript to Go over the past year. With native code speed and shared-memory parallelism, &#8220;TypeScript 7.0 is often about 10 times faster than TypeScript 6.0&#8221; [E93]. The post said: &#8220;Our current plan is to release TypeScript 7.0 within the next two months&#8221; [E94]. Two months from the post would be about late June 2026. A stable programmatic API is planned &#8220;for TypeScript 7.1 or later&#8221; [E95].</p><p><strong>What is not known.</strong> Whether TypeScript 7.0 has shipped as a stable release is not in the evidence. The newest dated evidence of a compiler in use is Anthropic&#8217;s API SDK building its sub-packages with TypeScript 6.0.3, in version 0.127.0 of 18 September 2026 [E61].</p><h3>6.2 Node.js runs TypeScript directly</h3><p><a href="https://nodejs.org/api/typescript.html">Node.js documentation</a> states: &#8220;Type stripping is now stable.&#8221; [E99] Its version history records this for Node.js v25.2.0 and v24.12.0.</p><ul><li><p><strong>How it works.</strong> By default Node.js &#8220;will execute TypeScript files that contains only erasable TypeScript syntax&#8221;. It replaces that syntax with whitespace, &#8220;and no type checking is performed&#8221; [E101].</p></li><li><p><strong>Why it is light.</strong> The feature is designed to be lightweight. It deliberately leaves out syntax that needs JavaScript code generation, so Node.js runs TypeScript without source maps [E102].</p></li><li><p><strong>The two options.</strong> Node.js documents two ways to run TypeScript. A third-party package gives &#8220;full support of all of TypeScript&#8217;s syntax and features, including using any version of TypeScript&#8221;. The built-in type stripping gives &#8220;lightweight support&#8221; [E100].</p></li></ul><p>The limits this brings are in section 8.3.</p><h3>6.3 The SDKs&#8217; stated directions</h3><p>The evidence holds no roadmap for any SDK beyond these statements:</p><ul><li><p><strong>OpenAI</strong> commits to the Agents SDK as an open-source framework [E81].</p></li><li><p><strong>DeepSeek</strong> lists pooling of SDK children as &#8220;future work&#8221; [E71].</p></li><li><p><strong>The Claude Agent SDK</strong> tracks Claude Code: its latest entry is &#8220;Updated to parity with Claude Code v2.1.319&#8221; [E21].</p></li><li><p><strong>The Claude API SDK</strong> reached 1.0.0 with a new API version on 21 October 2026 [E56].</p></li><li><p><strong>TypeScript</strong> plans a stable programmatic API for 7.1 or later [E95].</p></li></ul><h2>7. Community evidence</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8TX1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98586fae-c038-4673-bedd-fff90aab4210_1240x1644.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8TX1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98586fae-c038-4673-bedd-fff90aab4210_1240x1644.png 424w, https://substackcdn.com/image/fetch/$s_!8TX1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98586fae-c038-4673-bedd-fff90aab4210_1240x1644.png 848w, https://substackcdn.com/image/fetch/$s_!8TX1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98586fae-c038-4673-bedd-fff90aab4210_1240x1644.png 1272w, https://substackcdn.com/image/fetch/$s_!8TX1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98586fae-c038-4673-bedd-fff90aab4210_1240x1644.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!8TX1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98586fae-c038-4673-bedd-fff90aab4210_1240x1644.png" width="1240" height="1644" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/98586fae-c038-4673-bedd-fff90aab4210_1240x1644.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1644,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:235387,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/224402095?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98586fae-c038-4673-bedd-fff90aab4210_1240x1644.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_!8TX1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98586fae-c038-4673-bedd-fff90aab4210_1240x1644.png 424w, https://substackcdn.com/image/fetch/$s_!8TX1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98586fae-c038-4673-bedd-fff90aab4210_1240x1644.png 848w, https://substackcdn.com/image/fetch/$s_!8TX1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98586fae-c038-4673-bedd-fff90aab4210_1240x1644.png 1272w, https://substackcdn.com/image/fetch/$s_!8TX1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98586fae-c038-4673-bedd-fff90aab4210_1240x1644.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h4>Further points from these sources:</h4><ul><li><p><strong>AI involvement in pull requests.</strong> Octoverse 2026 reports that TypeScript, Python and Rust, &#8220;the fastest-growing communities, have the highest shares, about 40% to 44% of merged pull requests&#8221; [E113]. In the report this is each language&#8217;s share of merged pull requests with detected AI involvement, not TypeScript&#8217;s share of all pull requests.</p></li><li><p><strong>Python&#8217;s place.</strong> The same 2025 report that ranks TypeScript first adds: &#8220;Python remains dominant for AI and data science workloads, while the JavaScript/TypeScript ecosystem still accounts for more overall activity than Python alone&#8221; [E108].</p></li><li><p><strong>The same split in 2021.</strong> The 2022 paper cited the 2021 Stack Overflow survey for JavaScript being the most widely used language [E123], and Octoverse for TypeScript&#8217;s growing popularity [E124].</p></li><li><p><strong>Why the measures disagree.</strong> Octoverse counts contributors on GitHub [E110], while the survey counts respondents [E117]. They measure different populations, so they can disagree without either being wrong.</p></li></ul><h2>8. The trade-offs</h2><p>I have called the trade-offs the most important part of the question [E12]. The evidence supports nine. Each ends with its bearing on Grove.</p><h3>8.1 Better code quality, but not fewer bugs</h3><p>The 2022 paper &#8220;<a href="https://arxiv.org/html/2203.11115">To Type or Not to Type? A Systematic Comparison of the Software Quality of JavaScript and TypeScript Applications on GitHub</a>&#8220; compared JavaScript and TypeScript applications. Its abstract reports three findings:</p><ul><li><p><strong>Quality.</strong> &#8220;TS applications exhibit significantly better code quality and understandability than JS applications&#8221; [E120].</p></li><li><p><strong>Bugs.</strong> &#8220;Contrary to expectations, however, bug proneness and bug resolution time of our TS sample were not significantly lower than for JS.&#8221; The mean bug-fix commit ratio of the TypeScript projects was more than 60% larger (0.206 against 0.126), and they took on average more than a day longer to fix bugs (33.04 against 31.86 days) [E121].</p></li><li><p><strong>The </strong><code>any</code><strong> type.</strong> Using <code>any</code> less &#8220;appears to be beneficial&#8221;: its frequency correlated significantly with every metric except bug proneness [E122].</p></li></ul><p>That is the real tension in the evidence: better quality and understandability, but no lower bug proneness, in the same study [E120][E121].</p><p>The paper&#8217;s related-work section describes earlier studies, with their own samples, that lean the other way:</p><ul><li><p><strong>Zhang et al. (2020):</strong> &#8220;Within their sample, dynamically typed languages consumed 59.5% more time for bug resolution than statically typed ones.&#8221; [E126]</p></li><li><p><strong>Gao et al. (2017):</strong> using TypeScript &#8220;would have prevented 60 of the 400 bugs they examined (15%)&#8221; [E127].</p></li></ul><p>These are different studies, not more data from the 2022 paper&#8217;s sample. No source in the run studies agent harnesses or SDK codebases specifically.</p><p><em>For Grove:</em> the evidence supports types for code quality and understandability. It does not promise fewer bugs.</p><h3>8.2 Types are erased at run time</h3><p>In the 2022 paper&#8217;s description, &#8220;TS performs type checking at transpile-time, while JS performs type checking at run-time&#8221; [E118]. Node.js&#8217;s type stripping replaces TypeScript syntax with whitespace and performs no type checking [E101]. Two things follow:</p><ul><li><p>Data that crosses a boundary, such as model output, tool input or a message between processes, needs a run-time schema (section 2.2).</p></li><li><p>The type check has to run as a step of its own.</p></li></ul><p><em>For Grove:</em> it does both. Every persisted or exchanged structure is a zod schema [E14], and the type check runs across all packages [E11] and in CI [E8].</p><h3>8.3 Running TypeScript directly has syntax limits</h3><p>Type stripping runs only erasable syntax [E101]:</p><ul><li><p><strong>Transformed features fail.</strong> Enum declarations, namespaces with runtime code, parameter properties and import aliases need transformation rather than stripping [E103].</p></li><li><p><strong>Decorators fail.</strong> They are not transformed and cause a parser error. Node.js &#8220;will not support decorators until they are supported natively in JavaScript&#8221; [E104].</p></li><li><p><strong>Type imports need the </strong><code>type</code><strong> keyword.</strong> Without it Node.js treats a type import as a value import, which is a run-time error [E105].</p></li><li><p><strong>Full syntax needs a package.</strong> Full TypeScript syntax, or a chosen TypeScript version, needs a third-party package [E100].</p></li></ul><p><em>For Grove:</em> its first milestone report says there is no build step, because Node runs the TypeScript directly [E9]. Its plan lists tsx and tsup for development and build [E4]. The evidence does not say which mechanism Grove&#8217;s direct run uses, so whether these limits bind Grove is a gap.</p><h3>8.4 Python&#8217;s place in AI and machine learning</h3><ul><li><p><strong>Dominance.</strong> Python &#8220;remains dominant for AI and data science workloads&#8221; [E108].</p></li><li><p><strong>Contributors.</strong> It is second on GitHub [E110], added 3.23 million monthly contributors in a year [E111], and is forecast to reach about the same size as TypeScript by September 2027 [E112].</p></li><li><p><strong>Survey use.</strong> 58.0% of the 2026 survey&#8217;s respondents use it, against 43.8% for TypeScript [E117].</p></li></ul><p>The evidence states Python&#8217;s dominance in AI in one sentence. No source compares the two languages&#8217; machine-learning libraries.</p><p><em>For Grove:</em> its records already keep a Python boundary. Its machine-learning codebase is Python [E13], and three ports may be re-implemented in Python: the model provider, the context source and the scorer [E16].</p><h3>8.5 Where the Python SDKs lead or differ</h3><p>The only comparison in the evidence is the three Python changes made to match the TypeScript Agent SDK [E38][E39][E40]. Nothing in the evidence shows where Python leads.</p><p><em>For Grove:</em> the evidence neither confirms nor rules out a Python-only capability that Grove would miss.</p><h3>8.6 The cost of keeping two languages</h3><ul><li><p><strong>DeepSeek</strong> keeps two SDKs over one protocol [E66][E67][E74]. It built the TypeScript one because TypeScript consumers &#8220;had nothing to import&#8221; [E68].</p></li><li><p><strong>Anthropic</strong> keeps the Python Agent SDK in step with the TypeScript one by matching its behaviour, options and types one change at a time [E38][E39][E40].</p></li></ul><p>In both cases a single shared protocol or shape holds the two languages together. No source counts what that costs.</p><p><em>For Grove:</em> it avoids a second SDK by design:</p><ul><li><p>one TypeScript implementation;</p></li><li><p>contracts any language can read, exported as JSON Schema [E14];</p></li><li><p>digests any language can reproduce [E15];</p></li><li><p>a subprocess protocol only for the ports that move [E16].</p></li></ul><h3>8.7 Subprocess SDKs cost runtime and need cancellation</h3><p>DeepSeek&#8217;s design boots a complete plugin tree for each child, and has no pooling yet [E71]. Its wire has no cancel method, so a timed-out turn keeps running on the server until the process is torn down [E72].</p><p><em>For Grove:</em> its planned subprocess protocol maps cancellation to SIGTERM and has a timeout [E16]. Section 10 covers the open part.</p><h3>8.8 Popularity measures disagree</h3><p>TypeScript is first on GitHub by contributors [E110] and sixth in the 2026 Stack Overflow survey [E116][E117]. Popularity alone does not settle the case either way.</p><p><em>For Grove:</em> the case rests better on sections 2 to 4 than on rankings.</p><h3>8.9 Compiler speed and stability are in transition</h3><p>The TypeScript 7.0 beta is reported as often about ten times faster than 6.0 [E93]. A stable programmatic API comes only with 7.1 or later [E95], and the evidence does not show that 7.0 has shipped (section 6.1).</p><p><em>For Grove:</em> no Grove decision in the evidence addresses TypeScript 7.</p><h2>9. Grove&#8217;s recorded position against the evidence</h2><h3>9.1 What Grove has recorded</h3><ul><li><p><strong>TypeScript-first.</strong> Grove is TypeScript-first [E13], and stays TypeScript with language-neutral contracts because some modules will later move to the Python machine-learning codebase [E1][E6].</p></li><li><p><strong>One schema per structure.</strong> Every persisted or exchanged structure is defined once as a zod schema in Grove&#8217;s public contracts package, and exported as JSON Schema with a schema version [E14][E2][E10]. This covers run records, run events, artifacts, provenance, memory entries, model selection, messages, errors and configuration [E14].</p></li><li><p><strong>Portable digests.</strong> Digests use canonical JSON (keys sorted recursively, undefined values dropped) followed by sha256, &#8220;so any language reproduces them&#8221; [E15].</p></li><li><p><strong>A subprocess protocol, planned.</strong> Ports that may be re-implemented in Python will get a local subprocess protocol: NDJSON request and response over stdio, schema-validated messages, cancellation mapped to SIGTERM, and a timeout [E16]. The plan&#8217;s risk register lists the TypeScript&#8211;Python split as an architecture risk. Its mitigation is that protocol plus a schema conformance script [E7].</p></li><li><p><strong>Checks.</strong> Grove&#8217;s traceability table marks its TypeScript-first typed contracts as tested, by a unit test and by the type check in CI [E8]. The first milestone report lists the type check across all packages, and a lint step for the dependency rule [E11].</p></li><li><p><strong>Models.</strong> Grove&#8217;s private expert is a local OpenAI-compatible model server (Ollama on CPU-only hosts, vLLM on a GPU host), reached through Grove&#8217;s OpenAI-compatible provider at a configured address [E5]. The plan lists Anthropic&#8217;s TypeScript SDK and the AWS Bedrock runtime client as optional dependencies of Grove&#8217;s model router [E4].</p></li></ul><h3>9.2 Where the evidence supports it</h3><ul><li><p><strong>Static types and compile-time boundaries.</strong> These are argued for by proponents [E119], used by DeepSeek [E69][E70], and used in Grove&#8217;s own dependency rule [E3].</p></li><li><p><strong>Schema-first contracts.</strong> They match how the Claude SDKs, the Vercel AI SDK, the OpenAI Agents SDK, Google&#8217;s ADK and the MCP SDK handle schemas [E32][E45][E84][E80][E92][E77].</p></li><li><p><strong>TypeScript SDKs exist and are maintained.</strong> The Claude API SDK shows frequent dated releases (section 3.2). On three points, the Python Agent SDK followed the TypeScript one [E38][E39][E40].</p></li><li><p><strong>DeepSeek also puts a protocol between languages.</strong> It runs one wire protocol with TypeScript and Python SDKs on top [E64][E66][E67], the approach Grove plans for the ports that move to Python [E16].</p></li><li><p><strong>Agent use.</strong> GitHub links TypeScript&#8217;s rise to agent-assisted coding, and finds it more common in repositories with agent signals. These are GitHub&#8217;s interpretation [E107][E114][E115].</p></li></ul><h3>9.3 Where the evidence qualifies it</h3><ul><li><p><strong>Mixed quality evidence.</strong> Code quality and understandability are better, but bug proneness is not lower [E120][E121]. Limiting <code>any</code> appears to help [E122].</p></li><li><p><strong>Python&#8217;s lead in AI.</strong> Python is dominant for AI and data science [E108]. Grove&#8217;s records already keep a Python boundary for the machine-learning codebase [E13].</p></li><li><p><strong>Erased types.</strong> Types are erased at run time [E101], so Grove&#8217;s run-time schemas are necessary, not optional.</p></li><li><p><strong>Direct-run syntax limits.</strong> Running TypeScript directly limits the syntax that can be used [E103][E104][E105]. Whether this binds Grove is a gap (section 8.3).</p></li><li><p><strong>Popularity.</strong> The popularity measures disagree [E110][E116][E117].</p></li><li><p><strong>Subprocess costs.</strong> Subprocess designs carry runtime and cancellation costs [E71][E72].</p></li></ul><h3>9.4 Where the evidence contradicts it</h3><p>Nothing in the evidence contradicts Grove&#8217;s recorded position outright. The nearest is the 2022 paper&#8217;s finding that TypeScript projects did not have fewer bugs [E121]. That qualifies the general argument for static types [E119], not Grove&#8217;s design.</p><h2>10. What Grove should adopt or avoid</h2><p>Each point below is drawn only from the evidence above. The last column says whether a Grove decision quoted in the evidence already settles it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!L6sI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c196314-9f50-42bf-b3ca-2de7027d75cd_1240x2800.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!L6sI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c196314-9f50-42bf-b3ca-2de7027d75cd_1240x2800.png 424w, https://substackcdn.com/image/fetch/$s_!L6sI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c196314-9f50-42bf-b3ca-2de7027d75cd_1240x2800.png 848w, https://substackcdn.com/image/fetch/$s_!L6sI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c196314-9f50-42bf-b3ca-2de7027d75cd_1240x2800.png 1272w, https://substackcdn.com/image/fetch/$s_!L6sI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c196314-9f50-42bf-b3ca-2de7027d75cd_1240x2800.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!L6sI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c196314-9f50-42bf-b3ca-2de7027d75cd_1240x2800.png" width="1240" height="2800" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6c196314-9f50-42bf-b3ca-2de7027d75cd_1240x2800.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:2800,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:721132,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/224402095?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c196314-9f50-42bf-b3ca-2de7027d75cd_1240x2800.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_!L6sI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c196314-9f50-42bf-b3ca-2de7027d75cd_1240x2800.png 424w, https://substackcdn.com/image/fetch/$s_!L6sI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c196314-9f50-42bf-b3ca-2de7027d75cd_1240x2800.png 848w, https://substackcdn.com/image/fetch/$s_!L6sI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c196314-9f50-42bf-b3ca-2de7027d75cd_1240x2800.png 1272w, https://substackcdn.com/image/fetch/$s_!L6sI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c196314-9f50-42bf-b3ca-2de7027d75cd_1240x2800.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>No row proposes new components. Rows 6, 7, 10 and 12 need an owner decision, or evidence the run did not gather. Row 8 needs a test.</p><h2>11. Conflicts, gaps and coverage limits</h2><h3>11.1 Conflicts</h3><ul><li><p><strong>The real tension.</strong> Within the 2022 study, TypeScript applications had better code quality and understandability [E120], but bug proneness and bug resolution time were not lower [E121].</p></li><li><p><strong>Not a conflict: how TypeScript is checked and run.</strong> The 2022 paper describes TypeScript as transpiled by <code>tsc</code>, with types checked at transpile time [E118]. Node.js can run erasable TypeScript directly, with no type checking [E101][E102]. That is one way a project can have no build step, as Grove reports [E9], with type checking as a separate step [E11].</p></li><li><p><strong>Not a conflict: the 59.5% figure.</strong> Zhang et al.&#8217;s result [E126] comes from a different study and sample than the 2022 paper&#8217;s own [E121].</p></li><li><p><strong>Not a conflict: the popularity rankings.</strong> GitHub and Stack Overflow measure different populations (section 7).</p></li></ul><h3>11.2 Gaps: what the sources do not say</h3><ol><li><p>Whether TypeScript 7.0 has shipped as a stable release. The newest evidence is the 21 April 2026 plan [E94].</p></li><li><p>A full feature comparison of Claude&#8217;s TypeScript and Python SDKs, or where the Python SDKs lead.</p></li><li><p>Release dates for the Claude Agent SDK&#8217;s TypeScript and Python versions. Both changelogs give versions only.</p></li><li><p>The limits stated in DeepSeek Harness&#8217;s safety notice. It was fetched, but no verified quote was kept.</p></li><li><p>Whether DeepSeek has addressed the per-child cost or the missing cancel method since July 2026 [E71][E72].</p></li><li><p>A comparison of TypeScript&#8217;s and Python&#8217;s machine-learning ecosystems, beyond one sentence [E108].</p></li><li><p>Evidence on software quality in agent harnesses or SDK codebases specifically. The studies cover general GitHub applications [E120][E121][E126][E127], and type-constrained code generation [E128].</p></li><li><p>The cost of maintaining SDKs in two languages.</p></li><li><p>Which mechanism Grove&#8217;s direct run of TypeScript uses [E9][E4].</p></li><li><p>Whether Grove&#8217;s subprocess protocol has been built [E16][E6], and whether DeepSeek&#8217;s API has been tried through Grove&#8217;s OpenAI-compatible provider [E5][E75].</p></li><li><p>Roadmaps for any of the SDKs, beyond the statements in section 6.3.</p></li></ol><h3>11.3 Coverage limits</h3><ul><li><p><strong>Long pages were read only in part.</strong> The run read the first 720 lines (six windows of 120 lines) of each long page. The pages affected are:</p><ul><li><p>the Claude Agent SDK changelogs for TypeScript and Python;</p></li><li><p>the Agent SDK&#8217;s TypeScript reference;</p></li><li><p>the Claude API&#8217;s TypeScript and Python SDK pages;</p></li><li><p>the Anthropic TypeScript SDK changelog;</p></li><li><p>both Octoverse reports;</p></li><li><p>the 2022 paper, all but its last five lines.</p></li></ul><p>Older changelog history and later sections were not read.</p></li><li><p><strong>Two pages were truncated.</strong> The fetch truncated the Agent SDK&#8217;s TypeScript reference and the Anthropic TypeScript SDK changelog, so only their start was examined.</p></li><li><p><strong>Eight Grove documents were not read.</strong> The run reads at most ten local sources. Five decision records, two milestone reports and an operations note ranked below the top ten and were not read.</p></li><li><p><strong>Some sources gave no quotes.</strong></p><ul><li><p>Five of the nine Grove documents read yielded no quote.</p></li><li><p>Four fetched web pages gave no verified quote: the Claude Agent SDK overview, the Python Agent SDK README, the Claude API&#8217;s Python SDK page and DeepSeek Harness&#8217;s safety notice.</p></li></ul></li><li><p><strong>Rejected quotes are a coverage limit, not missing material.</strong> 54 candidate quotes were rejected because the model paraphrased instead of copying. The rejected quotes are not used here, and nothing is missing from the sources.</p></li></ul><h2>Sources</h2><p>Each cited id maps to one source below. Grove&#8217;s own documents are described by their role. Web pages were retrieved on 7 November 2026.</p><h3>Research brief and Grove&#8217;s own documents</h3><h3>1. Research brief</h3><h5>1. Owner&#8217;s brief: the case for TypeScript SDKs in Grove</h5><p>Evidence: E12<br>Role: My request for this deep dive, recorded word for word<br>Date: 7 November 2026</p><h3>2. Grove v0.1 &#8212; discovery, implementation and traceability</h3><h5>2. Grove v0.1 &#8212; Phase 0 discovery report and implementation plan</h5><p>Evidence: E1&#8211;E7<br>Role: Grove&#8217;s plan, decision log and risk register<br>Date: Last updated 20 October 2026</p><h5>3. Grove v0.1 traceability</h5><p>Evidence: E8<br>Role: Grove&#8217;s table mapping each component to its code and its tests<br>Date: Undated; read as of 7 November 2026</p><h5>4. Grove v0.1 &#8212; first milestone report (agent foundation)</h5><p>Evidence: E9&#8211;E11<br>Role: Grove&#8217;s first milestone report<br>Date: 20 October 2026</p><h3>3. Language-neutral architecture and portability</h3><h5>5. Language-neutral contracts for portability to the machine-learning codebase</h5><p>Evidence: E13&#8211;E16<br>Role: Grove&#8217;s decision record on language-neutral contracts<br>Date: 20 October 2026</p><h2>Web sources</h2><p>All web pages were retrieved on 7 November 2026. Evidence IDs in brackets correspond to citations in the article.</p><h3>1. Anthropic &#8212; Claude SDKs</h3><h5>1. <a href="https://raw.githubusercontent.com/anthropics/claude-agent-sdk-typescript/main/README.md?utm_source=chatgpt.com">Claude Agent SDK (README)</a></h5><p>Evidence: E17<br>Date: Undated</p><h5>2. <a href="https://raw.githubusercontent.com/anthropics/claude-agent-sdk-typescript/main/CHANGELOG.md?utm_source=chatgpt.com">Claude Agent SDK for TypeScript: Changelog</a></h5><p>Evidence: E18&#8211;E27<br>Date: Undated; versions 0.3.292 to 0.3.319</p><h5>3. <a href="https://code.claude.com/docs/en/agent-sdk/typescript.md?utm_source=chatgpt.com">Agent SDK reference &#8212; TypeScript</a></h5><p>Evidence: E28&#8211;E37<br>Date: Undated</p><h5>4. <a href="https://raw.githubusercontent.com/anthropics/claude-agent-sdk-python/main/CHANGELOG.md?utm_source=chatgpt.com">Claude Agent SDK for Python: Changelog</a></h5><p>Evidence: E38&#8211;E40<br>Date: Undated; versions 0.2.126 to 0.2.160</p><h5>5. <a href="https://platform.claude.com/docs/en/cli-sdks-libraries/overview.md?utm_source=chatgpt.com">SDKs, CLI, and libraries</a></h5><p>Evidence: E41<br>Date: Undated</p><h5>6. <a href="https://platform.claude.com/docs/en/cli-sdks-libraries/sdks/typescript.md?utm_source=chatgpt.com">TypeScript SDK &#8212; Claude API documentation</a></h5><p>Evidence: E42&#8211;E51<br>Date: Undated</p><h5>7. <a href="https://raw.githubusercontent.com/anthropics/anthropic-sdk-typescript/main/CHANGELOG.md?utm_source=chatgpt.com">Anthropic TypeScript SDK: Changelog</a></h5><p>Evidence: E52&#8211;E61<br>Date: Entries dated 15 September to 5 November 2026</p><h3>2. DeepSeek &#8212; Harness and SDK architecture</h3><h5>8. <a href="https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/README.md?utm_source=chatgpt.com">DeepSeek Harness (README)</a></h5><p>Evidence: E62&#8211;E63<br>Date: Undated</p><h5>9. <a href="https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/packages/sdk/README.md?utm_source=chatgpt.com">sdk/ &#8212; drive a Harness runtime from another process</a></h5><p>Evidence: E64&#8211;E66<br>Date: Undated</p><h5>10. <a href="https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/python/sdk/README.md?utm_source=chatgpt.com">DeepSeek Harness Python SDK</a></h5><p>Evidence: E67<br>Date: Undated</p><h5>11. <a href="https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/.agents/notes/archived/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.md?utm_source=chatgpt.com">Agent Note: TypeScript SDK client and the SDK subagent backend</a></h5><p>Evidence: E68&#8211;E72<br>Date: 27 July 2026; archived 4 September 2026</p><h5>12. <a href="https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/docs/architecture.md?utm_source=chatgpt.com">DeepSeek Harness Architecture</a></h5><p>Evidence: E73&#8211;E74<br>Date: Undated</p><h5>13. <a href="https://api-docs.deepseek.com/?utm_source=chatgpt.com">DeepSeek API Docs: Your First API Call</a></h5><p>Evidence: E75<br>Date: Undated</p><h3>3. Other TypeScript agent SDKs and toolkits</h3><h5>14. <a href="https://raw.githubusercontent.com/modelcontextprotocol/typescript-sdk/main/README.md?utm_source=chatgpt.com">MCP TypeScript SDK (README)</a></h5><p>Evidence: E76&#8211;E77<br>Date: Undated</p><h5>15. <a href="https://raw.githubusercontent.com/openai/openai-agents-js/main/README.md?utm_source=chatgpt.com">OpenAI Agents SDK (JavaScript/TypeScript) (README)</a></h5><p>Evidence: E78&#8211;E81<br>Date: Undated</p><h5>16. <a href="https://raw.githubusercontent.com/vercel/ai/main/packages/ai/README.md?utm_source=chatgpt.com">AI SDK (Vercel) (README)</a></h5><p>Evidence: E82&#8211;E87<br>Date: Undated</p><h5>17. <a href="https://raw.githubusercontent.com/mastra-ai/mastra/main/README.md?utm_source=chatgpt.com">Mastra (README)</a></h5><p>Evidence: E88&#8211;E90<br>Date: Undated</p><h5>18. <a href="https://raw.githubusercontent.com/google/adk-js/main/README.md?utm_source=chatgpt.com">Agent Development Kit (ADK) for TypeScript (README)</a></h5><p>Evidence: E91&#8211;E92<br>Date: Undated</p><h3>4. TypeScript and Node.js &#8212; language and runtime</h3><h5>19. <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-7-0-beta/?utm_source=chatgpt.com">Announcing TypeScript 7.0 Beta</a></h5><p>Evidence: E93&#8211;E95<br>Date: 21 April 2026</p><h5>20. <a href="https://devblogs.microsoft.com/typescript/typescript-native-port/?utm_source=chatgpt.com">A 10x Faster TypeScript</a></h5><p>Evidence: E96&#8211;E98<br>Date: 11 March 2025</p><h5>21. <a href="https://nodejs.org/api/typescript.html?utm_source=chatgpt.com">Modules: TypeScript &#8212; Node.js documentation</a></h5><p>Evidence: E99&#8211;E105<br>Date: Undated; type stripping marked stable in v25.2.0 and v24.12.0</p><h3>5. Developer community and language adoption</h3><h5>22. <a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/?utm_source=chatgpt.com">Octoverse: A new developer joins GitHub every second as AI leads TypeScript to #1</a></h5><p>Evidence: E106&#8211;E109<br>Date: 28 October 2025; updated 28 February 2026</p><h5>23. <a href="https://github.blog/news-insights/octoverse/octoverse-commits-pushes-reach-new-highs-in-2026-as-developers-build-with-agents/?utm_source=chatgpt.com">Octoverse: Commits, pushes, reach new highs in 2026 as developers build with agents</a></h5><p>Evidence: E110&#8211;E115<br>Date: 28 October 2026; updated 6 November 2026</p><h5>24. <a href="https://survey.stackoverflow.co/2026/technology?utm_source=chatgpt.com">Stack Overflow Developer Survey 2026: Technology</a></h5><p>Evidence: E116&#8211;E117<br>Date: 2026 survey; no publication date on the page</p><h3>6. Research papers &#8212; software quality and type-constrained code generation</h3><h5>25. <a href="https://arxiv.org/html/2203.11115?utm_source=chatgpt.com">To Type or Not to Type? A Systematic Comparison of the Software Quality of JavaScript and TypeScript Applications on GitHub</a> &#8212; Bogner and Merkel</h5><p>Evidence: E118&#8211;E127<br>Date: 2022; arXiv v1 of 21 March 2022</p><h5>26. <a href="https://arxiv.org/abs/2504.09246?utm_source=chatgpt.com">Type-Constrained Code Generation with Language Models</a> &#8212; M&#252;ndler et al.</h5><p>Evidence: E128<br>Date: 2025; submitted 12 April 2025, revised 8 May 2025</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ahsu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 424w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 848w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1272w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png" width="1456" height="211" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:211,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ahsu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 424w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 848w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1272w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[ಕೊಡಗಿನ ನಗು | Kodagu Smiles]]></title><description><![CDATA[Beyond the landscapes, a portrait of the people, everyday lives and quiet diversity of Kodagu.]]></description><link>https://blog.phagyul.ai/p/kodagu-smiles</link><guid isPermaLink="false">https://blog.phagyul.ai/p/kodagu-smiles</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Fri, 06 Nov 2026 07:49:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ul-H!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><p><em><strong>Kodagu is often spoken of through its landscapes. Its coffee plantations, mist-covered hills, forests, winding roads and beautiful homes are familiar images that have come to represent this part of Karnataka.</strong></em></p></div><p>But there is another Kodagu that reveals itself when we slow down and look beyond the landscape.</p><p>It is found in its streets, neighbourhoods, homes and marketplaces. In the conversations that happen outside shops, the daily routines of people at work, the warmth of an unexpected smile, and the quiet moments that might otherwise pass unnoticed.</p><p>During my time in Virajpet, and exploring around Coorg, I found myself drawn to these everyday encounters. Not necessarily to extraordinary moments, but to ordinary ones that, when observed closely, begin to tell us something about a place and the people who inhabit it.</p><h2>The town</h2><p>Every town has its own character. Sometimes it is found in its architecture, sometimes in its streets, and often in the little details we tend to overlook. Virajpet reveals itself gradually, through familiar corners and everyday movement.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ID57!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ed0f615-395c-4c84-980d-f020405ab9d4_1800x1800.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ID57!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ed0f615-395c-4c84-980d-f020405ab9d4_1800x1800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ID57!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ed0f615-395c-4c84-980d-f020405ab9d4_1800x1800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ID57!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ed0f615-395c-4c84-980d-f020405ab9d4_1800x1800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ID57!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ed0f615-395c-4c84-980d-f020405ab9d4_1800x1800.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ID57!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ed0f615-395c-4c84-980d-f020405ab9d4_1800x1800.jpeg" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0ed0f615-395c-4c84-980d-f020405ab9d4_1800x1800.jpeg&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;:1114765,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223449757?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ed0f615-395c-4c84-980d-f020405ab9d4_1800x1800.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ID57!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ed0f615-395c-4c84-980d-f020405ab9d4_1800x1800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ID57!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ed0f615-395c-4c84-980d-f020405ab9d4_1800x1800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ID57!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ed0f615-395c-4c84-980d-f020405ab9d4_1800x1800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ID57!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0ed0f615-395c-4c84-980d-f020405ab9d4_1800x1800.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>People</h2><p>Perhaps the most beautiful way to understand a place is through its people. A glance, a smile, a fleeting expression or simply the willingness to pause for a photograph. Every face carries a story, even when we know very little about it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hmkW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da567ad-674f-49f9-a83f-708686340b3c_1800x1800.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hmkW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da567ad-674f-49f9-a83f-708686340b3c_1800x1800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!hmkW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da567ad-674f-49f9-a83f-708686340b3c_1800x1800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!hmkW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da567ad-674f-49f9-a83f-708686340b3c_1800x1800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!hmkW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da567ad-674f-49f9-a83f-708686340b3c_1800x1800.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!hmkW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da567ad-674f-49f9-a83f-708686340b3c_1800x1800.jpeg" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6da567ad-674f-49f9-a83f-708686340b3c_1800x1800.jpeg&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;:1006435,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223449757?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da567ad-674f-49f9-a83f-708686340b3c_1800x1800.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hmkW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da567ad-674f-49f9-a83f-708686340b3c_1800x1800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!hmkW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da567ad-674f-49f9-a83f-708686340b3c_1800x1800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!hmkW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da567ad-674f-49f9-a83f-708686340b3c_1800x1800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!hmkW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da567ad-674f-49f9-a83f-708686340b3c_1800x1800.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>At home</h2><p>Beyond the streets and marketplaces are quieter moments of everyday life. Families, children, older generations and the familiar spaces they inhabit. These are intimate glimpses into lives that rarely find their way into photographs of a destination.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8UTi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F121439d2-7047-4b45-a223-3a4db4879917_1800x1800.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8UTi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F121439d2-7047-4b45-a223-3a4db4879917_1800x1800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!8UTi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F121439d2-7047-4b45-a223-3a4db4879917_1800x1800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!8UTi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F121439d2-7047-4b45-a223-3a4db4879917_1800x1800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!8UTi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F121439d2-7047-4b45-a223-3a4db4879917_1800x1800.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!8UTi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F121439d2-7047-4b45-a223-3a4db4879917_1800x1800.jpeg" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/121439d2-7047-4b45-a223-3a4db4879917_1800x1800.jpeg&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;:902965,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223449757?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F121439d2-7047-4b45-a223-3a4db4879917_1800x1800.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8UTi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F121439d2-7047-4b45-a223-3a4db4879917_1800x1800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!8UTi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F121439d2-7047-4b45-a223-3a4db4879917_1800x1800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!8UTi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F121439d2-7047-4b45-a223-3a4db4879917_1800x1800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!8UTi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F121439d2-7047-4b45-a223-3a4db4879917_1800x1800.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>Work and movement</h2><p>Much of a town&#8217;s rhythm comes from the people who keep it moving. Those who work, travel, carry, build, sell and contribute in ways that often go unnoticed. Their everyday routines are as much a part of Kodagu&#8217;s identity as its landscapes.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3h7e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F736b7a5b-2958-470a-b8c7-c3b0fa7f014e_1800x1800.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3h7e!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F736b7a5b-2958-470a-b8c7-c3b0fa7f014e_1800x1800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!3h7e!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F736b7a5b-2958-470a-b8c7-c3b0fa7f014e_1800x1800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!3h7e!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F736b7a5b-2958-470a-b8c7-c3b0fa7f014e_1800x1800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!3h7e!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F736b7a5b-2958-470a-b8c7-c3b0fa7f014e_1800x1800.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!3h7e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F736b7a5b-2958-470a-b8c7-c3b0fa7f014e_1800x1800.jpeg" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/736b7a5b-2958-470a-b8c7-c3b0fa7f014e_1800x1800.jpeg&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;:892813,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223449757?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F736b7a5b-2958-470a-b8c7-c3b0fa7f014e_1800x1800.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3h7e!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F736b7a5b-2958-470a-b8c7-c3b0fa7f014e_1800x1800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!3h7e!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F736b7a5b-2958-470a-b8c7-c3b0fa7f014e_1800x1800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!3h7e!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F736b7a5b-2958-470a-b8c7-c3b0fa7f014e_1800x1800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!3h7e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F736b7a5b-2958-470a-b8c7-c3b0fa7f014e_1800x1800.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>Market life</h2><p>Markets have always fascinated me. They are lively meeting places where people, produce, conversations and livelihoods come together. There is an unmistakable rhythm here &#8212; a little chaotic, wonderfully colourful and full of life. Spend enough time in a market and you begin to see much more than a place of trade.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ul-H!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ul-H!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ul-H!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ul-H!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ul-H!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ul-H!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg&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;:1531645,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223449757?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ul-H!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ul-H!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ul-H!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ul-H!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb551025-5a2c-4577-994a-8a2049104f55_1800x1800.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>Shared spaces</h2><p>What I find equally interesting about Kodagu is its diversity. Different communities, religious traditions, languages and ways of life exist alongside one another. This diversity is not always something that announces itself. Often, it is simply part of the everyday fabric of the place.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WorN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f47ab3e-fdd3-4e21-a587-ee1a38840d69_1800x897.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WorN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f47ab3e-fdd3-4e21-a587-ee1a38840d69_1800x897.jpeg 424w, https://substackcdn.com/image/fetch/$s_!WorN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f47ab3e-fdd3-4e21-a587-ee1a38840d69_1800x897.jpeg 848w, https://substackcdn.com/image/fetch/$s_!WorN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f47ab3e-fdd3-4e21-a587-ee1a38840d69_1800x897.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!WorN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f47ab3e-fdd3-4e21-a587-ee1a38840d69_1800x897.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!WorN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f47ab3e-fdd3-4e21-a587-ee1a38840d69_1800x897.jpeg" width="724" height="360.79333333333335" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4f47ab3e-fdd3-4e21-a587-ee1a38840d69_1800x897.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:897,&quot;width&quot;:1800,&quot;resizeWidth&quot;:724,&quot;bytes&quot;:249960,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223449757?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe78feef3-e340-4a02-a2eb-6a5302bee72e_1800x1800.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WorN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f47ab3e-fdd3-4e21-a587-ee1a38840d69_1800x897.jpeg 424w, https://substackcdn.com/image/fetch/$s_!WorN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f47ab3e-fdd3-4e21-a587-ee1a38840d69_1800x897.jpeg 848w, https://substackcdn.com/image/fetch/$s_!WorN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f47ab3e-fdd3-4e21-a587-ee1a38840d69_1800x897.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!WorN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f47ab3e-fdd3-4e21-a587-ee1a38840d69_1800x897.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>You see it in children going to school, families outside their homes, shopkeepers serving their customers and people sharing the same streets and neighbourhoods. Their lives may be very different, but the town brings them together in ways that are both ordinary and meaningful.</p><p>I don&#8217;t think a handful of photographs can explain this coexistence, nor should they attempt to. But they can offer glimpses of it. They can encourage us to look at the people around us with a little more curiosity and perhaps a little more understanding.</p><p>There is also something to be said about the pace of life here. Not everything seems to revolve around urgency. The marketplace has its own rhythm, conversations take their time, and everyday interactions often carry a warmth that is easy to miss when we are in a hurry.</p><p>Perhaps this is what drew me to these photographs in the first place. The small gestures, expressions and interactions that make up the texture of everyday life.</p><div class="pullquote"><h3><em><strong>The title &#3221;&#3274;&#3233;&#3223;&#3263;&#3240; &#3240;&#3223;&#3265; | Kodagu Smiles came from this feeling.</strong></em><strong> </strong></h3></div><blockquote><p><em><strong>Not every photograph contains a smile, and that is intentional. A smile can be an expression, but it can also be a feeling associated with a place &#8212; its people, their openness, their resilience and the simple humanity of everyday encounters.</strong></em></p></blockquote><p>This collection is my attempt to explore that feeling through photography.</p><p>I am happy to have these photographs become part of <strong>Kalaa Utsava Kodagu 2026</strong>, the tenth edition of the art festival, bringing together different forms of artistic expression in Virajpet. The exhibition offers an opportunity to share these observations with people beyond the camera and perhaps invite them to see Kodagu through a slightly different lens.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!diCA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66ab1af8-3ac4-46ab-ac1b-e07211ad4d00_2480x3312.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!diCA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66ab1af8-3ac4-46ab-ac1b-e07211ad4d00_2480x3312.jpeg 424w, https://substackcdn.com/image/fetch/$s_!diCA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66ab1af8-3ac4-46ab-ac1b-e07211ad4d00_2480x3312.jpeg 848w, https://substackcdn.com/image/fetch/$s_!diCA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66ab1af8-3ac4-46ab-ac1b-e07211ad4d00_2480x3312.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!diCA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66ab1af8-3ac4-46ab-ac1b-e07211ad4d00_2480x3312.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!diCA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66ab1af8-3ac4-46ab-ac1b-e07211ad4d00_2480x3312.jpeg" width="2480" height="3312" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/66ab1af8-3ac4-46ab-ac1b-e07211ad4d00_2480x3312.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:3312,&quot;width&quot;:2480,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:868333,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223449757?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71cfde8-9b29-48c2-aaf1-7011911d50a0_2480x3508.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!diCA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66ab1af8-3ac4-46ab-ac1b-e07211ad4d00_2480x3312.jpeg 424w, https://substackcdn.com/image/fetch/$s_!diCA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66ab1af8-3ac4-46ab-ac1b-e07211ad4d00_2480x3312.jpeg 848w, https://substackcdn.com/image/fetch/$s_!diCA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66ab1af8-3ac4-46ab-ac1b-e07211ad4d00_2480x3312.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!diCA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66ab1af8-3ac4-46ab-ac1b-e07211ad4d00_2480x3312.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>If you happen to visit, I hope you will spend a little time with these photographs. Look beyond the faces and see the relationships between people and their surroundings, the details of everyday life and the many stories that coexist within a small town.</p><blockquote><p><strong>Because sometimes, to understand a place, we need to look beyond its landscapes.</strong></p><p><strong>We need to meet its people.</strong></p></blockquote><div class="pullquote"><h1><strong>&#3221;&#3274;&#3233;&#3223;&#3263;&#3240; &#3240;&#3223;&#3265; | </strong><em>Kodagu Smiles.</em></h1></div><h4><strong>Kalaa Utsava Kodagu 2026</strong></h4><h5>10th Edition | 11 November &#8211; 31 December 2026</h5><h1>Location 01: Chombuka Art &amp; Farm, Virajpet, Kodagu, Karnataka.</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!c2ZH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c872b3c-085b-44f4-8240-005b0d486601_960x1280.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!c2ZH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c872b3c-085b-44f4-8240-005b0d486601_960x1280.jpeg 424w, https://substackcdn.com/image/fetch/$s_!c2ZH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c872b3c-085b-44f4-8240-005b0d486601_960x1280.jpeg 848w, https://substackcdn.com/image/fetch/$s_!c2ZH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c872b3c-085b-44f4-8240-005b0d486601_960x1280.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!c2ZH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c872b3c-085b-44f4-8240-005b0d486601_960x1280.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!c2ZH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c872b3c-085b-44f4-8240-005b0d486601_960x1280.jpeg" width="960" height="1280" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7c872b3c-085b-44f4-8240-005b0d486601_960x1280.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1280,&quot;width&quot;:960,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:433739,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223449757?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c872b3c-085b-44f4-8240-005b0d486601_960x1280.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!c2ZH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c872b3c-085b-44f4-8240-005b0d486601_960x1280.jpeg 424w, https://substackcdn.com/image/fetch/$s_!c2ZH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c872b3c-085b-44f4-8240-005b0d486601_960x1280.jpeg 848w, https://substackcdn.com/image/fetch/$s_!c2ZH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c872b3c-085b-44f4-8240-005b0d486601_960x1280.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!c2ZH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c872b3c-085b-44f4-8240-005b0d486601_960x1280.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ahsu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 424w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 848w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1272w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png" width="1456" height="211" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:211,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ahsu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 424w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 848w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1272w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[Art of Seeing]]></title><description><![CDATA[From mastering the technique to discovering the story]]></description><link>https://blog.phagyul.ai/p/art-of-seeing</link><guid isPermaLink="false">https://blog.phagyul.ai/p/art-of-seeing</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Tue, 03 Nov 2026 04:50:32 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!fjcK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p><em>Photography is where technology meets art. </em></p><p><em>To break the rules, we must first learn to master them.</em></p></blockquote><p>Over the past few months, I have been writing about my experience of photographing Hokkaido, Japan. Each story began with a particular visual curiosity &#8212; colour, monochrome, the behaviour of light, or the unexpected ways in which a camera can transform a landscape.</p><p>With <a href="https://blog.phagyul.ai/p/vibrant-hokkaido">Vibrant Hokkaido</a>, I explored how custom camera profiles could translate an imagined visual language into photographs. What began as an attempt to recreate the atmosphere I associated with Japanese films and anime gradually led me towards a deeper understanding of luminance and the subtle tonal relationships hidden within snow.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;0ca0302a-3073-4416-b2ef-0e9f959e97b4&quot;,&quot;caption&quot;:&quot;Several months before travelling to Hokkaido, I found myself doing something I had not originally planned.&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Vibrant Hokkaido&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-05-31T02:39:22.000Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!yFHV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/vibrant-hokkaido&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:199934487,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:1,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p><a href="https://blog.phagyul.ai/p/traditional-japan-monochrome">Traditional Japan (Monochrome)</a> took me in another direction. By removing colour, I discovered how form, texture, atmosphere and negative space could communicate a sense of timelessness.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;4141d6ab-2604-4a56-9d14-894369410eed&quot;,&quot;caption&quot;:&quot;When I first arrived in Hokkaido, I was captivated by colour.&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Traditional Japan (Monochrome)&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-06-01T05:22:49.000Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!GRC8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_1536x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/traditional-japan-monochrome&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:200075615,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>Then came <a href="https://blog.phagyul.ai/p/silence-in-three-movements">Silence in Three Movements</a>, where I began noticing something I had not anticipated when I travelled to Hokkaido: landscapes that appeared to separate into distinct visual planes, almost as if multiple images had been arranged within a single frame.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;e0dd32e3-3348-491d-baf3-3aa0534c3f64&quot;,&quot;caption&quot;:&quot;I headed to Hokkaido, Japan, in February 2026 with two visual themes already shaping the journey in my mind: Vibrant Hokkaido and Traditional Japan. (post upcomingon Traditional Japan)&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Silence in Three Movements&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-05-29T05:29:14.000Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!vDQY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F950ff4b1-5138-4652-91d6-e864e88bdf34_1535x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/silence-in-three-movements&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:199695112,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>These were different experiments, but they shared a common starting point.</p><p>I was learning to understand not just what my camera could capture, but how its technology could influence the way I saw the world.</p><p>Somewhere along the way, however, another question began to emerge.</p><div class="pullquote"><p><strong>What happens when I stop thinking primarily about the technique and start thinking about the story telling?</strong></p></div><p>That question is where <em>Art of Seeing</em> begins.</p><h2>First, learn the rules</h2><p>I have always been fascinated by the intersection of <strong>technology and art</strong>.</p><p>My background in technology has naturally influenced the way I approach photography. I enjoy understanding how things work, experimenting with settings, studying the behaviour of light and finding ways to make equipment perform according to a particular intention.</p><p>A camera is an extraordinary technological instrument. Aperture, shutter speed, focal length, focus, exposure, picture profiles and post-processing all influence the final outcome.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_xEd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32877d53-d9b7-4718-bba2-8aec2172e2f2_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_xEd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32877d53-d9b7-4718-bba2-8aec2172e2f2_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!_xEd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32877d53-d9b7-4718-bba2-8aec2172e2f2_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!_xEd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32877d53-d9b7-4718-bba2-8aec2172e2f2_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!_xEd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32877d53-d9b7-4718-bba2-8aec2172e2f2_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!_xEd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32877d53-d9b7-4718-bba2-8aec2172e2f2_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/32877d53-d9b7-4718-bba2-8aec2172e2f2_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;:2032320,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223272881?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32877d53-d9b7-4718-bba2-8aec2172e2f2_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_!_xEd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32877d53-d9b7-4718-bba2-8aec2172e2f2_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!_xEd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32877d53-d9b7-4718-bba2-8aec2172e2f2_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!_xEd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32877d53-d9b7-4718-bba2-8aec2172e2f2_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!_xEd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32877d53-d9b7-4718-bba2-8aec2172e2f2_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Understanding these fundamentals matters.</p><p><em>A shallow depth of field can isolate a subject. A long focal length can compress a landscape. A slower shutter speed can transform movement into a gesture. Exposure and tonal control can determine whether snow appears as a featureless white surface or a landscape filled with subtle patterns and depth.</em></p><blockquote><p><strong>These are not merely technical decisions. Each one changes how a photograph communicates.</strong></p></blockquote><p>For me, the first stage of learning photography was about understanding these possibilities and developing the ability to use them deliberately.</p><p>But mastering a technique is not the same as making a meaningful photograph.</p><p>Knowing how to create a <em>blurred image</em> does not explain why the blur should exist. Understanding exposure does not tell us what deserves to remain visible. Learning composition does not automatically reveal what a frame should make someone feel.</p><p>Technique gives us the vocabulary.</p><p>What we choose to say with it is another matter.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ahsu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 424w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 848w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1272w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png" width="1456" height="211" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:211,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ahsu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 424w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 848w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1272w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>I am beginning to realise that the more comfortable I become with the technical side of photography, the more freedom I have to move beyond it.</p><p>Perhaps that is what it means to learn the rules before breaking them.</p><p>Not to abandon the rules, but to reach a point where they no longer dictate every decision.</p><div><hr></div><h2>When the subject is no longer enough</h2><p>Wildlife photography often encourages us to pursue a familiar objective: find the subject, achieve focus, capture the behaviour and make the animal stand out against its surroundings.</p><p>There is nothing wrong with this. A technically accomplished portrait of a wild animal can be beautiful, powerful and important.</p><p>But I have increasingly found myself drawn towards photographs in which the animal is not necessarily the only thing that matters.</p><p>Sometimes, it is the relationship between the subject and the landscape that interests me. Sometimes, it is the way light separates one form from another. At other times, it is an imperfect, fleeting gesture that could never be reproduced in a conventional portrait.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NY66!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd402e542-2396-43ad-911e-a04bd312b730_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NY66!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd402e542-2396-43ad-911e-a04bd312b730_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!NY66!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd402e542-2396-43ad-911e-a04bd312b730_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!NY66!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd402e542-2396-43ad-911e-a04bd312b730_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!NY66!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd402e542-2396-43ad-911e-a04bd312b730_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!NY66!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd402e542-2396-43ad-911e-a04bd312b730_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d402e542-2396-43ad-911e-a04bd312b730_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;:2045286,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223272881?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd402e542-2396-43ad-911e-a04bd312b730_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_!NY66!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd402e542-2396-43ad-911e-a04bd312b730_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!NY66!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd402e542-2396-43ad-911e-a04bd312b730_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!NY66!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd402e542-2396-43ad-911e-a04bd312b730_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!NY66!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd402e542-2396-43ad-911e-a04bd312b730_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The subject remains important, but the photograph begins to mean something beyond its identity.</p><p><em><sub>A bird can become a line within a composition.</sub></em></p><p><em><sub>A landscape can become a sequence of tones.</sub></em></p><p><em><sub>A moment of movement can become an abstract gesture.</sub></em></p><p>And an apparently incomplete image can invite the viewer to participate in completing it.</p><p>These possibilities do not necessarily require elaborate manipulation or complicated equipment. Sometimes, they emerge simply by changing the way I look through the viewfinder.</p><p>The question gradually shifts from <em><strong>What am I photographing?</strong></em><strong> &#8594; </strong><em><strong>What is it about this moment that I want to communicate?</strong></em></p><p>That shift has been particularly noticeable in the photographs I began making during my winter journey through Hokkaido.</p><div><hr></div><h2>Searching: discovering the image within the landscape</h2><p>One of the most unexpected discoveries during the trip was how strongly a winter landscape could resemble an arrangement of separate visual layers.</p><p>Snowfields, belts of vegetation and distant woodland seemed to occupy distinct planes. Differences in tone, texture and atmosphere created boundaries that were not immediately obvious when looking at the physical landscape.</p><p>Through the camera, however, these relationships became remarkably pronounced.</p><p>I found myself looking at the scene differently. Rather than treating the landscape as a continuous environment, I began to see it as a composition of shapes, tonal regions and intervals.</p><p>The wildlife subject became part of this arrangement.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!y7uJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965cfbdb-c565-42c2-8791-acc88719ccdd_1920x1281.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y7uJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965cfbdb-c565-42c2-8791-acc88719ccdd_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!y7uJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965cfbdb-c565-42c2-8791-acc88719ccdd_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!y7uJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965cfbdb-c565-42c2-8791-acc88719ccdd_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!y7uJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965cfbdb-c565-42c2-8791-acc88719ccdd_1920x1281.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!y7uJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965cfbdb-c565-42c2-8791-acc88719ccdd_1920x1281.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/965cfbdb-c565-42c2-8791-acc88719ccdd_1920x1281.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1100472,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223272881?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965cfbdb-c565-42c2-8791-acc88719ccdd_1920x1281.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!y7uJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965cfbdb-c565-42c2-8791-acc88719ccdd_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!y7uJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965cfbdb-c565-42c2-8791-acc88719ccdd_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!y7uJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965cfbdb-c565-42c2-8791-acc88719ccdd_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!y7uJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965cfbdb-c565-42c2-8791-acc88719ccdd_1920x1281.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In <em><strong>Searching</strong></em>, a solitary crane occupies a distant ridge, surrounded by layers of winter woodland and snow. The bird is small within the frame, and that is precisely what makes the photograph interesting to me.</p><p>The landscape does not simply provide context for the animal. It determines how the animal is discovered.</p><p>The tonal transitions create the impression of three distinct visual planes, almost like separate images brought together within a single composition. The viewer&#8217;s attention moves across these layers before settling on the crane.</p><p>I did not set out to create an image about perception. I was initially interested in the landscape itself, however, the crane become merged made it further interesting.</p><p>Reviewing the photograph made me realise that the act of finding the subject had become part of the experience I wanted to convey.</p><p>The image asks for a little patience.</p><p>It rewards looking rather than merely glancing.</p><p>And that, for me, is an important distinction between documenting a subject and telling a story through it.</p><div><hr></div><h2>Reconstruction: allowing the viewer to participate</h2><p>Another photograph emerged from a very different way of looking.</p><p>In <em>Reconstruction</em>, I approached the crane as though I were making an artistic study of its form rather than a conventional wildlife portrait.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!n3Mo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e21e809-7c95-41be-b277-b3b0852e696c_5088x3306.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!n3Mo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e21e809-7c95-41be-b277-b3b0852e696c_5088x3306.jpeg 424w, https://substackcdn.com/image/fetch/$s_!n3Mo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e21e809-7c95-41be-b277-b3b0852e696c_5088x3306.jpeg 848w, https://substackcdn.com/image/fetch/$s_!n3Mo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e21e809-7c95-41be-b277-b3b0852e696c_5088x3306.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!n3Mo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e21e809-7c95-41be-b277-b3b0852e696c_5088x3306.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!n3Mo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e21e809-7c95-41be-b277-b3b0852e696c_5088x3306.jpeg" width="5088" height="3306" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5e21e809-7c95-41be-b277-b3b0852e696c_5088x3306.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:3306,&quot;width&quot;:5088,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:353639,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223272881?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d6f40f0-f73c-4018-997d-6ea6b2a89a89_5088x3392.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!n3Mo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e21e809-7c95-41be-b277-b3b0852e696c_5088x3306.jpeg 424w, https://substackcdn.com/image/fetch/$s_!n3Mo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e21e809-7c95-41be-b277-b3b0852e696c_5088x3306.jpeg 848w, https://substackcdn.com/image/fetch/$s_!n3Mo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e21e809-7c95-41be-b277-b3b0852e696c_5088x3306.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!n3Mo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e21e809-7c95-41be-b277-b3b0852e696c_5088x3306.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The head, body and other elements do not resolve into one immediately recognisable, unified figure. Instead, they occupy different areas of the frame, with generous white space separating them.</p><p>The image invites the viewer to assemble these fragments mentally.</p><p>I am particularly interested in how our minds respond to incomplete information. We instinctively search for patterns, establish relationships and attempt to make sense of what we see.</p><p>A conventional portrait presents the subject as a complete form.</p><p>Here, I wanted to explore what might happen if I gave different parts of that form their own visual importance, almost as if I were sketching a portrait through separate studies rather than drawing it in a single continuous gesture.</p><p>The result sits somewhere between wildlife photography and abstraction.</p><p>The crane is still recognisable, but recognition is no longer the only objective. The spaces between the forms become as important as the forms themselves.</p><p>This was not an attempt to correct reality or improve the subject through technology.</p><p>It was an attempt to reinterpret what I had seen.</p><p>And that distinction matters to me. Photography need not always be a literal representation of the world. It can also be an expression of how an individual experiences and understands it.</p><div><hr></div><h2>Between presence and absence</h2><p>Some photographs become interesting because of what they conceal.</p><p>In <em>Between Presence and Absence</em>, two cranes occupy the same snowy environment, but their forms are rendered differently. One is relatively distinct; the other dissolves into a soft, indistinct presence.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rE6E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6891c7f0-1466-4423-a708-861170bf2aa0_2561x3840.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rE6E!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6891c7f0-1466-4423-a708-861170bf2aa0_2561x3840.jpeg 424w, https://substackcdn.com/image/fetch/$s_!rE6E!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6891c7f0-1466-4423-a708-861170bf2aa0_2561x3840.jpeg 848w, https://substackcdn.com/image/fetch/$s_!rE6E!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6891c7f0-1466-4423-a708-861170bf2aa0_2561x3840.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!rE6E!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6891c7f0-1466-4423-a708-861170bf2aa0_2561x3840.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!rE6E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6891c7f0-1466-4423-a708-861170bf2aa0_2561x3840.jpeg" width="1456" height="2183" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6891c7f0-1466-4423-a708-861170bf2aa0_2561x3840.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:2183,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1575076,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223272881?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6891c7f0-1466-4423-a708-861170bf2aa0_2561x3840.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rE6E!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6891c7f0-1466-4423-a708-861170bf2aa0_2561x3840.jpeg 424w, https://substackcdn.com/image/fetch/$s_!rE6E!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6891c7f0-1466-4423-a708-861170bf2aa0_2561x3840.jpeg 848w, https://substackcdn.com/image/fetch/$s_!rE6E!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6891c7f0-1466-4423-a708-861170bf2aa0_2561x3840.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!rE6E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6891c7f0-1466-4423-a708-861170bf2aa0_2561x3840.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The contrast creates a tension between recognition and uncertainty.</p><p><strong>A symmetry, yet not quite!</strong></p><p>We know that another bird is there, yet we cannot experience both subjects in the same way. One commands attention through its clarity. The other becomes an impression, something we perceive without fully resolving.</p><p>I find this relationship more interesting than a photograph in which both birds are rendered with equal clarity.</p><p>The difference creates a visual dialogue between presence and absence, between what is immediately available to the eye and what remains just beyond its grasp.</p><p>It also reminds me that the photographic frame is never a neutral window onto reality.</p><p>Focus, depth of field, perspective and timing all influence what becomes prominent and what recedes. Even when I am photographing an entirely natural moment, the resulting image reflects a series of choices.</p><p>The photograph is a record of what was there, but it is also a particular way of experiencing it.</p><div><hr></div><h2>Emergence: when the environment becomes the subject</h2><p>In <em>Emergence</em>, deer appear within a landscape of frost-covered branches and drifting fog.</p><p>The scene is not built around the immediate recognition of the animals. Instead, the surrounding woodland initially dominates the experience. Branches, tonal variations and mist create layers through which the deer gradually become visible.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fjcK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fjcK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fjcK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fjcK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fjcK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!fjcK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg&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;:3394944,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223272881?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fjcK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fjcK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fjcK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fjcK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0553a070-679c-4d11-aa9b-b0f903fa6fae_3000x3000.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The longer I look at the photograph, the more the relationship between subject and environment interests me.</p><p>The deer are not isolated from their surroundings. Their presence is inseparable from the atmosphere that partially conceals them.</p><p>This is another reason I have become increasingly interested in negative space and restrained compositions.</p><p>What we leave unresolved can be as important as what we reveal.</p><p>A photograph does not always need to announce its subject immediately. Sometimes, allowing the viewer to discover it creates a more engaging experience.</p><p>It introduces time into the act of looking.</p><p>The viewer has to pause, search and establish relationships within the frame.</p><p>And perhaps, in doing so, begins to experience the landscape a little differently.</p><div><hr></div><h2>Winter Calligraphy: when technique becomes expression</h2><p>Of all the directions I explored, intentional motion blur has perhaps offered the clearest example of technique becoming a creative language.</p><p>In <em>Winter Calligraphy</em>, the movement of a bird is transformed into a flowing gesture against a pale winter background.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sSk8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d0f69a-ecab-4e1a-8410-f365e9f096dc_3000x2316.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sSk8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d0f69a-ecab-4e1a-8410-f365e9f096dc_3000x2316.jpeg 424w, https://substackcdn.com/image/fetch/$s_!sSk8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d0f69a-ecab-4e1a-8410-f365e9f096dc_3000x2316.jpeg 848w, https://substackcdn.com/image/fetch/$s_!sSk8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d0f69a-ecab-4e1a-8410-f365e9f096dc_3000x2316.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!sSk8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d0f69a-ecab-4e1a-8410-f365e9f096dc_3000x2316.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!sSk8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d0f69a-ecab-4e1a-8410-f365e9f096dc_3000x2316.jpeg" width="1456" height="1124" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/68d0f69a-ecab-4e1a-8410-f365e9f096dc_3000x2316.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1124,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:422130,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223272881?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d0f69a-ecab-4e1a-8410-f365e9f096dc_3000x2316.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!sSk8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d0f69a-ecab-4e1a-8410-f365e9f096dc_3000x2316.jpeg 424w, https://substackcdn.com/image/fetch/$s_!sSk8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d0f69a-ecab-4e1a-8410-f365e9f096dc_3000x2316.jpeg 848w, https://substackcdn.com/image/fetch/$s_!sSk8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d0f69a-ecab-4e1a-8410-f365e9f096dc_3000x2316.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!sSk8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d0f69a-ecab-4e1a-8410-f365e9f096dc_3000x2316.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The resulting form is not intended to describe every feather or preserve the conventional sharpness expected of a wildlife photograph. Instead, the movement itself becomes the subject.</p><p>The bird leaves behind an impression, almost like a brushstroke across an otherwise quiet canvas.</p><p>This is where I find the relationship between technology and art particularly fascinating.</p><p>Shutter speed is a technical parameter. Motion blur is a physical consequence of how movement is recorded during an exposure.</p><p>But the expressive possibilities of that blur depend on intention.</p><p>A blurred photograph caused by an accident and a blurred photograph created to convey movement may share a technical characteristic, yet they do not necessarily share the same artistic purpose.</p><p>The difference lies in the decision behind the image.</p><blockquote><p><em><strong>I am not suggesting that every technical imperfection should be reclassified as art. Nor do I believe that abstraction automatically makes a photograph more meaningful.</strong></em></p></blockquote><p>What interests me is the freedom to choose a different visual outcome because it serves the story I want to tell.</p><p>Once I understand what a technique does, I can begin asking what else it might express.</p><p>That is when experimentation becomes more than an exercise.</p><p>It becomes a way of seeing.</p><div><hr></div><h2>Ghost of the North: the landscape completes the story</h2><p>The red fox crossing the blue-toned snow offered another lesson.</p><p>Initially, the contrast between the warm colour of the fox and the cold blue landscape seemed to provide the photograph&#8217;s defining characteristic.</p><p>But as I spent more time studying the image, my attention shifted towards the snow.</p><p>The wind-shaped patterns across its surface created pathways through the frame. Subtle tonal differences established depth and direction. The lighter and darker areas guided the eye towards the fox.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ztao!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33afa243-e8e7-400d-81fd-f63c86043adf_1920x1281.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ztao!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33afa243-e8e7-400d-81fd-f63c86043adf_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Ztao!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33afa243-e8e7-400d-81fd-f63c86043adf_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Ztao!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33afa243-e8e7-400d-81fd-f63c86043adf_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Ztao!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33afa243-e8e7-400d-81fd-f63c86043adf_1920x1281.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ztao!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33afa243-e8e7-400d-81fd-f63c86043adf_1920x1281.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/33afa243-e8e7-400d-81fd-f63c86043adf_1920x1281.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1198942,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223272881?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33afa243-e8e7-400d-81fd-f63c86043adf_1920x1281.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ztao!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33afa243-e8e7-400d-81fd-f63c86043adf_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Ztao!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33afa243-e8e7-400d-81fd-f63c86043adf_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Ztao!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33afa243-e8e7-400d-81fd-f63c86043adf_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Ztao!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33afa243-e8e7-400d-81fd-f63c86043adf_1920x1281.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The snow was doing more than providing a background.</p><p>It was creating the composition.</p><p>I had explored this idea earlier in <a href="https://blog.phagyul.ai/p/vibrant-hokkaido">Vibrant Hokkaido</a>, where I wrote about what I came to think of as <em><strong>Snow Luminance Control</strong></em><strong>:</strong> preserving the tonal relationships that give winter landscapes their depth and character.</p><p>With <em>Ghost of the North</em>, that technical exploration became part of a broader artistic consideration.</p><p>The fox did not need to dominate the frame.</p><p>Its presence was enough to complete a visual arrangement that the landscape had already established.</p><p>This is an idea I want to carry forward into my photography: the most important element in a photograph is not necessarily the largest, sharpest or most visually striking one.</p><p>Sometimes, it is the element that brings everything else together.</p><div><hr></div><h2>The Watchers: turning the gaze around</h2><p>Photography is often described as an act of observation. We look at the world, select a moment and decide how to frame it.</p><p>But what happens when the act of looking becomes part of the photograph itself?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!99uJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b96ea3a-ceaf-4e29-b00a-d9fd3b88c812_1920x1667.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!99uJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b96ea3a-ceaf-4e29-b00a-d9fd3b88c812_1920x1667.jpeg 424w, https://substackcdn.com/image/fetch/$s_!99uJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b96ea3a-ceaf-4e29-b00a-d9fd3b88c812_1920x1667.jpeg 848w, https://substackcdn.com/image/fetch/$s_!99uJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b96ea3a-ceaf-4e29-b00a-d9fd3b88c812_1920x1667.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!99uJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b96ea3a-ceaf-4e29-b00a-d9fd3b88c812_1920x1667.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!99uJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b96ea3a-ceaf-4e29-b00a-d9fd3b88c812_1920x1667.jpeg" width="1456" height="1264" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3b96ea3a-ceaf-4e29-b00a-d9fd3b88c812_1920x1667.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1264,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1082046,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223272881?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b96ea3a-ceaf-4e29-b00a-d9fd3b88c812_1920x1667.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!99uJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b96ea3a-ceaf-4e29-b00a-d9fd3b88c812_1920x1667.jpeg 424w, https://substackcdn.com/image/fetch/$s_!99uJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b96ea3a-ceaf-4e29-b00a-d9fd3b88c812_1920x1667.jpeg 848w, https://substackcdn.com/image/fetch/$s_!99uJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b96ea3a-ceaf-4e29-b00a-d9fd3b88c812_1920x1667.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!99uJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b96ea3a-ceaf-4e29-b00a-d9fd3b88c812_1920x1667.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In <em><strong>The Watchers</strong></em><strong>,</strong> the people observing wildlife become part of the visual narrative. Their attention, posture and relationship with the unseen subject tell a story that extends beyond the animal they have come to see.</p><p>The photograph becomes less about a single encounter with wildlife and more about the human desire to witness it.</p><p>We travel to remote places. We wait for encounters. We raise our cameras and try to preserve something of an experience that may last only a few seconds.</p><p>Yet the photograph can reveal more than the intended subject. It can reveal our own presence within the experience.</p><p>This has made me increasingly conscious of the relationship between the photographer, the subject and the eventual viewer.</p><p>Every photograph begins with someone looking.</p><p>Every frame includes certain things and excludes others.</p><p>And every viewer brings their own memories, assumptions and imagination to the finished image.</p><p>The photograph, in that sense, is never entirely complete when I press the shutter.</p><p>Its interpretation continues long after the moment has passed.</p><div><hr></div><h2>From photographs to stories</h2><p>Looking back at these images, I can see that they do not all belong to the same visual style.</p><p>Some are minimalist. Some rely on atmospheric layers. Others explore fragmentation, movement or the relationship between humans and wildlife.</p><p>What connects them is not a common technique.</p><p>It is a common question.</p><div class="pullquote"><p><strong>Can I use photography to communicate not just what I saw, but how I experienced it?</strong></p></div><p>That question has begun to change how I approach the entire process.</p><p>Earlier, I might have started with a technical objective: create a particular colour palette, experiment with monochrome, preserve the tonal detail in snow or achieve a specific depth of field.</p><p>I still value those objectives. They remain essential tools.</p><p>But increasingly, I want to begin with a feeling, a question or an idea.</p><p>I want to understand why a scene holds my attention before deciding how to photograph it. I want to explore whether a conventional portrait is the right response, or whether the subject might be better expressed through abstraction, negative space, movement or its relationship with the environment.</p><p>And I want to spend more time considering how individual photographs might relate to one another.</p><p>A single photograph can be compelling. A carefully considered sequence can create something different: a narrative that develops as the viewer moves from one image to the next.</p><p>This is where titles, sequencing and the relationships between photographs become important.</p><p>A title can direct attention without prescribing an interpretation. A sequence can introduce an idea, complicate it and eventually resolve it. A collection can become more than the sum of its individual images.</p><p>These are possibilities I am only beginning to explore seriously.</p><p>But they represent an exciting next step in my photographic journey.</p><div><hr></div><h2>Learning to break the rules</h2><p>I often return to a simple thought:</p><div class="pullquote"><p><em><strong>Photography is where technology meets art.</strong></em></p></div><p>Technology gives us the means to control the image. Art gives us reasons to make those choices.</p><p>Neither exists in isolation.</p><p>Without understanding the camera(tool), it can be difficult to translate an intention into a photograph. Without an artistic intention, technical mastery can become an end in itself.</p><p>For me, the challenge is to marrying two together.</p><p>I want to continue learning the technical foundations of photography, experimenting with equipment and understanding the science behind the images I make. But I also want to become more comfortable questioning familiar expectations.</p><h4><em><strong><sub>Why must a wildlife portrait always be sharp?</sub></strong></em></h4><h4><em><strong><sub>Why must the subject dominate the frame?</sub></strong></em></h4><h4><em><strong><sub>Why should a landscape always convey depth in the conventional sense?</sub></strong></em></h4><h4><em><strong><sub>Why must a photograph explain everything it contains?</sub></strong></em></h4><p></p><p>There are no universal answers to these questions, and I am not interested in breaking rules simply for the sake of doing so.</p><p>I want to understand the rules well enough to recognise when following them serves the image &#8212; and when departing from them might reveal something I would otherwise miss.</p><p>That, to me, is the difference between applying a technique and developing a personal visual language.</p><div><hr></div><h2>An ongoing journey</h2><p><em>Art of Seeing</em> is not a finished body of work, nor is it an attempt to define a single style of photography.</p><p>It is an evolving exploration of how I look at the world and how that experience might be translated into images.</p><p>Hokkaido provided the setting for many of these discoveries, but the questions extend well beyond Japan and winter wildlife. I want to explore them in other landscapes, with other subjects and under entirely different conditions.</p><p>I also want to continue bringing these photographs together as a coherent body of work &#8212; through essays, carefully sequenced series and, eventually, the possibility of an exhibition.</p><p>More importantly, I want to resist the temptation to settle too quickly into a familiar way of making images.</p><p>There will always be more techniques to learn, more equipment to understand and more ways to process a photograph. But I suspect the more interesting journey lies in discovering what to do with that knowledge.</p><p>Perhaps the next stage of photography is not about learning to control every aspect of the image.</p><p>Perhaps it is about knowing when to let the image become something unexpected.</p><p>I began this journey wanting to make better photographs.</p><p>I now find myself asking a different question:</p><p><strong>What kind of stories can I tell through the way I see?</strong></p><p>That is the question I hope to keep exploring.</p><p>And that is what <em>Art of Seeing</em> means to me.</p><div><hr></div><p>Some more attempts which are yet to be fine tuned either by revisualing or reprocessing</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7nQQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c03343c-929a-410a-81f1-87333b28a696_1467x2200.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7nQQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c03343c-929a-410a-81f1-87333b28a696_1467x2200.jpeg 424w, https://substackcdn.com/image/fetch/$s_!7nQQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c03343c-929a-410a-81f1-87333b28a696_1467x2200.jpeg 848w, https://substackcdn.com/image/fetch/$s_!7nQQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c03343c-929a-410a-81f1-87333b28a696_1467x2200.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!7nQQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c03343c-929a-410a-81f1-87333b28a696_1467x2200.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!7nQQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c03343c-929a-410a-81f1-87333b28a696_1467x2200.jpeg" width="1456" height="2184" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6c03343c-929a-410a-81f1-87333b28a696_1467x2200.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:2184,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1135195,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223272881?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c03343c-929a-410a-81f1-87333b28a696_1467x2200.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7nQQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c03343c-929a-410a-81f1-87333b28a696_1467x2200.jpeg 424w, https://substackcdn.com/image/fetch/$s_!7nQQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c03343c-929a-410a-81f1-87333b28a696_1467x2200.jpeg 848w, https://substackcdn.com/image/fetch/$s_!7nQQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c03343c-929a-410a-81f1-87333b28a696_1467x2200.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!7nQQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c03343c-929a-410a-81f1-87333b28a696_1467x2200.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Witnesses, making the Snow monkey enjoying celebrity status with people around her with cameras, tripods or just simply amazed to watch her</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4VAd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f942b5c-8965-488f-b0c0-a220c7afd925_1920x1281.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4VAd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f942b5c-8965-488f-b0c0-a220c7afd925_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!4VAd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f942b5c-8965-488f-b0c0-a220c7afd925_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!4VAd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f942b5c-8965-488f-b0c0-a220c7afd925_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!4VAd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f942b5c-8965-488f-b0c0-a220c7afd925_1920x1281.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!4VAd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f942b5c-8965-488f-b0c0-a220c7afd925_1920x1281.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0f942b5c-8965-488f-b0c0-a220c7afd925_1920x1281.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:304100,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223272881?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f942b5c-8965-488f-b0c0-a220c7afd925_1920x1281.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4VAd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f942b5c-8965-488f-b0c0-a220c7afd925_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!4VAd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f942b5c-8965-488f-b0c0-a220c7afd925_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!4VAd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f942b5c-8965-488f-b0c0-a220c7afd925_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!4VAd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f942b5c-8965-488f-b0c0-a220c7afd925_1920x1281.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>A celebrity, indeed!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bY62!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faba1a042-5a17-4927-b26a-d7dd09f0e060_1745x1164.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bY62!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faba1a042-5a17-4927-b26a-d7dd09f0e060_1745x1164.jpeg 424w, https://substackcdn.com/image/fetch/$s_!bY62!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faba1a042-5a17-4927-b26a-d7dd09f0e060_1745x1164.jpeg 848w, https://substackcdn.com/image/fetch/$s_!bY62!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faba1a042-5a17-4927-b26a-d7dd09f0e060_1745x1164.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!bY62!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faba1a042-5a17-4927-b26a-d7dd09f0e060_1745x1164.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!bY62!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faba1a042-5a17-4927-b26a-d7dd09f0e060_1745x1164.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aba1a042-5a17-4927-b26a-d7dd09f0e060_1745x1164.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1118345,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/223272881?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faba1a042-5a17-4927-b26a-d7dd09f0e060_1745x1164.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bY62!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faba1a042-5a17-4927-b26a-d7dd09f0e060_1745x1164.jpeg 424w, https://substackcdn.com/image/fetch/$s_!bY62!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faba1a042-5a17-4927-b26a-d7dd09f0e060_1745x1164.jpeg 848w, https://substackcdn.com/image/fetch/$s_!bY62!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faba1a042-5a17-4927-b26a-d7dd09f0e060_1745x1164.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!bY62!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faba1a042-5a17-4927-b26a-d7dd09f0e060_1745x1164.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In between the line(s)..!</p>]]></content:encoded></item><item><title><![CDATA[Building Grove v0.1: The Agent Harness as a First-Class Citizen (as well as first principle)]]></title><description><![CDATA[From architectural principles to local experimentation with Gemma4:31B, Ollama, and an in-house research agent in the pipeline. More agents to follow.. namely, documentation, coding]]></description><link>https://blog.phagyul.ai/p/building-grove-v01-the-agent-harness</link><guid isPermaLink="false">https://blog.phagyul.ai/p/building-grove-v01-the-agent-harness</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Mon, 02 Nov 2026 05:26:49 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!7TZm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>AN ENGINEERING FIELD NOTE &#183; OCTOBER 2026 &#183; WORK IN PROGRESS</strong></p><div><hr></div><blockquote><p><strong>An engineering work-in-progress note</strong></p><p>This note documents an early development and experimentation phase of Grove v0.1. The implementation and experiments described here were conducted in a contained, local development environment, using Ollama and locally hosted models Gemma 4:31B Dense model on an Apple Mac (M3 Max).</p><p>The architecture, model configurations, runtime parameters, agent workflows and performance observations represent the state of experimentation at the time of writing. They are not production benchmarks, final specifications or commitments to a particular implementation.</p><p>Grove is actively evolving. These configurations, architectural decisions and experimental observations may change as development progresses, further testing is conducted, and additional models and capabilities are introduced. The purpose of publishing this note is to share the engineering process transparently, including the decisions, observations, limitations and unresolved questions.</p><p>Most importantly the journey, evolution and learning</p></blockquote><div><hr></div><h2>1. The Agent Harness as a First Principle</h2><h3>1.1.What Is an Agent Harness?</h3><p>A language model can understand instructions, reason through problems and generate responses. But building a useful AI agent requires more than connecting an application to a model. The agent also needs a way to manage its context, use tools, execute tasks, handle errors and decide what to do next.</p><blockquote><h4>This surrounding system is called the <strong>agent harness</strong>.</h4></blockquote><p><em>In simple terms, think of the model as the engine and the harness as the machinery that allows the engine to do useful work. </em>The model provides the intelligence; the harness provides the structure, controls and environment in which that intelligence operates.</p><p>A useful way to express this relationship is:</p><div class="pullquote"><h3 style="text-align: center;"><strong>Agent = Model + Harness</strong></h3><div><hr></div><h3>1.2. DeepSeek Harness: A Case Study in Composable Design</h3><p>An interesting example of this approach is <strong>DeepSeek Harness (dsh)</strong>. Rather than building an agent around one large, tightly coupled core, it follows an <em>everything-is-a-plugin</em> design. Capabilities are organised into independently mounted components, each responsible for a specific part of the agent&#8217;s operation. We felt this more useful for our harness building internally majorly for two advantages off-the-shelf using DeepSeek: </p><p>Harness as a pluggable model, helps for using multiple open and closed models for different usecases: Research, documentation, coding etc.</p><p>TypeScript SDK support for orchestration</p></div><p>Some of its key architectural ideas include:</p><ul><li><p><strong>Session management:</strong> Maintains an event log of the interaction and derives the conversation history that is presented to the model.</p></li><li><p><strong>System prompt assembly:</strong> Brings together tool descriptions and prompt sections to construct the model&#8217;s working instructions.</p></li><li><p><strong>Tool execution:</strong> Provides a scoped tool registry and a guarded execution pipeline.</p></li><li><p><strong>Agent and execution loop:</strong> Defines how agents are registered and how their execution is driven.</p></li><li><p><strong>Capability seams:</strong> Creates boundaries that allow underlying providers to be replaced without having to redesign the capabilities that depend on them.</p></li></ul><p>The important idea is not simply that the system supports plugins. It is that the harness itself is designed to be modular, replaceable and extensible.</p><h3>1.3. How Grove Interprets This</h3><p>Grove follows the same broader principle: the harness should not be an incidental layer hidden inside an agent implementation. It should be an independent, first-class part of the architecture.</p><p>Our interpretation is that <strong>agents should define what work needs to be done, models should provide the intelligence, and the harness should govern how that work is carried out.</strong></p><p>This separation allows Grove to introduce new agents and experiment with different models without having to rebuild the underlying runtime each time. The harness provides the common execution foundation, while individual agents bring their own capabilities, workflows and domain-specific instructions.</p><p>For Grove, this is both an architectural principle and an ongoing engineering direction. The objective is to build a foundation where models and agents can evolve independently, while the harness provides consistency, control and extensibility across the system.</p><p>A useful working formulation for understanding modern AI agents is:</p><div class="pullquote"><h3 style="text-align: center;"><strong>Agent = Model + Harness</strong></h3></div><p>In this framework, the language model provides the underlying intelligence, while the harness serves as the runtime that converts that intelligence into actual work.</p><p>The harness constitutes the infrastructure that couples an LLM to the world through a loop, tools, orchestration, safety controls, context management, and extension surfaces. Specifically, the harness is critical because it mediates trajectory control, action execution, tool use, observation, and the interpretation of feedback.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7TZm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7TZm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!7TZm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!7TZm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!7TZm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!7TZm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1188017,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/222878658?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.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_!7TZm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!7TZm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!7TZm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!7TZm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5494313-1fba-4ca4-9a39-c9d8702b2554_1774x887.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><blockquote><p><strong>Grove adopts the philosophy by treating its harness as both a first principle&#8212;the governing rules every agent run must obey regardless of the model&#8217;s behaviour&#8212;and a first-class citizen.</strong></p></blockquote><p>This is reflected in the implementation: Grove maintains the harness as its own distinct component within <code>@grove/runtime</code>, where it manages the run lifecycle, deadlines, cancellation, error policies, and provides a recorder with redaction for observability.</p><p>The distinction matters. The model should be replaceable without fundamentally changing the runtime that governs how an agent operates.</p><h2>2. Pluggable and Composable Architecture: The DeepSeek Harness Case Study</h2><p>Research into dynamic composition indicates that modern software, including evolving agent harnesses, increasingly requires composability.</p><p>A primary example is the <a href="https://github.com/deepseek-ai/deepseek-harness">DeepSeek Harness (dsh)</a>, which employs an &#8220;<em><strong>everything-is-a-plugin</strong></em>&#8221; design.</p><h3>DeepSeek Harness architecture</h3><p>The dsh avoids a privileged core; instead, it is extended by mounting plugins that can be unwound upon unloading.</p><p>Its architecture is segmented into packages owning specific context keys:</p><ul><li><p><code>core/session</code>: Owns the <code>ctx.sessions</code> append-only <code>SessionEvent</code> log.</p></li><li><p><code>core/system-prompt</code>: Manages tool-schema and prompt-section assembly (<code>ctx.systemPrompt</code>).</p></li><li><p><code>core/tools</code>: Handles the guarded execution pipeline and scoped tool registry (<code>ctx.tools</code>).</p></li><li><p><code>core/agent</code> and <code>core/agent-loop</code>: Define the <code>Agent</code> interface, live registry, and default driver (<code>ctx.agents</code>, <code>ctx.agentLoop</code>).</p></li></ul><p>Further architectural details are available in the <a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/architecture.md">DeepSeek Harness architecture documentation</a> and its <a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/core.md">core subsystem documentation</a>.</p><h3>Key technical features of dsh</h3><p><strong>Session log</strong></p><p>The session log is the primary source for model context. It uses <code>deriveMessages()</code> to project history; notably, it retains failed, cancelled, or retried attempts in <code>assistant/attempt</code> without adding them to the model&#8217;s history.</p><p>Reference: <a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/session.md">DeepSeek Harness &#8211; Session subsystem</a>.</p><p><strong>Capability seams</strong></p><p>dsh utilises &#8220;seams&#8221; that allow for provider swaps without requiring provider forks. For example, shifting filesystem and subprocess providers to a remote sandbox moves Bash, LSP, and PTY collectively.</p><h3>Comparison with Grove</h3><p>While the available evidence does not detail every architectural component of Grove&#8217;s harness, it shows that Grove similarly implements pluggable agents via an <code>AgentDefinition</code> contract in <code>@grove/sdk</code>, ensuring that registering a new agent does not change the runtime.</p><p>Like dsh, Grove separates the runtime from the agent implementations.</p><p>The comparison here is architectural, rather than a claim that both systems have identical implementations.</p><h2>3. Current Implementation: Grove Local Testing</h2><p>Grove&#8217;s harness is currently being hosted and tested on a local Mac using Ollama.</p><ul><li><p>For testing purposes, a Gemma 4 31B dense model has been run locally using the <code>gemma4:31b</code> model identifier.</p></li><li><p>Additionally, smoke tests have been conducted on an Apple M3 Max (CPU only) using <code>qwen2.5:3b</code> via Docker Desktop.</p></li></ul><p>The local-inference infrastructure and its configurations are documented in the <a href="https://github.com/JagadeeshRampam/parjanya-workspace/blob/c10faf4f4e1669193793bca4ea7a760c33fe8583/grove/infra/local-inference/README.md">Grove local-inference README</a>.</p><p>These are development and experimentation environments, not production deployment configurations.</p><h2>4. Initial Release Model Strategy</h2><p>The initial release involves consideration of the following models:</p><ul><li><p>Gemma (latest version)</p></li><li><p>LLama Muse </p></li><li><p>Qwen 3.8</p></li><li><p>GLM 5.3</p></li><li><p>Kimi 3.1</p></li></ul><p>The intention is to use a model router to manage these multiple models. The design of this router or the planned implementation is using <strong>Mixture of Experts (MoE)</strong>. </p><h2>5. Roadmap: Agentic Pipeline Evolution</h2><p>Grove&#8217;s agentic pipeline is intended to evolve in the following order.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0K04!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F053f7122-2600-417f-a0a9-a7e9156a5c24_1774x887.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0K04!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F053f7122-2600-417f-a0a9-a7e9156a5c24_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!0K04!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F053f7122-2600-417f-a0a9-a7e9156a5c24_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!0K04!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F053f7122-2600-417f-a0a9-a7e9156a5c24_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!0K04!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F053f7122-2600-417f-a0a9-a7e9156a5c24_1774x887.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!0K04!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F053f7122-2600-417f-a0a9-a7e9156a5c24_1774x887.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/053f7122-2600-417f-a0a9-a7e9156a5c24_1774x887.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1376328,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/222878658?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F053f7122-2600-417f-a0a9-a7e9156a5c24_1774x887.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_!0K04!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F053f7122-2600-417f-a0a9-a7e9156a5c24_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!0K04!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F053f7122-2600-417f-a0a9-a7e9156a5c24_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!0K04!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F053f7122-2600-417f-a0a9-a7e9156a5c24_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!0K04!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F053f7122-2600-417f-a0a9-a7e9156a5c24_1774x887.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h3>5.1 Research Agent</h3><p>Intended for evidence-grounded research, literature reviews, and white papers.</p><p>It utilises a staged pipeline with human review gates and specific roles for extraction, drafting, and verification.</p><p>The current Research Agent implementation can be explored in the <a href="https://github.com/JagadeeshRampam/parjanya-workspace/blob/c10faf4f4e1669193793bca4ea7a760c33fe8583/grove/libs/agents/research/src/index.ts">Grove Research Agent source</a>.</p><h3>5.2 Documentation Agent</h3><p>Aimed at documentation drafting and maintenance.</p><p>This agent is described in the project&#8217;s documentation but has not yet been registered or built in v0.1.</p><h3>5.3 Coding Agent</h3><p>Designed as a repository-aware engineering assistant for Nx consolidation.</p><p>Its goal is to move from a polyrepo to a modular monolith with an application layer encompassing the backend, frontend (with future mobile/desktop apps), and shared libraries.</p><p>It will utilise a &#8220;read-only analysis first&#8221; approach followed by gated patch proposals in a sandbox.</p><p>These three agents represent the intended evolution of Grove&#8217;s agentic pipeline, not a claim that all three are already implemented.</p><h2>6. Interface and Distribution</h2><p>Grove v0.1&#8217;s interface is interpreted to consist of a CLI, which serves as the composition root to wire the system together.</p><p>The technology stack for the harness and SDK is TypeScript.</p><blockquote><p><strong>Grove is a potential open-source release under the name <a href="https://parjanya.phagyul.ai/guide">Parjanya</a> by <a href="https://phagyul.ai">Phagyul</a> AI Systems Pvt Ltd.</strong></p></blockquote><p>The interface and distribution strategy remain subject to further development.</p><div><hr></div><h1>7. Experimental Record: Gemma 4 31B on Local Ollama</h1><p>This section documents the experimental configuration and observations from running Grove&#8217;s research agent locally.</p><p>The run was hosted and tried on an Apple Mac M3 Max using Ollama running <code>gemma4:31b</code>.</p><p>The following records cover token consumption, observed performance, research-agent limits, sampling parameters, engine-level settings, and related environment configuration.</p><h2>7.1 Token Usage and Performance</h2><h3>Individual model calls</h3><p>The process involved varying input and output token counts across different sequences.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!33DF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cb01752-0231-49a6-a2a4-11704597e523_1240x874.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!33DF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cb01752-0231-49a6-a2a4-11704597e523_1240x874.png 424w, https://substackcdn.com/image/fetch/$s_!33DF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cb01752-0231-49a6-a2a4-11704597e523_1240x874.png 848w, https://substackcdn.com/image/fetch/$s_!33DF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cb01752-0231-49a6-a2a4-11704597e523_1240x874.png 1272w, https://substackcdn.com/image/fetch/$s_!33DF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cb01752-0231-49a6-a2a4-11704597e523_1240x874.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!33DF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cb01752-0231-49a6-a2a4-11704597e523_1240x874.png" width="1240" height="874" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3cb01752-0231-49a6-a2a4-11704597e523_1240x874.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:874,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:95685,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/222878658?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cb01752-0231-49a6-a2a4-11704597e523_1240x874.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_!33DF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cb01752-0231-49a6-a2a4-11704597e523_1240x874.png 424w, https://substackcdn.com/image/fetch/$s_!33DF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cb01752-0231-49a6-a2a4-11704597e523_1240x874.png 848w, https://substackcdn.com/image/fetch/$s_!33DF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cb01752-0231-49a6-a2a4-11704597e523_1240x874.png 1272w, https://substackcdn.com/image/fetch/$s_!33DF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cb01752-0231-49a6-a2a4-11704597e523_1240x874.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>These are selected individual model-call observations from the experimental run.</p><h3>Total usage</h3><p>Across 38 model calls, the total token usage for writing the first post draft was:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!le9X!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777762ef-a1e0-4027-aa12-a9951a3e2296_1240x390.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!le9X!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777762ef-a1e0-4027-aa12-a9951a3e2296_1240x390.png 424w, https://substackcdn.com/image/fetch/$s_!le9X!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777762ef-a1e0-4027-aa12-a9951a3e2296_1240x390.png 848w, https://substackcdn.com/image/fetch/$s_!le9X!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777762ef-a1e0-4027-aa12-a9951a3e2296_1240x390.png 1272w, https://substackcdn.com/image/fetch/$s_!le9X!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777762ef-a1e0-4027-aa12-a9951a3e2296_1240x390.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!le9X!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777762ef-a1e0-4027-aa12-a9951a3e2296_1240x390.png" width="1240" height="390" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/777762ef-a1e0-4027-aa12-a9951a3e2296_1240x390.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:390,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:47810,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/222878658?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777762ef-a1e0-4027-aa12-a9951a3e2296_1240x390.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_!le9X!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777762ef-a1e0-4027-aa12-a9951a3e2296_1240x390.png 424w, https://substackcdn.com/image/fetch/$s_!le9X!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777762ef-a1e0-4027-aa12-a9951a3e2296_1240x390.png 848w, https://substackcdn.com/image/fetch/$s_!le9X!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777762ef-a1e0-4027-aa12-a9951a3e2296_1240x390.png 1272w, https://substackcdn.com/image/fetch/$s_!le9X!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777762ef-a1e0-4027-aa12-a9951a3e2296_1240x390.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h3>Performance records</h3><p>The recorded performance observations were:</p><ul><li><p><strong>Prompt evaluation speed:</strong> Ranged from approximately 79.60 tokens per second (seq 1531) to 118.39 tokens per second (seq 0).</p></li><li><p><strong>Generation speed:</strong> Ranged between 8.49 tokens per second (seq 946) and 13.61 tokens per second (seq 925).</p></li></ul><p>These figures are observations from the recorded run and should not be interpreted as controlled or generalised model benchmarks.</p><h2>7.2 Research Agent Limits and Thresholds</h2><p>The following limits and thresholds were used for the research agent.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6zhG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d22ed48-8e78-42a8-83dc-ea3f7c4fc1de_1240x1164.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6zhG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d22ed48-8e78-42a8-83dc-ea3f7c4fc1de_1240x1164.png 424w, https://substackcdn.com/image/fetch/$s_!6zhG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d22ed48-8e78-42a8-83dc-ea3f7c4fc1de_1240x1164.png 848w, https://substackcdn.com/image/fetch/$s_!6zhG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d22ed48-8e78-42a8-83dc-ea3f7c4fc1de_1240x1164.png 1272w, https://substackcdn.com/image/fetch/$s_!6zhG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d22ed48-8e78-42a8-83dc-ea3f7c4fc1de_1240x1164.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!6zhG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d22ed48-8e78-42a8-83dc-ea3f7c4fc1de_1240x1164.png" width="1240" height="1164" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4d22ed48-8e78-42a8-83dc-ea3f7c4fc1de_1240x1164.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1164,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:156427,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/222878658?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d22ed48-8e78-42a8-83dc-ea3f7c4fc1de_1240x1164.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_!6zhG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d22ed48-8e78-42a8-83dc-ea3f7c4fc1de_1240x1164.png 424w, https://substackcdn.com/image/fetch/$s_!6zhG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d22ed48-8e78-42a8-83dc-ea3f7c4fc1de_1240x1164.png 848w, https://substackcdn.com/image/fetch/$s_!6zhG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d22ed48-8e78-42a8-83dc-ea3f7c4fc1de_1240x1164.png 1272w, https://substackcdn.com/image/fetch/$s_!6zhG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d22ed48-8e78-42a8-83dc-ea3f7c4fc1de_1240x1164.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The timeout and retry values are defined in the Gemma expert configuration. The context budget is defined in the research-agent harness configuration, and the default deadline is defined in the Research Agent implementation.</p><p>Relevant implementation reference: <a href="https://github.com/JagadeeshRampam/parjanya-workspace/blob/c10faf4f4e1669193793bca4ea7a760c33fe8583/grove/libs/agents/research/src/index.ts">Grove Research Agent</a>.</p><h2>7.3 Ollama Sampling Parameters</h2><p>The sampling settings recorded for the <code>gemma4:31b</code> model were as follows:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VBh9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa43df42f-748e-4d31-b5ff-ac26c0442e9a_1240x656.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VBh9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa43df42f-748e-4d31-b5ff-ac26c0442e9a_1240x656.png 424w, https://substackcdn.com/image/fetch/$s_!VBh9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa43df42f-748e-4d31-b5ff-ac26c0442e9a_1240x656.png 848w, https://substackcdn.com/image/fetch/$s_!VBh9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa43df42f-748e-4d31-b5ff-ac26c0442e9a_1240x656.png 1272w, https://substackcdn.com/image/fetch/$s_!VBh9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa43df42f-748e-4d31-b5ff-ac26c0442e9a_1240x656.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!VBh9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa43df42f-748e-4d31-b5ff-ac26c0442e9a_1240x656.png" width="1240" height="656" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a43df42f-748e-4d31-b5ff-ac26c0442e9a_1240x656.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:656,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:63717,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/222878658?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa43df42f-748e-4d31-b5ff-ac26c0442e9a_1240x656.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_!VBh9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa43df42f-748e-4d31-b5ff-ac26c0442e9a_1240x656.png 424w, https://substackcdn.com/image/fetch/$s_!VBh9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa43df42f-748e-4d31-b5ff-ac26c0442e9a_1240x656.png 848w, https://substackcdn.com/image/fetch/$s_!VBh9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa43df42f-748e-4d31-b5ff-ac26c0442e9a_1240x656.png 1272w, https://substackcdn.com/image/fetch/$s_!VBh9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa43df42f-748e-4d31-b5ff-ac26c0442e9a_1240x656.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Both observations are retained here rather than choosing one value without further verification.</p><p>For parameter definitions and their behaviour, refer to the <a href="https://github.com/ollama/ollama/blob/main/docs/modelfile.mdx">official Ollama Modelfile documentation</a>.</p><h2>7.4 Model Engine and Environment Settings</h2><h3>llama-server parameters</h3><p>The following engine-level parameters were recorded when Ollama started the llama-server for this run.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!q6XA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b3f2ed6-8c3a-43a7-ab2f-c9cabf73950e_1240x830.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!q6XA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b3f2ed6-8c3a-43a7-ab2f-c9cabf73950e_1240x830.png 424w, https://substackcdn.com/image/fetch/$s_!q6XA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b3f2ed6-8c3a-43a7-ab2f-c9cabf73950e_1240x830.png 848w, https://substackcdn.com/image/fetch/$s_!q6XA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b3f2ed6-8c3a-43a7-ab2f-c9cabf73950e_1240x830.png 1272w, https://substackcdn.com/image/fetch/$s_!q6XA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b3f2ed6-8c3a-43a7-ab2f-c9cabf73950e_1240x830.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!q6XA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b3f2ed6-8c3a-43a7-ab2f-c9cabf73950e_1240x830.png" width="1240" height="830" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5b3f2ed6-8c3a-43a7-ab2f-c9cabf73950e_1240x830.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:830,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:118773,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/222878658?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b3f2ed6-8c3a-43a7-ab2f-c9cabf73950e_1240x830.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_!q6XA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b3f2ed6-8c3a-43a7-ab2f-c9cabf73950e_1240x830.png 424w, https://substackcdn.com/image/fetch/$s_!q6XA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b3f2ed6-8c3a-43a7-ab2f-c9cabf73950e_1240x830.png 848w, https://substackcdn.com/image/fetch/$s_!q6XA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b3f2ed6-8c3a-43a7-ab2f-c9cabf73950e_1240x830.png 1272w, https://substackcdn.com/image/fetch/$s_!q6XA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b3f2ed6-8c3a-43a7-ab2f-c9cabf73950e_1240x830.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>These are the recorded llama-server settings from the model-load log.</p><h3>Related Ollama environment configuration</h3><p>The following values are present in Grove&#8217;s Docker Compose configuration for local inference:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dcH1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24719334-ee74-4311-b518-11639f5f64a4_1240x594.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dcH1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24719334-ee74-4311-b518-11639f5f64a4_1240x594.png 424w, https://substackcdn.com/image/fetch/$s_!dcH1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24719334-ee74-4311-b518-11639f5f64a4_1240x594.png 848w, https://substackcdn.com/image/fetch/$s_!dcH1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24719334-ee74-4311-b518-11639f5f64a4_1240x594.png 1272w, https://substackcdn.com/image/fetch/$s_!dcH1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24719334-ee74-4311-b518-11639f5f64a4_1240x594.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!dcH1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24719334-ee74-4311-b518-11639f5f64a4_1240x594.png" width="1240" height="594" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/24719334-ee74-4311-b518-11639f5f64a4_1240x594.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:594,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:77204,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/222878658?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24719334-ee74-4311-b518-11639f5f64a4_1240x594.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_!dcH1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24719334-ee74-4311-b518-11639f5f64a4_1240x594.png 424w, https://substackcdn.com/image/fetch/$s_!dcH1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24719334-ee74-4311-b518-11639f5f64a4_1240x594.png 848w, https://substackcdn.com/image/fetch/$s_!dcH1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24719334-ee74-4311-b518-11639f5f64a4_1240x594.png 1272w, https://substackcdn.com/image/fetch/$s_!dcH1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24719334-ee74-4311-b518-11639f5f64a4_1240x594.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Important distinction:</strong> These values are documented in Grove&#8217;s Docker Compose configuration. The Gemma experiment described above used the Ollama application on the Mac, not the Docker Compose Ollama service. Therefore, these environment variables should not be interpreted as confirmed settings for that specific experiment.</p><p>Configuration reference: <a href="https://github.com/JagadeeshRampam/parjanya-workspace/blob/c10faf4f4e1669193793bca4ea7a760c33fe8583/grove/infra/local-inference/docker-compose.yml">Grove local-inference Docker Compose</a>.</p><p>For additional context on Ollama environment variables and context-window configuration, refer to the <a href="https://github.com/ollama/ollama/blob/main/docs/faq.mdx">official Ollama FAQ</a>.</p><h2>7.5 Conflicts and Uncertainties in the Experimental Configuration</h2><p>There are two configuration discrepancies worth documenting.</p><p><strong>1. Conflict in </strong><code>top_p</code></p><p>There is a conflict between the llama-server load log, which specifies <code>top_p</code> as 1.0, and the Ollama model parameters, which list it as 0.95.</p><p><strong>2. Uncertainty in context length</strong></p><p>It is unclear which setting took precedence during the run:</p><ul><li><p>The llama-server was started with a context size of 32,768 tokens.</p></li><li><p>The <code>OLLAMA_CONTEXT_LENGTH</code> environment variable in the related Docker configuration was set to 16,384.</p></li></ul><p>Since the Docker configuration was not used for the documented Mac experiment, the latter value does not establish the effective context length for that run.</p><p>The sources do not specify any other limits or parameters beyond those listed above.</p><div><hr></div><h1>8. Evolving Grove: Areas of Continued Development</h1><p>Grove v0.1 is an initial foundation, not a finished system. As the architecture evolves and additional models are integrated, several areas will receive further attention, experimentation and refinement.</p><p>Some of the areas we intend to explore include:</p><ul><li><p><strong>Multi-model intelligence and routing:</strong> Expanding model support and developing the model router, including the exploration of a Mixture of Experts (MoE) approach to direct tasks to suitable models based on their capabilities.</p></li><li><p><strong>Multimodal research capabilities:</strong> Further developing image-processing workflows, including handling high-bit-depth RAW files, image analysis and more effective filtering and evidence extraction.</p></li><li><p><strong>Documentation automation:</strong> Extending the Documentation Agent to support practical engineering and publishing workflows, including blog posts, READMEs, technical documentation and white papers, with integration into the relevant model services.</p></li><li><p><strong>Interfaces and accessibility:</strong> Exploring interfaces beyond the initial CLI as Grove&#8217;s runtime and agent capabilities mature.</p></li><li><p><strong>Performance and model evaluation:</strong> Comparing models across different hardware and execution environments, with a focus on inference speed, token consumption, reliability and task quality.</p></li></ul><p>These are evolving areas of engineering work rather than fixed specifications. Their implementation and priorities will be shaped by experimentation, practical usage and feedback as Grove develops.</p><p>For a more detailed view of ongoing work, planned enhancements and implementation priorities, refer to the <a href="https://github.com/JagadeeshRampam/parjanya-issues/issues">Parjanya Engineering Issues and Roadmap</a>.</p><p>For shipped improvements and version-specific changes, follow the <a href="https://parjanya.phagyul.ai/release-notes">Parjanya Release Notes</a>.</p><div><hr></div><h1>9. References and Evidence</h1><p>The following public references provide context for the architecture, implementation and experimental configuration.</p><h3>Architecture and agent harness</h3><ol><li><p><a href="https://github.com/deepseek-ai/deepseek-harness">DeepSeek Harness &#8211; Official Repository</a></p></li><li><p><a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/architecture.md">DeepSeek Harness &#8211; Architecture</a></p></li><li><p><a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/core.md">DeepSeek Harness &#8211; Core Subsystems</a></p></li><li><p><a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/session.md">DeepSeek Harness &#8211; Session Subsystem</a></p></li></ol><h3>Grove implementation</h3><ol start="5"><li><p><a href="https://github.com/JagadeeshRampam/parjanya-workspace/blob/c10faf4f4e1669193793bca4ea7a760c33fe8583/grove/infra/local-inference/README.md">Grove &#8211; Local Inference README</a></p></li><li><p><a href="https://github.com/JagadeeshRampam/parjanya-workspace/blob/c10faf4f4e1669193793bca4ea7a760c33fe8583/grove/infra/local-inference/docker-compose.yml">Grove &#8211; Local Inference Docker Compose</a></p></li><li><p><a href="https://github.com/JagadeeshRampam/parjanya-workspace/blob/c10faf4f4e1669193793bca4ea7a760c33fe8583/grove/libs/agents/research/src/index.ts">Grove &#8211; Research Agent Implementation</a></p></li></ol><h3>Model and runtime documentation</h3><ol start="8"><li><p><a href="https://github.com/ollama/ollama/blob/main/docs/modelfile.mdx">Ollama &#8211; Modelfile Reference</a></p></li><li><p><a href="https://github.com/ollama/ollama/blob/main/docs/faq.mdx">Ollama &#8211; FAQ</a></p></li><li><p><a href="https://ai.google.dev/gemma/docs/core/model_card_4">Google &#8211; Gemma 4 Model Card</a></p></li></ol><h3>Internal experimental evidence</h3><p>The experimental figures in this note are based on the local run records, Ollama model-load logs, request logs, Grove configuration and run records captured during the experiment.</p><p>These are internal development artifacts and are not publicly accessible through the links above. The original evidence export records the associated source files, line ranges, quoted passages and file fingerprints.</p><p>The local logs and configuration snapshots are retained as the supporting engineering record.</p><div><hr></div><p><em>Grove v0.1 is a work in progress. This note captures an early point in its development, not a final destination. The architecture will evolve, the models may change, and the experimental parameters will be revisited as the system matures. We are sharing the process as it happens, including what works, what remains uncertain, and what we learn along the way.</em></p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ahsu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 424w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 848w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1272w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png" width="1456" height="211" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:211,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ahsu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 424w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 848w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1272w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[How We Cut AI Inference Cold Starts in Half: Optimising GPU Startup for Photo Analysis]]></title><description><![CDATA[Two months of measuring, profiling and simplifying Parjanya&#8217;s AI infrastructure &#8212; from GPU cold starts and model loading to inference speed, cost, and verdict consistency.]]></description><link>https://blog.phagyul.ai/p/how-we-cut-ai-inference-cold-starts</link><guid isPermaLink="false">https://blog.phagyul.ai/p/how-we-cut-ai-inference-cold-starts</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Wed, 30 Sep 2026 06:25:54 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2Pxx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F536858c9-a951-46b1-870e-a142bfa11708_1774x887.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I started working on the performance of Parjanya&#8217;s AI analysis, I thought I was looking at a fairly straightforward infrastructure problem.</p><p>The GPUs were taking too long to start.</p><p>Fix the startup time, make the model faster, and the problem would be solved.</p><p>It turned out to be much more interesting than that.</p><p>Over the past two months, I ended up digging through cold starts, GPU behaviour, model loading, storage bottlenecks, inference paths, numerical differences between GPUs, and even the way a tiny change in floating-point computation can alter a photographic verdict.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2Pxx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F536858c9-a951-46b1-870e-a142bfa11708_1774x887.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2Pxx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F536858c9-a951-46b1-870e-a142bfa11708_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!2Pxx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F536858c9-a951-46b1-870e-a142bfa11708_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!2Pxx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F536858c9-a951-46b1-870e-a142bfa11708_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!2Pxx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F536858c9-a951-46b1-870e-a142bfa11708_1774x887.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2Pxx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F536858c9-a951-46b1-870e-a142bfa11708_1774x887.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/536858c9-a951-46b1-870e-a142bfa11708_1774x887.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1546036,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/218125985?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F536858c9-a951-46b1-870e-a142bfa11708_1774x887.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_!2Pxx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F536858c9-a951-46b1-870e-a142bfa11708_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!2Pxx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F536858c9-a951-46b1-870e-a142bfa11708_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!2Pxx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F536858c9-a951-46b1-870e-a142bfa11708_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!2Pxx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F536858c9-a951-46b1-870e-a142bfa11708_1774x887.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>More importantly, it reminded me of something I have learned repeatedly while building products:</p><blockquote><p><strong>The hardest engineering problems are often not the ones that look technically complicated. They are the ones where speed, cost, correctness and user experience collide.</strong></p></blockquote><div class="pullquote"><p><strong>This is the story of how we brought Parjanya&#8217;s first AI verdict from roughly 7.5&#8211;9.2 minutes down to about 5 minutes, while keeping the system affordable and, more importantly, keeping the verdicts stable.</strong></p></div><h2>First, what actually happens when you upload photographs?</h2><p>When you upload a shoot to Parjanya, two things happen.</p><p>First, a quick technical check runs immediately.</p><p>Then each photograph goes to a GPU machine running our vision-language model. That model produces the critique, identifies areas for improvement, and eventually gives the photograph a <strong>Keeper / Review / Skip</strong> verdict.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!O4QF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb88a90e-cd49-4c57-a2c4-200a20b49599_1080x1350.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!O4QF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb88a90e-cd49-4c57-a2c4-200a20b49599_1080x1350.png 424w, https://substackcdn.com/image/fetch/$s_!O4QF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb88a90e-cd49-4c57-a2c4-200a20b49599_1080x1350.png 848w, https://substackcdn.com/image/fetch/$s_!O4QF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb88a90e-cd49-4c57-a2c4-200a20b49599_1080x1350.png 1272w, https://substackcdn.com/image/fetch/$s_!O4QF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb88a90e-cd49-4c57-a2c4-200a20b49599_1080x1350.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!O4QF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb88a90e-cd49-4c57-a2c4-200a20b49599_1080x1350.png" width="1080" height="1350" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bb88a90e-cd49-4c57-a2c4-200a20b49599_1080x1350.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1350,&quot;width&quot;:1080,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1175600,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/218125985?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb88a90e-cd49-4c57-a2c4-200a20b49599_1080x1350.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_!O4QF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb88a90e-cd49-4c57-a2c4-200a20b49599_1080x1350.png 424w, https://substackcdn.com/image/fetch/$s_!O4QF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb88a90e-cd49-4c57-a2c4-200a20b49599_1080x1350.png 848w, https://substackcdn.com/image/fetch/$s_!O4QF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb88a90e-cd49-4c57-a2c4-200a20b49599_1080x1350.png 1272w, https://substackcdn.com/image/fetch/$s_!O4QF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb88a90e-cd49-4c57-a2c4-200a20b49599_1080x1350.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The interesting part is that those GPU machines aren&#8217;t running all the time. </p><div class="pullquote"><p><strong>When we say average of 18,000+ images processed in a week or two it is definitely not guaranteed that 1200+ images per day, perhaps, it is quite possible that 80-90% traffic across tenants on a single or two to three days</strong></p></div><p>At our current scale, keeping GPUs running continuously would mean paying for machines that spend most of their time doing nothing.</p><p>So we turn them off when there is no work.</p><p>That gives us a very attractive infrastructure cost profile &#8212; but introduces a <strong>cold start</strong>.</p><p>When your upload arrives and nothing is running, we have to:</p><ol><li><p>Request a GPU machine.</p></li><li><p>Boot it.</p></li><li><p>Download the software.</p></li><li><p>Download the AI models.</p></li><li><p>Copy the models to local storage.</p></li><li><p>Load the models into GPU memory.</p></li><li><p>Process your first photograph.</p></li></ol><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EPGw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c14d10f-de48-4912-a926-91ea4b7f90d6_2172x368.png 424w, https://substackcdn.com/image/fetch/$s_!EPGw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c14d10f-de48-4912-a926-91ea4b7f90d6_2172x368.png 848w, https://substackcdn.com/image/fetch/$s_!EPGw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c14d10f-de48-4912-a926-91ea4b7f90d6_2172x368.png 1272w, https://substackcdn.com/image/fetch/$s_!EPGw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c14d10f-de48-4912-a926-91ea4b7f90d6_2172x368.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!EPGw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c14d10f-de48-4912-a926-91ea4b7f90d6_2172x368.png" width="2172" height="368" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0c14d10f-de48-4912-a926-91ea4b7f90d6_2172x368.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:368,&quot;width&quot;:2172,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:938437,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/218125985?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa621cfb5-bd81-405b-8e05-3828f8a53631_2172x724.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_!EPGw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c14d10f-de48-4912-a926-91ea4b7f90d6_2172x368.png 424w, https://substackcdn.com/image/fetch/$s_!EPGw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c14d10f-de48-4912-a926-91ea4b7f90d6_2172x368.png 848w, https://substackcdn.com/image/fetch/$s_!EPGw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c14d10f-de48-4912-a926-91ea4b7f90d6_2172x368.png 1272w, https://substackcdn.com/image/fetch/$s_!EPGw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c14d10f-de48-4912-a926-91ea4b7f90d6_2172x368.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div></figure></div><p>At the end of July, that entire journey could take <strong>up to nine minutes</strong>.</p><p>For someone trying <a href="https://parjanya.phagyul.ai">Parjanya</a> for the first time, nine minutes doesn&#8217;t feel like &#8220;AI infrastructure is warming up.&#8221;</p><p>It feels like the product is broken.</p><p>That was the problem I wanted to solve.</p><div><hr></div><h2>The numbers before and after</h2><p>Here is what we measured.</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/XDJLf/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/600030c1-b58d-4f7a-946b-e0bd93e8aa55_1220x628.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e16e5d69-ef91-485b-9c8a-c5e9ddb43151_1220x628.png&quot;,&quot;height&quot;:300,&quot;title&quot;:&quot;Created with Datawrapper&quot;,&quot;description&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/XDJLf/1/" width="730" height="300" frameborder="0" scrolling="no" loading="lazy"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><h6>Note: The 27 September numbers are from single cold starts; I&#8217;ll keep measuring this as more real-world uploads arrive. But getting there wasn&#8217;t one optimisation.</h6><p>It was a series of relatively small discoveries.</p><p>And the first discovery was perhaps the most embarrassing one.</p><div><hr></div><h1>1. I couldn&#8217;t optimise what I wasn&#8217;t measuring</h1><p>The first thing I discovered was that roughly <strong>four minutes of every cold start wasn&#8217;t being measured at all</strong>.</p><p>Our logs started measuring the model&#8217;s work only after the machine had already:</p><ul><li><p>booted,</p></li><li><p>downloaded the software,</p></li><li><p>copied the model,</p></li><li><p>and reached the point where inference could begin.</p></li></ul><p>Everything before that was invisible.</p><p>There was another problem.</p><p>Our machine logs were identified using network addresses.</p><p>Those addresses get reused.</p><p>So when multiple machines started around the same time, it wasn&#8217;t always possible to tell which log belonged to which machine.</p><p>In other words, I was trying to optimise a system without having a reliable stopwatch.</p><p>So the first optimisation was not an optimisation at all.</p><p>We changed the observability.</p><p>Every machine now has a unique identity in the logs, and the boot process records timestamps for every major stage &#8212; from &#8220;<strong>machine running</strong>&#8221; all the way to &#8220;<strong>model loaded</strong>.&#8221;</p><p>And I changed another rule internally:</p><blockquote><p><strong>A performance change doesn&#8217;t get a tick simply because the code was merged. It gets a tick only after it is deployed and measured in the Production. </strong></p></blockquote><p>That sounds obvious.</p><p>In practice, it changes how you work.</p><div><hr></div><h1>2. Wake the GPU when the work arrives</h1><p>The next surprise was the queue.</p><p>Our machines were being started based on the length of the work queue.</p><p>That sounds sensible.</p><p>It wasn&#8217;t fast.</p><p>The queue publishes its length periodically. Another mechanism checks that number periodically. Only then does the system decide that it needs another machine.</p><p>We measured the delay.</p><blockquote><p><strong>2 minutes 44 seconds.</strong></p></blockquote><p>Before the GPU had even started doing anything, almost three minutes had disappeared.</p><p>So we changed the trigger.</p><p>The same operation that puts the photograph into the queue now directly requests a machine.</p><p>On the first cold start after that change, the machine was requested <strong>15 seconds</strong> after the first photograph arrived.</p><p>That was a much more direct relationship:</p><blockquote><p><strong>Work arrived &#8594; ask for compute.</strong></p></blockquote><p>We also changed how many machines we started.</p><p>Previously, the system essentially reacted to &#8220;is anything waiting?&#8221;</p><p>That meant a 13-photo upload could potentially wake every available machine.</p><p>Now the fleet sizes itself against the backlog.</p><div class="pullquote"><p>Small upload? One or two machines.</p><p>Large upload? More machines.</p><p>That change brought a large batch from around <strong>69 minutes to about 4 minutes</strong>.</p><p><strong>I call this queue-aware scaling</strong></p></div><h1>3. If two things don&#8217;t depend on each other, why run them sequentially?</h1><p>A new machine needs to download two large things:</p><ul><li><p>our analysis software &#8212; roughly a 5 GB container image</p></li><li><p>the model weights</p></li></ul><p>Previously, these happened one after another.</p><p>There was no real dependency between them.</p><p>So we made them happen simultaneously.</p><p>The machine now waits for both operations to complete before loading the model.</p><p>That saved approximately <strong>110 seconds</strong> on each of the two machines we measured.</p><p>There is a small engineering detail here that I think is worth mentioning.</p><p>Once you start overlapping operations, measurement becomes harder.</p><p>If you only record the end time, you lose the ability to understand where the time actually went.</p><p>So we record the beginning and end of each stage.</p><p>That way, when operations overlap, we can still reconstruct the timeline.</p><p>And if a download fails, the machine stops cleanly rather than continuing with a half-ready environment.</p><p>Fast is useful.</p><p><strong>Fast and observable is much more useful.</strong></p><div><hr></div><h1>4. The fastest download tool couldn&#8217;t solve a disk bottleneck</h1><p>By mid-September, we had reached another bottleneck.</p><p>Model copying had become the slowest part of the boot.</p><p>The obvious idea was:</p><blockquote><p>Can we download it faster?</p></blockquote><p>So we tried six different ways of copying the same 21 GB.</p><p>The result?</p><p>They were all within about <strong>5% of one another</strong>.</p><p>That was the clue.</p><p>We separated network performance from disk performance.</p><p>The network could deliver around <strong>780 MB/s</strong>.</p><p>The local disk could write only around <strong>165 MB/s</strong>.</p><p>The network wasn&#8217;t the bottleneck.</p><p>The disk was.</p><p>That meant no amount of cleverness in the download tool was going to solve the fundamental problem.</p><p>So we asked a different question:</p><blockquote><p><strong>Can we move less data?</strong></p></blockquote><p>That worked.</p><p>Our main model runs in a compressed 4-bit representation.</p><p>Previously, every machine downloaded the full 17 GB model and compressed it during startup.</p><p>Instead, we now compress it once, store the compressed version, and download approximately <strong>6 GB</strong>.</p><p>That changed:</p><ul><li><p>model loading: <strong>51s &#8594; 20s</strong></p></li><li><p>copying: <strong>164s &#8594; 102s</strong></p></li><li><p>machine readiness: approximately <strong>90 seconds sooner</strong></p></li></ul><p>We also verified something that mattered enormously to me:</p><p>The stored weights were byte-for-byte identical to the weights each machine previously generated for itself.</p><p>And a production photograph re-analysed with them produced exactly the same result.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!S0_D!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36a6c188-46ce-475d-9883-c5653cbc398f_1774x887.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!S0_D!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36a6c188-46ce-475d-9883-c5653cbc398f_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!S0_D!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36a6c188-46ce-475d-9883-c5653cbc398f_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!S0_D!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36a6c188-46ce-475d-9883-c5653cbc398f_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!S0_D!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36a6c188-46ce-475d-9883-c5653cbc398f_1774x887.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!S0_D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36a6c188-46ce-475d-9883-c5653cbc398f_1774x887.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/36a6c188-46ce-475d-9883-c5653cbc398f_1774x887.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1220157,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/218125985?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36a6c188-46ce-475d-9883-c5653cbc398f_1774x887.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_!S0_D!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36a6c188-46ce-475d-9883-c5653cbc398f_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!S0_D!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36a6c188-46ce-475d-9883-c5653cbc398f_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!S0_D!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36a6c188-46ce-475d-9883-c5653cbc398f_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!S0_D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36a6c188-46ce-475d-9883-c5653cbc398f_1774x887.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This was a good reminder of a general optimisation principle:</p><blockquote><p><strong>When the disk is the bottleneck, reducing bytes can be more valuable than making the pipe faster.</strong></p></blockquote><div><hr></div><h1>5. Then I started looking inside the model</h1><p>Once the infrastructure was reasonably healthy, I turned to the actual photo analysis.</p><p>Parjanya currently uses two GPU types:</p><ul><li><p>NVIDIA T4 &#8212; older, cheaper</p></li><li><p>NVIDIA A10G &#8212; newer, faster</p></li></ul><p>A photograph took roughly <strong>106 seconds on a T4</strong>.</p><p>So we profiled the model layer by layer.</p><p>The first major discovery was a particular operation that cuts the photograph into small patches for the model to process.</p><p>That single layer was taking around <strong>31 seconds</strong>.</p><p>The T4 doesn&#8217;t have hardware support for the number format that layer was using &#8212; bfloat16 &#8212; so it was falling back to a very slow path.</p><p>Running that layer in standard 32-bit precision took only milliseconds.</p><p>That brought the photo from roughly:</p><p><strong>106 seconds &#8594; 75 seconds</strong></p><p>Then we found another optimisation in the attention mechanism.</p><p>Switching the language part of the model to a simpler attention implementation brought the photo down to around:</p><p><strong>56 seconds</strong></p><p>Our first production T4 run measured <strong>65 seconds from start to finish</strong>.</p><p>At this point, it looked like a straightforward win.</p><p>And then things became much more interesting.</p><div><hr></div><h1>6. Faster didn&#8217;t necessarily mean the same answer</h1><p>This was the part I didn&#8217;t expect.</p><p>The speed improvements changed numerical behaviour.</p><p>Not dramatically.</p><p>Not obviously.</p><p>But enough.</p><p>In the first optimisation, only <strong>527 out of 3.7 million values</strong> moved by the smallest step representable by the format.</p><p>That sounds insignificant.</p><p>For most photographs, it was.</p><p>But for photographs sitting close to a decision boundary, it could change the final verdict.</p><p>So we did something that became one of the most important experiments in this entire exercise.</p><p>We ran the same photographs through both GPU types.</p><p>Each GPU was perfectly repeatable.</p><p>Same photograph.</p><p>Same GPU.</p><p>Same answer.</p><p>Every time.</p><p>But the two GPUs did not always agree with each other.</p><p>Across 64 varied production photographs, they agreed on 45.</p><p>And 15 photographs received a <strong>Keeper on one GPU and Skip on the other</strong>.</p><p>That changed how I thought about performance optimisation.</p><p>The question wasn&#8217;t:</p><blockquote><p>&#8220;Did the model get faster?&#8221;</p></blockquote><p>It became:</p><blockquote><p><strong>&#8220;Did the model get faster while preserving the thing the user actually cares about?&#8221;</strong></p></blockquote><p>In our case, that thing isn&#8217;t milliseconds.</p><p>It&#8217;s the verdict.</p><div><hr></div><h1>7. We chose consistency over raw speed</h1><p>That led us to three decisions.</p><h3>First: stability before speed</h3><p>Across 159 photographs, the faster T4 path agreed with the A10G about as often as the old T4 path did:</p><p><strong>122 vs 125.</strong></p><p>Within the noise of the experiment, speed hadn&#8217;t meaningfully damaged consistency.</p><p>That gave us confidence to keep the optimisation.</p><h3>Second: prefer one GPU type for new work</h3><p>We now start T4 machines first and use the A10G only when a T4 isn&#8217;t available.</p><p>Since August, T4 launches succeeded <strong>47 out of 48 times</strong>.</p><p>That means almost every new photograph is now analysed on the same class of GPU.</p><h3>Third: make the curation rule less sensitive to a single tone issue</h3><p>Our curation layer turns model findings into the final verdict.</p><p>We found that a single severe tone-related issue &#8212; exposure, dynamic range or noise &#8212; was one of the places where the GPU differences mattered most.</p><p>So we changed the rule:</p><p>A single severe tone problem by itself now counts as moderate rather than immediately sending the photograph to Skip.</p><p>Importantly, we didn&#8217;t rewrite history.</p><p>Photographs analysed before these changes retain the verdict they were given.</p><p>The new rules apply to new analyses.</p><p>That is deliberate.</p><p>If someone has already acted on a verdict, silently changing it underneath them isn&#8217;t something I want to do.</p><div><hr></div><h2>8. Some of the best engineering decisions were the things we didn&#8217;t ship</h2><p>One of my favourite parts of this exercise is not actually the list of things we improved.</p><p>It is the list of things we <strong>tried, measured, and deliberately decided not to ship</strong>.</p><p>That distinction matters.</p><p>When you&#8217;re building a product, especially one involving AI infrastructure, it is very easy to fall into a particular pattern:</p><blockquote><p>&#8220;This technology is faster, therefore we should use it.&#8221;</p></blockquote><p>Or:</p><blockquote><p>&#8220;This optimisation is supposed to help, therefore let&#8217;s implement it.&#8221;</p></blockquote><p>But an engineering optimisation is only useful if it improves the system <strong>under our actual constraints</strong>.</p><p>For Parjanya, those constraints aren&#8217;t just latency.</p><p>We also care about:</p><ul><li><p>GPU cost</p></li><li><p>availability</p></li><li><p>reliability</p></li><li><p>consistency of AI verdicts</p></li><li><p>privacy of photographers&#8217; work</p></li><li><p>operational complexity</p></li><li><p>and whether an improvement is actually meaningful to the person using the product</p></li></ul><p>That led to several experiments that ended with a very satisfying outcome:</p><p><strong>We didn&#8217;t ship them.</strong></p><p>Here are some of them.</p><h3>1. &#8220;Can we just download the model faster?&#8221;</h3><p>This was the most obvious idea when model copying became the slowest part of the boot.</p><p>We were moving a lot of data, so the natural assumption was:</p><blockquote><p>If downloading is slow, find a faster way to download.</p></blockquote><p>So we tried <strong>six different approaches</strong> to copying the same 21 GB.</p><p>The result was surprisingly boring.</p><p>All six were within roughly <strong>5% of one another</strong>.</p><p>At first, that was frustrating.</p><p>Then it became useful.</p><p>We separated the network from the local disk and measured both independently.</p><p>The network could deliver approximately <strong>780 MB/s</strong>.</p><p>The local disk could write only around <strong>165 MB/s</strong>.</p><p>That made the bottleneck obvious.</p><p>The network was capable of delivering data much faster than the machine could actually write it.</p><p>So changing the download tool wasn&#8217;t going to solve the problem.</p><p>We could spend days making the network path more sophisticated and still be limited by the disk.</p><p>The lesson was simple:</p><p><strong>Before optimising a pipeline, find the slowest component in the pipeline.</strong></p><p>In our case, the answer wasn&#8217;t &#8220;download faster.&#8221;</p><p>It was:</p><blockquote><p><strong>Move less data.</strong></p></blockquote><p>That led to the pre-compressed 4-bit model and saved roughly 90 seconds of machine startup.</p><h3>2. &#8220;What if we put the software image on the fast disk too?&#8221;</h3><p>Once we discovered that the local disk was the bottleneck, another idea naturally came up.</p><p>The machine has a fast local disk.</p><p>Why not put more of the boot assets there?</p><p>The problem was that the fast disk was already doing the work of receiving and storing the model.</p><p>Adding the software image would mean <strong>more data being written to the same bottleneck</strong>.</p><p>In other words, we would have been trying to fix a traffic jam by adding more cars to the road.</p><p>There was also another subtle point.</p><p>Moving the software image to the fast disk could improve one stage while making another stage slower because of the additional writes.</p><p>So we decided against it.</p><p>This is a useful pattern in performance engineering:</p><p><strong>A faster component doesn&#8217;t automatically make every workload faster.</strong></p><p>Sometimes the right optimisation is to reduce the amount of work that reaches the fast component in the first place.</p><h3>3. &#8220;Can we load both models at the same time?&#8221;</h3><p>Parjanya uses more than one model during the analysis process.</p><p>So another obvious question was:</p><blockquote><p>If we load them sequentially today, can we load them simultaneously?</p></blockquote><p>Normally, parallelising independent work is a good optimisation.</p><p>And we did test it.</p><p>But by the time we had already pre-compressed the main model, the combined loading time of the two models had fallen to roughly <strong>22 seconds</strong>.</p><p>At that point, parallelising them didn&#8217;t leave us much to win.</p><p>This is an important distinction between a technically valid optimisation and a worthwhile optimisation.</p><p>Yes, we could make two operations overlap.</p><p>But if the total time we&#8217;re trying to eliminate is already small, the complexity isn&#8217;t justified.</p><p>So we left it alone.</p><p><strong>Not every measurable optimisation is worth implementing.</strong></p><h3>4. &#8220;Should we warm up the model with a fake photograph?&#8221;</h3><p>This one came from an observation that initially looked quite convincing.</p><p>We thought the first photograph processed by a newly started GPU might be dramatically slower than the photographs that followed.</p><p>If that were true, we could start the machine, process a dummy photograph, throw away the result, and then give the user the &#8220;real&#8221; warmed-up inference.</p><p>It sounded reasonable.</p><p>So we measured it properly.</p><p>The result?</p><p>The first photograph on the <strong>same GPU type</strong> was at most around <strong>12 seconds slower</strong> than subsequent photographs.</p><p>That wasn&#8217;t remotely large enough to justify processing an extra photograph every time a machine started.</p><p>And there is a deeper reason why this matters.</p><p>A cold start already happens because a real photograph is waiting.</p><p>If we process a fake photograph first, we haven&#8217;t eliminated the work.</p><p>We&#8217;ve simply moved it earlier in the sequence.</p><p>So instead of:</p><p><strong>Start &#8594; analyse user&#8217;s photo</strong></p><p>we would have:</p><p><strong>Start &#8594; analyse fake photo &#8594; analyse user&#8217;s photo</strong></p><p>The user would still be waiting.</p><p>We decided not to do it.</p><p>This was a good reminder that sometimes the best optimisation is recognising that a cost <strong>cannot actually be removed</strong> &#8212; only moved around.</p><h3>5. &#8220;Can we cache the fixed part of the prompt?&#8221;</h3><p>This one looked much more promising.</p><p>Every photograph we send to the model comes with a fairly long set of instructions.</p><p>Most of those instructions are identical from photograph to photograph.</p><p>That immediately suggests caching.</p><p>If the instructions don&#8217;t change, why make the model process them repeatedly?</p><p>So we investigated it.</p><p>The surprise was where the time was actually going.</p><p>Only around <strong>490 tokens</strong> come before the photograph in the current prompt structure.</p><p>That&#8217;s roughly a second of work.</p><p>The much larger component we had mentally categorised as &#8220;prompt processing&#8221; was actually the <strong>vision side of the model</strong> processing the photograph.</p><p>So caching the fixed text wasn&#8217;t going to give us the large improvement we had imagined.</p><p>There was another complication: separating and computing that part independently changed the model outputs.</p><p>So we would have been taking on additional complexity and potentially changing verdict behaviour for a relatively small performance gain.</p><p>We didn&#8217;t ship it.</p><p>However, this investigation did reveal a more interesting possibility.</p><p>If we <strong>reorder the instructions so that the reusable part comes before the photograph</strong>, a much larger portion of the prompt could potentially become cacheable.</p><p>That is now a separate future experiment.</p><p>And, like every model optimisation we&#8217;re considering, it will have to pass the same verdict-consistency tests before it goes anywhere near production.</p><h3>6. &#8220;What about FlashAttention 2?&#8221;</h3><p>If you&#8217;ve spent any time optimising transformer inference, FlashAttention is an obvious thing to investigate.</p><p>We did.</p><p>The problem was much simpler than benchmarking:</p><p><strong>It doesn&#8217;t run on the T4.</strong></p><p>Our infrastructure deliberately uses the T4 because it is cheaper and generally available for our workload.</p><p>So an optimisation that requires hardware we aren&#8217;t primarily running on isn&#8217;t really an optimisation for Parjanya.</p><p>It might be a useful path if our hardware strategy changes.</p><p>For the current system, it isn&#8217;t.</p><h3>7. &#8220;Why don&#8217;t we just run everything on the faster A10G?&#8221;</h3><p>This is probably the most tempting option.</p><p>The A10G is faster.</p><p>If the goal is simply to reduce inference time, why not use it everywhere?</p><p>Because the GPU isn&#8217;t free.</p><p>The A10G costs more per photo.</p><p>It is also harder to obtain consistently.</p><p>In one of our three zones, it isn&#8217;t offered at all.</p><p>And in <strong>3 of 54 recent scale-ups</strong>, an A10G wasn&#8217;t available in any zone.</p><p>So we would be paying more for a resource that isn&#8217;t always available, while our cheaper T4 machines were giving us sufficiently good performance and, importantly, consistent verdicts.</p><p>There is also a product consideration here.</p><p>A photograph isn&#8217;t just a unit of GPU work.</p><p>It is someone&#8217;s photograph.</p><p>If changing hardware can change a borderline Keeper / Review / Skip decision, then &#8220;faster GPU&#8221; isn&#8217;t automatically better.</p><p>For our current workload, the T4 gives us a combination of:</p><p><strong>reasonable inference time + lower cost + much better availability + predictable behaviour.</strong></p><p>That&#8217;s a trade-off we&#8217;re comfortable with today.</p><p>It may not be the right trade-off forever.</p><h2>The pattern behind all these decisions</h2><p>Looking back, there is a common thread in almost every experiment we abandoned.</p><p>We started with a plausible hypothesis.</p><p>Then we measured it.</p><p>Sometimes the measurement disproved the hypothesis.</p><p>Sometimes the improvement was real but too small.</p><p>Sometimes the improvement solved one problem while making another worse.</p><p>And sometimes the technology simply didn&#8217;t fit our actual infrastructure.</p><p>That is why I increasingly think of optimisation as a <strong>constraint-solving exercise</strong>, rather than a race to make a benchmark number smaller.</p><p>For example:</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/zepKb/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/523d65cc-f02d-4299-a886-b064b3883966_1220x954.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/147ae06b-9041-4d8d-883b-528653ab5542_1220x1024.png&quot;,&quot;height&quot;:511,&quot;title&quot;:&quot;Benchmarks&quot;,&quot;description&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/zepKb/1/" width="730" height="511" frameborder="0" scrolling="no" loading="lazy"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><p>And that leads to perhaps my favourite lesson from this entire exercise:</p><blockquote><p><strong>An optimisation isn&#8217;t valuable simply because it makes something faster.</strong></p></blockquote><p>It is valuable when it improves the product <strong>without creating a worse trade-off somewhere else</strong>.</p><p>For a developer, that might mean not introducing complexity for a 2% gain.</p><p>For a founder, it might mean not doubling infrastructure costs to shave a few seconds off a workflow that users don&#8217;t actually care about.</p><p>And for a photographer using the product, it might mean accepting a slightly slower GPU if that gives us a more consistent verdict and lets us keep the economics sustainable.</p><p>The engineering work is therefore not simply:</p><blockquote><p><strong>Make it faster.</strong></p></blockquote><p>It is:</p><blockquote><p><strong>Make the right thing faster, at the right cost, without compromising what the product is supposed to do.</strong></p></blockquote><p>That distinction has probably been the most valuable outcome of this entire cold-start exercise.</p><div><hr></div><h1>9. Why aren&#8217;t we just keeping a GPU warm?</h1><p>This is probably the obvious question.</p><p>If cold starts are the problem, why not simply keep a GPU running?</p><p>Because infrastructure economics matter.</p><p>Today, Parjanya sees well under one cold start per day.</p><p>Most uploads are batches, which means hundreds of photographs (sometimes 500-1000 batches and multiple users) can share the cost of a single cold start.</p><p>Keeping a GPU running 24&#215;7 to eliminate a wait that happens occasionally isn&#8217;t obviously a better product decision.</p><p>There are several possible versions of a warm pool:</p><h3>Stopped pool</h3><p>Boot machines once, put the software and models on them, then stop them.</p><p>Starting one should take roughly 1.5&#8211;2.5 minutes rather than around four.</p><h3>Warm during working hours</h3><p>Keep one machine running during defined hours.</p><h3>Always on</h3><p>Keep one GPU running continuously.</p><p>Then the first verdict would mostly be limited to inference time &#8212; around a minute on a T4.</p><p>The last option is obviously the most expensive.</p><p>So we haven&#8217;t done it.</p><p>Yet.</p><p>What would change my mind?</p><p>Several cold starts per day.</p><p>Several accounts uploading regularly.</p><p>Faster user growth.</p><p>Users abandoning the product after their first upload.</p><p>Or a product promise that requires a genuinely fast first result.</p><p>In other words:</p><p><strong>The right infrastructure architecture depends on the workload, not on what looks technically elegant.</strong></p><div><hr></div><h1>10. There are bigger optimisations ahead</h1><p>The current work made the infrastructure we already have faster.</p><p>The next improvements require more fundamental changes.</p><p>One possibility is reordering the model instructions so that the reusable portion can be cached.</p><p>Today, much of the prompt comes after the photograph.</p><p>Because the photograph changes every time, the model cannot simply reuse everything.</p><p>Moving the stable instructions before the photograph could make much more of them cacheable.</p><p>But this needs to be tested carefully.</p><p>Even tiny numerical changes can move borderline verdicts.</p><p>So we would run the same verdict-agreement tests before shipping it.</p><div><hr></div><h2>What about vLLM?</h2><p>Another possibility is moving from the standard Python model runtime to a dedicated serving engine such as vLLM.</p><p>These systems are designed to make better use of GPUs by:</p><ul><li><p>interleaving requests,</p></li><li><p>managing model memory,</p></li><li><p>caching repeated prompt text,</p></li><li><p>and improving throughput.</p></li></ul><p>It is tempting to assume that this will automatically make Parjanya dramatically faster.</p><p>I don&#8217;t.</p><p>Our machines already analyse roughly one photograph per minute, and we overlap fetching the next photograph with analysing the current one.</p><p>So I expect a potential <strong>double-digit percentage improvement in photos per hour</strong>, rather than some magical 10&#215; transformation.</p><p>Before adopting it, I&#8217;d want to prove five things:</p><ol><li><p>Our exact vision-language model works correctly.</p></li><li><p>The 4-bit weights work correctly.</p></li><li><p>Throughput improves on identical photographs.</p></li><li><p>Verdicts remain consistent.</p></li><li><p>Cold-start time doesn&#8217;t get worse.</p></li></ol><p>The last one is particularly important.</p><p>A serving engine that makes inference faster but makes startup slower might not actually improve the experience.</p><div><hr></div><h1>11. And what about a hosted AI API?</h1><p>This is another obvious architectural option.</p><p>Send the photograph to a hosted model API.</p><p>No GPU cold starts.</p><p>No idle machines.</p><p>No GPU fleet management.</p><p>From a purely operational perspective, that sounds attractive.</p><p>But there is another consideration that matters much more for Parjanya.</p><p><strong>Photographers upload real work.</strong></p><p>A lot of it is unpublished client work.</p><p>Sometimes it is work covered by contractual obligations.</p><p>So &#8220;processed on infrastructure we control&#8221; is not merely an infrastructure preference for us.</p><p>It is part of the product promise.</p><p>A hosted API would mean sending photographs to another company.</p><p>That makes data handling the first question, not performance.</p><p>Even if that question were resolved, there are other trade-offs:</p><ul><li><p>per-call costs grow with volume,</p></li><li><p>external outages become part of our pipeline,</p></li><li><p>rate limits become another dependency,</p></li><li><p>and a provider could change its model and potentially change verdicts.</p></li></ul><p>I can see a hosted model eventually playing a role as a fallback for bursts or GPU shortages.</p><p>But I don&#8217;t see it replacing the infrastructure we control without a much stronger reason.</p><div><hr></div><h1>12. The less glamorous work underneath all of this</h1><p>There is also some groundwork we need before those bigger architectural changes become easy.</p><p>Today, the analysis code builds the model directly.</p><p>I&#8217;d rather have a clean interface:</p><p><strong>photograph + instructions &#8594; structured analysis</strong></p><p>Then today&#8217;s model becomes one backend.</p><p>A future serving engine becomes another.</p><p>A hosted API becomes another.</p><p>And we can run the same photographs through two backends and compare their verdicts.</p><p>Because for Parjanya, the backend is not the product.</p><p><strong>The verdict is the product.</strong></p><p>So a backend doesn&#8217;t get shipped simply because its benchmark is faster.</p><p>It has to preserve the behaviour that users depend on.</p><div><hr></div><h1>What I learned from this</h1><p>After spending two months inside this problem, these are the lessons I am taking away.</p><h3>1. Measure before optimising</h3><p>The &#8220;mysterious four minutes&#8221; wasn&#8217;t mysterious.</p><p>We simply weren&#8217;t measuring it.</p><p>A proper boot profile answered the question in a day.</p><h3>2. Make every optimisation explain itself in numbers</h3><p>Twice, a number that initially looked like a regression or an opportunity turned out to be a mixture of different GPU types.</p><p>We now compare before and after on the same hardware.</p><h3>3. Be willing to correct yourself publicly</h3><p>One of our early figures claimed <strong>221 seconds saved</strong>.</p><p>It was wrong.</p><p>We had omitted a stage that had become slower.</p><p>The actual saving was <strong>132 seconds</strong>.</p><p>We corrected the number.</p><p>I think that&#8217;s an important part of building in public.</p><p>The point isn&#8217;t to always have the right answer.</p><p>It&#8217;s to make the process visible enough that you can correct the wrong one.</p><h3>4. When the disk is the bottleneck, move less data</h3><p>We tried faster ways to move data.</p><p>The better solution was to have less data to move.</p><h3>5. Test the actual production system</h3><p>One version of our attention optimisation accidentally changed the vision part of the model as well, because of how the model library propagated configuration settings.</p><p>Our tests passed.</p><p>A short startup census caught the mistake on the first development boot.</p><p>We then added a guard that prevents the model from starting if any component unexpectedly falls back to the CPU.</p><p>That kind of defensive engineering isn&#8217;t glamorous.</p><p>But it is the difference between a benchmark and a reliable system.</p><h3>6. Speed and correctness are connected</h3><p>This was probably the biggest lesson.</p><p>A performance optimisation can change numerical behaviour.</p><p>Numerical behaviour can change a borderline classification.</p><p>And a classification can change what a photographer does with their work.</p><p>So from now on, every model performance change has two measurements:</p><p><strong>How much faster is it?</strong></p><p>and</p><p><strong>How often does it still give the same verdict?</strong></p><div><hr></div><h1>So what does this mean for someone using Parjanya?</h1><p>Practically, not much has changed in the workflow.</p><p>You upload your photographs.</p><p>You can close the browser and the analysis continues.</p><p>On a quiet day, the first verdict currently arrives roughly <strong>six to seven minutes after the upload finishes</strong>.</p><p>While the machines start, the gallery shows:</p><blockquote><p><strong>Warming up the AI analysis</strong></p></blockquote><p>After that, each machine processes roughly one photograph per minute, and larger batches get more machines.</p><p>Most importantly, new photographs now go through a more consistent analysis path, with the updated curation rules.</p><div><hr></div><h1>The bigger picture</h1><p>When I started this work, I thought the goal was simple:</p><p><strong>Make Parjanya faster.</strong></p><p>I ended up with a more nuanced definition.</p><p>The goal is not to make an AI system as fast as technically possible.</p><p>It is to find the right point on the curve between:</p><p><strong>speed &#215; cost &#215; consistency &#215; privacy &#215; product experience.</strong></p><p>For a young product, those trade-offs are very real.</p><p>I could make the first verdict faster by keeping GPUs running.</p><p>I could make inference faster by using more expensive hardware.</p><p>I could remove much of the infrastructure complexity by using a hosted model API.</p><p>But each of those choices moves a different part of the equation.</p><p>So for now, we&#8217;re taking the slightly less glamorous path:</p><p><strong>measure carefully, optimise what matters, keep the infrastructure under our control, and change architecture only when the workload justifies it.</strong></p><p>And perhaps the most satisfying outcome isn&#8217;t that we got from nine minutes to five.</p><p>It is that we now understand <em>why</em> those five minutes exist.</p><p>That makes the next five minutes much easier to attack.</p><div><hr></div><h2>Building in the open</h2><p>All of this work is tracked publicly.</p><p>The cold-start programme lives in our public tracker, and every release is documented in the release notes.</p><p><a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/49">https://github.com/JagadeeshRampam/parjanya-issues/issues/49</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_!BwCi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26d58da0-7251-4664-a2c7-efc5b6205067_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BwCi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26d58da0-7251-4664-a2c7-efc5b6205067_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!BwCi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26d58da0-7251-4664-a2c7-efc5b6205067_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!BwCi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26d58da0-7251-4664-a2c7-efc5b6205067_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!BwCi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26d58da0-7251-4664-a2c7-efc5b6205067_1672x941.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!BwCi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26d58da0-7251-4664-a2c7-efc5b6205067_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/26d58da0-7251-4664-a2c7-efc5b6205067_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1599771,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/218125985?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26d58da0-7251-4664-a2c7-efc5b6205067_1672x941.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_!BwCi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26d58da0-7251-4664-a2c7-efc5b6205067_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!BwCi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26d58da0-7251-4664-a2c7-efc5b6205067_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!BwCi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26d58da0-7251-4664-a2c7-efc5b6205067_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!BwCi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26d58da0-7251-4664-a2c7-efc5b6205067_1672x941.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><a href="https://parjanya.phagyul.ai/release-notes">https://parjanya.phagyul.ai/release-notes</a></p><p>If you&#8217;re a developer interested in GPU infrastructure, a photographer curious about what happens after you upload a shoot, or a founder working through the same uncomfortable trade-offs between <strong>cost, speed and reliability</strong>, I hope this was useful.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ahsu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 424w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 848w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1272w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png" width="2103" height="305" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:305,&quot;width&quot;:2103,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:825033,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/218125985?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1826709-c58d-41fa-b1eb-38a600903518_2103x748.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_!ahsu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 424w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 848w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1272w, https://substackcdn.com/image/fetch/$s_!ahsu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cf7ad7d-aa75-4aae-ac03-709eb0423cb5_2103x305.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p>I&#8217;m particularly interested in hearing from others who have solved similar cold-start problems differently.</p><p><strong>What would you like to see optimised next?</strong></p>]]></content:encoded></item><item><title><![CDATA[The Image Was Fine. Our Pipeline Wasn't.]]></title><description><![CDATA[How a 16-bit grayscale TIFF exposed a hidden failure in our preview pipeline&#8212;and why fixing one line of code wasn't enough.]]></description><link>https://blog.phagyul.ai/p/the-image-was-fine-our-pipeline-wasnt</link><guid isPermaLink="false">https://blog.phagyul.ai/p/the-image-was-fine-our-pipeline-wasnt</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Thu, 24 Sep 2026 06:11:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!H7nW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa783bfa-1030-426e-a85f-19867a95127f_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are bugs that announce themselves immediately.</p><blockquote><p>A service crashes.<br>A file refuses to open.<br>A test turns red.</p></blockquote><p>And then there are bugs that are much more dangerous: the system works exactly as designed, produces a perfectly reasonable answer, and is still completely wrong.</p><p>I recently ran into one of those while building <a href="https://parjanya.phagyul.ai/guide">Parjanya 2.0</a>, our image QA platform for professional photographers.</p><p>A photographer uploaded a batch of scanned medium-format negatives. Twenty-six images eventually turned out to be affected. Some were rejected as blank before they ever reached AI analysis. Others went through the pipeline and received what looked like perfectly plausible photographic criticism.</p><p>The interesting part wasn&#8217;t just the TIFF bug.</p><p>It was everything around it: how I found it, how the first hypothesis was wrong, how a correct rejection concealed an upstream defect, how two corrupted images escaped detection because they were <em>not quite blank enough</em>, and how fixing one line of code uncovered two more bugs waiting behind it.</p><p>That made this incident worth writing down. </p><div><hr></div><h2>The platform I was building</h2><p><a href="https://parjanya.phagyul.ai/guide">Parjanya 2.0</a> is designed around a simple idea: before asking an AI model to judge a photograph, I should first make sure I am actually giving it a photograph.</p><p>The platform ingests batches of images and runs each one through two stages.</p><p>The first is a fast technical gate. It doesn&#8217;t need a vision model. It checks whether the file can be decoded, whether its resolution is sane, whether it actually contains photographic content rather than a blank rectangle, and whether it is a duplicate.</p><p>Only after an image survives those checks does it reach the second stage, where a vision-language model evaluates things such as composition, sharpness, exposure and other characteristics that matter to a working photographer.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!a_90!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2acd76a-f164-4fbc-b9e9-90fe0ca380f2_1670x942.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!a_90!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2acd76a-f164-4fbc-b9e9-90fe0ca380f2_1670x942.png 424w, https://substackcdn.com/image/fetch/$s_!a_90!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2acd76a-f164-4fbc-b9e9-90fe0ca380f2_1670x942.png 848w, https://substackcdn.com/image/fetch/$s_!a_90!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2acd76a-f164-4fbc-b9e9-90fe0ca380f2_1670x942.png 1272w, https://substackcdn.com/image/fetch/$s_!a_90!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2acd76a-f164-4fbc-b9e9-90fe0ca380f2_1670x942.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!a_90!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2acd76a-f164-4fbc-b9e9-90fe0ca380f2_1670x942.png" width="1456" height="821" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a2acd76a-f164-4fbc-b9e9-90fe0ca380f2_1670x942.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:821,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1455122,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/217185600?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2acd76a-f164-4fbc-b9e9-90fe0ca380f2_1670x942.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_!a_90!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2acd76a-f164-4fbc-b9e9-90fe0ca380f2_1670x942.png 424w, https://substackcdn.com/image/fetch/$s_!a_90!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2acd76a-f164-4fbc-b9e9-90fe0ca380f2_1670x942.png 848w, https://substackcdn.com/image/fetch/$s_!a_90!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2acd76a-f164-4fbc-b9e9-90fe0ca380f2_1670x942.png 1272w, https://substackcdn.com/image/fetch/$s_!a_90!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2acd76a-f164-4fbc-b9e9-90fe0ca380f2_1670x942.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Most of the images we see are JPEGs and RAW camera files and supported 34 formats </p><p>Some are TIFFs.</p><p>And TIFF is one of those formats where the filename tells you much less than you think.</p><p>A TIFF can represent a surprisingly large number of combinations of bit depth, channels, byte order, tone conventions and other metadata.</p><p>This incident came from one particular combination:</p><div class="pullquote"><p><strong>16-bit + single-channel grayscale TIFF.</strong></p></div><h1>Chapter 1: The rejection was telling the truth</h1><p>The first signal was straightforward.</p><p>A batch of TIFFs was being rejected within seconds of upload, before any AI analysis ran.</p><p>That timing mattered.</p><p>Our technical gate was doing exactly what it was supposed to do: decode the image, check its dimensions and determine whether there was meaningful visual content.</p><p>The blank-frame detector uses image statistics such as luminance entropy and standard deviation. If both are sufficiently low, the image is considered blank and rejected before we spend GPU time on it.</p><p>Upon inspecting one of the rejected files and verified the source directly.</p><p>It was not blank.</p><p>It had a wide tonal range. The pixel data was fully populated. It was a perfectly legitimate photograph!</p><p>Then I ran our own preview-generation code against that exact file.</p><p>And there it was.</p><p>A completely white rectangle - blank frame.</p><p>The source image was fine.</p><p>Our preview was not.</p><p>The blank detector was measuring the preview, not the original. So from its perspective, the rejection was completely correct.</p><p>That distinction turned out to be the entire incident.</p><blockquote><p><strong>The gate wasn&#8217;t wrong about the preview. The preview was wrong about the photograph.</strong></p></blockquote><p>That is a particularly nasty class of bug.</p><p>A rejection with a technically correct reason can still be evidence of a failure upstream.</p><div><hr></div><h1>Chapter 2: 65,535 is not 255</h1><p>To understand what happened, I had to go back to two fairly basic imaging concepts: bit depth and channels.</p><p>A normal 8-bit image stores each pixel between 0 and 255.</p><p>A 16-bit image stores each pixel between 0 and 65,535.</p><p>That&#8217;s 256 times more possible tonal values.</p><p>You don&#8217;t need that precision because your monitor can display 65,536 individual shades.</p><p>You need it because the file is often an intermediate master.</p><p>That is particularly important in film scanning (archivals).</p><p>A photographer or archivist can scan a negative at 16-bit precision and preserve a tremendous amount of tonal information. The actual interpretation&#8212;shadow recovery, highlight adjustment, grading, dodging and burning&#8212;can happen later without throwing away information prematurely.</p><p>Then there are channels.</p><p>A colour image normally has three channels: red, green and blue.</p><p>A grayscale image needs only one.</p><p>That isn&#8217;t a limitation. It is the correct representation when there is no colour information.</p><p>So the file that broke our pipeline was not strange at all.</p><p>It was actually a very reasonable professional archival file:</p><p><strong>16-bit + 1-channel grayscale TIFF.</strong></p><p>In fact, the file carried an embedded profile named <strong>EPSON Gray &#8211; Gamma 2.2</strong>, along with metadata identifying the editing software used.</p><p>This looked exactly like the kind of file I should expect from a real scan-to-digital workflow.</p><p>And that was precisely why our assumption about &#8220;<strong>supported TIFF</strong>&#8221; wasn&#8217;t good enough.</p><div><hr></div><h1>Chapter 3: My first hypothesis was wrong</h1><p>My first thought was obvious:</p><p><strong>Maybe 16-bit TIFFs are the problem.</strong></p><p>Then production gave me the counterexample.</p><p>The same batch contained both:</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/zm7sW/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/85a7cbd2-972e-4ce4-b573-cbb51f32fa5e_1220x324.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3ee34c94-041f-4cfc-971c-b209080f92fc_1220x324.png&quot;,&quot;height&quot;:153,&quot;title&quot;:&quot;Created with Datawrapper&quot;,&quot;description&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/zm7sW/1/" width="730" height="153" frameborder="0" scrolling="no" loading="lazy"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><p>Same bit depth.</p><p>Same encoder.</p><p>Same photographer.</p><p>Same upload session.</p><p>The variable that changed was the channel count.</p><p>That immediately narrowed the problem down.</p><p>It wasn&#8217;t simply &#8220;16-bit TIFF.&#8221;</p><p>It was the combination:</p><p><strong>16-bit + single-channel grayscale.</strong></p><p>That was the first important lesson for me:</p><blockquote><p>When production gives you naturally occurring controlled experiments, use them.</p></blockquote><p>I didn&#8217;t need to invent a synthetic test case to prove that 16-bit wasn&#8217;t the problem. The customer&#8217;s batch had already done the experiment for me.</p><div><hr></div><h1>Chapter 4: The one-line conversion that wasn&#8217;t harmless</h1><p>Once I followed the image through the preview pipeline, the mechanism became surprisingly small.</p><p>Our imaging library automatically rescales 16-bit samples when it decodes certain multi-channel colour images.</p><p>For single-channel 16-bit data, however, it returned the raw 16-bit values.</p><p>The next step in our pipeline was an unconditional conversion to standard 8-bit RGB.</p><p>That conversion was safe for the image modes we had exercised.</p><p>It wasn&#8217;t safe for this one.</p><p>Instead of <strong>rescaling</strong> 16-bit values into the 8-bit range, it effectively <strong>clipped</strong> them.</p><p>Those two operations sound similar.</p><p>They are not.</p><p>What should happen is:</p><pre><code><code>16-bit 200    &#8594; 8-bit 1
16-bit 32768  &#8594; 8-bit 128
16-bit 65535  &#8594; 8-bit 255</code></code></pre><p>What actually happened was closer to:</p><pre><code><code>16-bit 200    &#8594; 8-bit 200
16-bit 256    &#8594; 8-bit 255
16-bit 65535  &#8594; 8-bit 255</code></code></pre><p>Everything above 255 was flattened to 255.</p><p>And 255 is white.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!H7nW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa783bfa-1030-426e-a85f-19867a95127f_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!H7nW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa783bfa-1030-426e-a85f-19867a95127f_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!H7nW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa783bfa-1030-426e-a85f-19867a95127f_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!H7nW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa783bfa-1030-426e-a85f-19867a95127f_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!H7nW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa783bfa-1030-426e-a85f-19867a95127f_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!H7nW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa783bfa-1030-426e-a85f-19867a95127f_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aa783bfa-1030-426e-a85f-19867a95127f_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;:1534168,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/217185600?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa783bfa-1030-426e-a85f-19867a95127f_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_!H7nW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa783bfa-1030-426e-a85f-19867a95127f_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!H7nW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa783bfa-1030-426e-a85f-19867a95127f_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!H7nW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa783bfa-1030-426e-a85f-19867a95127f_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!H7nW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faa783bfa-1030-426e-a85f-19867a95127f_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The arithmetic makes the severity obvious.</p><p>An 8-bit conversion preserves only 255 values below the maximum out of a possible 65,535.</p><p>That&#8217;s roughly <strong>0.39% of the original tonal range</strong>.</p><p>For a typical scanned negative using a broad portion of the 16-bit range, almost everything therefore became white.</p><p>The photograph hadn&#8217;t disappeared.</p><p>We had mathematically crushed it into a white rectangle.</p><div><hr></div><h1>Chapter 5: The bug was even more interesting than I first thought</h1><p>At this point I had an explanation for the obviously rejected images.</p><p>But something didn&#8217;t quite add up.</p><p>Two larger TIFFs in the same batch had apparently processed successfully.</p><p>That initially looked like evidence that the bug affected some narrower scanner-specific variant.</p><p>So I went back and measured them instead of trusting the earlier interpretation.</p><p>That changed the story.</p><p>They weren&#8217;t actually healthy.</p><p>They were also 16-bit single-channel grayscale files.</p><p>Their previews were approximately <strong>98% and 96% solid white</strong>.</p><p>They had simply escaped our blank-frame detector.</p><p>Why?</p><p>Our blank check uses two conditions: low entropy <em>and</em> low variance.</p><p>Those two images had slightly more surviving shadow information, because they originated from digital captures converted to black-and-white rather than from analog film scans.</p><p>That tiny amount of surviving information was enough to push their variance above the rejection threshold.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wk6x!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75b06d81-a075-4ddf-906b-2596b37339a1_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wk6x!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75b06d81-a075-4ddf-906b-2596b37339a1_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!wk6x!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75b06d81-a075-4ddf-906b-2596b37339a1_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!wk6x!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75b06d81-a075-4ddf-906b-2596b37339a1_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!wk6x!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75b06d81-a075-4ddf-906b-2596b37339a1_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!wk6x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75b06d81-a075-4ddf-906b-2596b37339a1_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/75b06d81-a075-4ddf-906b-2596b37339a1_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;:1596225,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/217185600?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75b06d81-a075-4ddf-906b-2596b37339a1_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_!wk6x!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75b06d81-a075-4ddf-906b-2596b37339a1_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!wk6x!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75b06d81-a075-4ddf-906b-2596b37339a1_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!wk6x!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75b06d81-a075-4ddf-906b-2596b37339a1_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!wk6x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75b06d81-a075-4ddf-906b-2596b37339a1_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>So the images were not rejected.</p><p>They went to the AI stage.</p><p>And the AI did exactly what I had asked it to do.</p><p>It looked at a nearly blank white rectangle and produced a confident photographic assessment&#8212;essentially describing it as severely overexposed.</p><p>That was much more concerning than a simple rejection.</p><p>A visibly broken file gets investigated.</p><p>A corrupted file that passes the gate and receives a plausible AI explanation can look completely legitimate.</p><p>The original automated log suggested 24 affected images.</p><p>The actual number was <strong>26</strong>.</p><p>Two corrupted images had successfully made it far enough downstream to receive convincing-looking AI output.</p><p>That changed how I thought about remediation.</p><p>I couldn&#8217;t say:</p><blockquote><p>&#8220;Find all the files that were rejected and fix them.&#8221;</p></blockquote><p>I had to say:</p><blockquote><p><strong>&#8220;Find every file that has the defect.&#8221;</strong></p></blockquote><p>The difference sounds subtle.</p><p>Operationally, it is enormous.</p><p>So we identified remediation candidates using the actual container metadata&#8212;bit depth and channel count&#8212;not the symptom produced by the broken pipeline.</p><div><hr></div><h1>Chapter 6: The obvious fix took ten minutes. Shipping it took three days.</h1><p>The immediate fix looked almost embarrassingly simple:</p><p><strong>Rescale the 16-bit values to 8-bit before converting to RGB.</strong></p><p>I could write that in minutes.</p><p>I deliberately didn&#8217;t ship it.</p><p>Because once you touch a central image-conversion path, the question isn&#8217;t:</p><blockquote><p>&#8220;Does this fix the file that broke?&#8221;</p></blockquote><p>The question is:</p><blockquote><p><strong>&#8220;What else passes through this code?&#8221;</strong></p></blockquote><p>So I built synthetic files covering sixteen different variants.</p><p>Different byte orders.</p><p>Inverted-tone scans.</p><p>Packed sub-byte formats.</p><p>Signed samples.</p><p>Floating-point samples.</p><p>Four-channel print files.</p><p>Different combinations of formats that a real imaging library can encounter.</p><p>And that exercise immediately found two more problems.</p><div><hr></div><h1>Chapter 7: Fixing the bug almost created a photographic negative</h1><p>Some scanners use an inverted tone convention.</p><p>In those files, zero can represent white rather than black.</p><p>At 8-bit depth, the imaging library was silently correcting for that.</p><p>At 16-bit depth, it wasn&#8217;t.</p><p>Previously, our clipping bug had destroyed the image so completely that this difference was invisible.</p><p>Once I fixed the clipping, it suddenly mattered.</p><p>A naive fix would have transformed some of those scans into photographic negatives.</p><p>In other words:</p><p><strong>the first bug had been masking the second bug.</strong></p><p>That is one of the reasons I have become much more cautious about declaring a conversion problem &#8220;fixed&#8221; after a single successful test.</p><p>Removing one failure mode can expose another one that was hiding behind it.</p><div><hr></div><h1>Chapter 8: Then I found a metadata bug hiding somewhere else</h1><p>The next surprise wasn&#8217;t even in the conversion code.</p><p>Our orientation-correction step creates a fresh image object.</p><p>That fresh object didn&#8217;t retain all of the original technical metadata.</p><p>That mattered because the fix needed to know information such as bit depth and tone convention.</p><p>If I inspected that metadata early enough in the pipeline, it was available.</p><p>If I inspected it after the orientation step, it was gone.</p><p>This was a useful reminder that image-processing pipelines aren&#8217;t just a sequence of transformations.</p><p>They are also a sequence of <strong>information loss</strong>.</p><p>Every transformation potentially changes:</p><ul><li><p>pixel values</p></li><li><p>dimensions</p></li><li><p>colour space</p></li><li><p>metadata</p></li><li><p>orientation</p></li><li><p>bit depth</p></li><li><p>tone interpretation</p></li></ul><p>And once information disappears, a later stage can&#8217;t magically recover it.</p><p>So the correct place to make a decision isn&#8217;t necessarily where the decision is easiest to implement.</p><p>It is where the required information still exists.</p><div><hr></div><h1>Chapter 9: I rejected an attractive shortcut</h1><p>There was another tempting idea.</p><p>TIFF files can contain metadata describing the brightest value actually used in the image.</p><p>It seemed reasonable to use that value as the denominator when converting 16-bit to 8-bit.</p><p>Why scale against a theoretical maximum if I know the maximum value actually present?</p><p>Because that would subtly change the photograph.</p><p>Imagine a perfectly normal photograph whose brightest pixel is 55,000 rather than 65,535.</p><p>Scaling against 55,000 would brighten the entire image.</p><p>That isn&#8217;t a bit-depth conversion anymore.</p><p>It is an automatic contrast adjustment.</p><p>And the photographer didn&#8217;t ask me to change their exposure.</p><p>So we deliberately rejected that shortcut.</p><p>The conversion is based on the <strong>declared bit depth</strong>, not whatever happened to be present in one particular image.</p><p>I also locked that decision into a regression test.</p><div><hr></div><h1>Chapter 10: The better fix wasn&#8217;t just a better conversion</h1><p>The most durable change I made wasn&#8217;t actually the 16-bit fix.</p><p>It was adding a self-checking preview writer.</p><p>Instead of assuming:</p><blockquote><p>&#8220;The conversion function returned successfully, therefore the preview is good.&#8221;</p></blockquote><p>the preview writer now compares meaningful tonal variation before and after the transformation.</p><p>If a photograph goes in with substantial tonal variation and comes out essentially flat, the preview generation itself fails.</p><p>It refuses to save the preview as if everything succeeded.</p><p>That distinction is important.</p><p>The system doesn&#8217;t need to know that the bug is TIFF.</p><p>It doesn&#8217;t need to know that the input is 16-bit.</p><p>It doesn&#8217;t need to know about grayscale channels.</p><p>It only needs to recognise something more fundamental:</p><p><strong>a photograph went in, and almost nothing came out.</strong></p><p>On our known-good conversions, the input/output variation ratio clustered around 1.0.</p><p>The broken examples were 0.35 or lower.</p><p>The original file that started this investigation was exactly 0.00.</p><p>That gives us a generic trip-wire for future bugs we haven&#8217;t imagined yet.</p><p>And that is much more valuable than a test that only knows about today&#8217;s failure.</p><div><hr></div><h1>Chapter 11: The AI wasn&#8217;t the problem. The pipeline was.</h1><p>There is another lesson here that I think matters beyond image processing.</p><p>It would have been easy to describe this as an &#8220;AI quality&#8221; problem.</p><p>It wasn&#8217;t.</p><p>The VLM was downstream of a corrupted image.</p><p>It received a nearly blank frame and produced a plausible interpretation of what it saw.</p><p>The failure happened earlier.</p><p>That distinction becomes increasingly important as we build systems where AI is only one component in a much larger automated pipeline.</p><p>If the data entering the model is wrong, a more capable model doesn&#8217;t necessarily make the system safer.</p><p>It may make the failure <strong>more convincing</strong>.</p><p>That is something I now think about whenever I design an automated workflow:</p><blockquote><p><strong>Before asking whether the model&#8217;s answer is correct, ask whether the model received the thing I thought I gave it.</strong></p></blockquote><div><hr></div><h1>Chapter 12: The second AI session had already fixed it</h1><p>There was one more twist.</p><p>By the time the fix was deployed and I was ready to reprocess the affected images, I discovered that the reprocessing had apparently already happened.</p><p>Another session had been working on the same incident in parallel.</p><p>Nothing had explicitly told me it was complete.</p><p>It was just... done.</p><p>The tempting responses were:</p><ol><li><p>Trust that it was already completed.</p></li><li><p>Run it again just to be safe.</p></li></ol><p>I didn&#8217;t want to do either.</p><p>Trusting silence isn&#8217;t verification.</p><p>Blindly rerunning a potentially expensive job isn&#8217;t verification either.</p><p>So I checked the artefact.</p><p>First, I ran the reprocessing tool in dry-run mode.</p><p>It still identified the same affected files from their actual container metadata, and all of them now showed as successfully processed.</p><p>Then I checked the record store independently.</p><p>The timestamps lined up with the deployment window.</p><p>Finally, the infrastructure logs showed a burst of preview-generation activity immediately after deployment that was much higher than normal traffic.</p><p>Three independent signals.</p><p>Only then did I consider the remediation complete.</p><p>This is becoming increasingly relevant as engineering moves from one developer sitting in one terminal to multiple people&#8212;and increasingly multiple AI agents&#8212;working concurrently on the same system.</p><p>When two workers might be acting on the same incident, the right question isn&#8217;t:</p><blockquote><p>&#8220;Did someone say they did it?&#8221;</p></blockquote><p>It is:</p><blockquote><p><strong>&#8220;Can I independently verify the artifact that proves it happened?&#8221;</strong></p></blockquote><div><hr></div><h1>What actually happened?</h1><p>The final numbers made the incident much clearer.</p><p>Before the fix:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UwA7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f9ea224-fea5-455a-8a0c-1ebcc01ea64c_1240x407.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UwA7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f9ea224-fea5-455a-8a0c-1ebcc01ea64c_1240x407.png 424w, https://substackcdn.com/image/fetch/$s_!UwA7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f9ea224-fea5-455a-8a0c-1ebcc01ea64c_1240x407.png 848w, https://substackcdn.com/image/fetch/$s_!UwA7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f9ea224-fea5-455a-8a0c-1ebcc01ea64c_1240x407.png 1272w, https://substackcdn.com/image/fetch/$s_!UwA7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f9ea224-fea5-455a-8a0c-1ebcc01ea64c_1240x407.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!UwA7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f9ea224-fea5-455a-8a0c-1ebcc01ea64c_1240x407.png" width="1240" height="407" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4f9ea224-fea5-455a-8a0c-1ebcc01ea64c_1240x407.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:407,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:52456,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/217185600?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71bf26cd-fbaf-4c4a-95fe-c90bc1c6a93c_1240x524.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_!UwA7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f9ea224-fea5-455a-8a0c-1ebcc01ea64c_1240x407.png 424w, https://substackcdn.com/image/fetch/$s_!UwA7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f9ea224-fea5-455a-8a0c-1ebcc01ea64c_1240x407.png 848w, https://substackcdn.com/image/fetch/$s_!UwA7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f9ea224-fea5-455a-8a0c-1ebcc01ea64c_1240x407.png 1272w, https://substackcdn.com/image/fetch/$s_!UwA7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f9ea224-fea5-455a-8a0c-1ebcc01ea64c_1240x407.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The customer&#8217;s batch returned to a normal curation mix: roughly 60% accepted and 40% rejected for genuine photographic reasons such as blur or exposure.</p><p>Most importantly, <strong>the original source files were never damaged</strong>.</p><p>The corruption existed entirely in the generated previews.</p><p>So remediation was simply a matter of generating those previews correctly.</p><p>The entire cycle&#8212;from report to root cause, fix, deployment, verification and closure&#8212;took three days.</p><div><hr></div><h1>What I would tell another engineering team</h1><h3>1. &#8220;Supported&#8221; and &#8220;decodable&#8221; are not the same thing</h3><p>Putting TIFF on a supported-format list doesn&#8217;t mean you&#8217;ve supported every real-world TIFF.</p><p>TIFF is a container.</p><p>Inside that container are many combinations of properties that your pipeline may never have exercised.</p><p>A format can be technically supported and operationally untested.</p><p>That gap is where this bug lived.</p><h3>2. A correct rejection doesn&#8217;t prove the system is working</h3><p>Our blank detector was correct.</p><p>The preview it examined was wrong.</p><p>When an automated check reports a technically accurate failure, I now trace upstream before assuming the input is at fault.</p><p>The last check in a pipeline can be completely correct while everything feeding it is broken.</p><h3>3. Remediate based on the defect, not the symptom</h3><p>The two images that escaped our rejection logic would have remained corrupted if I had searched only for rejected files.</p><p>I had to identify the actual format signature:</p><p><strong>16-bit + single-channel grayscale.</strong></p><p>The symptom was &#8220;blank.&#8221;</p><p>The defect was something else.</p><h3>4. The blast radius of a fix can be larger than the blast radius of the bug</h3><p>The original incident was about clipping.</p><p>Testing the fix uncovered inverted-tone behaviour and metadata loss.</p><p>If I had stopped after the first successful test, I would have introduced new image corruption while fixing the old corruption.</p><h3>5. Build checks that don&#8217;t know what tomorrow&#8217;s bug looks like</h3><p>A format-specific regression test protects against known failures.</p><p>A structural fidelity check can catch unknown ones.</p><p>That is why I like the idea of measuring the transformation itself:</p><p><strong>Did meaningful image information survive the operation?</strong></p><h3>6. Verify the artefact, not the silence</h3><p>Whether the other worker is a colleague on another shift or another AI session running in parallel, &#8220;nothing complained&#8221; is not evidence of completion.</p><p>Look at the output.</p><p>Look at the records.</p><p>Look at an independent signal.</p><p>Then close the incident.</p><div><hr></div><h1>The broader lesson</h1><p>I started this investigation thinking I had a TIFF problem.</p><p>What I actually found was a systems problem.</p><p>A professional photographer supplied a perfectly legitimate archival file.</p><p>Our software accepted the format.</p><p>The file decoded.</p><p>The preview-generation function returned successfully.</p><p>The automated quality gate correctly detected a blank image.</p><p>The AI then produced a plausible assessment on two corrupted images.</p><p>Every individual component behaved reasonably according to the information it had.</p><p>And yet the system as a whole was wrong.</p><p>That&#8217;s the part I find most interesting.</p><p>As we build more automated products, especially products where traditional software, image processing and AI models sit in the same pipeline, I think we need to become much more interested in <strong>fidelity between stages</strong>.</p><p>Not just:</p><blockquote><p>Did the function return successfully?</p></blockquote><p>But:</p><blockquote><p>Did the meaning survive the transformation?</p></blockquote><p>For Parjanya, that means being increasingly careful about the long tail of real-world photography formats.</p><p>For developers, it means testing the combinations that production will eventually discover for you if you don&#8217;t.</p><p>For photographers, it is a reminder that &#8220;supported format&#8221; doesn&#8217;t necessarily mean &#8220;faithfully interpreted format.&#8221;</p><p>And for founders, it is a reminder that automation doesn&#8217;t remove responsibility.</p><p>It moves the responsibility upstream.</p><p>The system needs to know not only when it can produce an answer, but when it should <strong>refuse to trust its own answer</strong>.</p><p>That is probably the more important fix I took away from this incident.</p><div><hr></div><p><em><a href="https://parjanya.phagyul.ai/guide">Parjanya</a> is the image QA platform we&#8217;re building as part of <a href="https://phagyul.ai/">Phagyul</a>  eco-system for professional photographers. If you&#8217;re working on heterogeneous image ingestion, archival photography, AI-assisted review pipelines, or reliability problems in AI-driven systems, I&#8217;d love to compare notes.</em></p><div><hr></div><p><strong>Related engineering incident:</strong> <a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/87?utm_source=chatgpt.com">GitHub Issue #87 &#8212; 16-bit grayscale TIFF preview corruption</a></p><h6><sub><span data-color="#d0e0e3" style="color: rgb(208, 224, 227);">&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;</span></sub></h6><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Cq54!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8f20920-b99e-475d-a448-1d3ae5722a41_2059x309.png 424w, https://substackcdn.com/image/fetch/$s_!Cq54!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8f20920-b99e-475d-a448-1d3ae5722a41_2059x309.png 848w, https://substackcdn.com/image/fetch/$s_!Cq54!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8f20920-b99e-475d-a448-1d3ae5722a41_2059x309.png 1272w, https://substackcdn.com/image/fetch/$s_!Cq54!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8f20920-b99e-475d-a448-1d3ae5722a41_2059x309.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Cq54!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8f20920-b99e-475d-a448-1d3ae5722a41_2059x309.png" width="2059" height="309" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f8f20920-b99e-475d-a448-1d3ae5722a41_2059x309.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:309,&quot;width&quot;:2059,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:820141,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/217185600?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb56df41f-25fd-4bc7-9836-e7088884b322_2103x748.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_!Cq54!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8f20920-b99e-475d-a448-1d3ae5722a41_2059x309.png 424w, https://substackcdn.com/image/fetch/$s_!Cq54!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8f20920-b99e-475d-a448-1d3ae5722a41_2059x309.png 848w, https://substackcdn.com/image/fetch/$s_!Cq54!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8f20920-b99e-475d-a448-1d3ae5722a41_2059x309.png 1272w, https://substackcdn.com/image/fetch/$s_!Cq54!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8f20920-b99e-475d-a448-1d3ae5722a41_2059x309.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[Parjanya 2.0 is open to everyone ]]></title><description><![CDATA[Release notes from seven weeks of closed beta: 18,884 images, 18+ formats, 20+ photographers, and what they contributed.]]></description><link>https://blog.phagyul.ai/p/parjanya-20-is-open-to-everyone</link><guid isPermaLink="false">https://blog.phagyul.ai/p/parjanya-20-is-open-to-everyone</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Mon, 14 Sep 2026 05:28:09 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Bsi_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On 27 July we quietly opened Parjanya 2.0 to a small group of photographers and asked them to do one thing: upload real shoots, not portfolios, and tell us and looked for their feedback and how they would wanted the application to be. Twenty-plus people took us up on it: wildlife, nature, landscape and architecture photographers, from working professionals to few who bought their first camera this year and mobile photographer. They brought 1,400-frame safari mornings, bracketed dawns, archival film scans and RAW from bodies our decoder had never met. By this weekend the pipeline had enriched <strong>18,884 images across more than 18 file formats</strong> for that group.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Bsi_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Bsi_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.png 424w, https://substackcdn.com/image/fetch/$s_!Bsi_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.png 848w, https://substackcdn.com/image/fetch/$s_!Bsi_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.png 1272w, https://substackcdn.com/image/fetch/$s_!Bsi_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Bsi_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.png" width="1456" height="816" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:816,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:99914,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/215603782?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.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_!Bsi_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.png 424w, https://substackcdn.com/image/fetch/$s_!Bsi_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.png 848w, https://substackcdn.com/image/fetch/$s_!Bsi_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.png 1272w, https://substackcdn.com/image/fetch/$s_!Bsi_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8b579a5-b61b-416f-b0c1-c33966c57834_1456x816.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Today it is open to everyone. This post is the release notes: what Parjanya does, who tested it and what they found, everything that changed between the July baseline and now, and what is coming next. The engineering detail is here too, because this blog has always been the place for it.</p><h2><strong>What Parjanya does, in two passes</strong></h2><p>You drop a folder or files from your card or hard drive straight into the browser, and the files go from the browser directly into private storage over signed, resumable transfers. The moment the upload says complete you can close your browser or session: the analysis picks the work up on its own, and every upload and every verdict is recorded as a replayable intent, so nothing is lost to a dropped connection or a busy GPU. (The upload path and the reconciliation model behind it, TBIE, in-house research paper successfully verified for our usecase and evolved and tested for 18+ usecases.) Parjanya makes fast previews from every file (majority is RAW files across DSLR, mirrorless, mobile phones and Analog converted to Digital) and then checks each frame twice, in a fixed order.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xnYa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39869bda-325b-4585-964b-06d6f29c0549_960x540.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xnYa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39869bda-325b-4585-964b-06d6f29c0549_960x540.gif 424w, https://substackcdn.com/image/fetch/$s_!xnYa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39869bda-325b-4585-964b-06d6f29c0549_960x540.gif 848w, https://substackcdn.com/image/fetch/$s_!xnYa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39869bda-325b-4585-964b-06d6f29c0549_960x540.gif 1272w, https://substackcdn.com/image/fetch/$s_!xnYa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39869bda-325b-4585-964b-06d6f29c0549_960x540.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xnYa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39869bda-325b-4585-964b-06d6f29c0549_960x540.gif" width="960" height="540" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/39869bda-325b-4585-964b-06d6f29c0549_960x540.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:540,&quot;width&quot;:960,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:988167,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/215603782?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39869bda-325b-4585-964b-06d6f29c0549_960x540.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xnYa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39869bda-325b-4585-964b-06d6f29c0549_960x540.gif 424w, https://substackcdn.com/image/fetch/$s_!xnYa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39869bda-325b-4585-964b-06d6f29c0549_960x540.gif 848w, https://substackcdn.com/image/fetch/$s_!xnYa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39869bda-325b-4585-964b-06d6f29c0549_960x540.gif 1272w, https://substackcdn.com/image/fetch/$s_!xnYa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39869bda-325b-4585-964b-06d6f29c0549_960x540.gif 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><ul><li><p><strong>Pass one is a technical gate.</strong> Cheap, strict, and deliberately narrow: unreadable or damaged files, images whose pixel size disagrees with what the file claims, blank frames, near-solid exposures (a frame is set aside only when almost every pixel is pure white or pure black, so brackets and silhouettes pass), duplicates by perceptual fingerprint (frames within ten seconds on the same body are a burst, never duplicates), and screenshots or exports in formats no camera writes will be filtered out. Anything set aside lands in Skip with the reason attached. Nothing is deleted.</p></li><li><p><strong>Pass two is VLM enrichment.</strong> A vision-language model running on our own GPUs reads the frame and writes what you see on the detail page: what the photo is doing, how it is composed, what is holding it back and how strongly, plus the tags search runs on. A deterministic rule engine turns those findings into <strong>Keeper, Review or Skip</strong> with the reason attached. There is no score out of ten, on purpose: the same findings give the same verdict every time. (our v2.0 major change proved score engine doesn&#8217;t hold true and a deterministic rule engine does the best for our usecase)</p></li></ul><p>You curate in a three-tab gallery where any verdict can be overruled, search the shoot in your own words (&#8221;leopard in dappled light&#8221;, &#8220;long exposure, silky water&#8221;, &#8220;symmetry, blue hour&#8221;), and after 500 uploads you get <strong>Parjanya Vision</strong>: a report card written like a coach rather than a mark sheet.</p><h2><strong>The people who tested it</strong></h2><p>The pilot group was small enough that every one of them changed something. A wildlife shooter pressed Stop on a 479-image batch expecting a pause; that single click is why Pause and Resume exist. A documentary photographer was first to point out that a Review/Skip line drawn only on technique penalises intentional motion and grain, which is now an open design question on the tracker (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/58">#58</a>). Someone on their first camera uploaded iPhone photos that were accepted and never analysed. An archivist uploaded 16-bit grayscale scans that came back as blank white frames(<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/87">#87</a>). A landscape photographer with a body released this year sent RAW files our decoder had never seen, and they came back in false colour until it learned to fall back to the camera&#8217;s own embedded preview. And a mix of legacy camera bodies, manual lens and more.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SrDU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f849f63-c83a-43fd-8149-6da956264913_1456x816.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SrDU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f849f63-c83a-43fd-8149-6da956264913_1456x816.png 424w, https://substackcdn.com/image/fetch/$s_!SrDU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f849f63-c83a-43fd-8149-6da956264913_1456x816.png 848w, https://substackcdn.com/image/fetch/$s_!SrDU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f849f63-c83a-43fd-8149-6da956264913_1456x816.png 1272w, https://substackcdn.com/image/fetch/$s_!SrDU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f849f63-c83a-43fd-8149-6da956264913_1456x816.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!SrDU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f849f63-c83a-43fd-8149-6da956264913_1456x816.png" width="1456" height="816" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4f849f63-c83a-43fd-8149-6da956264913_1456x816.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:816,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:141680,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/215603782?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f849f63-c83a-43fd-8149-6da956264913_1456x816.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_!SrDU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f849f63-c83a-43fd-8149-6da956264913_1456x816.png 424w, https://substackcdn.com/image/fetch/$s_!SrDU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f849f63-c83a-43fd-8149-6da956264913_1456x816.png 848w, https://substackcdn.com/image/fetch/$s_!SrDU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f849f63-c83a-43fd-8149-6da956264913_1456x816.png 1272w, https://substackcdn.com/image/fetch/$s_!SrDU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f849f63-c83a-43fd-8149-6da956264913_1456x816.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Several of the pilot group are credited on the public tracker against the issues they raised; where someone preferred to stay unnamed, the issue says &#8220;pilot feedback&#8221; and nothing more. The onboarding guide itself, the ten-minute walkthrough new users get today, was recommended by one of the pilot experts.</p><p>Thank you, all of you. The list of fixes below is mostly your list. </p><p><a href="https://github.com/JagadeeshRampam/parjanya-issues/issues">https://github.com/JagadeeshRampam/parjanya-issues/issues</a></p><h2><strong>What changed since the July baseline</strong></h2><p>The v2.0.0 baseline was cut on 11 July after a 12,000-image validation run. Between then and today, 34 items on the public tracker were closed. Grouped by what you will notice:</p><h3><strong>Uploads and formats</strong></h3><ul><li><p><strong>iPhone photos process now.</strong> HEIC and HEIF were on the supported list and were accepted at upload, then stranded silently with no preview and no analysis. The decoder library was installed the whole time; the one line that registers it with the imaging library had been lost in a refactor. Fixed and verified on real iPhone uploads (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/40">#40</a>).</p></li><li><p><strong>16-bit grayscale scans no longer come back white.</strong> Single-channel 16-bit TIFFs were clipped to solid white during preview generation and then, correctly, set aside as blank. The fix rescales by bit depth and validates every preview it writes. All 28 affected images were reprocessed (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/87">#87</a>).</p></li><li><p><strong>Canon CR3 previews lost their magenta cast and dark border</strong> (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/16">#16</a>).</p></li><li><p><strong>Filenames with spaces render previews again</strong> (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/69">#69</a>), and camera and lens names no longer carry trailing padding from fixed-width metadata fields, which had been splitting one lens into two entries in filters (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/48">#48</a>).</p></li><li><p><strong>Upload progress no longer flashes &#8220;Uploading: 0&#8221;</strong> mid-transfer (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/3">#3</a>), and switching accounts in the same tab no longer shows the previous account&#8217;s upload bar (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/33">#33</a>).</p></li><li><p><strong>When an upload is blocked</strong>, by a trial cap or an account hold, the app now says why and what to do, instead of a generic error (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/24">#24</a>).</p></li></ul><h3><strong>Processing you can control</strong></h3><ul><li><p><strong>Pause and Resume.</strong> Stop was permanent, and a photographer found that out on a 479-image batch. Pause parks queued work and Resume picks it up exactly where it left off; a frame already being analysed when you pause finishes and keeps its result (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/36">#36</a>). Stop still exists and now sticks end to end, including for work already in flight (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/32">#32</a>).</p></li><li><p><strong>&#8220;Warming up the AI analysis.&#8221;</strong> The GPU fleet starts on demand. When it is starting, the gallery now says so, so a cold start reads as a cold start and not as a broken product (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/62">#62</a>).</p></li><li><p><strong>Screenshots are turned away before they reach the GPU.</strong> Nine screenshots uploaded in August all passed the technical checks and three were accepted as good photographs. A metadata gate now rejects non-photographic content first (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/64">#64</a>).</p></li></ul><h3><strong>Reading the analysis</strong></h3><ul><li><p><strong>Critique and improvements are two cards now.</strong> The critique is served exactly as written. The one or two actions worth taking were previously the last sentence of an italic paragraph most readers had stopped reading; they are now their own card, and they never repeat what the critique already said (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/93">#93</a>).</p></li><li><p><strong>Burst groups show a per-frame breakdown</strong> when the frames in a burst got different verdicts (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/1">#1</a>).</p></li><li><p><strong>The gallery badge showed &#8220;Pending&#8221; for every auto-curated image</strong> because two parts of the system spelled the verdict differently. Fixed (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/90">#90</a>).</p></li></ul><h3><strong>Gallery and search</strong></h3><ul><li><p><strong>Newest first.</strong> The gallery was not listing your newest uploads first, which meant your own upload could be invisible to you. It reads from a recency index now (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/66">#66</a>), and the three tabs agree on what &#8220;newest&#8221; means (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/68">#68</a>).</p></li><li><p><strong>Semantic re-ranking</strong> using SigLIP 2 image embeddings is integrated behind a flag, and search now says visibly when it has fallen back to keyword ranking (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/28">#28</a>, <a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/30">#30</a>). Content filters for scene, lighting and mood are still hidden until every image carries those tags (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/72">#72</a>, <a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/25">#25</a>).</p></li></ul><h3><strong>Parjanya Vision</strong></h3><ul><li><p><strong>The report card shipped on 9 September.</strong> It started life as a per-shoot summary idea (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/85">#85</a>) and became a tenant-wide card: what you shoot, which camera bodies and formats, how far you zoom, where your Review pile clusters, how you curate (rescued versus demoted), and what to try. Every rate travels with its count. Copy is coach voice by rule; there is a test that fails the build if words like <em>mistake</em> or <em>grade</em> appear (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/98">#98</a>).</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!prCr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3819019d-0e62-469c-a181-0da48271d4d3_1456x816.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!prCr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3819019d-0e62-469c-a181-0da48271d4d3_1456x816.png 424w, https://substackcdn.com/image/fetch/$s_!prCr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3819019d-0e62-469c-a181-0da48271d4d3_1456x816.png 848w, https://substackcdn.com/image/fetch/$s_!prCr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3819019d-0e62-469c-a181-0da48271d4d3_1456x816.png 1272w, https://substackcdn.com/image/fetch/$s_!prCr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3819019d-0e62-469c-a181-0da48271d4d3_1456x816.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!prCr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3819019d-0e62-469c-a181-0da48271d4d3_1456x816.png" width="1456" height="816" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3819019d-0e62-469c-a181-0da48271d4d3_1456x816.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:816,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:132258,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/215603782?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3819019d-0e62-469c-a181-0da48271d4d3_1456x816.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_!prCr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3819019d-0e62-469c-a181-0da48271d4d3_1456x816.png 424w, https://substackcdn.com/image/fetch/$s_!prCr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3819019d-0e62-469c-a181-0da48271d4d3_1456x816.png 848w, https://substackcdn.com/image/fetch/$s_!prCr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3819019d-0e62-469c-a181-0da48271d4d3_1456x816.png 1272w, https://substackcdn.com/image/fetch/$s_!prCr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3819019d-0e62-469c-a181-0da48271d4d3_1456x816.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><ul><li><p>Two same-day fixes after the first photographers opened it: bars that overflowed their card, and a horizontal fill bar that read like a progress meter for what is really two counts being compared. It is a vertical bar chart now (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/99">#99</a>).</p></li></ul><h3><strong>Account, trial and email</strong></h3><ul><li><p><strong>Sign-up provisions correctly</strong> (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/22">#22</a>) and confirmation codes deliver (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/23">#23</a>), which sounds like table stakes and was the last launch dependency to close.</p></li><li><p><strong>Every account email exists now</strong>: three days before a trial ends, the day it ends, a follow-up a week later, when you are at 90% of a cap, when a cap is reached, and one for every action we take on an account, including a past-tense notice after a deletion completes (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/88">#88</a>, <a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/89">#89</a>, <a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/104">#104</a>).</p></li></ul><h2><strong>Where your photos live</strong></h2><p>Confidently, because it was audited before launch: your originals go from your browser straight into private, encrypted storage in Mumbai, in a space that belongs only to your account, with public access blocked at the bucket level and every connection over HTTPS. Every request is checked against your signed-in identity before it touches a record; there is no path from one photographer&#8217;s library to another&#8217;s. Every access to stored photos is written to an audit trail with alarms on any human or unexpected access. The vision model runs on GPUs we operate, so your photos are never sent to a third-party AI service and are never used to train models. And nothing is deleted by us: when a trial ends, uploads pause and everything already there stays readable and downloadable.</p><h2><strong>Search, in your own words</strong></h2><p>Search reads the critique, the composition notes and the closed-vocabulary tags the model writes for every frame (subject, scene, lighting, mood, dominant colours), so queries like <em>elephant herd at a waterhole, backlit</em>, <em>dew on a spider web</em>, <em>ridgeline at dawn, layered haze</em> or <em>stairwell, geometric shadows</em> work today. Two more pieces are built and switching on as the whole catalogue gets its tags and embeddings: filter chips for scene, lighting and mood, and a look-alike mode that ranks by visual similarity using SigLIP 2 image embeddings (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/11">#11</a>, <a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/25">#25</a>, <a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/72">#72</a>).</p><h2><strong>Three things the pilot taught us</strong></h2><p><strong>1. Stop is not Pause, and a UI should know the difference.</strong> The 479-image incident was not a bug; Stop did what it said. The bug was offering only an irreversible action for a reversible intent. Resume had one subtle requirement worth writing down: flip the records back to pending <em>before</em> re-queueing them. Queue first and a worker can pick the message up, still read &#8220;paused&#8221;, and drop the job on the floor.</p><p><strong>2. Small uploads should not summon the whole fleet.</strong> GPU scaling used to step up on a timer whenever the queue was non-empty. A 13-image batch could scale to the maximum fleet, most of which arrived after the work was done, and the fleet then took 69 minutes to scale back down. Scaling now targets an exact capacity from visible-plus-in-flight queue depth; the same drain takes about four minutes. The accepted side effect is that scale-in occasionally interrupts a job mid-inference, which the queue&#8217;s visibility timeout retries (about 1% of images, zero lost) (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/41">#41</a>).</p><p><strong>3. &#8220;Supported&#8221; is a promise about acceptance, not decoding.</strong> The HEIC and 16-bit TIFF cases were the same class of problem: a format we would accept at upload and then fail on quietly. The legacy and edge-case list from the pilot is now long and mostly handled: RAW from bodies newer than the decoder&#8217;s database (falls back to the camera&#8217;s embedded preview instead of false colour), 16-bit and grayscale scans (rescaled by bit depth), iPhone HEIC, 25 RAW formats including Canon CRW, Sony SRF/SR2, Hasselblad 3FR/FFF, Phase One IIQ and Sigma X3F, filenames with spaces, manufacturer-padded camera names, bracketed exposures (pass the gate), bursts (stack, best frame ranked). Still open: older bodies and phone JPEGs that record no capture time can have burst frames flagged as duplicates (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/70">#70</a>). Of the 34 formats, 18 are proven end to end in production; the next one we want a real file for is Fujifilm RAF (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/42">#42</a>, <a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/47">#47</a>). If you shoot Fuji, your first upload is a favour to us.</p><h2><strong>Numbers from the closed beta</strong></h2><ul><li><p>20+ photographer accounts, from first-camera to full-time professional</p></li><li><p>18,884 images enriched, across 18+ file formats</p></li><li><p>104 issues filed on the public tracker since July; 34 closed, every one with what actually shipped</p></li><li><p>Launch-day verification: 100 human-checked images, 51 Keeper / 47 Skip / 2 Review, zero stranded</p></li><li><p>GPU drain after a small upload: 69 minutes &#8594; about 4 minutes</p></li><li><p>Cold start after an idle period: 5 min 32 s today; 90 s is the target</p></li><li><p>28 archival scans and 261 verdict records repaired in place, nothing deleted</p></li></ul><h2><strong>The trial</strong></h2><p>30 days, 1,500 photos, 30 GB of storage including previews. Whichever runs out first ends the trial. Uploads pause at that point and nothing is removed; your gallery, critiques and downloads keep working. Ask and we can raise a cap on your existing account. No card is needed to start.</p><h2><strong>What is next</strong></h2><p>In roughly the order we expect to ship:</p><ul><li><p><strong>A &#8220;your shoot is ready&#8221; notification</strong>, email and in-app, so you can close the laptop after the upload completes and be told when the analysis is done. Today the first verdicts after an idle period wait about five and a half minutes for the AI to warm up; the target is 90 seconds (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/105">#105</a>). Broader in-app notifications follow (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/8">#8</a>).</p></li><li><p><strong>Near-duplicate detection</strong>, burst-aware, on top of the exact-duplicate check that is live (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/4">#4</a>)</p></li><li><p><strong>Curation that learns from you.</strong> Every Keeper and Skip on a Review frame is already recorded; the model of your taste that reads them is next (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/5">#5</a>)</p></li><li><p><strong>Content filters in search</strong> once every image carries scene, lighting and mood tags (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/72">#72</a>), and a relevance floor so weak semantic matches stop looking strong (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/74">#74</a>)</p></li><li><p><strong>Parjanya Vision phase 4</strong>: gear-specific advice that unlocks only when your own photos provide the evidence (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/100">#100</a>), and phase 5, genre for your older photos from stored embeddings without reprocessing (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/101">#101</a>)</p></li><li><p><strong>Self-serve payment</strong> (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/9">#9</a>), and <strong>burst covers</strong> that show the best frame rather than the middle one (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/92">#92</a>)</p></li><li><p><strong>The onboarding guide in more formats</strong>: a video walkthrough with voice-over is next (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/53">#53</a>)</p></li></ul><p>Everything, including the items we have not fixed yet, is public at <a href="https://github.com/JagadeeshRampam/parjanya-issues/issues">github.com/JagadeeshRampam/parjanya-issues</a>. Open and closed alike. The people who tested this deserved to see the list, and so do you.</p><h2><strong>Start</strong></h2><p>Onboarding guide, ten minutes start to finish: <a href="https://parjanya.phagyul.ai/guide.html?utm_source=blog&amp;utm_medium=referral&amp;utm_campaign=v2_public_launch_2026_09&amp;utm_content=release_notes">parjanya.phagyul.ai/guide.html</a></p><p>Create your account: <a href="https://parjanya.phagyul.ai/signup?utm_source=blog&amp;utm_medium=referral&amp;utm_campaign=v2_public_launch_2026_09&amp;utm_content=release_notes">parjanya.phagyul.ai/signup</a></p><p>For the pilot group of Experts across the world and my buddies: thank you again! &#128591;</p><p><em>Jagadeesh</em></p><div><hr></div><h2><strong>Engineering appendix (for readers who came for the systems)</strong></h2><p>Short entries; each has a longer post either published or drafted.</p><ul><li><p><strong>Why there is no score.</strong> The rule engine reads distortion <em>type and severity</em> (motion blur: heavy) rather than a numeric quality score. Scores compressed incompatible defects onto one axis and gave photographers nothing to act on. The model still emits one; the gate ignores it.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;06cc812c-04cf-4241-b164-69bf1db11431&quot;,&quot;caption&quot;:&quot;I did not set out to replace a scoring engine with a rule engine. I set out to make the system cheaper, easier to explain, and less fragile as I was not keen on moving to g5.xlarge or g6.xlarge due to prompt sizes increased and would be lot of churn in terms of architectural and infra changes, comes with re testing every functionality and the increase i&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;From Score Engine to Rule Engine: Why I Rebuilt the Decision Layer&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-05-14T11:27:06.000Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!UKjF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5df5ef7-0eb5-4b90-88c2-f0f4439a82d6_1536x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/from-score-engine-to-rule-engine&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:197643272,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></li><li><p><strong>Caching that never existed.</strong> The dashboards were designed against a response cache that was never provisioned in production, so every dashboard call recomputed. They now serve from a snapshot store warmed by an in-process loop; the admin pane, which took up to 29 seconds per range, answers in under a second (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/34">#34</a>).</p></li><li><p><strong>The month that weighed nothing.</strong> A field rename mid-July left usage attribution reading the old name <em>and</em> projecting only the old name from the database, so every image uploaded for a month contributed zero bytes to per-tenant attribution. The headline figure stayed right because it preferred a storage-measured value, which is exactly why nobody noticed. Lesson written down: a rename has to land in the projection too, and a test fixture that only builds one spelling cannot catch a rename (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/81">#81</a>).</p></li><li><p><strong>Idempotent email.</strong> Trial emails failed silently for three weeks after the flag went live because the execution role never received send permission, and a failed send was marked as delivered before it was attempted, so it could never retry. The rewrite is claim &#8594; send &#8594; confirm, with release on failure, and it is the helper every new notification now uses (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/88">#88</a>, <a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/89">#89</a>, <a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/104">#104</a>).</p></li><li><p><strong>Dedup that could eat a whole cluster.</strong> Symmetric concurrent rejection let every member of a duplicate cluster defer to another member that was also being discarded. Twelve images got no analysis. Survivors are now chosen by a total order, earliest wins (<a href="https://github.com/JagadeeshRampam/parjanya-issues/issues/97">#97</a>).</p></li><li><p><strong>TBIE.</strong> The reconciliation model behind all of this, Truth, Belief, Intent, Execution, has its own post: <em>From Pipeline to Platform</em>. The white paper is in draft.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;e7c4c65d-910e-43a0-9a0f-c6a6eebd4d1a&quot;,&quot;caption&quot;:&quot;Abstract&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;TBIE in Practice: Designing Resilient AI Pipelines That Recover, Reconcile, and Re-run&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-05-25T05:36:28.000Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!ok-g!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe12bff-5e6a-4f47-92ca-1f9569ff933d_1692x929.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/tbie-in-practice-designing-resilient&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:199145206,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></li><li><p><strong>From localhost friction to production-shaped architecture </strong></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;671aaaff-5c09-431f-b5a6-ed053cb614ee&quot;,&quot;caption&quot;:&quot;Lessons from Parjanya v2.0 and the v5.4 architecture revision&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;From localhost friction to production-shaped architecture&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-05-03T13:20:51.000Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!cfp7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11907347-42b7-499a-b390-f5d655628b58_1536x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/from-localhost-friction-to-production&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:196307889,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png" width="2015" height="261" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:261,&quot;width&quot;:2015,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:704966,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/215603782?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42ffabd3-6e9b-49ba-9891-fa9838947d9e_2103x748.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_!mmQN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[Price Is Only Half the Compute Problem]]></title><description><![CDATA[Why the right infrastructure decision is not &#8220;cheapest instance,&#8221; but the right capacity at the right price and the right time.]]></description><link>https://blog.phagyul.ai/p/price-is-only-half-the-compute-problem</link><guid isPermaLink="false">https://blog.phagyul.ai/p/price-is-only-half-the-compute-problem</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Mon, 24 Aug 2026 07:12:44 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Jqmt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eafb652-37e0-484e-9e16-1d6dc3e2219b_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Jqmt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eafb652-37e0-484e-9e16-1d6dc3e2219b_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Jqmt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eafb652-37e0-484e-9e16-1d6dc3e2219b_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Jqmt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eafb652-37e0-484e-9e16-1d6dc3e2219b_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Jqmt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eafb652-37e0-484e-9e16-1d6dc3e2219b_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Jqmt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eafb652-37e0-484e-9e16-1d6dc3e2219b_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Jqmt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eafb652-37e0-484e-9e16-1d6dc3e2219b_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2eafb652-37e0-484e-9e16-1d6dc3e2219b_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;:1436924,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/212492595?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eafb652-37e0-484e-9e16-1d6dc3e2219b_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_!Jqmt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eafb652-37e0-484e-9e16-1d6dc3e2219b_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Jqmt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eafb652-37e0-484e-9e16-1d6dc3e2219b_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Jqmt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eafb652-37e0-484e-9e16-1d6dc3e2219b_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Jqmt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eafb652-37e0-484e-9e16-1d6dc3e2219b_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>1. The morning I looked at the bill</h2><p>On May 3rd, I ran a cost audit on Parjanya&#8217;s AWS account because the number I&#8217;d been carrying in my head &#8212; <strong>&#8220;it&#8217;s cheap, it&#8217;s a GPU worker and some Lambdas&#8221;</strong> &#8212; didn&#8217;t match what Billing was showing me.</p><blockquote><p><strong>It wasn&#8217;t cheap.</strong></p></blockquote><p>The account was running at roughly <strong>$100/day</strong>, and GPU EC2 accounted for most of that at the time: <strong>57&#8211;65% of the bill</strong>. Two <code>g4dn.2xlarge</code> instances were running 24/7 on 100% on-demand capacity for our Qwen3-VL-8B image-quality worker.</p><p>Then I checked the launch template.</p><pre><code><code>"OnDemandPercentageAboveBaseCapacity": 100</code></code></pre><p>A hundred percent.</p><p>The Terraform module already supported Spot allocation. The <code>mixed_instances_policy</code> had been there since March. I simply hadn&#8217;t enabled it.</p><p>That is where a typical cloud-cost story might end: find the waste, flip the switch, move on.</p><p>But that only answered one question:</p><p><strong>Which pool should an instance come from?</strong></p><p>It took me much longer to ask the second:</p><p><strong>How many instances do I actually need?</strong></p><p>That second question turned out to matter even more.</p><h2>2. What I believed about Spot capacity &#8212; and what the data showed</h2><p>I had an assumption I&#8217;d never re-tested: GPU Spot capacity in Mumbai wasn&#8217;t reliable enough to build around.</p><p>That assumption was the reason the ASG had remained on-demand-only since March. It wasn&#8217;t really an oversight. It was an old decision that I hadn&#8217;t revisited.</p><p>So before changing anything, I pulled seven days of Spot price history across the GPU instance types we could realistically use:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!O-F9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff71cee81-1a21-4ba3-94c1-1c61c8a9b4c1_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!O-F9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff71cee81-1a21-4ba3-94c1-1c61c8a9b4c1_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!O-F9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff71cee81-1a21-4ba3-94c1-1c61c8a9b4c1_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!O-F9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff71cee81-1a21-4ba3-94c1-1c61c8a9b4c1_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!O-F9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff71cee81-1a21-4ba3-94c1-1c61c8a9b4c1_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!O-F9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff71cee81-1a21-4ba3-94c1-1c61c8a9b4c1_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f71cee81-1a21-4ba3-94c1-1c61c8a9b4c1_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;:1303473,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/212492595?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff71cee81-1a21-4ba3-94c1-1c61c8a9b4c1_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_!O-F9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff71cee81-1a21-4ba3-94c1-1c61c8a9b4c1_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!O-F9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff71cee81-1a21-4ba3-94c1-1c61c8a9b4c1_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!O-F9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff71cee81-1a21-4ba3-94c1-1c61c8a9b4c1_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!O-F9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff71cee81-1a21-4ba3-94c1-1c61c8a9b4c1_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The assumption hadn&#8217;t been unreasonable when I made it. It was simply stale.</p><p>By May, <code>g4dn.xlarge</code> Spot capacity was looking healthy across all three availability zones. <code>g5.xlarge</code> was a different story: better GPU capacity, but available in only two AZs.</p><p>Rather than rely entirely on historical pricing, I ran a live canary.</p><p>I switched the ASG to Spot, terminated two on-demand instances, and sent the same workload through both configurations.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3tTz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d500ffc-cd2c-4d8a-8dda-148709511f63_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3tTz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d500ffc-cd2c-4d8a-8dda-148709511f63_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!3tTz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d500ffc-cd2c-4d8a-8dda-148709511f63_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!3tTz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d500ffc-cd2c-4d8a-8dda-148709511f63_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!3tTz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d500ffc-cd2c-4d8a-8dda-148709511f63_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!3tTz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d500ffc-cd2c-4d8a-8dda-148709511f63_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8d500ffc-cd2c-4d8a-8dda-148709511f63_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;:1202403,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/212492595?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d500ffc-cd2c-4d8a-8dda-148709511f63_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_!3tTz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d500ffc-cd2c-4d8a-8dda-148709511f63_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!3tTz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d500ffc-cd2c-4d8a-8dda-148709511f63_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!3tTz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d500ffc-cd2c-4d8a-8dda-148709511f63_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!3tTz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d500ffc-cd2c-4d8a-8dda-148709511f63_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>The measured result was a 61% reduction in cost per unit of work.</strong></p><p>The important lesson wasn&#8217;t just about Spot.</p><p>The thing standing between me and that saving wasn&#8217;t a technical limitation. It was an assumption I had stopped questioning.</p><h2>3. Why I didn&#8217;t go 100% Spot</h2><p>Spot capacity can disappear with little warning.</p><p>Our worker also has a significant warm-up cost: pulling the container image and loading a roughly 17GB model. If an instance is reclaimed during warm-up, it produces no useful work.</p><p>So I didn&#8217;t want the entire fleet to depend on Spot availability.</p><p>The configuration became a combination of on-demand and Spot:</p><pre><code><code>gpu_instance_types       = ["g5.xlarge", "g4dn.xlarge"]
on_demand_base_capacity  = 4
on_demand_percentage     = 0
spot_allocation_strategy = "price-capacity-optimized"</code></code></pre><p>The idea is simple:</p><ul><li><p>Keep a small on-demand base as insurance.</p></li><li><p>Use Spot for everything above that base.</p></li><li><p>Let the fleet scale with demand without paying the full on-demand price for every instance.</p></li></ul><p>The on-demand base provides a floor that doesn&#8217;t depend on Spot availability. The Spot fleet provides most of the cost efficiency.</p><p>That combination turned out to be much more useful than thinking of Spot as an all-or-nothing decision.</p><h2>4. Widening the pool &#8212; then narrowing it again</h2><p>The next experiment was about the instance pool itself.</p><p>On July 9th, I saw several <code>g4dn.xlarge</code> Spot instances get reclaimed during warm-up. A pool containing only <code>g5.xlarge</code> and <code>g4dn.xlarge</code> was too narrow to absorb that pressure.</p><p>So I temporarily added:</p><ul><li><p><code>g4dn.2xlarge</code></p></li><li><p><code>g5.2xlarge</code></p></li></ul><p>These instances had the same GPUs as their xlarge counterparts but more CPU and RAM than the workload really needed.</p><p>I wasn&#8217;t buying additional GPU throughput.</p><p>I was buying <strong>capacity insurance</strong>.</p><p>The idea was that <code>price-capacity-optimized</code> could use the larger instances only when the cheaper pools were under pressure. In that situation, paying a little more for an instance that actually becomes available can be better than waiting for a cheaper instance that doesn&#8217;t exist.</p><p>I calculated the worst-case premium before enabling it. Across a 12,000-image batch, the additional cost would have been roughly <strong>$3</strong>.</p><p>That was an acceptable temporary trade-off.</p><p>On July 28th, I removed the 2xlarge types again.</p><p>The reason was straightforward: as a permanent configuration, paying for extra CPU and RAM that the GPU workload didn&#8217;t use wasn&#8217;t attractive.</p><p>The temporary insurance had done its job. Once the capacity pressure eased, the simpler pool made more sense.</p><p>This also exposed an important operational principle:</p><p><strong>A good configuration isn&#8217;t necessarily a permanent configuration.</strong></p><p>Sometimes the right response to a capacity problem is to widen your options temporarily, then narrow them again when the underlying conditions change.</p><h2>5. Two Spot capacity droughts</h2><p>The experiments also exposed the limits of Spot.</p><h3>July 9th</h3><p>Mumbai&#8217;s <code>g4dn</code> Spot capacity went dry across the region.</p><p>The fleet dropped from five instances to one during a 450-image batch.</p><p>No allocation strategy could solve that. There simply wasn&#8217;t enough Spot capacity available.</p><p>The on-demand base was what kept the workload alive, so I increased the base from one to three instances that afternoon.</p><h3>August 5th&#8211;7th</h3><p>This time the problem was <code>g5.xlarge</code>.</p><p>There was no Spot support in one of its two available AZs, while the other experienced an on-demand capacity gap.</p><p>There were three launch failures over three days.</p><p><code>price-capacity-optimized</code> was able to route around the problem by falling back to <code>g4dn.xlarge</code>, although the fallback introduced additional latency.</p><p>These two incidents changed how I think about Spot availability.</p><p>The answer isn&#8217;t simply that availability is &#8220;better&#8221; or &#8220;worse.&#8221;</p><p>It is better on average for some pools, but individual instance families can still experience significant capacity constraints.</p><p><strong>Spot is a probability and capacity-management problem, not just a pricing problem.</strong></p><h2>6. What changed when I moved to price-capacity-optimized</h2><p>There are two strategies that are easy to confuse:</p><p><code>capacity-optimized</code> chooses the Spot pool with the deepest available capacity. Price isn&#8217;t part of the primary decision.</p><p><code>price-capacity-optimized</code> considers both capacity availability and price, choosing among pools that have a reasonable likelihood of remaining available.</p><p>The distinction matters.</p><p>The May canary that produced the 61% cost reduction used <code>capacity-optimized</code>. I later moved to <code>price-capacity-optimized</code> on July 9th.</p><p>I don&#8217;t have a controlled, back-to-back experiment proving the exact dollar improvement from PCO. So I don&#8217;t want to manufacture one.</p><p>The decision was based on the allocation model and the observed capacity conditions rather than a clean A/B test.</p><p>That distinction matters when discussing infrastructure results:</p><p><strong>Measured results and engineering judgments are not the same thing.</strong></p><p>There was another useful discovery in the same change.</p><p>The Terraform module had an override issue that was silently alphabetizing the instance-type list rather than preserving the intended priority order.</p><p>So the configuration had effectively been saying one thing while the infrastructure was doing another.</p><p>It was a good reminder that infrastructure configuration needs the same level of testing and observability as application code.</p><h2>7. The bigger question: how many instances?</h2><p>This is where the more interesting problem appeared.</p><p>Until July 27th, both scale-up and scale-down used <code>SimpleScaling</code>.</p><p>The logic was effectively:</p><blockquote><p>Is the queue empty?</p></blockquote><p>If yes, scale down.</p><p>If no, scale up.</p><p>The problem is that this treats a queue containing 13 messages exactly like a queue containing 1,300 messages.</p><p>The system knew whether work existed.</p><p>It didn&#8217;t know <strong>how much work existed</strong>.</p><p>On July 27th, a small 13-image upload caused the fleet to scale to its maximum. Three of six instances processed nothing, and the timer-based scale-down took <strong>69 minutes</strong>.</p><p>The post-incident calculation showed approximately <strong>4.6 instance-hours</strong> spent for around 20 minutes of actual work.</p><p>The fix was to make scaling <strong>backlog-aware</strong>.</p><p>Instead of looking only at whether the queue was non-empty, the scaling logic now considers the combined backlog &#8212; visible and in-flight messages &#8212; and maps it to an explicit target fleet size:</p><pre><code><code>backlog     target

1&#8211;25        &#8594; 1 instance
25&#8211;100      &#8594; 2
100&#8211;500     &#8594; 4
500+        &#8594; maximum</code></code></pre><p>The policy also changed from incremental scaling to <strong>ExactCapacity</strong>.</p><p>Instead of saying:</p><blockquote><p>Add one instance.</p></blockquote><p>it says:</p><blockquote><p>The fleet should contain four instances.</p></blockquote><p>That difference is important.</p><p>Each scaling decision can converge directly on the desired fleet size rather than repeatedly increasing or decreasing the fleet one instance at a time.</p><p>In a later measured run, the same class of drain dropped from <strong>69 minutes to 4 minutes</strong>.</p><p>But I made another mistake.</p><p>On August 8th, I reduced every scaling band by half.</p><p>That worked for small batches. It also meant that a 108-image production run on August 11th stayed on one instance for roughly 50 minutes when a second instance could have provided useful parallelism after its warm-up period.</p><p>Three days later, I adjusted the bands again rather than reverting the entire change.</p><p>The lesson was bigger than the individual thresholds:</p><p><strong>Scaling needs to understand both price and workload depth.</strong></p><p>Choosing the right Spot pool answers:</p><blockquote><p>Which instance should I buy?</p></blockquote><p>Autoscaling answers:</p><blockquote><p>How many instances should I buy?</p></blockquote><p>Those are different optimization problems.</p><p>And I had spent months tuning the first one before realizing the second one was costing me more.</p><h2>8. Why this isn&#8217;t just a startup problem</h2><p>It&#8217;s easy to think of backlog-blind scaling as an early-stage infrastructure problem.</p><p>I don&#8217;t think it is.</p><p>Any system where demand arrives in bursts can have the same problem.</p><p>Consider:</p><ul><li><p>Batch customer onboarding</p></li><li><p>Large data imports</p></li><li><p>End-of-month reporting</p></li><li><p>Media processing</p></li><li><p>Scheduled analytics workloads</p></li><li><p>Seasonal traffic spikes</p></li><li><p>Any SaaS workload with uneven usage</p></li></ul><p>A presence-based alarm can tell you:</p><blockquote><p>There is work waiting.</p></blockquote><p>It cannot tell you:</p><blockquote><p>There are 20 messages versus 20,000 messages.</p></blockquote><p>Those situations require completely different capacity decisions.</p><p>The mechanism is general:</p><p><strong>Scaling decisions should consider the amount of work waiting, not just the existence of work.</strong></p><p>The exact thresholds will vary by system, but the principle applies broadly.</p><h2>9. What actually changed</h2><p>Here are the results I can measure and reproduce:</p><ul><li><p><strong>61% lower cost per unit of work</strong> in the Spot vs. on-demand canary.</p></li><li><p><strong>69 minutes &#8594; 4 minutes</strong> for a comparable production drain after moving to depth-aware ExactCapacity scaling.</p></li><li><p><strong>~4.6 instance-hours</strong> consumed by an inefficient scaling response to a small workload.</p></li><li><p><strong>~$3 maximum premium</strong> calculated for temporarily widening the Spot pool for a 12,000-image batch.</p></li><li><p><strong>3 launch failures over 3 days</strong> during the August <code>g5.xlarge</code> capacity issue.</p></li></ul><p>The longer-term Cost Explorer data tells a similar story.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1c9Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbfb317-0862-4195-9d0d-c1e7d8448ed5_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1c9Y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbfb317-0862-4195-9d0d-c1e7d8448ed5_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!1c9Y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbfb317-0862-4195-9d0d-c1e7d8448ed5_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!1c9Y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbfb317-0862-4195-9d0d-c1e7d8448ed5_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!1c9Y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbfb317-0862-4195-9d0d-c1e7d8448ed5_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!1c9Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbfb317-0862-4195-9d0d-c1e7d8448ed5_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2cbfb317-0862-4195-9d0d-c1e7d8448ed5_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;:1147549,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/212492595?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbfb317-0862-4195-9d0d-c1e7d8448ed5_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_!1c9Y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbfb317-0862-4195-9d0d-c1e7d8448ed5_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!1c9Y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbfb317-0862-4195-9d0d-c1e7d8448ed5_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!1c9Y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbfb317-0862-4195-9d0d-c1e7d8448ed5_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!1c9Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbfb317-0862-4195-9d0d-c1e7d8448ed5_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Across the GPU hours recorded this year, on-demand averaged roughly <strong>$0.64/hour</strong>, while Spot averaged roughly <strong>$0.30/hour</strong> &#8212; about a <strong>53% discount</strong>.</p><p>For the 785 Spot hours recorded year-to-date, paying the blended on-demand rate would have cost approximately $505. Actual Spot spend was about $235.</p><p>That&#8217;s roughly <strong>$270 in measured savings from those Spot hours alone</strong>.</p><p>GPU EC2 has cost <strong>$967.85</strong> year-to-date against <strong>$6,637.43</strong> in total account spend through August 22 &#8212; roughly 15% of total spend.</p><p>The important point isn&#8217;t the exact percentage.</p><p>It is that the optimization moved from a simple:</p><blockquote><p>&#8220;Can I get cheaper GPU instances?&#8221;</p></blockquote><p>to a much broader question:</p><blockquote><p>&#8220;Am I buying the right capacity, from the right pool, for the amount of work actually waiting?&#8221;</p></blockquote><p>That is a much more useful infrastructure question.</p><h2>10. The bigger takeaway: price and capacity must be optimized together</h2><p>The biggest lesson from this exercise isn&#8217;t simply that Spot is cheaper than on-demand.</p><p>It is that <strong>price and capacity need to be considered together</strong>.</p><p><code>price-capacity-optimized</code> matters because the cheapest Spot instance isn&#8217;t necessarily the cheapest option if that capacity isn&#8217;t available &#8212; or is likely to be reclaimed. A slightly more expensive pool with better capacity can be the better economic choice when the alternative is waiting for capacity that may never arrive.</p><p>That is the real value of price-capacity optimization:</p><blockquote><p><strong>Don&#8217;t optimize for the lowest price. Optimize for the lowest viable cost of reliable capacity.</strong></p></blockquote><p>The distinction became particularly clear during the capacity droughts I encountered. No allocation strategy can create capacity that doesn&#8217;t exist, which is why the on-demand base remained important. But when multiple Spot pools were available, price-capacity-optimized gave the fleet a better way to balance <strong>availability and cost</strong> instead of treating either one in isolation.</p><p>There is, however, a second layer that is just as important.</p><p><code>price-capacity-optimized</code> answers:</p><blockquote><p><strong>Which capacity should I use?</strong></p></blockquote><p>Autoscaling answers:</p><blockquote><p><strong>How much capacity do I need?</strong></p></blockquote><p>Those are separate problems.</p><p>The configuration that ultimately worked for me brought both together:</p><ol><li><p><strong>Keep an on-demand base</strong> as protection against a complete Spot capacity shortage.</p></li><li><p><strong>Use price-capacity-optimized Spot allocation</strong> to balance price and capacity across viable pools.</p></li><li><p><strong>Keep multiple instance options available when capacity is constrained</strong>, but avoid permanently paying for resources the workload doesn&#8217;t actually use.</p></li><li><p><strong>Scale based on backlog depth</strong>, rather than simply checking whether work exists.</p></li><li><p><strong>Use ExactCapacity targets</strong> so the fleet converges directly on the capacity the workload needs.</p></li></ol><p>This changed how I think about compute optimization.</p><p>The goal isn&#8217;t to find the cheapest instance.</p><p>It isn&#8217;t even to find the cheapest Spot pool.</p><p>The goal is to find the <strong>right amount of reliable capacity at the lowest practical cost</strong>.</p><p>That is what <code>price-capacity-optimized</code> ultimately taught me: <strong>price optimization without capacity awareness is incomplete, and capacity optimization without workload awareness can still waste money.</strong></p><p>The real optimization happens when all three line up:</p><div class="pullquote"><p><strong>the right pool &#8594; the right price &#8594; the right amount of capacity.</strong></p></div><h2>11. The connection to context engineering</h2><p>This is where this experiment connects with the earlier post on <a href="https://blog.phagyul.ai/p/context-engineering-and-context-debt">Context Engineering and Context Debt</a>.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;05e4d326-96cf-4690-8668-43d553ed1e78&quot;,&quot;caption&quot;:&quot;TL;DR: I noticed Haiku 4.5 being spawned as a subagent during an Opus 4.7 session. That observation opened a data investigation that revealed ~77% of my token spend was context accumulation waste, not productive reasoning. This is the framework I built to fix it &#8212; and the problem has a name:&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Context Engineering and Context Debt&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-05-20T06:06:57.000Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!dA7S!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcea4dfbb-67e2-4a62-af94-c33dac8db92a_1774x887.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/context-engineering-and-context-debt&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:198514119,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:3,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>The two problems look different, but the underlying optimization pattern is surprisingly similar.</p><p>In context management, you have to decide:</p><p><strong>Which information belongs in the context?</strong></p><p>Then separately:</p><p><strong>How much context should the model actually carry?</strong></p><p>The GPU fleet has the same two layers.</p><p><strong>Price-capacity-optimized</strong> answers:</p><blockquote><p>Which pool should the instance come from?</p></blockquote><p><strong>Depth-aware scaling</strong> answers:</p><blockquote><p>How many instances does the workload justify?</p></blockquote><p>Getting the first decision right doesn&#8217;t automatically make the second one right.</p><p>That was the mistake I made.</p><p>I optimized the price and availability of each unit without first asking whether I needed that many units.</p><p>The same pattern appears in context management: a good retrieval strategy can still become expensive if the context budget itself isn&#8217;t being managed.</p><p>The broader lesson for me is simple:</p><p><strong>Optimization is rarely one decision. It is usually a stack of decisions.</strong></p><p>You can optimize the individual resource and still waste money because you&#8217;re using too much of it.</p><p>You can optimize the model and still waste tokens because you&#8217;re sending too much context.</p><p>You can optimize the database query and still waste resources because you&#8217;re running it too many times.</p><p>The useful question is therefore not just:</p><blockquote><p>&#8220;What&#8217;s the cheapest way to do this?&#8221;</p></blockquote><p>It is:</p><blockquote><p><strong>&#8220;What is the minimum amount of the right resource needed to do this reliably?&#8221;</strong></p></blockquote><p>That is the question I should have asked much earlier.</p><div><hr></div><p><em>Configuration referenced in this post reflects the production setup as of August 12, 2026. Cost figures are based on a Cost Explorer pull covering January 1 through August 22, 2026.</em></p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jtmq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b58187f-f338-4a63-800a-88ecfa455087_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!jtmq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b58187f-f338-4a63-800a-88ecfa455087_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!jtmq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b58187f-f338-4a63-800a-88ecfa455087_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!jtmq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b58187f-f338-4a63-800a-88ecfa455087_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!jtmq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b58187f-f338-4a63-800a-88ecfa455087_2015x261.png" width="2015" height="261" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1b58187f-f338-4a63-800a-88ecfa455087_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:261,&quot;width&quot;:2015,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:704966,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jtmq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b58187f-f338-4a63-800a-88ecfa455087_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!jtmq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b58187f-f338-4a63-800a-88ecfa455087_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!jtmq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b58187f-f338-4a63-800a-88ecfa455087_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!jtmq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b58187f-f338-4a63-800a-88ecfa455087_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[N+1 Without an ORM: The Hidden Cost of Extra Round Trips]]></title><description><![CDATA[How we found duplicate DynamoDB reads, unbatched CloudWatch calls, and a cache that quietly wasn&#8217;t there]]></description><link>https://blog.phagyul.ai/p/n1-without-an-orm-the-hidden-cost</link><guid isPermaLink="false">https://blog.phagyul.ai/p/n1-without-an-orm-the-hidden-cost</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Tue, 18 Aug 2026 05:50:41 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!JHtk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80b2372-63ef-40bf-9f08-e375bb2b8a01_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>The Problem, in One Sentence</h2><p>The N+1 query problem is what happens when fetching N items costs you N+1 round trips to a data store instead of one &#8212; and it is, without much competition, one of the most common performance bugs I see in software that talks to a database.</p><p>I want to write about it here not because we hit the textbook version. We didn&#8217;t. What we ran into while building a new feature for <a href="https://parjanya.phagyul.ai">Parjanya</a> were two close cousins of N+1, caught at different points in the same week.</p><p>What made the experience worth writing about was the pattern-matching involved. Once I started asking <em><strong>&#8220;how many times does this data actually need to leave the system?&#8221;</strong></em> rather than just <em><strong>&#8220;does this code work?&#8221;</strong></em>, both problems became much easier to see.</p><p>I think that is a useful engineering habit for anyone building on top of an ORM, a NoSQL table, or a cloud API with a batch endpoint nobody on the team has used yet.</p><h2>Why N+1 Gets Its Own Name</h2><p>Picture the canonical example, the one I have either written or fixed more times than I&#8217;d like to admit: I load a list of blog posts, then loop over them to print each author&#8217;s name.</p><pre><code><code>posts = Post.objects.all()          # 1 query
for post in posts:
    print(post.author.name)         # N queries &#8212; one per post</code></code></pre><p>One query becomes N+1 queries.</p><p>With 10 posts, that&#8217;s mildly wasteful. With 10,000 posts loaded on an admin page, it can be the difference between a 200ms response and a request that never comes back.</p><p>Once I started looking for the shape rather than the syntax, I found it everywhere: a GraphQL resolver fetching a <code>Book</code> per <code>Author</code> node instead of batching with a <code>DataLoader</code>; a Rails view calling <code>.comments.count</code> inside an <code>each</code> block; a microservice calling <code>GET /users/:id</code> once per row instead of <code>POST /users/batch</code>.</p><p>Different stacks, same root cause &#8212; a per-item operation standing in for a single query or batch operation the data layer was perfectly capable of running.</p><p>What makes N+1 worth having a name of its own, rather than simply calling it &#8220;a slow endpoint,&#8221; is <em>how</em> it hides.</p><p>The loop looks correct in code review. It <em>is</em> correct &#8212; just expensive.</p><p>Unit tests don&#8217;t necessarily expose it either. A fixture with three rows produces three extra queries, but nobody notices when the entire test takes 40ms.</p><p>It usually becomes visible only with real data volume: a production dashboard gets slower, a support ticket says a page &#8220;used to be fast,&#8221; and by then the same pattern has often been copied into two other endpoints.</p><p>That&#8217;s why I care about catching this class of problem early. The fix can be a five-line change when I catch it during design or review. Once the data has grown into the architecture, the same fix can become a multi-file refactor with a production incident attached.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JHtk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80b2372-63ef-40bf-9f08-e375bb2b8a01_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JHtk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80b2372-63ef-40bf-9f08-e375bb2b8a01_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!JHtk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80b2372-63ef-40bf-9f08-e375bb2b8a01_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!JHtk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80b2372-63ef-40bf-9f08-e375bb2b8a01_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!JHtk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80b2372-63ef-40bf-9f08-e375bb2b8a01_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!JHtk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80b2372-63ef-40bf-9f08-e375bb2b8a01_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e80b2372-63ef-40bf-9f08-e375bb2b8a01_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;:1803223,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/211664136?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80b2372-63ef-40bf-9f08-e375bb2b8a01_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_!JHtk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80b2372-63ef-40bf-9f08-e375bb2b8a01_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!JHtk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80b2372-63ef-40bf-9f08-e375bb2b8a01_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!JHtk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80b2372-63ef-40bf-9f08-e375bb2b8a01_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!JHtk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80b2372-63ef-40bf-9f08-e375bb2b8a01_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>Our Version Wasn&#8217;t the Textbook Case &#8212; Which Is Exactly the Point</h2><p>At <a href="https://parjanya.phagyul.ai">Parjanya</a>, we don&#8217;t run a traditional ORM &#8212; no ActiveRecord, no Django QuerySets, no lazy-loaded relationships waiting to surprise us.</p><p>Our data layer is DynamoDB, queried directly, with explicit <code>asyncio.gather</code> calls instead of implicit lazy loading.</p><p>At first glance, that seems like it should rule out N+1 entirely. Nothing is silently issuing a query behind a property access.</p><p>It doesn&#8217;t.</p><p>It just changes the shape of the problem.</p><p>We found two variants in the same week while building the same feature, and neither looked anything like the classic blog-posts-and-authors example.</p><h3>Cousin #1: The Same Partition, Fetched Twice by Two Honest Code Paths</h3><p>In mid-July, we built <code>GET /api/v1/admin/dashboard</code> &#8212; a cross-tenant operations view for Parjanya: pipeline health, queue depth, GPU fleet state, reconciler activity, and a per-tenant usage/cost table, all on one screen for whoever&#8217;s on call.</p><p>Two of those blocks needed the same underlying data.</p><p>The pipeline-health block needed every tenant&#8217;s image records to compute stale-pending buckets.</p><p>The per-tenant table needed the <em>same</em> tenant&#8217;s image records to compute that tenant&#8217;s usage numbers &#8212; through <code>UsageMetricsService.build_dashboard</code>, a method that already existed and already queried DynamoDB for exactly this.</p><p>The straightforward implementation would have called <code>build_dashboard</code> once per tenant, which queries that tenant&#8217;s image partition, and then separately queried the same partition again to build the pipeline block.</p><p>For T tenants, that meant 2T DynamoDB queries against partitions we only needed to read once each.</p><p>There was no obvious <code>for tenant_id in tenant_ids: await fetch(tenant_id)</code> loop. Nothing screamed &#8220;N+1.&#8221;</p><p>Instead, I had two well-intentioned pieces of code, written for two different sections of the same page, each doing the right thing in isolation and the wrong thing together.</p><p>We caught it before it merged by asking the same question the textbook N+1 case teaches us to ask:</p><p><em>How many times does this data actually need to leave DynamoDB?</em></p><p>The answer was once.</p><p>So we fetched it once:</p><pre><code><code># One image-field fetch per tenant, shared by the pipeline block AND
# the per-tenant usage dashboards (build_dashboard accepts prefetched
# images) &#8212; avoids double-charging the DDB partitions.
images_by_tenant = await self._fetch_images(tenant_ids, attention)

results = await asyncio.gather(
    self._pipeline_block(images_by_tenant, days, now),
    ...
    self._tenants_block(tenant_configs, images_by_tenant, days, now, email_by_tenant),
    return_exceptions=True,
)</code></code></pre><p>Then I changed <code>build_dashboard</code> so it could accept data the caller had already fetched instead of insisting on fetching it again:</p><pre><code><code>async def build_dashboard(
    self,
    tenant_id: str,
    days: int,
    images: list[dict[str, Any]] | None = None,
) -&gt; UsageDashboardResponse:
    """Build the dashboard; ``images`` lets callers that already fetched
    the tenant's image fields (admin dashboard) avoid a second query."""
    if images is None:
        images = await self.db.query_image_usage_fields(tenant_id)</code></code></pre><p>One parameter. One shared dictionary threaded through two call sites.</p><p>2T queries became T.</p><p>There is an important detail here that I think is easy to miss.</p><p>We didn&#8217;t make the T queries sequential. They still run concurrently through <code>asyncio.gather</code>, one per tenant.</p><p>That distinction matters because concurrency can fool me into thinking I&#8217;ve fixed the problem.</p><p>Concurrency hides N+1&#8217;s <strong>latency</strong> cost.</p><p>T parallel queries can sometimes return in roughly the time of one query.</p><p>But concurrency does nothing to reduce the <strong>volume</strong> cost.</p><p>I&#8217;m still paying for T reads against T partitions. I&#8217;m still consuming T times the read capacity. And I&#8217;m still one slow or misbehaving tenant away from holding up the batch.</p><p>A parallel N+1 is faster to run and just as expensive to pay for.</p><p>The fix that matters is cutting the fetch count, not merely parallelizing it.</p><h3>Cousin #2: An API With a Batch Endpoint You Forgot Existed</h3><p>The same dashboard also needed CloudWatch metrics &#8212; reconciler activity across five pipeline stages times four counters each, giving us 20 data series, SQS queue ages for up to three queues, and GPU fleet throughput.</p><p>The naive implementation would have made a <code>get_metric_data</code> call per series.</p><p>That&#8217;s 20 calls for the reconciler block alone, plus one per queue, plus one for fleet throughput.</p><p>Every one of those is a network round trip. Every one is a CloudWatch API call subject to its own rate limits. Every one has its own chance to fail independently in the middle of the request.</p><p>This is probably the most common shape of N+1&#8217;s cousin that I now look for: not a data-modeling problem, but a case where I forgot that the SDK already has a native batch primitive for exactly what I&#8217;m trying to do.</p><p><code>boto3</code>&#8216;s CloudWatch client accepts a list of <code>MetricDataQueries</code> in a single <code>get_metric_data</code> call &#8212; up to 500 of them &#8212; and returns the results together.</p><p>So I built one small helper around that and used it everywhere we needed metrics:</p><pre><code><code>async def _get_metric_data(
    self, queries: list[dict[str, Any]], start: datetime, end: datetime
) -&gt; dict[str, float]:
    """One batched GetMetricData; returns {query_id: latest/sum value}."""
    resp = self.cloudwatch.get_metric_data(
        MetricDataQueries=queries, StartTime=start, EndTime=end,
        ScanBy="TimestampDescending",
    )
    ...</code></code></pre><p>The reconciler block builds all 20 queries &#8212; 5 stages &#215; 4 metrics &#8212; as one list and makes one call.</p><p>The queue-age lookup builds one query per queue and makes one call.</p><p>Fleet throughput reuses the same helper.</p><p>Twenty-some potential round trips collapsed into three calls for the whole dashboard build: one per logical block, not one per metric.</p><p>And I didn&#8217;t want the batching optimization to compromise resilience.</p><p>We kept the per-tenant and per-block exception isolation through <code>asyncio.gather(..., return_exceptions=True)</code>.</p><p>That means one broken AWS permission or one tenant&#8217;s bad data can still degrade that panel to a <code>signal_unavailable</code> note instead of taking down the entire request.</p><p>For me, that&#8217;s an important architectural point: batching and graceful degradation aren&#8217;t in tension. I just have to design for both instead of treating &#8220;make it one call&#8221; as permission to let one failure take down everything.</p><p>Both of these changes shipped in the same commit, <code>feat(admin): per-environment admin dashboard API</code>, alongside 11 new tests.</p><p>Neither would have shown up on a code-review checklist that only asked, <em>&#8220;Is there a loop calling the database?&#8221;</em></p><p>The first problem was two separate, individually-correct code paths.</p><p>The second was a missed SDK capability.</p><p>The habit that catches both is the same habit that catches classic N+1:</p><p><strong>Before I merge anything that talks to a data store or external API more than once, I want to know exactly how many round trips it costs and whether that number scales with something that&#8217;s about to grow.</strong></p><h2>The Sequel: Batched Isn&#8217;t the Same as Cached</h2><p>This is actually the part of the story I find most useful, because from the outside it looked like we&#8217;d already solved the problem.</p><p>Four days after that commit, I was checking why admin dashboard loads still felt sluggish when we found this:</p><blockquote><p><em>Verified live: no ElastiCache exists in any deployed environment (zero clusters, no VALKEY_* env vars), so ValkeyCache silently no-ops and every dashboard load was a full rebuild (~29s admin builds, a Cost Explorer call per view).</em></p></blockquote><p>We had designed the endpoint to be cached.</p><p>There was a <code>ValkeyCache</code> layer wired in from the start, a 3-minute TTL, and the whole shape of what looked like a normal caching story.</p><p>What we hadn&#8217;t verified was the one thing that mattered:</p><p><strong>Did the cache actually exist in any running environment?</strong></p><p>It didn&#8217;t.</p><p>ElastiCache had never been provisioned.</p><p>Every cache read quietly missed, every single time.</p><p>That meant every dashboard view was re-running the entire fan-out we&#8217;d just finished optimizing: T parallel DynamoDB queries, three batched-but-not-free CloudWatch calls, and a Cost Explorer call none of us wanted running on every page load.</p><p>We had reduced the number of round trips per build from something like 2T+20 down to T+3.</p><p>And then we paid that reduced-but-still-real cost on every request because nothing was actually skipping the build.</p><p>That was the moment the distinction became very clear to me:</p><p><strong>Fixing N+1-shaped fan-out is necessary, but it isn&#8217;t sufficient if the whole expensive operation still runs on every request.</strong></p><p>A cache I haven&#8217;t verified in a running environment is, for all practical purposes, no cache.</p><p>And an unverified cache in front of a well-batched N+1 fix just means I&#8217;m repeatedly paying a smaller bill instead of a larger one.</p><p>The real fix didn&#8217;t require adding another managed service.</p><p>Instead, we used what we already had &#8212; the images table and the long-running ECS task &#8212; rather than depending on infrastructure that had quietly never existed:</p><ul><li><p>A <code>SnapshotStore</code> writes gzip&#8217;d JSON dashboard snapshots into DynamoDB itself, with a read-time <code>expires_at</code> and a fail-open contract. Any DynamoDB hiccup degrades to a cache miss, which is just today&#8217;s behavior, never worse.</p></li><li><p>A background warmer, running in the API process&#8217;s own lifespan, rebuilds the admin snapshot on a roughly 4-minute cadence and each tenant&#8217;s usage snapshot every 8 hours. We chose those cadences based on how often the underlying signals actually change, rather than picking arbitrary TTLs.</p></li><li><p>The Cost Explorer block gets its own 8-hour snapshot inside the costs block, since Cost Explorer data itself only refreshes a few times a day. That takes it from roughly one call per view to roughly three calls a day.</p></li><li><p>Both <code>/usage/dashboard</code> and <code>/admin/dashboard</code> now serve snapshots by default, with an explicit <code>refresh=true</code> escape hatch for anyone who genuinely needs the live number.</p></li></ul><p>Nobody waits on a cold build anymore.</p><p>And, just as importantly, nobody is silently re-running a 29-second, multi-block AWS fan-out every time someone opens a browser tab.</p><h2>Why Catching This Early Mattered More Than Usual, Here</h2><p><a href="https://parjanya.phagyul.ai">Parjanya</a> launched to its first self-serve trial cohort on 1st August.</p><p>Both fixes &#8212; the shared-fetch deduplication and batched metrics, followed by the snapshot cache that replaced a cache that never actually existed &#8212; landed before that date, while tenant counts were still near zero and nobody outside the team was looking at the admin dashboard.</p><p>That timing is the whole argument for dealing with N+1-shaped problems early.</p><p>At near-zero scale, 2T queries and T queries cost about the same amount of nothing.</p><p>A 29-second rebuild on every page view is merely annoying when I&#8217;m the only engineer clicking refresh.</p><p>None of this was a production incident.</p><p>But I could see exactly how it would become one.</p><p>As tenant count and dashboard traffic grew, the fan-out cost would scale linearly with exactly the number a growing SaaS product is supposed to grow.</p><p>The phantom-cache cost would scale linearly with exactly the traffic a real launch is supposed to bring.</p><p>We found both by asking a very simple question while the answer was still cheap to change:</p><p><strong>How many round trips does this cost, and does that number grow with our own success?</strong></p><p>I&#8217;d much rather answer that question before customers force me to.</p><h2>What I&#8217;d Tell a Team Building This Kind of Thing</h2><p><strong>Ask the round-trip question before merge, not after a slow-page complaint.</strong></p><p>For any code that touches a database or an external API more than once per request, I ask explicitly: how many round trips does this cost today, and what does that number scale with?</p><p>If the answer is &#8220;the number of tenants&#8221; or &#8220;the number of rows on this page,&#8221; that&#8217;s the moment to fix it &#8212; not a note for later.</p><p><strong>A loop isn&#8217;t required for N+1&#8217;s cousins to exist.</strong></p><p>Our duplicate-fetch case had no <code>for tenant_id in tenant_ids: await fetch(tenant_id)</code> shape at all.</p><p>It was two separately-written, individually-reasonable code paths that happened to want the same data.</p><p>I now watch for that pattern specifically: two features, built at different times, that each independently fetch &#8220;this tenant&#8217;s records&#8221; without either one knowing the other exists.</p><p><strong>Check whether your SDK already has a batch verb before writing the loop.</strong></p><p>CloudWatch&#8217;s <code>GetMetricData</code> takes a list.</p><p>So does DynamoDB&#8217;s <code>BatchGetItem</code>.</p><p>So do many well-designed cloud APIs from the last decade.</p><p>The fix for &#8220;N calls instead of one&#8221; is very often not custom code.</p><p>It is reading one more section of the SDK documentation.</p><p><strong>Concurrency is not the same fix as batching.</strong></p><p><code>asyncio.gather</code> over N calls is faster than N sequential calls, and it is <em>still</em> N calls.</p><p>It hides the latency symptom without touching the cost or capacity symptom.</p><p>I don&#8217;t want a parallel version of the bug to pass code review as if it were the batched version.</p><p><strong>A cache is a claim, not a fact, until I&#8217;ve verified it in every running environment.</strong></p><p>The most expensive line in this whole story wasn&#8217;t a query.</p><p>It was an unprovisioned ElastiCache cluster that let a caching layer silently no-op for days while looking, in every log line and every code review, exactly like it was working.</p><p>If I can&#8217;t point to the cache-hit rate on a dashboard, I don&#8217;t want to assume the cache is working.</p><p>I want to verify it.</p><p><strong>Small scale is when this is cheap to fix, not evidence that it doesn&#8217;t need fixing.</strong></p><p>The version of this bug that costs nothing to run also costs almost nothing to fix.</p><p>The version that ships to production and grows with user count is the same bug, several engineer-days more expensive, with a support ticket attached.</p><div><hr></div><p><em><a href="https://parjanya.phagyul.ai">Parjanya</a> is the multi-tenant image QA platform we&#8217;re building at <a href="https://phagyul.ai/">Phagyul</a> for professional photographers. If your team has its own N+1 cousins &#8212; duplicate fetches across features that don&#8217;t know about each other, unbatched calls to an API that quietly supports batching, caches that looked wired but weren&#8217;t &#8212; I&#8217;d love to compare notes.</em></p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png" width="1456" height="189" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:189,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[From Managed Services to Primitives (DX vs DIY)]]></title><description><![CDATA[What Building Parjanya v2.0 Taught Me About Managed Platforms, Self-Hosted AI, and Owning the Right Abstractions]]></description><link>https://blog.phagyul.ai/p/from-managed-services-to-primitives</link><guid isPermaLink="false">https://blog.phagyul.ai/p/from-managed-services-to-primitives</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Mon, 17 Aug 2026 04:37:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!JqNv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd239184d-a5bd-445c-915e-68382df98afb_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JqNv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd239184d-a5bd-445c-915e-68382df98afb_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JqNv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd239184d-a5bd-445c-915e-68382df98afb_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!JqNv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd239184d-a5bd-445c-915e-68382df98afb_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!JqNv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd239184d-a5bd-445c-915e-68382df98afb_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!JqNv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd239184d-a5bd-445c-915e-68382df98afb_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JqNv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd239184d-a5bd-445c-915e-68382df98afb_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d239184d-a5bd-445c-915e-68382df98afb_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;:1913288,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/211508956?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd239184d-a5bd-445c-915e-68382df98afb_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_!JqNv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd239184d-a5bd-445c-915e-68382df98afb_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!JqNv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd239184d-a5bd-445c-915e-68382df98afb_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!JqNv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd239184d-a5bd-445c-915e-68382df98afb_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!JqNv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd239184d-a5bd-445c-915e-68382df98afb_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>A few months ago, I wrote a short note arguing that developer-experience platforms are excellent at velocity, but that AI systems demand a different kind of architectural thinking.</p><div class="comment" data-attrs="{&quot;url&quot;:&quot;https://open.substack.com/&quot;,&quot;commentId&quot;:223754757,&quot;comment&quot;:{&quot;id&quot;:223754757,&quot;date&quot;:&quot;2026-03-06T04:28:57.360Z&quot;,&quot;edited_at&quot;:null,&quot;body&quot;:&quot;DX vs DIY in the AI Era\n\nManaged developer experience platforms are great for velocity.\n\n\n\n\n\nPreview environments\n\n\n\nZero-config deployments\n\n\n\nEdge functions.\n\nBut in AI systems, the trade-offs change.\n\nA simple architectural shortcut can silently turn into AI debt:\n\n\n\n\n\nrunaway inference cost\n\n\n\nreproducibility gaps\n\n\n\ngovernance risk\n\n\n\ndebugging complexity across distributed edge nodes\n\nOne pattern that works well is what I call an AI-safe hybrid architecture:\n\nUse the edge as a traffic director, not a compute executor.\n\nStatic assets and lightweight routing can live at the edge.\n\nBut keep these centralized:\n\n\n\n\n\nauthentication model resolution\n\n\n\ninference execution\n\n\n\ntelemetry and logging\n\nThis keeps cost, lineage, and governance under control.\n\nThe real enabler behind this is unified engineering.\n\nSmall cross-functional teams that understand frontend, backend, and infrastructure can reason about the full system &#8212; and prevent architectural drift.\n\nDX where it helps. Control where it matters.\n\nThe organizational pattern is unified engineering: small platform teams own CI &#8594; CDN &#8594; inference and rotate engineers across layers so decisions are informed end-to-end.\n\nfrom personal experience as L6 Engineering Lead at Amazon and from the tech blogs of Netflix, and Google what I have learned, as well an interesting contrasting case study at Cloudflare used Edge \n\n\n\n\n\nNetflix &#8212; edge for delivery, region for logic\n\nNetflix designs its content delivery and playback stack to reduce origin load (CDN caches, client-side playback intelligence). They keep complex, stateful logic and billing/governance centralized (accounting, personalization models, recommendation scoring pipelines are resolved and served from control planes rather than being executed indiscriminately at edge nodes). The goal: global responsiveness with centralized control of heavy compute and data lineage.\n\nPattern to note: aggressive caching + client intelligence, regional/trusted control plane for personalization/inference.\n\n\n\n\n\nGoogle &amp; Amazon Web Services &#8212; unified platform culture\n\nAt the largest scale, Google and AWS set examples of platform thinking: SRE/platform teams codify deployment patterns, guardrails, and observability. Teams owning product features lean on platform primitives (IAM, KMS, managed registries) rather than inventing bespoke workflows. For ML, both invest heavily in model governance tooling (registries, metadata, reproducible pipelines) and encourage centralization of expensive compute.\n\nPattern to note: platform teams + standardized primitives reduce drift and enable fast, safe scaling.\n\nAlso, a contrasting case study and intentional by Cloudflare\n\n\n\n\n\nCloudflare &#8212; edge-native capabilities\n\nCloudflare&#8217;s stack is deliberately edge-native: Workers, KV, and global routing enable running meaningful compute at POPs. That capability is powerful for low-latency personalization and caching, but it also requires disciplined use when you&#8217;re serving ML-backed features &#8212; otherwise you risk global fan-out of expensive inference.\n\nPattern to note: edge compute is powerful; use it for safe, stateless ops or extremely lightweight personalization &#8212; not for heavy inference unless you have strong disciple in terms of setting limits &amp; cost controls.\n\nTo summarise,\n\nLarge, well-engineered platforms (think Netflix and Uber) treat the edge as a traffic director, not a compute engine: aggressive caching and lightweight client/edge logic for responsiveness, with heavy stateful work &#8212; auth, model resolution, inference, and telemetry &#8212; resolved in a centralized control plane. That pattern preserves developer velocity where it matters while keeping inference cost, reproducibility, and governance tightly controlled. The organizational enabler is unified engineering: small platform teams that own CI &#8594; CDN &#8594; inference and rotate engineers across layers so the system evolves with discipline rather than accreting accidental AI debt.&quot;,&quot;body_json&quot;:{&quot;type&quot;:&quot;doc&quot;,&quot;attrs&quot;:{&quot;schemaVersion&quot;:&quot;v1&quot;},&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;DX vs DIY in the AI Era&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Managed developer experience platforms are great for velocity.&quot;}]},{&quot;type&quot;:&quot;bulletList&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Preview environments&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Zero-config deployments&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Edge functions.&quot;}]}]}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;But in AI systems, the trade-offs change.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;A simple architectural shortcut can silently turn into &quot;},{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;AI debt&quot;},{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;:&quot;}]},{&quot;type&quot;:&quot;bulletList&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;runaway inference cost&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;reproducibility gaps&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;governance risk&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;debugging complexity across distributed edge nodes&quot;}]}]}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;One pattern that works well is what I call an &quot;},{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;AI-safe hybrid architecture&quot;},{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;:&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Use the edge as a &quot;},{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;traffic director&quot;},{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;, not a compute executor.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Static assets and lightweight routing can live at the edge.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;But keep these centralized:&quot;}]},{&quot;type&quot;:&quot;bulletList&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;authentication model resolution&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;inference execution&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;telemetry and logging&quot;}]}]}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;This keeps cost, lineage, and governance under control.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;The real enabler behind this is &quot;},{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;unified engineering&quot;},{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Small cross-functional teams that understand frontend, backend, and infrastructure can reason about the full system &#8212; and prevent architectural drift.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;DX where it helps. Control where it matters.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;The organizational pattern is &quot;},{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;unified engineering&quot;},{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;: small platform teams own CI &#8594; CDN &#8594; inference and rotate engineers across layers so decisions are informed end-to-end.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;from personal experience as L6 Engineering Lead at Amazon and from the tech blogs of Netflix, and Google what I have learned, as well an interesting contrasting case study at Cloudflare used Edge &quot;}]},{&quot;type&quot;:&quot;orderedList&quot;,&quot;attrs&quot;:{&quot;start&quot;:1,&quot;type&quot;:null},&quot;content&quot;:[{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;Netflix &#8212; edge for delivery, region for logic&quot;}]}]}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Netflix designs its content delivery and playback stack to reduce origin load (CDN caches, client-side playback intelligence). They keep complex, stateful logic and billing/governance centralized (accounting, personalization models, recommendation scoring pipelines are resolved and served from control planes rather than being executed indiscriminately at edge nodes). The goal: global responsiveness with centralized control of heavy compute and data lineage.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;Pattern to note:&quot;},{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot; aggressive caching + client intelligence, regional/trusted control plane for personalization/inference.&quot;}]},{&quot;type&quot;:&quot;orderedList&quot;,&quot;attrs&quot;:{&quot;start&quot;:2,&quot;type&quot;:null},&quot;content&quot;:[{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;Google &amp; Amazon Web Services &#8212; unified platform culture&quot;}]}]}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;At the largest scale, Google and AWS set examples of platform thinking: SRE/platform teams codify deployment patterns, guardrails, and observability. Teams owning product features lean on platform primitives (IAM, KMS, managed registries) rather than inventing bespoke workflows. For ML, both invest heavily in model governance tooling (registries, metadata, reproducible pipelines) and encourage centralization of expensive compute.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;Pattern to note:&quot;},{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot; platform teams + standardized primitives reduce drift and enable fast, safe scaling.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;italic&quot;}],&quot;text&quot;:&quot;Also, a contrasting case study and intentional by Cloudflare&quot;}]},{&quot;type&quot;:&quot;orderedList&quot;,&quot;attrs&quot;:{&quot;start&quot;:3,&quot;type&quot;:null},&quot;content&quot;:[{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;Cloudflare &#8212; edge-native capabilities&quot;}]}]}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Cloudflare&#8217;s stack is deliberately edge-native: Workers, KV, and global routing enable running meaningful compute at POPs. That capability is powerful for low-latency personalization and caching, but it also requires disciplined use when you&#8217;re serving ML-backed features &#8212; otherwise you risk global fan-out of expensive inference.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;Pattern to note:&quot;},{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot; edge compute is powerful; use it for safe, stateless ops or extremely lightweight personalization &#8212; not for heavy inference unless you have strong disciple in terms of setting limits &amp; cost controls.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;To summarise,&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Large, well-engineered platforms (think Netflix and Uber) treat the edge as a &quot;},{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;italic&quot;}],&quot;text&quot;:&quot;traffic director&quot;},{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;, not a compute engine: aggressive caching and lightweight client/edge logic for responsiveness, with heavy stateful work &#8212; auth, model resolution, inference, and telemetry &#8212; resolved in a centralized control plane. That pattern preserves developer velocity where it matters while keeping inference cost, reproducibility, and governance tightly controlled. The organizational enabler is unified engineering: small platform teams that own CI &#8594; CDN &#8594; inference and rotate engineers across layers so the system evolves with discipline rather than accreting accidental AI debt.&quot;}]}]},&quot;restacks&quot;:0,&quot;reaction_count&quot;:0,&quot;children_count&quot;:0,&quot;attachments&quot;:[{&quot;id&quot;:&quot;c1a8951d-2079-499f-a5b5-af42dac3dd31&quot;,&quot;type&quot;:&quot;image&quot;,&quot;imageUrl&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8339661b-c38e-4720-8c44-d62e24d426fb_1024x1536.png&quot;,&quot;imageWidth&quot;:1024,&quot;imageHeight&quot;:1536,&quot;explicit&quot;:false}],&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;user_id&quot;:12091074,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;user_bestseller_tier&quot;:null,&quot;userStatus&quot;:{&quot;bestsellerTier&quot;:null,&quot;subscriberTier&quot;:1,&quot;leaderboard&quot;:null,&quot;vip&quot;:false,&quot;badge&quot;:{&quot;type&quot;:&quot;subscriber&quot;,&quot;tier&quot;:1,&quot;accent_colors&quot;:null},&quot;subscriber&quot;:null}},&quot;source&quot;:null,&quot;forumChannel&quot;:null}" data-component-name="CommentPlaceholder"></div><p>My argument was that convenient shortcuts can eventually accumulate into what I called <strong>AI debt</strong>: runaway costs, reproducibility gaps, and debugging opacity.</p><p>That argument was written from conviction.</p><p>This one is written from production.</p><p>I launched <strong><a href="https://parjanya.phagyul.ai">Parjanya v2.0</a></strong>, our multi-tenant SaaS platform for professional photographers, as a self-serve trial on 1st August 2026. </p><div class="pullquote"><p>Under the hood, it runs a self-hosted 8B-parameter vision-language model, Qwen3-VL-8B in 4-bit quantization, alongside Google&#8217;s SigLIP 2 for semantic-search embeddings.</p></div><p>The system has processed individual photography sessions containing 12,000 images and roughly 450 GB in a single pass, and today serves tens of thousands of requests a week.</p><p>Between the first sprint in March and the July launch, I went through four complete architecture generations.</p><p>Almost every generation boundary came down to the same question:</p><h3><strong>Do I buy the platform, or do I own the primitive?</strong></h3><p>Sometimes I adopted the managed service. Sometimes I replaced it. And sometimes I came very close to replacing a primitive with a managed service, only to run the numbers and walk away.</p><p>The four headline decisions were:</p><ol><li><p><strong>SageMaker vs. Bedrock vs. raw AWS primitives for VLM and SigLIP 2 inference</strong></p></li><li><p><strong>Vercel vs. S3 + CloudFront for the React + TypeScript frontend</strong></p></li><li><p><strong>OpenRouter vs. a self-hosted model gateway</strong></p></li><li><p><strong>Clerk vs. Cognito + SES for authentication and transactional email</strong></p></li></ol><p>There were also three less glamorous decisions that ended up moving the bill more than some of the headline ones:</p><ul><li><p><strong>Spot and Graviton</strong></p></li><li><p><strong>OpenSearch and Step Functions</strong></p></li><li><p><strong>CloudWatch, networking and storage classes</strong></p></li></ul><p>For each decision, I wanted to understand not only what the comparison tables said, but what actually happened after the architecture met production.</p><p>That distinction turned out to matter enormously.</p><p>My operating rule today is simple:</p><blockquote><p><strong>Buy managed services for their operations, not their defaults &#8212; and leave them when their cost floor or cold start starts fighting your workload.</strong></p></blockquote><div><hr></div><h1>1. SageMaker vs. Bedrock vs. AWS Primitives</h1><h2>The decision at the center of Parjanya</h2><p>The heart of Parjanya is batch visual inference.</p><p>A photographer uploads a session &#8212; routinely 4,000 or more images, and sometimes 12,000. Every image that passes a cheap deterministic technical-quality gate is scored by the VLM and embedded using SigLIP 2.</p><p>The workload characteristics are important because they tell me almost immediately where the different approaches will fit.</p><p>The workload is <strong>bursty</strong>, not steady.</p><p>A queue can go from zero to thousands of images and then return to zero. There can be days when almost nothing arrives.</p><p>It is also <strong>batch tolerant</strong>.</p><p>Nobody needs a score in 200 milliseconds. What matters is that 4,000 images are processed by morning.</p><p>It is <strong>privacy sensitive</strong>.</p><p>These are often unreleased professional photographs belonging to clients. Keeping image bytes inside our VPC is not merely an architectural preference; it is something I can actually explain to a customer.</p><p>And finally, the economics are dominated by <strong>GPU time</strong>.</p><p>Before optimization, GPU compute represented well over half of the entire bill.</p><p>That combination &#8212; bursty, batch-oriented, private and GPU-heavy &#8212; became the single biggest predictor of which architecture made sense.</p><h2>I started with SageMaker</h2><p>The obvious managed options were Bedrock and SageMaker.</p><p>Bedrock represented the pure developer-experience end of the spectrum: API calls, no infrastructure, no cold-start management and managed models.</p><p>SageMaker sat somewhere in the middle: managed infrastructure around our own container and model.</p><p>Raw AWS primitives were the opposite end: EC2 GPU instances, Auto Scaling, SQS, SNS, CloudWatch and an AMI with the model baked in.</p><p>I used all three lenses, and two of them in anger.</p><p>Generation 2 ran on SageMaker.</p><p>I started with a BYOC real-time endpoint and then moved to Batch Transform.</p><p>SageMaker did exactly what I expected it to do: it got me to a working GPU pipeline quickly.</p><p>That is the promise of DX, and in this case, it delivered.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;e2b6428c-4861-4a3b-aa19-352f2c62e1ed&quot;,&quot;caption&quot;:&quot;As a follow-up to the original engineering note on Parjanya v2.0, this deep dive explores the architectural decisions, operational lessons, and production incidents that shaped the migration away from Amazon SageMaker toward a purpose-built AWS-native inference orchestration platform.&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;When SageMaker Wasn't the Problem&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-06-24T05:23:41.049Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!QzHI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_1536x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/when-sagemaker-wasnt-the-problem&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:203346926,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>Then two things happened.</p><h3>Quantization changed the economics more than the platform did</h3><p>Qwen3-VL-8B in BF16 wants roughly 16 GB of VRAM.</p><p>A T4 has exactly 16 GB &#8212; and does not support BF16.</p><p>Moving to NF4 4-bit quantization using bitsandbytes brought VRAM usage down to roughly 5 GB, which made an 8B model practical on a T4.</p><p>More importantly, it produced a roughly <strong>13&#215; per-image speedup</strong>.</p><p>Our batch cost collapsed from approximately <strong>$500 to $40&#8211;50</strong>.</p><p>That was my first major lesson from self-hosting:</p><blockquote><p><strong>The model configuration can be a much bigger cost lever than the hosting substrate.</strong></p></blockquote><p>A managed platform doesn&#8217;t automatically pull that lever for you.</p><h3>Then SageMaker&#8217;s operational shape started fighting the workload</h3><p>The first problem was cold starts.</p><p>The managed endpoint took on the order of ten minutes to become useful, largely because of model-weight loading.</p><p>Our replacement &#8212; an AMI/NVMe-staged model running on a raw EC2 GPU worker &#8212; loads roughly 17 GB of weights in under two minutes.</p><p>For a workload that scales from zero, warmup <em>is</em> latency.</p><p>The second problem was the cost floor.</p><p>A real-time endpoint costs money every hour it exists, whether a single image arrives or not.</p><p>One GPU endpoint represented a standing tax of roughly $500+ per month.</p><p>At one point, I discovered a forgotten endpoint costing almost <strong>$870/month</strong>.</p><p>Our worst single day was roughly <strong>$1,000</strong>, around three to four times our typical monthly development spend at the time. The root cause was endpoint provisioning and extended runs.</p><p>The most important early optimization was almost embarrassingly simple: a scheduled shutdown Lambda.</p><p>We kept the endpoint warm only during a seven-hour nightly window, which reduced its cost by roughly 70%, from about <strong>$540 to $160 per month</strong>.</p><p>That taught me something I now use as a general diagnostic:</p><blockquote><p><strong>When your best optimization for a managed platform is a cron job that turns the platform off, your workload and the platform&#8217;s default posture probably disagree.</strong></p></blockquote><p>The third problem was debuggability.</p><p>When something went wrong on primitives, I could inspect a queue, an alarm, an Auto Scaling event and a container log.</p><p>Everything was directly readable.</p><p>On the managed platform, the same investigation often disappeared behind an abstraction that I could not see through as clearly.</p><p>That was ultimately what made the decision for me.</p><h2>I moved to EC2 Spot</h2><p>In April, Generation 3 deprecated SageMaker entirely.</p><p>I moved to EC2 Spot GPU workers &#8212; primarily the g4dn family with NVIDIA T4s &#8212; inside an Auto Scaling group driven by SQS queue depth.</p><p>The fleet genuinely scales to zero.</p><p>The minimum size is zero.</p><p>A scheduler Lambda watches the queue every two minutes, and the scale-in rule only fires after both visible and in-flight messages have been zero for five consecutive minutes.</p><p>For Spot interruptions, I added a five-second metadata poll.</p><p>The worker finishes the current image, checkpoints the state to DynamoDB and exits cleanly.</p><p>After months in production, we have lost <strong>zero images to Spot interruption</strong>.</p><p>The result was substantially better than our early expectations.</p><p>Our largest autonomous run drained roughly <strong>2,400 images in under eight hours on four Spot GPUs</strong>, scaled itself back to zero three minutes after the queue emptied, and required no operator intervention.</p><p>The total bill was approximately <strong>$20</strong>.</p><p>Pure GPU inference now costs roughly <strong>$0.002&#8211;0.005 per image</strong>, or around <strong>$0.005&#8211;0.008 all-in</strong>.</p><p>Compared with the SageMaker era, that is an order-of-magnitude difference.</p><p>Overall platform cost fell by roughly <strong>65&#8211;75%</strong> from its pre-optimization peak.</p><p>At our worst, we were spending around $80&#8211;90/day.</p><p>Under load today, it is closer to $20&#8211;30/day, with an idle floor around $5/day.</p><p>Spot itself delivered a measured <strong>56&#8211;61% saving</strong> against on-demand, roughly $0.26&#8211;0.29/hour versus about $0.55/hour for a T4 in Mumbai.</p><p>I also ran an A/B test of going 100% Spot.</p><p>It beat its own forecast.</p><p>Drain time roughly halved, cost per message fell by around 60%, and we experienced zero interruptions.</p><p>The written verdict was simply:</p><p><strong>Stay 100% Spot.</strong></p><p>There was another Spot lesson that was less obvious.</p><p>I now treat quota increases as <strong>spend risk</strong>, not simply performance capacity.</p><p>The cost is in instance-hours, not instance count. Increasing a GPU quota to &#8220;improve throughput&#8221; also increases the maximum possible blast radius on the bill.</p><p>I manage the on-demand/Spot quota ratio as deliberately as I manage the fleet itself.</p><h2>What about Bedrock?</h2><p>I did not dismiss Bedrock.</p><p>I benchmarked it.</p><p>A managed vision API came in at roughly <strong>$0.01/image</strong>.</p><p>Our Spot fleet sits around <strong>$0.002&#8211;0.005/image</strong>.</p><p>That is a 2&#8211;5&#215; gap, but it exists because I am doing three things simultaneously:</p><ul><li><p>scaling to zero</p></li><li><p>running a quantized model</p></li><li><p>using Spot capacity</p></li></ul><p>If I ran the same fleet on-demand and kept it always on (warm), Bedrock would win.</p><p>I keep that Bedrock number as a standing benchmark.</p><p>The day the fleet stops being well run, I want the spreadsheet to tell me so.</p><p>There are also two reasons I would keep self-hosting even if the economics reached parity:</p><ol><li><p>Image bytes never leave our VPC.</p></li><li><p>I control model version pinning completely.</p></li></ol><p>Those are not spreadsheet variables.</p><h2>What the industry says</h2><p>The broader industry experience broadly supports this progression.</p><p>Discord describes a deliberate strategy of prototyping against managed frontier APIs to validate whether current-generation models can solve the product problem, then moving to self-hosted open models once scale justifies the operational burden. <a href="https://discord.com/blog/developing-rapidly-with-generative-ai">https://discord.com/blog/developing-rapidly-with-generative-ai</a></p><p>Shopify built its Merlin ML platform on open-source primitives rather than committing to a managed ML platform, largely because its teams had conflicting requirements and needed a frictionless prototype-to-production path.</p><p><a href="https://shopify.engineering/merlin-shopify-machine-learning-platform">https://shopify.engineering/merlin-shopify-machine-learning-platform</a></p><p>Independent comparisons generally place the self-hosting break-even around 10&#8211;20k requests/day, with much larger savings at higher volumes.</p><p>And AWS itself frames Bedrock versus SageMaker as a genuine trade-off between serverless convenience and control.</p><p>My experience added a third fork:</p><p><strong>sometimes the right answer is neither.</strong></p><p>Sometimes the right answer is EC2, SQS and an AMI.</p><h2>What production taught me that comparison tables didn&#8217;t</h2><p>The first lesson was that primitives compose &#8212; but not freely.</p><p>Our warm-pool design passed architecture review and failed during </p><p><code>terraform apply</code>.</p><p>AWS does not allow a warm pool on an Auto Scaling group with a mixed-instances policy.</p><p>The DIY tax isn&#8217;t necessarily writing more Terraform.</p><p>It is discovering the composition rules the hard way.</p><p>The second lesson was that design numbers are not production numbers.</p><p>Our AMI-bake design promised roughly 90-second model loads.</p><p>Fresh instances actually took <strong>30&#8211;40 minutes</strong>.</p><p>Lazy EBS restore meant a new instance reading 17 GB of untouched blocks crawled at single-digit MB/s.</p><p>The solution was NVMe staging.</p><p>It brought the 17 GB load down to under two minutes &#8212; measured in production.</p><p>I now put a date and configuration hash next to every performance number in our documentation.</p><p>Benchmark rot is a debt class.</p><p>The third lesson was about deterministic gates.</p><p>Before anything reaches a GPU, a sub-cent Lambda gate rejects technically unusable files.</p><p>That rewrite replaced an earlier ML-based scorer, reducing that stage&#8217;s cost by roughly <strong>90%</strong>, from around $13 to less than $1/month, while also reducing its cold start from about 15 seconds to roughly two seconds.</p><p>More importantly, the deterministic rule engine owns the accept/reject decision.</p><p>If I change the curation policy, I can replay stored model outputs through the new rules in under a minute for pennies.</p><p>I do not need to run the GPU again.</p><blockquote><p><strong>The cheapest inference is the inference I skip. The second cheapest is the inference I never have to redo.</strong></p></blockquote><p>And then there was the prompt.</p><p>The prompt is infrastructure.</p><p>Our worst GPU incident was a CUDA out-of-memory crash caused not by the model or the fleet, but by prompt creep.</p><p>The scoring prompt had quietly grown beyond 4,000 tokens.</p><p>Instead of buying a larger GPU at twice the price, I audited the prompt and cut it by roughly 60%.</p><p>A lot of the removed instruction was teaching the model to produce outputs that the deterministic rule engine downstream deliberately ignored.</p><p>I was literally paying VRAM to generate information the system threw away.</p><p>On a 16 GB card, token budgets are a debt ceiling.</p><div><hr></div><h1>2. Vercel vs. S3 + CloudFront</h1><p>The frontend is a React 19 + TypeScript + Vite SPA.</p><p>It contains the gallery, curation workflow, uploads and administration interface, and serves photographers globally while the FastAPI backend runs in Mumbai.</p><p>During launch, I needed fast global static delivery, many deployments a day, instant rollback and strict security headers.</p><p>The default answer in 2026 is Vercel.</p><p>And I understand why.</p><p>Git-push deployments, preview environments, an edge network and almost no infrastructure knowledge required.</p><p>But I chose <strong>S3 + CloudFront</strong>.</p><p>The deployment pipeline is intentionally boring:</p><p><strong>Vite build &#8594; S3 sync &#8594; CloudFront invalidation</strong></p><p>GitHub Actions handles it through OIDC.</p><p>Merging to <code>main</code> deploys development.</p><p>Production remains a manual, human-triggered workflow.</p><p>The cache design does most of the work.</p><p>Hashed assets under <code>/assets/*</code> are immutable and carry a one-year TTL.</p><p><code>index.html</code> gets a 60-second TTL.</p><p>That makes the cache policy itself the deployment lever.</p><p>A release becomes globally visible within about a minute, and rollback is simply redeploying the previous build.</p><p>Security headers &#8212; HSTS with preload, frame-deny and nosniff &#8212; are handled by a CloudFront response-headers policy.</p><p>The cost is generally in the single-digit dollars per month and, most months, sits inside the free tier.</p><p>The reason I chose it was not that Vercel is bad.</p><p>It was that <strong>the frontend was not where I needed Vercel&#8217;s strengths</strong>.</p><p>Cached SPA loads from London, New York and Sydney are already measured in tens of milliseconds.</p><p>What users actually feel is the dynamic API round trip to Mumbai.</p><p>A page making three to five sequential API calls can add more than a second from North America or Europe.</p><p>No edge frontend platform can fix that.</p><p>The answer is API design: batching, caching and eventually regional read replicas.</p><p>That reinforced the thesis I started with:</p><blockquote><p><strong>The edge is a traffic director, not a compute executor.</strong></p></blockquote><p>Static assets and routing belong at the edge.</p><p>Authentication, model resolution, inference and telemetry remain centralized.</p><p>For a Vite SPA, the DX delta was also surprisingly small.</p><p>Vercel&#8217;s real advantage appears in SSR, ISR, preview deployments and framework-integrated serverless functions.</p><p>I wasn&#8217;t using most of those features.</p><p>For me, the DX advantage amounted largely to one GitHub Action.</p><p>The third consideration was cost topology.</p><p>S3 + CloudFront scales predictably with traffic.</p><p>Platform function pricing scales with invocations &#8212; precisely the axis I hope will explode as Parjanya grows.</p><p>I didn&#8217;t reject Vercel.</p><p>I simply didn&#8217;t want to pay a platform premium for capabilities my architecture wasn&#8217;t using.</p><div><hr></div><h1>3. OpenRouter vs. a Self-Hosted Gateway</h1><p>Every AI product eventually has to answer four questions:</p><ul><li><p>Which model serves this request?</p></li><li><p>What happens when it becomes unavailable?</p></li><li><p>Who tracks the spend?</p></li><li><p>Whose infrastructure sees the payload?</p></li></ul><p>Managed gateways such as OpenRouter answer these questions across hundreds of hosted models.</p><p>One API key.</p><p>Automatic fallback.</p><p>Unified billing.</p><p>For Parjanya, however, there was a twist.</p><p>Our production models are self-hosted open weights:</p><ul><li><p>Qwen3-VL-8B</p></li><li><p>SigLIP 2</p></li></ul><p>They run on our own GPUs.</p><p>There is no third-party inference endpoint sitting in the hot path.</p><p>So I asked a slightly different question:</p><p><strong>What plays the role of the gateway when the models are mine?</strong></p><p>I ended up decomposing the gateway into primitives.</p><p>Model resolution is a three-tier loading ladder on the GPU worker.</p><p><strong>Tier 1:</strong> weights staged on local NVMe from the AMI bake.</p><p><strong>Tier 2:</strong> S3 synchronization fallback.</p><p><strong>Tier 3:</strong> Hugging Face download.</p><p>Every load records the tier.</p><p>In healthy production, I should only ever see Tier 1.</p><p>A Tier 2 or Tier 3 log line is therefore an alert.</p><p>I also made the upstream dependency deliberately boring.</p><p>Hugging Face is contacted exactly once per model version, during AMI baking in CI.</p><p>Production instances never download models from it.</p><p>A scheduled job compares the upstream model commit hash with our baked AMI tags and tells a human when a rebake is worth considering.</p><p>That gives me something I care about enormously in an inference system:</p><p><strong>model versions are pinned by construction.</strong></p><p>Fallback is handled by the mixed-instances policy across GPU families and the loading ladder.</p><p>Spend accounting comes from CloudWatch and tagged infrastructure.</p><p>Every inference dollar can be attributed to an EC2 line item.</p><p>For our particular architecture, a managed gateway would introduce three structural costs:</p><ol><li><p>A per-request economic layer.</p></li><li><p>A data-path layer where client payloads transit someone else&#8217;s infrastructure.</p></li><li><p>A rate-limit layer where our ceiling becomes somebody else&#8217;s policy.</p></li></ol><p>OpenRouter&#8217;s published model, for example, includes roughly a 5% platform fee on provider pass-through pricing.</p><p>For a self-hosted, single-model, VPC-contained workload, I don&#8217;t get enough routing benefit to justify those layers.</p><p>But there is an important concession here.</p><p>If I were calling frontier hosted models, I would absolutely use a gateway.</p><p>And I would probably use a managed one first.</p><p>Standing up LiteLLM with a database, cache and pager before I have meaningful multi-provider traffic is premature infrastructure.</p><p>The gateway decision comes <strong>after</strong> the hosting decision.</p><p>It is not independent of it.</p><h2>The lesson from our fallback</h2><p>A fallback I have never exercised is not a fallback.</p><p>For a while, our Tier 2 S3 fallback was configuration theater.</p><p>The environment variables existed in the design.</p><p>They were never actually injected into the container.</p><p>The fallback existed on paper and nowhere else.</p><p>I fixed it by deliberately breaking Tier 1 and watching what happened.</p><p>That is one of the biggest operational differences between managed and primitive systems:</p><p><strong>if I decompose a managed capability, I inherit the obligation to rehearse every part of it.</strong></p><div><hr></div><h1>4. Clerk vs. Cognito + SES</h1><p>Authentication was the closest call.</p><p>Parjanya needs multi-tenant signup, email/password authentication, JWTs carrying an immutable tenant identifier, trial limits and transactional email for verification and password resets.</p><p>Clerk is extremely attractive here.</p><p>Polished UI.</p><p>Session management.</p><p>A much nicer developer experience.</p><p>And, critically, email that simply works.</p><p>The alternative was Cognito + SES.</p><p>I chose Cognito + SES.</p><h2>Why</h2><p>First, economics.</p><p>At our current scale, Cognito costs us essentially nothing under its applicable MAU threshold and remains materially cheaper through the growth range we are targeting.</p><p>For a product whose unit economics depend on very high gross margins on per-image pricing, a permanent per-MAU platform fee is a margin haircut on every future user.</p><p>Second, and more importantly:</p><p><strong>the token is the tenancy model.</strong></p><p>Our JWTs carry an immutable <code>tenant_id</code> claim.</p><p>The backend verifies it using RS256 against Cognito&#8217;s JWKS, deliberately avoiding a signing secret in the backend.</p><p>Every S3 bucket policy and DynamoDB access pattern keys off that claim.</p><p>The backend issues short-lived, tag-scoped STS credentials per tenant.</p><p>Buckets are per-tenant.</p><p>KMS keys are per-tenant.</p><p>Cross-tenant access is explicitly denied at the policy layer.</p><p>Auth is therefore not just a login box.</p><p>It is the root of the isolation tree.</p><p>I wanted that root inside the same Terraform, account boundary and audit trail as everything it protects.</p><p>A hosted authentication provider can issue my token.</p><p>But it cannot itself be the IAM principal that my storage policies deny against.</p><p>Third, there is the privacy argument.</p><p>One bill.</p><p>One IAM boundary.</p><p>No additional identity-data processor.</p><p>For a privacy-positioned product, that is a sales answer as much as it is an architecture answer.</p><h2>And then DIY sent me the bill</h2><p>This is where I think infrastructure writing is often too polite.</p><p>The DIY option has a cost.</p><p>I want to list mine.</p><p>Cognito immutable attributes really are immutable.</p><p>I verified that in production.</p><p>Get your custom claims right the first time.</p><p>Schema changes can also be pool-destroying.</p><p>Adding a new schema attribute through Terraform can force user-pool replacement and therefore destroy every user account.</p><p>I added a role claim through the CLI instead, knowingly accepting permanent drift for that resource.</p><p>Cognito also does not support cross-account user-pool migration.</p><p>When we reorganized into a multi-account AWS organization, the pool&#8217;s location became a one-way door.</p><p>Either users would re-register or we would face a mass password reset.</p><p>Then there were session bugs.</p><p>Our frontend token cache survived logout.</p><p>User two could briefly see user one&#8217;s data until I added an explicit cache clear at every login boundary.</p><p>Presigned upload URLs had another subtle problem.</p><p>They inherit the STS credential&#8217;s expiry rather than the nominal URL lifetime.</p><p>An upload presigned at minute zero failed at minute 61 with a signature that looked valid.</p><p>These are precisely the integration bugs that a mature hosted authentication SDK has probably already encountered.</p><p>And then there was email.</p><p>Cognito&#8217;s default email channel has a 50-email/day per-pool cap and is best effort.</p><p>During launch, password-reset emails were silently dropped.</p><p>The API returned success.</p><p>CloudTrail recorded the event.</p><p>No email arrived.</p><p>That is one of the worst failure modes in distributed systems:</p><blockquote><p><strong>The lying green checkmark.</strong></p></blockquote><p>The fix was SES with a verified domain, DKIM and developer sending enabled through Cognito.</p><p>That led into SES production-access review.</p><p>Our first request was denied, almost certainly because our submission said too little about bounce handling.</p><p>SES sandbox status became the sole external blocker on our release lock.</p><p>We eventually documented the ordering constraint in red:</p><p><strong>auto-confirm cannot be switched off while SES is sandboxed, or every signup breaks.</strong></p><p>This is exactly where Clerk&#8217;s pitch becomes compelling.</p><p>You don&#8217;t have to think about any of this.</p><p>And during launch week, that matters.</p><p>DIY auth is paid for in calendar time and attention.</p><p>Those were the two currencies I had the least of during launch.</p><h2>My verdict</h2><p>Cognito + SES was right for Parjanya.</p><p>But it was the closest decision of the four.</p><p>The SES saga is actually the strongest argument for DX in this entire post.</p><p>A managed platform&#8217;s ability to make an entire class of launch-week failures impossible has real value.</p><p>If authentication were not the root of our isolation model, I would have been much more comfortable paying a per-MAU platform fee at seed scale.</p><div><hr></div><h1>5. The Decisions That Don&#8217;t Make Blog Titles</h1><p>Some of the decisions that affected the bill the most had nothing to do with DX platforms.</p><h2>Spot &#8212; and learning when a lever isn&#8217;t a lever</h2><p>The Spot decision gets most of the attention because the savings are obvious.</p><p>We measured roughly 56&#8211;61% savings versus on-demand.</p><p>Our A/B test of 100% Spot beat its forecast. There are additional optimisations like cost-performance optimisation by AWS, which I will detail in upcoming posts.</p><p>Interruption handling has lost zero images.</p><p>We even measured Spot pricing within the region and found that availability-zone prices for the same instance type could differ by more than 50%.</p><p>So the fleet biases toward the cheaper zone.</p><p>But some fashionable optimizations simply failed the arithmetic.</p><p>Multi-region Spot arbitrage died because inter-region data transfer consumed most of the projected savings.</p><p>A neighboring region also turned out not to have GPU capacity to arbitrage in the first place.</p><p>The more interesting story was Graviton.</p><p>Our first Graviton audit found that only one of four Lambda functions could even run on ARM64.</p><p>Native dependency wheels, CUDA and unbenchmarked inference libraries blocked the rest.</p><p>The projected saving was approximately <strong>0.4% of the total bill</strong> &#8212; about a quarter of a dollar per month.</p><p>Meanwhile, quantization, Spot and scheduling were saving 40&#8211;60%.</p><p>So I wrote down the conclusion and walked away:</p><blockquote><p><strong>Sometimes the best architecture decision is knowing where not to spend your engineering time.</strong></p></blockquote><p>Months later, a dependency shipped ARM64 wheels.</p><p>The blocker disappeared.</p><p>We revisited the decision and migrated.</p><p>The measured Lambda saving was approximately <strong>20%</strong>, almost exactly what we had projected.</p><p>Both halves of the story matter.</p><p>I needed the discipline to defer a fashionable optimization.</p><p>But I also needed the paper trail that allowed me to revisit it later without starting the research from scratch.</p><p>My rule now is simple:</p><blockquote><p><strong>A two-hour ARM benchmark costs pennies and beats two weeks of debugging a premature migration.</strong></p></blockquote><p>And I never flip Terraform to ARM64 before the image has actually run there.</p><div><hr></div><h1>6. OpenSearch and Step Functions</h1><p>Two other managed services lost to arithmetic.</p><h3>Search</h3><p>I kept search in-process.</p><p>No OpenSearch.</p><p>No external vector database.</p><p>At our scale, the smallest useful OpenSearch domain costs more per month than our entire reconciliation control plane costs per year.</p><p>Rather than guessing, I measured the ceiling.</p><p>Today, search latency is around two seconds at a few thousand rows and degrades toward the load balancer timeout somewhere beyond 100k rows.</p><p>So I wrote down the trigger:</p><p><strong>roughly 30 tenants.</strong></p><p>That is when OpenSearch becomes a yes.</p><p>SigLIP 2 vectors are already ready for a proper vector store when that trigger fires.</p><h3>Orchestration</h3><p>I also rejected Step Functions and workflow engines.</p><p>Our orchestration is a roughly 200-line reconciler.</p><p>DynamoDB Streams provide the fast path.</p><p>An hourly sweep provides the backstop.</p><p>The entire control plane costs a few cents a month.</p><p>I made the same arithmetic-driven decision around AWS Config and commercial compliance tooling.</p><p>A weekly EventBridge + Lambda audit covers the rules we actually need at effectively zero cost.</p><p>There is a famous industry parallel here: Amazon&#8217;s Prime Video team moved a monitoring service away from Step Functions and Lambda to a plain ECS monolith and reported roughly 90% lower infrastructure cost.</p><p>But DIY orchestration has its own failure modes.</p><p>Our replay Lambda once lost a single IAM permission and logged <code>AccessDenied</code> on every invocation for half a day.</p><p>The dashboards stayed green.</p><p>Hundreds of images stalled.</p><p>Nothing drained.</p><p>Then, on our launch-baseline day, the reconciler itself became the incident.</p><p>A read-amplification bug caused it to consume tens of millions of DynamoDB read units in 24 hours.</p><p>The bill was roughly $15/day.</p><p>The pipeline itself was almost entirely healthy.</p><p>The repair mechanism had become the damage.</p><p>I added targeted query guards and reduced that spend by roughly 85&#8211;90%.</p><p>Both incidents ended as code.</p><p>An alarm on silence.</p><p>A conditional-write guard.</p><p>A query guard.</p><p>That is an important property of primitives:</p><blockquote><p><strong>Institutional memory can become code.</strong></p></blockquote><div><hr></div><h1>7. Where the Bill Actually Hides</h1><p>Three numbers changed how I think about infrastructure.</p><p>The first was CloudWatch.</p><p>Ungoverned CloudWatch can quietly consume 20&#8211;40% of a small platform&#8217;s operating cost.</p><p>A single chatty DEBUG-level Lambda can generate roughly $20+/month in log ingestion &#8212; more than our entire early operating budget for that stage.</p><p>Embedded Metric Format instead of per-call metric APIs saved around $15/month by itself.</p><p>Composite alarms reduced alarm costs by roughly 70%.</p><p>I also stopped creating per-tenant dashboards.</p><p>At $3/dashboard/month, that becomes a fixed cost that scales in exactly the wrong direction.</p><p>With those changes, observability fell back to a few dollars per month.</p><p>The second number was networking.</p><p>While investigating that roughly $20 autonomous GPU drain run, I discovered that almost half the bill wasn&#8217;t GPU time.</p><p>It was NAT gateway egress from around 180 GB of S3 reads.</p><p>The GPU wasn&#8217;t the expensive part.</p><p>The data path was.</p><p>VPC gateway endpoints for S3 and DynamoDB eliminated most of that cost and had already saved roughly $30&#8211;45/month of standing NAT expense.</p><p>A handful of interface endpoints cut the remaining NAT data by another ~80%.</p><p>That was another reminder that no SageMaker-vs-EC2 comparison table is going to tell you that your data path may cost more than your compute.</p><p>The third number was storage.</p><p>At photography scale, storage-class economics matter.</p><p>I rejected S3 Intelligent-Tiering for previews because its per-1,000-object monitoring fee becomes meaningful when you have millions of tiny files.</p><p>Instead, previews go directly into Infrequent Access, around 46% cheaper than Standard in our region.</p><p>Originals step down to Glacier Instant Retrieval, around 83% cheaper.</p><p>Rejected images move to Deep Archive after a grace period.</p><p>At 10 TB of rejected images, that&#8217;s roughly $10/month.</p><p>The result is about <strong>3.7&#215; cheaper</strong> than na&#239;vely keeping everything in Standard.</p><p>The broader industry has demonstrated this at enormous scale.</p><p>Canva, for example, moved tens of billions of objects to Glacier Instant Retrieval after measuring that access collapses after the first couple of weeks, saving millions annually.</p><p>The meta-lesson for me was even simpler.</p><p>Our weekly audit Lambda costs effectively nothing.</p><p>It caught roughly <strong>7,500 objects sitting in the wrong storage class for months</strong>.</p><p>It also found an S3 versioning configuration where the console suggested around 2,000 objects while the bucket actually contained more than 100,000 hidden version objects.</p><p>Left unchecked, that could have grown into millions of noncurrent versions, terabytes of invisible storage and a 5&#8211;10&#215; inflated storage bill.</p><p>On primitives, <strong>audit is the platform</strong>.</p><div><hr></div><h1>8. The Incident Ledger</h1><p>A fair DIY-versus-DX discussion has to include the incident ledger.</p><p>The operational burden that managed platforms sell against is real.</p><p>Between the first sprint and the post-launch study window, I logged <strong>17 incidents across 12 classes</strong>.</p><p>Here are a few.</p><p>Terraform drift nearly became a self-inflicted outage.</p><p>After weeks of console-side firefighting, a routine Terraform plan came back with:</p><p><strong>173 to add.<br>127 to destroy.</strong></p><p>A blind apply would have deleted the NAT gateway, the DynamoDB table containing every VLM verdict and the Cognito user pool containing every login.</p><p>Getting back to a clean 0/0/0 state took roughly four focused hours spread across four days.</p><p>A managed DX platform wouldn&#8217;t have given me that state file.</p><p>But it also wouldn&#8217;t have given me a state file proving exactly what production was.</p><p>There was a six-hour preview outage caused by deleting the wrong &#8220;stale&#8221; grant.</p><p>What looked like a leftover origin-access policy was actually the live one.</p><p>Every preview returned 403 until I restored it.</p><p>There was a burst-photography incident caused by a silently failing install.</p><p>A shell <code>|| echo</code> swallowed both a 404 and a missing archive.</p><p>We shipped a worker image without its EXIF tool.</p><p>Near-identical burst frames then started being falsely rejected as duplicates.</p><p>Launch went out with exact-match-only deduplication as the safe setting.</p><p>There was a wrong-bucket incident where hundreds of images hung on repeated download errors because queue payloads contained a valid key pointing to the wrong bucket.</p><p>And there was a weekend bulk import where messages silently expired from SQS because queue retention was shorter than the weekend.</p><p>Retention is now an invariant with a name.</p><p>Not a default.</p><p>These incidents sound like arguments against primitives.</p><p>I actually think they demonstrate the opposite.</p><p>Every incident ended as code:</p><ul><li><p>a Terraform validation block</p></li><li><p>a conditional write</p></li><li><p>a CI grep</p></li><li><p>a CloudWatch alarm</p></li><li><p>a queue invariant</p></li></ul><p>Institutional memory became executable.</p><p>And across all 17 incidents, recurrence after adding the guardrails is currently <strong>zero</strong>.</p><p>That is the bargain I am making with primitives.</p><p>I accept the initial operational burden in exchange for owning the system completely enough to turn every lesson into a permanent constraint.</p><p>The multi-account reorganization was another example.</p><p>It was triggered partly by a deployment script accidentally pushing to production from the wrong local context.</p><p>The reorganization added roughly $10/month in duplicated audit tooling and moved around 135 GB of data for pennies.</p><p>In return, it dramatically reduced blast radius.</p><p>That kind of control is difficult to purchase from a single-tenant DX platform&#8217;s pricing page.</p><h2>One uncomfortable AI footnote</h2><p>Parjanya was substantially AI-assisted in its construction.</p><p>Two of the nastiest silent failures in the incident ledger &#8212; the swallowed <code>exiftool</code> installation and a bare-except registry writer &#8212; were both machine-written and machine-reviewed code.</p><p>Their common property was silence.</p><p>The answer wasn&#8217;t to use less automation.</p><p>It was to write better contracts:</p><ul><li><p>CI greps for exception-swallowing patterns</p></li><li><p>log-line contracts for every pipeline tier</p></li><li><p>alarms on absence</p></li><li><p>explicit invariants</p></li></ul><p>The same discipline that makes primitives operable also makes AI-written code operable.</p><div><hr></div><h1>9. The Repatriation Debate, From the Cheap Seats</h1><p>All of this sits inside the much larger cloud-versus-hardware debate.</p><p>37signals has made the case for leaving the cloud, with a reported reduction from roughly $3.2M to $1.3M annually and projected savings of more than $10M over five years.</p><p>Ahrefs has argued that owned hardware saved them hundreds of millions compared with AWS list pricing.</p><p>Canva has taken almost the opposite position: stay in the cloud, but become extremely good at engineering the bill.</p><p>At Parjanya&#8217;s scale, I&#8217;m much closer to Canva&#8217;s school.</p><p>But I think there is an important distinction.</p><p>I haven&#8217;t left the cloud.</p><p>I also haven&#8217;t left managed services.</p><p>DynamoDB, SQS, Lambda, CloudFront and Cognito are still managed services in our architecture.</p><p>I keep them because I want their operations.</p><p>What I left were the managed services whose <strong>cost floors and cold starts fought the workload</strong>.</p><p>A real-time inference endpoint billing through the night for a queue that is empty by midnight isn&#8217;t an operations benefit.</p><p>It is a subscription to someone else&#8217;s default posture.</p><p>That is the distinction I think the broader repatriation debate sometimes misses.</p><p>It isn&#8217;t really:</p><p><strong>cloud vs. metal</strong></p><p>or:</p><p><strong>platform vs. primitives</strong></p><p>It is:</p><blockquote><p><strong>What is the right economic and operational shape for each individual workload?</strong></p></blockquote><p>And that answer should be re-run when the workload changes.</p><div><hr></div><h1>10. The Decision Framework I Use Now</h1><p>After five months and four architecture generations, I have reduced the decision process to four questions.</p><h2>1. Is the expensive part of the hot path bursty?</h2><p>If yes, the platform&#8217;s cost floor may be your enemy.</p><p>Scale-to-zero primitives are probably worth the setup cost.</p><p>If the load is steady, the cost floor becomes less relevant and the managed platform&#8217;s operational value may be worth buying.</p><p>That one question explains why I left SageMaker, benchmarked and declined Bedrock, declined Vercel and kept DynamoDB on-demand.</p><h2>2. When it breaks at 2 a.m., can I read the failure surface?</h2><p>This ultimately mattered more to me than cost.</p><p>A queue.</p><p>An alarm.</p><p>An Auto Scaling event.</p><p>A container log.</p><p>These are things I can read.</p><p>If my team cannot or does not want to own that failure surface, the managed abstraction is doing real work for us.</p><p>I should pay for it.</p><h2>3. What currency does the DIY option cost &#8212; and do I have that currency right now?</h2><p>Cognito + SES cost me launch-week calendar time.</p><p>That was the scarcest resource I had.</p><p>The exact same decision at another point in the company&#8217;s life would have cost almost nothing.</p><p>So I no longer think only in dollars.</p><p>I ask:</p><p><strong>What resource am I actually short of?</strong></p><p>Money?</p><p>Engineering hours?</p><p>Attention?</p><p>Launch-week calendar time?</p><p>Operational confidence?</p><p>The right architecture can change depending on the answer.</p><h2>4. Have I written down the condition that would reverse my decision?</h2><p>This is probably the most useful practice I have adopted.</p><p>A &#8220;no&#8221; is not a permanent architectural belief.</p><p>It is a decision with a trigger.</p><p>For example:</p><ul><li><p>vLLM becomes a yes around 500 active users or sustained 100+ images/minute.</p></li><li><p>OpenSearch becomes a yes around 30 tenants.</p></li><li><p>The monorepo decision changes with team growth.</p></li></ul><p>Every rejected option gets an <strong>un-rejection trigger</strong>.</p><p>That turns architecture from ideology into a portfolio that I can rebalance.</p><div><hr></div><h1>The Operating Sentence</h1><p>The note that started this journey argued that high-performing platforms should choose <strong>DX where it helps, and control where it matters</strong>.</p><p>After a launch, four architecture generations, seventeen logged incidents and a roughly two-thirds reduction in our platform bill, I would sharpen that sentence.</p><p>This is the rule I now keep at the top of our architecture decision register:</p><blockquote><p><strong>Buy managed services for their operations, not their defaults. Leave them when their cost floor or cold start fights your workload. And put deterministic gates around expensive models &#8212; the cheapest inference is the inference you skip.</strong></p></blockquote><p>Parjanya v2.0 is now live as a self-serve trial.</p><p>The production system runs Qwen3-VL-8B in NF4 and SigLIP 2 So400M on scale-to-zero Spot GPU workers in <code>ap-south-1</code>.</p><p>Everything sits behind a deterministic rule engine that owns every accept/reject decision.</p><p>The model observes.</p><p><strong>The system decides.</strong></p><p>And, perhaps more importantly, I now have a much clearer idea of when I want a platform to make the hard parts disappear &#8212; and when I would rather own the hard parts myself.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png" width="1456" height="189" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:189,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[When SageMaker Wasn't the Problem]]></title><description><![CDATA[The Parjanya v2.0 case study: how AWS primitives replaced a managed ML platform through reconciliation, replay, and event-driven orchestration]]></description><link>https://blog.phagyul.ai/p/when-sagemaker-wasnt-the-problem</link><guid isPermaLink="false">https://blog.phagyul.ai/p/when-sagemaker-wasnt-the-problem</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Wed, 24 Jun 2026 05:23:41 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!QzHI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a follow-up to the original engineering note on Parjanya v2.0, this deep dive explores the architectural decisions, operational lessons, and production incidents that shaped the migration away from Amazon SageMaker toward a purpose-built AWS-native inference orchestration platform.</p><p>The original note documented how a <em><strong>combination of EC2 GPU warm pools, Auto Scaling Groups, SQS, EventBridge, DynamoDB Streams, and pre-baked GPU AMIs enabled Parjanya to eliminate SageMaker cold-start penalties, achieve scale-to-zero economics, and build a replay-native control plane capable of self-repair and reconciliation</strong></em>. Rather than treating GPU inference as a model-serving problem, the architecture reframed it as an orchestration and reconciliation problem, resulting in dramatically lower startup latency, parallel execution, improved replay safety, and reduced operational cost.</p><p>This article expands on that foundation by examining the complete system architecture, the TBIE (Truth, Belief, Intent, Execution) operating model, the move from polling to event-driven reconciliation, and the real production incidents that ultimately shaped the platform&#8217;s reliability model.</p><h3>EXECUTIVE SUMMARY</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QzHI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QzHI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!QzHI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!QzHI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!QzHI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QzHI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4da6209a-e84d-4b8d-b391-3ad31aaa2e69_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;:1537810,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/203346926?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_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_!QzHI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!QzHI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!QzHI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!QzHI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4da6209a-e84d-4b8d-b391-3ad31aaa2e69_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Parjanya v2.0 is Phagyul AI&#8217;s image ingestion and GPU-based visual scoring, later evolved as curation platform by replacing score engine to rule engine. </p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;dc8842b8-bd28-4ff0-a8f2-d08d86644c7c&quot;,&quot;caption&quot;:&quot;I did not set out to replace a scoring engine with a rule engine. I set out to make the system cheaper, easier to explain, and less fragile as I was not keen on moving to g5.xlarge or g6.xlarge due to prompt sizes increased and would be lot of churn in terms of architectural and infra changes, comes with re testing every functionality and the increase i&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;From Score Engine to Rule Engine: Why I Rebuilt the Decision Layer&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-05-14T11:27:06.000Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!UKjF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5df5ef7-0eb5-4b90-88c2-f0f4439a82d6_1536x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/from-score-engine-to-rule-engine&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:197643272,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>Its nightly VLM inference pipeline was originally built on Amazon SageMaker. The pipeline processed photographer uploads using Qwen3-8B-VLM and worked &#8212; but it revealed a fundamental architectural mismatch over time. Wall-clock time regularly stretched to ~11 hours. Cold starts ate into every nightly window. Replay handling for failed enrichments grew fragile. Sequential execution prevented scale-out. And persistent managed-platform overhead stopped making financial sense for burst-only workloads.<br>The core insight that drove the migration was a reframing of the problem. The question was no longer </p><blockquote><p><strong>&#8216;how do we run a model?&#8217;</strong> </p></blockquote><p>It became: </p><blockquote><p><strong>&#8216;how do we orchestrate burst-scale inference reliably, replay safely, and cost-efficiently?&#8217;</strong> </p></blockquote><p>That reframing led to retiring SageMaker and rebuilding the pipeline entirely from native AWS primitives &#8212; EC2 GPU warm pools, Auto Scaling Groups, SQS-driven orchestration, EventBridge-triggered scale-out, and pre-baked GPU AMIs with Qwen3-8B-VLM weights embedded.</p><div class="comment" data-attrs="{&quot;url&quot;:&quot;https://open.substack.com/&quot;,&quot;commentId&quot;:263136758,&quot;comment&quot;:{&quot;id&quot;:263136758,&quot;date&quot;:&quot;2026-05-22T03:22:43.452Z&quot;,&quot;edited_at&quot;:null,&quot;body&quot;:&quot;Over the past few weeks, I&#8217;ve been working on a deep dive around one of the most interesting production transitions we made in Parjanya v2.0 under the TBIE case study series.\n\nI have retired a SageMaker-based VLM inference pipeline that processed uploaded photographer images nightly using Qwen3-8BVLM.\n\nThe original system worked.\n\nBut operationally, it exposed a deeper architectural mismatch.\n\nEvery nightly batch incurred GPU cold starts before the first image could even be processed. Replay handling for failed enrichments became increasingly fragile. Sequential execution slowed the overall pipeline. And for a workload that only needed burst GPU inference during specific windows, the managed overhead simply stopped making sense.\n\nThe pipeline regularly stretched close to ~11 hours wall-clock.\n\nWhat became obvious after observing the system in production was this:\n\nThe problem was no longer &#8220;how do we run a model?&#8221;\n\nThe real problem was: &#8220;How do we orchestrate burst-scale inference reliably, replay safely, and cost efficiently?&#8221;\n\nThat led to rebuilding the pipeline using native AWS primitives:\n\n\n\n\n\nEC2 GPU warm pools\n\n\n\nAuto Scaling Groups\n\n\n\nSQS-driven orchestration\n\n\n\nEventBridge-triggered scale-out\n\n\n\nPre-baked GPU AMIs with Qwen3-8B-VLM weights\n\n\n\nTBIE reconciliation for replay verification and automated recovery\n\nThe outcome was more than cost optimization.\n\nIt fundamentally changed how the system behaved operationally:\n\n\n\n\n\nnear-zero or sub-minute startup latency\n\n\n\nparallel GPU workers replacing sequential processing\n\n\n\nevent-driven replay handling\n\n\n\nscale-to-demand orchestration\n\n\n\ndrastically reduced idle GPU waste\n\nThe upcoming write-up is not just about infrastructure changes.\n\nIt is a deep dive into how TBIE reconciliation patterns were applied in Parjanya v2.0 to build replay-safe, scalable GPU inference orchestration in production.\n\nOn Monday, I&#8217;ll be sharing the full TBIE case study deep dive covering:\n\n\n\n\n\nwhy the original architecture struggled\n\n\n\nthe reasoning behind the migration\n\n\n\nreconciliation-driven orchestration\n\n\n\nreplay-safe enrichment pipelines\n\n\n\nburst-scale GPU worker design\n\n\n\nlessons learned from operating the system in production\n\nOne of the biggest lessons from this transition:\n\nNot every AI workload needs a managed ML platform.\n\nSometimes the real engineering challenge sits in orchestration, reconciliation, and operational resilience.&quot;,&quot;body_json&quot;:{&quot;type&quot;:&quot;doc&quot;,&quot;attrs&quot;:{&quot;schemaVersion&quot;:&quot;v1&quot;,&quot;title&quot;:null},&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Over the past few weeks, I&#8217;ve been working on a deep dive around one of the most interesting production transitions we made in Parjanya v2.0 under the TBIE case study series.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;I have retired a SageMaker-based VLM inference pipeline that processed uploaded photographer images nightly using Qwen3-8BVLM.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;bold&quot;}],&quot;text&quot;:&quot;The original system worked.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;But operationally, it exposed a deeper architectural mismatch.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Every nightly batch incurred GPU cold starts before the first image could even be processed. Replay handling for failed enrichments became increasingly fragile. Sequential execution slowed the overall pipeline. And for a workload that only needed burst GPU inference during specific windows, the managed overhead simply stopped making sense.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;The pipeline regularly stretched close to ~11 hours wall-clock.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;What became obvious after observing the system in production was this:&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;The problem was no longer &#8220;how do we run a model?&#8221;&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;marks&quot;:[{&quot;type&quot;:&quot;code&quot;}],&quot;text&quot;:&quot;The real problem was: &#8220;How do we orchestrate burst-scale inference reliably, replay safely, and cost efficiently?&#8221;&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;That led to rebuilding the pipeline using native AWS primitives:&quot;}]},{&quot;type&quot;:&quot;bulletList&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;EC2 GPU warm pools&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Auto Scaling Groups&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;SQS-driven orchestration&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;EventBridge-triggered scale-out&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Pre-baked GPU AMIs with Qwen3-8B-VLM weights&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;TBIE reconciliation for replay verification and automated recovery&quot;}]}]}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;The outcome was more than cost optimization.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;It fundamentally changed how the system behaved operationally:&quot;}]},{&quot;type&quot;:&quot;bulletList&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;near-zero or sub-minute startup latency&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;parallel GPU workers replacing sequential processing&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;event-driven replay handling&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;scale-to-demand orchestration&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;drastically reduced idle GPU waste&quot;}]}]}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;The upcoming write-up is not just about infrastructure changes.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;It is a deep dive into how TBIE reconciliation patterns were applied in Parjanya v2.0 to build replay-safe, scalable GPU inference orchestration in production.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;On Monday, I&#8217;ll be sharing the full TBIE case study deep dive covering:&quot;}]},{&quot;type&quot;:&quot;bulletList&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;why the original architecture struggled&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;the reasoning behind the migration&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;reconciliation-driven orchestration&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;replay-safe enrichment pipelines&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;burst-scale GPU worker design&quot;}]}]},{&quot;type&quot;:&quot;listItem&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;lessons learned from operating the system in production&quot;}]}]}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;One of the biggest lessons from this transition:&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Not every AI workload needs a managed ML platform.&quot;}]},{&quot;type&quot;:&quot;paragraph&quot;,&quot;content&quot;:[{&quot;type&quot;:&quot;text&quot;,&quot;text&quot;:&quot;Sometimes the real engineering challenge sits in orchestration, reconciliation, and operational resilience.&quot;}]}]},&quot;restacks&quot;:0,&quot;reaction_count&quot;:0,&quot;children_count&quot;:0,&quot;attachments&quot;:[{&quot;id&quot;:&quot;86f8c144-cee6-4a2d-9c22-124f46099fc5&quot;,&quot;type&quot;:&quot;image&quot;,&quot;imageUrl&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fa14b656-f349-498c-8608-dd4e34858433_1672x941.png&quot;,&quot;imageWidth&quot;:1672,&quot;imageHeight&quot;:941,&quot;explicit&quot;:false}],&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;user_id&quot;:12091074,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;user_bestseller_tier&quot;:null,&quot;userStatus&quot;:{&quot;bestsellerTier&quot;:null,&quot;subscriberTier&quot;:1,&quot;leaderboard&quot;:null,&quot;vip&quot;:false,&quot;badge&quot;:{&quot;type&quot;:&quot;subscriber&quot;,&quot;tier&quot;:1,&quot;accent_colors&quot;:null},&quot;subscriber&quot;:null}},&quot;source&quot;:null,&quot;forumChannel&quot;:null}" data-component-name="CommentPlaceholder"></div><p><br>This is a detailed internal engineering deep dive into that migration. It covers the original architecture and its failure modes, the design decisions behind each new component, how TBIE (Truth, Belief, Intent, Execution) reconciliation patterns were applied to make the system replay-safe and operationally resilient, the specific production incidents encountered and how each shaped the architecture, and the guardrails now embedded to prevent regression.<br>Key outcome: the rebuilt system achieved near-zero or sub-minute startup latency, parallel GPU workers replacing sequential processing, event-driven replay handling, scale-to-demand orchestration, and drastically reduced idle GPU waste. More importantly, it became a system that could reason about and repair its own state &#8212; a reconciliation system, not just a pipeline.</p><h2>BACKGROUND: WHAT IS PARJANYA V2.0?</h2><p>Parjanya v2.0 is the image ingestion and GPU-powered visual scoring platform at Phagyul AI Systems. Photographers upload raw images; the platform extracts technical metadata (EXIF, resolution, format), performs visual-language model inference to produce content quality scores, enforces content policy, and writes enriched metadata back to the workflow database.</p><p><strong>The data flow is:</strong></p><ul><li><p>Photographers upload images to per-tenant S3 buckets via browser-based presigned URLs &#8594; An S3 event triggers a Graviton Lambda for EXIF extraction and technical validation.</p></li><li><p>On successful validation, a DynamoDB workflow row is written with status <code>pending_vlm_enrichment</code>.</p></li><li><p>A GPU worker consumes this work, runs <strong>Qwen3-8B-VLM inference</strong>, and writes scored metadata back(later recuration) to DynamoDB.</p></li><li><p>A control plane (replay Lambda, reconciliation loop) monitors for stalled or missing work and re-orchestrates as needed.</p></li><li><p>The platform spans immutable uploads (S3), workflow state (DynamoDB), intent queues (SQS), Lambda orchestration, GPU autoscaling (ASG + EC2), browser-side uploads with CORS policies, content policy enforcement, and tenant isolation.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Xv1J!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42b8942d-8039-4017-8555-afd877e2f0d7_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Xv1J!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42b8942d-8039-4017-8555-afd877e2f0d7_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Xv1J!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42b8942d-8039-4017-8555-afd877e2f0d7_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Xv1J!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42b8942d-8039-4017-8555-afd877e2f0d7_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Xv1J!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42b8942d-8039-4017-8555-afd877e2f0d7_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Xv1J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42b8942d-8039-4017-8555-afd877e2f0d7_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/42b8942d-8039-4017-8555-afd877e2f0d7_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;:1482571,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/203346926?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42b8942d-8039-4017-8555-afd877e2f0d7_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_!Xv1J!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42b8942d-8039-4017-8555-afd877e2f0d7_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Xv1J!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42b8942d-8039-4017-8555-afd877e2f0d7_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Xv1J!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42b8942d-8039-4017-8555-afd877e2f0d7_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Xv1J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42b8942d-8039-4017-8555-afd877e2f0d7_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h3>THE ORIGINAL SAGEMAKER PIPELINE</h3><p>Parjanya&#8217;s first VLM inference implementation used Amazon SageMaker as the compute platform. A nightly batch job was triggered on a schedule. SageMaker endpoints were provisioned, images were submitted for inference in sequence, results were collected, and endpoints were torn down.</p><p>The original system worked. It produced correct results. But it had structural problems that compounded as the platform grew:</p><ul><li><p><strong>Cold-start tax:</strong> Every nightly run incurred GPU cold starts before the first image could be processed.</p></li><li><p><strong>Sequential execution:</strong> Image inference ran sequentially across the batch; there was no parallelism at the worker level.</p></li><li><p><strong>Fragile replay</strong>: Failed enrichments required increasingly fragile custom replay logic layered on top of SageMaker&#8217;s job model.</p></li><li><p><strong>Idle cost</strong>: The platform was billed for managed infrastructure overhead even during windows with no work to do.</p></li><li><p><strong>Throughput ceiling</strong>: Wall-clock time regularly stretched to approximately 11 hours per nightly run.</p></li></ul><h2>THE ARCHITECTURAL REFRAMING</h2><p>The decision to migrate was not triggered by a single catastrophic failure. It was triggered by a change in how the problem was understood.</p><div class="pullquote"><p><strong>&#8220;The problem was no longer &#8216;how do we run a model?&#8217;</strong><br>The real problem was: <strong>&#8216;how do we orchestrate burst-scale inference reliably, replay safely, and cost efficiently?&#8217;&#8221;</strong></p></div><p>Once the problem was stated that way, SageMaker was the wrong tool. SageMaker is an excellent managed platform for running models. It is not designed to be a burst-scale GPU orchestration layer with event-driven replay. Those properties had to be bolted on from outside, which is why the replay logic was fragile and why cold start latency was unavoidable.<br>Native AWS primitives offered a better fit for the actual problem: EC2 GPU instances could be pre-baked with model weights, Auto Scaling Groups could scale to demand rather than a fixed schedule, SQS provided durable, replayable intent, and EventBridge could trigger orchestration the moment new work appeared. The result is not a simpler system &#8212; it is a more intentional one.</p><h2>THE NEW ARCHITECTURE: NATIVE AWS- PRIMITIVES</h2><h3>EC2 GPU WARM POOLS</h3><p>Rather than provisioning GPU instances from scratch each time a job runs, Parjanya v2.0 uses EC2 warm pools attached to the Auto Scaling Group. Instances are pre-initialised and held in a stopped or standby state. When the ASG scales out, warm pool instances start in seconds rather than minutes, eliminating the cold start latency that dominated the original SageMaker pipeline.</p><blockquote><p><strong>Warm pool design note:</strong> instances in the warm pool must be pre-baked with model weights already on disk. Do not rely on model download during instance boot &#8212; download failures become silent launch failures. The AMI is the contract between infrastructure and runtime.</p></blockquote><h3>PRE-BAKED GPU AMIs WITH QWEN3-8B-VLM WEIGHTS</h3><p>Each GPU AMI is built with the <strong>Qwen3-8B-VLM</strong> model weights, runtime dependencies, and worker application code baked in. The AMI is immutable. When a new model version or dependency is needed, a new AMI is built and the launch template is updated. This makes the execution environment reproducible and testable before deployment.</p><h4>Key constraints on AMI design:</h4><p>All model weights must be present at AMI build time &#8212; no remote download at boot.<br>Python environment, CUDA libraries, and worker scripts must be included in the AMI.</p><p>The launch template image tag and the AMI must be kept in sync; stale launch templates are a production risk (see Incident 6).</p><p>Container and model artifact versions are a compatibility pair &#8212; they must be validated together.</p><h3>AUTO SCALING GROUPS (ASG)</h3><p>An Auto Scaling Group manages the GPU worker fleet. The ASG is configured with a minimum of 0 instances (scale-to-zero for cost efficiency) and a maximum that reflects the burst capacity needed during active processing windows. Desired capacity is driven by queue depth rather than a schedule.</p><h4>ASG configuration decisions:</h4><ol><li><p>Scale-out is triggered by the replay Lambda when SQS queue depth exceeds threshold.</p></li><li><p>Scale-in is time-based to prevent premature termination of in-flight workers.</p></li><li><p>Instance type selection balances GPU memory requirements (Qwen3-8B-VLM needs sufficient VRAM) against cost per inference.</p></li><li><p>Warm pool instances buffer the latency between a scale-out trigger and first inference.</p></li></ol><h3>SQS-DRIVEN ORCHESTRATION</h3><p>SQS is the durable intent layer. Each message represents a single VLM inference job for one image. Messages are not ephemeral transport &#8212; they are the replayable journal of work that must happen. This is a TBIE design principle: intent must survive transient failure.</p><h4>SQS configuration decisions:</h4><ul><li><p>Visibility timeout is set to exceed the maximum realistic inference time to prevent duplicate processing.</p></li><li><p>Queue retention is set to exceed the maximum expected outage window (e.g., weekend + holiday gap) so intent survives scale-to-zero periods.</p></li><li><p>A dead-letter queue captures messages that exceed the maximum receive count, enabling manual triage of terminal failures.</p></li><li><p>Message attributes carry routing metadata: tenant ID, image key, source bucket, expected output location.</p></li><li><p>Queue retention is not a generic operational setting. It is a resilience parameter. If the GPU fleet is at zero for 3 days, messages must still be present when the fleet wakes up. Set retention to match your worst-case outage window, not a default.</p></li></ul><h3>EVENTBRIDGE-TRIGGERED SCALE-OUT</h3><p>Scale-out is event-driven via EventBridge and DynamoDB Streams. When a DynamoDB row reaches <code>pending_vlm_enrichment</code>, the stream emits an event. A stream processor filters and batches records, then invokes the replay Lambda. The replay Lambda evaluates queue state (Belief) against database state (Truth), emits SQS messages (Intent), and increases ASG desired capacity (Execution trigger).<br>This replaces a polling model where a scheduled timer would periodically scan for work. The event-driven approach gives lower latency, eliminates wasted invocations during quiet periods, and makes the system&#8217;s reaction to new work causally clear:</p><blockquote><p><strong>Truth changes &#8594; control plane notices &#8594; Intent is created &#8594; Execution follows.</strong></p></blockquote><h3>REPLAY LAMBDA (CONTROL PLANE)</h3><p>The replay Lambda is the reconciliation control plane. It is invoked by DynamoDB Streams and by periodic safety-net schedules. Its job is to compare Truth (DynamoDB workflow state) against Intent (SQS queue depth) and repair any divergence: emitting missing messages, resetting stale state, and triggering ASG scale-out when work is present.<br>The replay Lambda is a first-class reliability surface, not a background helper. If it fails silently, every other safety net becomes weaker. Its observability must be stronger than ordinary worker observability.<br>Monitor its error rate, execution duration, and whether it successfully reads queue attributes. A lambda that runs but cannot see queue state is functionally blind.</p><h2>TBIE: TRUTH, BELIEF, INTENT, EXECUTION</h2><p>TBIE is the operating model used to design, debug, and evolve Parjanya v2.0. It decomposes a distributed system into four conceptually distinct layers. The model is most valuable as a diagnostic tool: when the system behaves unexpectedly, TBIE provides a structured vocabulary for identifying which layer has diverged.</p><h3>TRUTH</h3><p>Truth is the durable, authoritative record of what is actually true. It must survive worker restarts, deploys, transient outages, and infrastructure drift.<br>In Parjanya v2.0, Truth lives in:</p><p>S3 &#8212; immutable image uploads and preview artifacts. If an object is in S3, it exists.</p><p>DynamoDB &#8212; workflow rows recording status, EXIF metadata, VLM scores, curation state, and hashes.</p><p>Derived committed state &#8212; VLM output written durably after successful inference.</p><p><strong>Truth answers questions like: </strong></p><ul><li><p>What objects exist? </p></li><li><p>What stage is this image in? </p></li><li><p>What has been computed? </p></li><li><p>What is the authoritative record for this batch?</p></li></ul><h3>BELIEF</h3><p>Belief is the operational view of reality. It is derived from Truth and current signals, but it may lag, be partial, or be noisy. Belief is what operators see first &#8212; but it must never be confused with source-of-record Truth.</p><p>In Parjanya, Belief includes:</p><ol><li><p>SQS queue depth and in-flight message counts.</p></li><li><p>ASG desired capacity, running instance count, and warm pool state.</p></li><li><p>Worker health signals and CloudWatch alarms.</p></li><li><p>GPU availability and instance lifecycle state.</p></li></ol><p>A healthy Belief is not the same as a healthy system. The queue can appear empty while Truth still holds a large pending backlog. That gap is a reconciliation failure, not an idle system.</p><h3>INTENT</h3><p>Intent is the durable record of work that has been requested. It is the replayable journal of &#8216;<em>please do this work</em>.&#8217; </p><p>The critical property of Intent is replayability: if Intent can be lost too early, transient failures become permanent failures requiring manual rescue.</p><p>In Parjanya, Intent is:</p><ul><li><p>SQS messages &#8212; each representing a single VLM inference job.</p></li><li><p>Replay jobs &#8212; reconstructed Intent emitted for rows that had pending Truth without corresponding queue messages.</p></li><li><p>Regrade jobs &#8212; Intent emitted for historical reprocessing after policy changes.</p></li></ul><h3>EXECUTION</h3><p>Execution is the stateless work that turns Intent into side effects and updated Truth. Execution is where work happens, but in a resilient system it must never be allowed to erase the record of what was supposed to happen.</p><p>In Parjanya, Execution includes:</p><ul><li><p>Graviton Lambdas for EXIF extraction and technical validation.</p></li><li><p>GPU workers running Qwen3-8B-VLM inference and writing scored results to DynamoDB.</p></li><li><p>Replay Lambda emitting Intent and triggering ASG scale-out.</p></li><li><p>ASG and EC2 actions that instantiate the worker fleet.</p></li></ul><h3>TBIE AS A DIAGNOSTIC MODEL</h3><p>The power of TBIE is operational. Once internalised, it changes the first question asked during any incident. The question is no longer &#8216;<em>is the queue healthy?</em>&#8217; or &#8216;<em>are the GPU workers running?</em>&#8217; Those are Belief signals. The real question is:</p><blockquote><p><strong>Is the system waiting because Intent is missing &#8212; or because Intent is present but Execution cannot realise it?</strong></p></blockquote><p>That single question narrows the search space dramatically and prevents wasted time on the wrong layer.</p><h2>EVENT-DRIVEN RECONCILIATION</h2><p>Parjanya initially used a scheduled polling model. A timer would wake the replay Lambda periodically. The Lambda would scan for pending work and, if appropriate, emit SQS messages and trigger GPU autoscaling. This worked but introduced avoidable latency, wasted invocations, and operational ambiguity.<br>The move to DynamoDB Streams changed the architecture fundamentally. Now, when a workflow row reaches pending_vlm_enrichment, the stream emits an event immediately. An event source mapping filters for relevant writes, batches records briefly, and invokes the replay Lambda. The Lambda discovers missing or retriable work, emits Intent into SQS, and kicks the GPU ASG when necessary.</p><h4><strong>The net effect:</strong></h4><p>Reconciliation latency dropped from <code>O(poll_interval) to O(stream_propagation)</code> &#8212; typically seconds.</p><ul><li><p>Wasted Lambda invocations during idle periods eliminated.</p></li><li><p>Causal chain made explicit: Truth changes &#8594; stream emits &#8594; Lambda reacts &#8594; Intent created &#8594; Execution follows.</p></li><li><p>Operators can reason about system state without wondering &#8216;has the next poll happened yet?&#8217;</p></li><li><p>A reconciliation system does not rely on humans noticing a stalled queue and manually fixing it. </p></li></ul><p>It detects, explains, and repairs the divergence between Truth and Intent on its own. Event-driven streaming is what makes that self-repair fast enough to be useful in production.</p><h2>PRODUCTION FAILURE MODES &amp; LESSONS</h2><p>The following incidents occurred during the development and operation of Parjanya v2.0. Each is documented here not as a post-mortem but as a design lesson &#8212; how the failure shaped the architecture, and what guardrail was added as a result. TBIE is used throughout as the diagnostic lens.</p><h3>Incident 1: Transient GPU Failure Destroying Intent</h3><p>GPU workers were deleting SQS messages before the retry window had been exhausted. A worker could encounter a temporary S3 download failure or an OOM condition, write a failure status to DynamoDB, and still delete the queue message. At that point, Truth said the work had failed, but Intent no longer existed &#8212; the system had no automatic path to retry.</p><h4>TBIE diagnosis: Execution destroyed Intent prematurely.</h4><h4><strong>Resolution</strong>: </h4><p>Workers now return explicit outcome signals: retry, terminal_failure, or completed.</p><p><strong>retry</strong>: preserve the message. Visibility timeout and receive count govern re-attempts.</p><p><strong>terminal_failure</strong>: write durable failed Truth, then delete the message.</p><p><strong>completed</strong>: write final Truth, then delete the message.</p><p>That separation preserves replayability while still allowing durable failure when necessary. The message deletion decision became a function of execution outcome, not a side effect of worker exit.</p><h1>Worker outcome protocol</h1><p><code>if outcome == &#8216;retry&#8217;:<br># Do NOT delete. Let visibility timeout expire.<br>  return # SQS will re-deliver<br>elif outcome == &#8216;terminal_failure&#8217;:<br>  write_durable_failure(db, image_id)<br>  sqs.delete_message(receipt_handle)<br>elif outcome == &#8216;completed&#8217;:<br>  write_enriched_truth(db, image_id, scores)<br>  sqs.delete_message(receipt_handle)</code></p><h3>Incident 2: Pending Truth Without Intent (Reconciliation Gap)</h3><p>DynamoDB rows remained in <code>pending_vlm_enrichment</code> status, but no corresponding SQS messages existed. Queue depth showed zero. The system appeared idle. The backlog still existed in Truth but was invisible to Execution.</p><h4>TBIE diagnosis: Truth was pending while Intent never existed. Classic reconciliation gap.</h4><h4><strong>Resolution</strong>:</h4><ul><li><p>The replay Lambda now scans for pending rows without corresponding queue messages.</p></li><li><p>For each orphaned pending row, it regenerates a queue message and kicks the GPU ASG.</p></li><li><p>DynamoDB Streams ensure this scan is triggered promptly rather than waiting for a polling cycle.</p></li><li><p>The key insight: this is not a worker bug. Workers cannot fix work that was never queued. The control plane must own the responsibility of keeping Truth and Intent aligned.</p></li></ul><h3>Incident 3: Retry vs. Replay Distinction</h3><p>Some failures &#8212; S3 download errors, temporary GPU OOM &#8212; are retryable once the underlying condition is fixed. But simply re-enqueueing the message is insufficient when the workflow row contains partial or stale derived fields from the failed attempt.</p><h4>TBIE clarification: </h4><h4>a retry is another attempt at the same execution. A replay is a deliberate reset to a pre-execution boundary, removal of stale derived state, and emission of fresh Intent.</h4><h4><strong>Resolution</strong>:</h4><p><strong>Retry</strong>: re-attempt on the existing message, preserving current workflow state.</p><p><strong>Replay</strong>: reset the DynamoDB row to a clean pre-VLM boundary (clear stale score fields, VLM status, partial outputs), then emit a fresh SQS message.</p><p>Replay is a controlled reconstruction, not just another attempt on top of corrupted state. The distinction prevents accumulating corrupted derived fields across multiple failed attempts.</p><h3>Incident 4: Wrong Bucket, Right Key (Deterministic Misrouting)</h3><p>An SQS payload pointed to a valid preview key but in the wrong bucket. The worker repeatedly failed with S3 download errors even though the file existed &#8212; just not at that address. This was deterministic misrouting, not flaky execution.</p><h4>TBIE diagnosis: Intent encoded the wrong target. Not an Execution failure &#8212; an Intent construction failure.</h4><h4><strong>Resolution:</strong></h4><p>Preview keys now canonically use the uploads bucket as the authoritative source.<br>Intent construction validates bucket routing before emitting to SQS.<br>Eligibility checks were tightened: only objects confirmed present in the correct bucket are enqueued.<br>The lesson generalises: Intent must encode the correct target, not just some valid key. A message that is &#8216;almost correct&#8217; will fail deterministically and indefinitely until the Intent itself is repaired.</p><h3>Incident 5: Policy Change Requiring Historical Replay</h3><p>Content policy was updated to more strictly reject non-photographic content: screenshots, banners, infographics, social cards, slides, illustrations, and mockups. Historical images scored under the old policy needed to be re-evaluated.</p><h4>TBIE framing: policy change = controlled replay, not a patching exercise.</h4><h4><strong>Resolution:</strong></h4><p>Affected rows were identified by policy version marker in DynamoDB.<br>Each affected row was reset to a pre-VLM boundary: stale score fields cleared, VLM status reset to pending.<br>Fresh Intent was emitted into SQS so GPU workers re-scored under the new policy.<br>This is one of the most powerful properties of a replay-native system: policy evolution does not require one-off correction scripts. It becomes a controlled reprocessing event with clear before-and-after semantics. The same replay machinery used for failure recovery also handles deliberate re-evaluation.</p><h3>Incident 6: Execution Drift Below the Application Layer</h3><p>Two distinct incidents exposed failures where application code was correct but the execution environment was stale.</p><h4>6a: Stale Launch Template (Image Tag)</h4><p>A launch template continued to reference an old image tag that no longer existed. Cloud-init failed when pulling the nonexistent container image, and the GPU instance came up without ever starting the worker. The worker log group was empty &#8212; the application layer never ran.<br>Complete silence in the GPU log group is a critical signal. It usually means execution failed before the application layer started: image pull failure, IAM denial during bootstrap, or cloud-init crash.</p><h4>6b: Incomplete AMI (Missing Model Artifacts)</h4><p>A separate incident involved an AMI that was missing the Python files required by Qwen3-8B-VLM (a model that relies on remote code). The container started successfully, but the model loader crashed because local artifacts were incomplete.</p><h4><strong>Resolution &#8212; both incidents:</strong></h4><ul><li><p>Launch templates now include version assertions checked at deployment time.<br>AMI build pipelines validate the presence and integrity of all model artifacts before publishing.</p></li><li><p>Container version and model artifact version are treated as a compatibility pair, validated together.</p></li><li><p>Deployment tooling refreshes launch templates automatically when image tags change.</p></li></ul><h3>Incident 7: CORS and Browser Upload Split-State Failure</h3><p>The backend could write a pending upload record and generate a presigned URL, but the browser&#8217;s PUT could fail because of CORS misconfiguration. In that case, Truth at the API layer looked correct while Execution at the browser layer never completed.<br>Investigation revealed multiple independent configuration failures could co-exist: a bucket rejecting wildcard origins under restricted public bucket settings, while the client simultaneously used a global S3 endpoint that returned redirects that browsers would not follow on OPTIONS preflight.</p><h4>TBIE diagnosis: </h4><h4>Intent existed (presigned URL generated, pending row written). Execution was blocked by infrastructure configuration drift. Two independent misconfiguration layers were both wrong simultaneously.</h4><h4><strong>Resolution:</strong></h4><ul><li><p>CORS policies are version-controlled and validated in CI before deployment.</p></li><li><p>Bucket CORS and public access settings are treated as a matched pair, not configured independently.</p></li><li><p>Upload path includes client-side detection of presigned URL PUT failure with structured error reporting.</p></li><li><p>Pending rows created without a completed upload are detected by the replay Lambda and age-gated before re-emission.</p></li></ul><h3>Incident 8: Control Plane Blindness (Replay Lambda IAM Failure)</h3><p>The replay Lambda lacked permission to read SQS queue attributes. The function continued to be scheduled and invoked, but it crashed before it could inspect Belief (queue depth) or emit Intent. From the outside, everything appeared enabled. In reality, the control plane had gone blind.</p><p>This is the most dangerous failure mode in the system. A silently failing control plane means every other safety net weakens simultaneously. Worker failures that should self-repair accumulate without rescue. Operators see green infrastructure dashboards while reconciliation has effectively stopped.</p><h4><strong>Resolution:</strong></h4><ul><li><p>The replay Lambda&#8217;s IAM policy now explicitly grants <code>sqs:GetQueueAttributes</code>, <code>sqs:GetQueueUrl</code>, and <code>sqs:SendMessage</code>.</p></li><li><p>IAM policy drift is checked in deployment assertions &#8212; the Lambda will not deploy if required permissions are absent.</p></li><li><p>The Lambda now emits a structured heartbeat metric on every successful invocation, including after inspecting queue state.</p></li><li><p>Alarm on absence of heartbeat metric: silence means the control plane has likely failed.</p></li></ul><p>The operational philosophy shift from this incident: worker failures are recoverable noise. Control-plane blindness is a systemic risk. Observability on the control plane must be stronger than on individual workers.</p><h3>Incident 9: Dynamic Tenant Discovery and Queue Retention</h3><p>As the platform grew, static tenant lists became a bottleneck. Reconciliation could not depend on manually editing infrastructure configuration every time a new tenant was onboarded. Additionally, when the GPU fleet was scaled to zero for cost savings, queue retention was set too short &#8212; messages expired before the fleet woke up.</p><h4>Resolution:</h4><p>The control plane moved to dynamic tenant discovery from DynamoDB. Tenant registry markers are written by the upload path and discovered by the replay Lambda at runtime.<br>Queue retention policy was extended to match the maximum expected outage window, not an idealised constant.<br>New tenant onboarding now automatically creates the required DynamoDB registry marker without manual infrastructure changes.</p><h2>OPERATIONAL MODEL AND RUNBOOK THINKING</h2><p>By the time Parjanya matured into an event-driven reconciliation system, the debugging approach itself had changed. The starting question is no longer &#8216;<em><strong>is the queue healthy?</strong></em>&#8217; or &#8216;<em><strong>are GPU workers running?</strong></em>&#8217; &#8212; those are <strong>Belief signals</strong>. Every incident investigation now begins with a TBIE classification:</p><h3>THE DIAGNOSTIC SEQUENCE</h3><ul><li><p><strong>Step 1: Check Truth</strong></p></li></ul><p>Is DynamoDB accumulating rows in <code>pending_vlm_enrichment</code>? If so, the platform believes unfinished work exists, regardless of what the queue shows. A growing Truth backlog is the authoritative signal that the system is behind.</p><ul><li><p><strong>Step 2: Check Intent</strong></p></li></ul><p>Does SQS contain replayable work items? High Truth backlog + near-zero queue depth = reconciliation failure, not execution failure. The replay Lambda itself becomes suspect. Either it stopped emitting Intent, or it lost the ability to discover the work.</p><ul><li><p><strong>Step 3: Check Execution</strong></p></li></ul><p>If Intent exists but the backlog still does not move, shift to Execution health. GPU worker logs become critical. Check for:</p><ol><li><p>Deterministic S3 download errors (wrong bucket routing &#8212; see Incident 4).<br>Repeated OOM crashes (model too large for instance type).</p></li><li><p>Complete log group silence (execution failed before the application layer &#8212; check cloud-init).</p></li><li><p>Stale launch template (image tag no longer exists &#8212; check ASG launch configuration).</p></li></ol><ul><li><p><strong>Step 4: Check the Control Plane</strong></p></li></ul><p>If queue visibility is unchanged while pending Truth continues growing, the replay Lambda itself is the focus. Check: Is it being invoked? Is it completing successfully? Can it read <code>sqs:GetQueueAttributes</code>? Is it emitting its heartbeat metric?</p><p><strong>Operational summary of diagnostic signals:</strong></p><ul><li><p>Truth backlog growing &#8594; unfinished work exists</p></li><li><p>Intent near zero despite Truth backlog &#8594; reconciliation failure</p></li><li><p>Intent present but Execution failing &#8594; runtime or routing failure</p></li><li><p>GPU log silence &#8594; bootstrap failure (cloud-init, image pull, IAM at boot)</p></li><li><p>Replay Lambda silence &#8594; control-plane failure (IAM, crash, permission gap)</p></li><li><p>No heartbeat metric &#8594; control plane has gone blind</p></li></ul><h3>INCIDENT RESPONSE DECISION TREE</h3><h4>At 02:00 AM, when the queue looks empty but customers are waiting:</h4><ol><li><p>Check Truth: pull DynamoDB pending count. If non-zero, the system is behind regardless of queue state.</p></li><li><p>Check replay Lambda logs: has it run in the last cycle? Did it complete? Did it emit messages?</p></li><li><p>Check SQS: are messages present? If Truth is high and SQS is low, replay Lambda is suspect.</p></li><li><p>Check ASG desired capacity: did the Lambda set it correctly? Check CloudWatch ASG activity log.</p></li><li><p>Check GPU worker logs: any entries? Silence means boot failure. Errors usually indicate routing or model issues.</p></li><li><p>Check IAM: can the Lambda call sqs:GetQueueAttributes? Can the worker read the correct S3 bucket?</p></li><li><p>Check launch template: does the image tag still exist? Pull the AMI manifest.</p></li><li><p>OUTCOMES<br>The migration from SageMaker to native AWS primitives, combined with TBIE reconciliation, changed both the cost profile and the operational character of the pipeline.</p></li></ol><h3>OPERATIONAL IMPROVEMENTS</h3><ul><li><p>Latency: Startup latency: near-zero or sub-minute (down from 20&#8211;40 minutes cold start on SageMaker).</p></li><li><p>Parallelism: Workers process images in parallel rather than sequentially &#8212; throughput scales with fleet size.</p></li><li><p>Throughput: Wall-clock time reduced dramatically from the ~11 hour nightly baseline.</p></li><li><p>Replay: Event-driven replay handles failures automatically without manual intervention for most failure classes.</p></li><li><p>Cost: Scale-to-zero when no work is present; burst capacity available within seconds via warm pools.</p></li></ul><h3>ARCHITECTURAL IMPROVEMENTS</h3><p>The system can repair its own state: Truth without Intent is detected and corrected by the control plane.<br>Policy changes are handled as replay events &#8212; no custom migration scripts needed.<br>Tenant onboarding is dynamic &#8212; no infrastructure changes required per tenant.<br>Execution environments are immutable and reproducible via pre-baked AMIs.<br>Control plane observability now triggers independent alerting paths from worker failures.</p><h3>THE BROADER LESSON</h3><p>Not every AI workload needs a managed ML platform. Sometimes the real engineering challenge sits in orchestration, reconciliation, and operational resilience &#8212; not in model serving. When the problem is &#8216;how do we run a model?&#8217;, SageMaker is the right answer. When the problem is &#8216;<em><strong>how do we orchestrate burst-scale inference reliably, replay safely, and cost efficiently?</strong></em>&#8217;, native primitives and a clear reconciliation model are the right answer.</p><h2>GUARDRAILS, MAINTENANCE, AND OPERATIONAL CHECKLIST</h2><p>Parjanya&#8217;s reliability is not a property of its initial design. It is the accumulated result of incidents converted into permanent controls. The following checklist encodes what the system has already learned.</p><h3>INTENT PRESERVATION</h3><ul><li><p>Workers never delete SQS messages unless the outcome is terminal_failure or completed.</p></li><li><p>Visibility timeout exceeds maximum realistic inference time.</p></li><li><p>Queue retention exceeds maximum expected outage window.</p></li><li><p>Dead-letter queue is monitored and reviewed regularly.</p></li></ul><h3>EXECUTION ENVIRONMENT INTEGRITY</h3><p>Launch template image tags are validated against existing AMIs at deployment time.</p><p>AMI build pipelines assert presence of all model artifacts before publishing.</p><p>Container version and model artifact version are validated as a compatibility pair.</p><p>Launch templates are refreshed automatically when image tags change.</p><p>Python lockfiles are used to prevent dependency drift inside worker environments.</p><h3>CONTROL PLANE HEALTH</h3><p>Replay Lambda emits a structured heartbeat metric on every successful execution.</p><p>Alarm fires if heartbeat is absent for more than one poll cycle.</p><p>IAM policy grants for the Lambda are validated in deployment assertions.</p><p>Lambda error rate and duration are independently alarmed.</p><p>Control-plane CloudWatch logs are retained and searchable for incident forensics.</p><h3>RECONCILIATION INTEGRITY</h3><p>Truth backlog (pending DynamoDB rows) is monitored as a primary SLI.<br>Intent gap (pending Truth with no corresponding queue message) is checked by the Lambda on each invocation.</p><p>Replay logic resets Truth cleanly to a pre-execution boundary before re-emitting Intent.</p><p>Tenant discovery is dynamic &#8212; no manual configuration changes needed on onboarding.</p><p>Queue retention policy change requires explicit engineering review.</p><h3>INFRASTRUCTURE DRIFT PREVENTION</h3><p>CORS policies are version-controlled and validated in CI.</p><p>Bucket CORS and public access settings are configured as a matched pair.</p><p>API schema and frontend types have drift detection in CI.</p><p>S3 bucket routing is validated at Intent construction time, not only at worker download time.</p><h3>POLICY AND REGRADE</h3><p>Content policy version is stored per image in DynamoDB.</p><p>Policy changes trigger replay jobs for images scored under previous policy versions.</p><p>Regrade jobs use the same replay machinery as failure recovery &#8212; no custom tooling.</p><h2>IMPLICATIONS FOR AI PLATFORM DESIGN</h2><p>TBIE generalises beyond Parjanya. Any AI platform that spans storage, metadata, asynchronous work, GPU execution, and policy evolution benefits from the same model. The key is to stop thinking of the system as a one-way pipeline and treat it as a reconciliation loop that continuously restores alignment between durable truth and intended work.</p><p>That shift changes concrete architecture choices:</p><p>Queues: Queues become journals of intent rather than temporary transport.</p><p>Replay: Replay becomes a first-class product capability, not an ops workaround.</p><p>Autoscaling: Autoscaling becomes a consequence of work existing, not a heuristic guess.</p><p>Model packaging: Model packaging becomes part of execution correctness, not just deployment.</p><p>Browser uploads: Browser upload behaviour becomes part of the end-to-end reliability model.</p><p>Policy change: Policy change becomes a replay event rather than a manual repair task.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;5c4582d3-6e65-4595-bc62-caf291fd4f91&quot;,&quot;caption&quot;:&quot;In my previous post few weeks ago, I introduced TBIE &#8212; Truth, Belief, Intent and Execution &#8212; as a framework for reasoning about resilient distributed systems.&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;From Pipeline to Platform &quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-06-22T05:45:48.801Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!AEfT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/from-pipeline-to-platform&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:203038071,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>The right mental model for modern AI infrastructure is not &#8216;build a pipeline.&#8217; It is &#8216;build a system that can continuously reconcile truth and intent until intended work is actually realised.&#8217;</p><h2>APPENDIX A: COMPONENT MAPPING TABLE</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VsTY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360055ee-b572-404b-8939-928d326bbddd_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VsTY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360055ee-b572-404b-8939-928d326bbddd_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!VsTY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360055ee-b572-404b-8939-928d326bbddd_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!VsTY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360055ee-b572-404b-8939-928d326bbddd_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!VsTY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360055ee-b572-404b-8939-928d326bbddd_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!VsTY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360055ee-b572-404b-8939-928d326bbddd_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/360055ee-b572-404b-8939-928d326bbddd_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;:1601859,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/203346926?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360055ee-b572-404b-8939-928d326bbddd_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_!VsTY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360055ee-b572-404b-8939-928d326bbddd_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!VsTY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360055ee-b572-404b-8939-928d326bbddd_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!VsTY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360055ee-b572-404b-8939-928d326bbddd_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!VsTY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360055ee-b572-404b-8939-928d326bbddd_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>APPENDIX B: KEY TERMS</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Eth4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87cb7a50-8d9c-452e-9e55-1261931326f1_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Eth4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87cb7a50-8d9c-452e-9e55-1261931326f1_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Eth4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87cb7a50-8d9c-452e-9e55-1261931326f1_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Eth4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87cb7a50-8d9c-452e-9e55-1261931326f1_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Eth4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87cb7a50-8d9c-452e-9e55-1261931326f1_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Eth4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87cb7a50-8d9c-452e-9e55-1261931326f1_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/87cb7a50-8d9c-452e-9e55-1261931326f1_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;:1470043,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/203346926?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87cb7a50-8d9c-452e-9e55-1261931326f1_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_!Eth4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87cb7a50-8d9c-452e-9e55-1261931326f1_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Eth4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87cb7a50-8d9c-452e-9e55-1261931326f1_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Eth4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87cb7a50-8d9c-452e-9e55-1261931326f1_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Eth4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87cb7a50-8d9c-452e-9e55-1261931326f1_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png" width="1456" height="189" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:189,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[From Pipeline to Platform ]]></title><description><![CDATA[Event-Driven TBIE Architecture, Reconciliation Patterns, and the Lessons from Building Parjanya v2.0]]></description><link>https://blog.phagyul.ai/p/from-pipeline-to-platform</link><guid isPermaLink="false">https://blog.phagyul.ai/p/from-pipeline-to-platform</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Mon, 22 Jun 2026 05:45:48 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!AEfT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my previous post few weeks ago, I introduced TBIE &#8212; Truth, Belief, Intent and Execution &#8212; as a framework for reasoning about resilient distributed systems.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;869ed1a6-1c56-4907-a5b6-bcd1c8d765ad&quot;,&quot;caption&quot;:&quot;Abstract&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;TBIE in Practice: Designing Resilient AI Pipelines That Recover, Reconcile, and Re-run&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-05-25T05:36:28.000Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!ok-g!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe12bff-5e6a-4f47-92ca-1f9569ff933d_1692x929.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/tbie-in-practice-designing-resilient&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:199145206,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>The framework emerged from a simple observation:</p><p>Distributed systems rarely fail through catastrophic outages.</p><p>More often, they fail through divergence.</p><p>Truth says one thing.<br>Execution does another.<br>Intent disappears.<br>Belief becomes detached from reality.</p><p>TBIE gave me a vocabulary for understanding those failures.</p><p>What I did not fully appreciate at the time was the architectural consequence of taking TBIE seriously.</p><p>I thought I was building an AI pipeline.</p><p>I ended up building a platform.</p><div class="pullquote"><p>More specifically, I ended up building a reconciliation-driven control plane whose primary responsibility was not inference, enrichment, scoring, or curation.</p></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AEfT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AEfT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png 424w, https://substackcdn.com/image/fetch/$s_!AEfT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png 848w, https://substackcdn.com/image/fetch/$s_!AEfT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png 1272w, https://substackcdn.com/image/fetch/$s_!AEfT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!AEfT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png" width="1536" height="950" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:950,&quot;width&quot;:1536,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1673176,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/203038071?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd724deb0-7e36-4332-9a5a-3b8d4d003179_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_!AEfT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png 424w, https://substackcdn.com/image/fetch/$s_!AEfT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png 848w, https://substackcdn.com/image/fetch/$s_!AEfT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png 1272w, https://substackcdn.com/image/fetch/$s_!AEfT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e3c006b-8d0e-4176-8bfc-72a45027eb6d_1536x950.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Its primary responsibility was preserving correctness.</p><p>That realization fundamentally changed how I thought about reliability.</p><p>The hard problems in Parjanya v2.0 were not model problems.</p><p>They were coordination problems.</p><ul><li><p>Not GPU problems.</p></li><li><p>Not inference problems.</p></li><li><p>Not even scaling problems.</p></li></ul><p>The hardest problems emerged whenever the system lost alignment between:</p><ul><li><p>what was true,</p></li><li><p>what work should exist,</p></li><li><p>what execution was currently happening,</p></li><li><p>and what the system believed was happening.</p></li></ul><p>The original architecture looked deceptively simple.</p><p>Images landed in S3.</p><p>Metadata was written into DynamoDB.</p><p>Validation ran through Lambda functions.</p><p>GPU workers performed VLM enrichment and IQA processing.</p><p>Results were written back into DynamoDB.</p><p>Autoscaling reacted to queue depth.</p><p>At first glance, it looked like a fairly conventional event-driven AI pipeline.</p><p>Production quickly proved otherwise.</p><p>Workers crashed.</p><p>Queues drained without progress.</p><p>Pending images remained pending forever.</p><p>Retries became impossible.</p><p>Infrastructure drifted away from declared state.</p><p>The system could remain technically healthy while doing absolutely nothing useful.</p><p>That was the moment I realised we were solving the wrong problem.</p><p>The challenge was not moving images through a pipeline.</p><p>The challenge was continuously reconciling distributed state.</p><p>Once viewed through that lens, the architecture began evolving in a very different direction.</p><p>The replay engine stopped being a utility.</p><p>It became the control plane.</p><p>Queues stopped being transport mechanisms.</p><p>They became durable Intent.</p><p>Autoscaling stopped being a scaling feature.</p><p>It became a realization layer for Intent.</p><p>And the system itself stopped behaving like a pipeline.</p><p>It started behaving like a platform.</p><p>This article is the story of that evolution.</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_!UWpj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a269d84-eb4b-47c5-9cf4-3ba9f3a72c9e_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UWpj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a269d84-eb4b-47c5-9cf4-3ba9f3a72c9e_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!UWpj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a269d84-eb4b-47c5-9cf4-3ba9f3a72c9e_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!UWpj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a269d84-eb4b-47c5-9cf4-3ba9f3a72c9e_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!UWpj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a269d84-eb4b-47c5-9cf4-3ba9f3a72c9e_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!UWpj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a269d84-eb4b-47c5-9cf4-3ba9f3a72c9e_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0a269d84-eb4b-47c5-9cf4-3ba9f3a72c9e_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;:1545865,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/203038071?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a269d84-eb4b-47c5-9cf4-3ba9f3a72c9e_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_!UWpj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a269d84-eb4b-47c5-9cf4-3ba9f3a72c9e_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!UWpj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a269d84-eb4b-47c5-9cf4-3ba9f3a72c9e_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!UWpj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a269d84-eb4b-47c5-9cf4-3ba9f3a72c9e_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!UWpj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a269d84-eb4b-47c5-9cf4-3ba9f3a72c9e_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>Preface</h2><p>Distributed systems rarely fail in the way architecture diagrams suggest.</p><p>The boxes stay alive. The queues still exist. The databases continue accepting writes. The autoscaling groups look healthy. The dashboards even remain green.</p><p>And yet the system silently stops doing useful work.</p><p>An image sits in a pending state forever. A queue drains but no GPU ever runs. A worker crashes and deletes the only replayable work item. A presigned upload URL looks valid but browser execution never begins. A GPU instance launches correctly while the actual container inside it continuously crashloops.</p><p>Most production failures are not total outages. They are reconciliation failures.</p><p>Something the system believes should happen never actually happens. Or something already completed continues to look pending. Or a control plane silently loses the ability to coordinate execution.</p><p>Parjanya v2.0 forced us to confront this repeatedly.</p><p>Initially, the architecture looked straightforward:</p><ul><li><p>Images upload into S3</p></li><li><p>Metadata lands in DynamoDB</p></li><li><p>Lambdas perform validation and enrichment</p></li><li><p>GPU workers run VLM and IQA workloads</p></li><li><p>Results are written back into DynamoDB</p></li><li><p>Autoscaling follows queue depth</p></li></ul><p>At first glance, this looked like a normal AI pipeline.</p><p>In practice, it evolved into something else.</p><p>The deeper challenge was not inference. The challenge was maintaining alignment between:</p><p>the durable truth of the system,<br>the operational understanding of the system,<br>the work the system intended to perform,<br>and the execution layer actually performing it.</p><blockquote><p>Truth &#8594; Belief &#8594; Intent &#8594; Execution</p></blockquote><p>TBIE was never intended as branding. It emerged as an operational language for reasoning about reliability.</p><p>The model eventually shaped:</p><p>the event-driven reconciliation architecture,<br>the autoscaling strategy,<br>the replay model,<br>the control plane,<br>failure recovery,<br>multi-tenant orchestration,<br>policy regrading,<br>infrastructure debugging,<br>and eventually the broader direction of Parjanya itself.</p><p>This article is a deep dive into that journey.</p><p>It is not a summary. It is a detailed architectural walkthrough of:</p><p>how TBIE emerged,<br>why event-driven reconciliation mattered,<br>what failed in production,<br>how those failures were diagnosed,<br>and why reconciliation patterns matter far more than most AI infrastructure discussions acknowledge.</p><p>The goal is not merely to explain Parjanya.</p><p>The goal is to explain how resilient AI systems are actually built.</p><h2>1. The Real Problem in Distributed AI Systems</h2><p>Most modern AI infrastructure discussions focus heavily on models.</p><p>Which VLM?<br>Which embedding strategy?<br>Which vector database?<br>Which GPU?<br>Which inference framework?<br>Which quantization?</p><p>These questions matter.</p><p>But they are not usually what breaks systems.</p><p>The real production problems tend to look different:</p><p>Work disappears.<br>Retries become impossible.<br>Workers process stale state.<br>Uploads partially succeed.<br>Queues drain without progress.<br>Control planes silently stop coordinating.<br>Autoscaling behaves correctly against the wrong metric.<br>Infrastructure layers drift away from declared source-of-truth.</p><p>In other words:</p><p>The problem is not merely computation. The problem is reconciliation.</p><p>Distributed systems are fundamentally coordination systems.</p><p>A resilient architecture needs to answer:</p><p>What is the durable truth?<br>What work should exist?<br>What execution is currently happening?<br>Can the system reconstruct work after failures?<br>Can the system distinguish transient failure from terminal failure?<br>Can infrastructure drift be detected?<br>Can the system replay work safely?<br>Can policy changes be re-applied deterministically?</p><p>Most architectures answer these implicitly.</p><p>TBIE attempts to answer them explicitly.</p><h2>2. TBIE &#8212; Truth, Belief, Intent, Execution</h2><p>The TBIE model separates distributed systems into four operational layers.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JoPa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa319b520-37eb-4f90-ab0a-b458e9b31038_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JoPa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa319b520-37eb-4f90-ab0a-b458e9b31038_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!JoPa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa319b520-37eb-4f90-ab0a-b458e9b31038_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!JoPa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa319b520-37eb-4f90-ab0a-b458e9b31038_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!JoPa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa319b520-37eb-4f90-ab0a-b458e9b31038_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!JoPa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa319b520-37eb-4f90-ab0a-b458e9b31038_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a319b520-37eb-4f90-ab0a-b458e9b31038_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;:1312875,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/203038071?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa319b520-37eb-4f90-ab0a-b458e9b31038_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_!JoPa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa319b520-37eb-4f90-ab0a-b458e9b31038_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!JoPa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa319b520-37eb-4f90-ab0a-b458e9b31038_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!JoPa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa319b520-37eb-4f90-ab0a-b458e9b31038_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!JoPa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa319b520-37eb-4f90-ab0a-b458e9b31038_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The model becomes powerful because it forces explicit boundaries.</p><h3>Truth</h3><p>Truth represents the authoritative record.</p><p>Truth must be:</p><p>durable,<br>reconstructable,<br>queryable,<br>replayable,<br>and independent of transient execution state.</p><p>In Parjanya:</p><p>S3 object bytes are Truth.<br>DynamoDB workflow fields are Truth.<br>Pipeline status transitions are Truth.<br>Curation outputs are Truth.<br>Hashes and metadata are Truth.</p><p>Truth is what remains after workers crash.</p><p>Truth is what survives retries.</p><p>Truth is what operators use to reconstruct system state.</p><h3>Belief</h3><p>Belief is operational understanding.</p><p>Belief is not always perfectly accurate.</p><p>Examples:</p><ul><li><p>Queue depth</p></li><li><p>Autoscaling desired capacity</p></li><li><p>In-flight SQS messages</p></li><li><p>Worker health</p></li><li><p>Current GPU availability</p></li><li><p>Visibility timeout state</p></li></ul><p>Belief may lag reality. Belief may be partial. Belief may even temporarily be wrong.</p><p>But Belief matters because orchestration depends on it.</p><p>Importantly:</p><p>Belief should be derivable from Truth + Intent.</p><p>That distinction becomes critical later.</p><h3>Intent</h3><p>Intent represents durable declarations of work.</p><p>Intent answers:</p><blockquote><p>&#8220;What should the system attempt next?&#8221;</p></blockquote><p>In Parjanya:</p><p>SQS messages are Intent.<br>Replay queues are Intent.<br>Regrade operations are Intent.<br>Retry workflows are Intent.</p><p>Intent is one of the most important concepts in the entire architecture.</p><p>Execution should never destroy Intent casually.</p><p>Why?</p><p>Because Intent is replayability.</p><p>Without replayable Intent:</p><p>transient failures become permanent,<br>retries become manual,<br>reconciliation becomes impossible,<br>and the system loses self-healing capability.</p><h3>Execution</h3><p>Execution is the stateless machinery that realizes work.</p><p>Execution includes:</p><p>Lambdas,<br>GPU workers,<br>autoscaling groups,<br>validation services,<br>EXIF processors,<br>and inference pipelines.</p><p>Execution should ideally be:</p><p>disposable,<br>reproducible,<br>restartable,<br>and stateless.</p><p>If an execution worker disappears, the system should still be able to recover from Truth + Intent.</p><p>That principle drove many later architectural decisions.</p><h2>3. Mapping TBIE onto Parjanya v2.0</h2><p>Once TBIE became the operational lens, the architecture became easier to reason about.</p><h3>Truth Layer</h3><p>Truth in Parjanya consisted primarily of:</p><p><strong>S3</strong></p><ul><li><p>original uploads,</p></li><li><p>RAW image payloads,</p></li><li><p>generated previews,</p></li><li><p>derived thumbnails,</p></li><li><p>metadata artifacts.</p></li></ul><p><strong>DynamoDB</strong></p><p>Workflow state:</p><ul><li><p>batch_status</p></li><li><p>pipeline_status</p></li><li><p>curation</p></li><li><p>quality scores</p></li><li><p>VLM outputs</p></li><li><p>EXIF metadata</p></li><li><p>technical validation</p></li><li><p>image hashes</p></li><li><p>routing information</p></li></ul><p>Truth represented the durable state of every image.</p><h3>Intent Layer</h3><p>Intent existed primarily in SQS.</p><p>Examples:</p><ul><li><p>ml-large-jobs</p></li><li><p>replay queues</p></li><li><p>regrade operations</p></li><li><p>retry workflows</p></li></ul><p>Each Intent payload encoded:</p><ul><li><p>bucket,</p></li><li><p>object key,</p></li><li><p>tenant,</p></li><li><p>image id,</p></li><li><p>execution metadata.</p></li></ul><p>Intent was intentionally replayable.</p><p>That design decision later prevented multiple catastrophic replay-loss scenarios.</p><h3>Belief Layer</h3><p>Belief included:</p><ul><li><p>ASG desired capacity,</p></li><li><p>queue visibility counts,</p></li><li><p>in-flight message counts,</p></li><li><p>CloudWatch metrics,</p></li><li><p>worker availability,</p></li><li><p>queue backlog,</p></li><li><p>GPU scale state.</p></li></ul><p>Belief drove orchestration.</p><p>For example:</p><ul><li><p>queue depth controlled autoscaling,</p></li><li><p>replay Lambdas checked queue visibility,</p></li><li><p>scaling decisions relied on approximate message counts.</p></li></ul><p>Belief was operationally useful but never fully authoritative.</p><h3>Execution Layer</h3><p>Execution included:</p><p><strong>Lambda Workers</strong></p><ul><li><p>EXIF extraction</p></li><li><p>technical validation</p></li><li><p>replay orchestration</p></li><li><p>autoscaling control-plane logic</p></li></ul><p><strong>GPU Workers</strong></p><ul><li><p>Qwen VLM inference</p></li><li><p>IQA processing</p></li><li><p>curation scoring</p></li><li><p>natural-language enrichment</p></li></ul><p>Execution workers remained stateless wherever possible.</p><p>That allowed replay to remain safe.</p><h2>4. Why Reconciliation Matters</h2><p>A distributed system does not stay healthy merely because components exist.</p><p>Health depends on reconciliation.</p><p>Consider this state:</p><p>DynamoDB row says pending_vlm_enrichment<br>SQS queue is empty<br>GPU ASG is scaled to zero</p><p>Nothing is technically &#8220;down.&#8221;</p><p>And yet the system is stuck.</p><p>Truth says work should exist. Intent does not exist. Execution never begins. Belief incorrectly suggests the system is idle.</p><p>This is a reconciliation failure.</p><p>TBIE made this visible.</p><p>The system needed a mechanism that continuously aligned:</p><p>Truth &#8596; Intent &#8596; Execution</p><p>That eventually led to the event-driven reconciliation architecture.</p><h2>5. From Polling to Event-Driven Reconciliation</h2><p>The original architecture used scheduled polling.</p><p>Every few minutes:</p><p>EventBridge triggered a Lambda,<br>the Lambda scanned DynamoDB,<br>pending work was discovered,<br>SQS messages were emitted,<br>GPU autoscaling was triggered.</p><p>This worked.</p><p>But it introduced fundamental limitations.</p><h3>Problems with Polling</h3><p><strong>Latency</strong></p><p>An image could wait:</p><p>0&#8211;15 minutes before the next poll cycle.</p><p>GPU cold starts already consumed several minutes. Adding polling latency made the UX significantly worse.</p><p><strong>Waste</strong></p><p>Most polling invocations found no work.</p><p>The control plane continuously woke up merely to rediscover emptiness.</p><p><strong>Operational Ambiguity</strong></p><p>Polling blurred the distinction between:</p><p>&#8220;there is no work,&#8221;<br>and<br>&#8220;the system has not discovered the work yet.&#8221;</p><p>That ambiguity complicated debugging.</p><p><strong>Poor Reactive Scaling</strong></p><p>Autoscaling became tied to polling frequency.</p><p>Queue discovery latency directly affected GPU startup latency.</p><h2>6. DynamoDB Streams Changed the Architecture</h2><p>The major architectural shift came from moving reconciliation into an event-driven model.</p><p>Instead of periodically checking for state changes:</p><p>The system reacted immediately when Truth changed.</p><h3>The New Model</h3><p>DynamoDB row transitions to pending_vlm_enrichment<br>DynamoDB Streams emits an event<br>Event source mapping filters relevant writes<br>Replay Lambda triggers immediately<br>SQS Intent is emitted<br>GPU ASG is kicked from zero<br>GPU workers process work<br>Results are written back into Truth</p><p>The architecture became reactive.</p><h2>7. Anatomy of the Event-Driven TBIE</h2><h3>Architecture</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iIx-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F191eeab5-afd4-46c6-bd82-f0f651daa6b4_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iIx-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F191eeab5-afd4-46c6-bd82-f0f651daa6b4_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!iIx-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F191eeab5-afd4-46c6-bd82-f0f651daa6b4_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!iIx-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F191eeab5-afd4-46c6-bd82-f0f651daa6b4_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!iIx-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F191eeab5-afd4-46c6-bd82-f0f651daa6b4_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!iIx-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F191eeab5-afd4-46c6-bd82-f0f651daa6b4_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/191eeab5-afd4-46c6-bd82-f0f651daa6b4_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;:1627507,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/203038071?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F191eeab5-afd4-46c6-bd82-f0f651daa6b4_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_!iIx-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F191eeab5-afd4-46c6-bd82-f0f651daa6b4_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!iIx-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F191eeab5-afd4-46c6-bd82-f0f651daa6b4_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!iIx-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F191eeab5-afd4-46c6-bd82-f0f651daa6b4_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!iIx-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F191eeab5-afd4-46c6-bd82-f0f651daa6b4_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h4>DynamoDB Streams</h4><p>The table emits:</p><ul><li><p>INSERT events</p></li><li><p>MODIFY events</p></li></ul><p>Filtered specifically for:</p><p>batch_status = pending_vlm_enrichment</p><p>This is extremely important.</p><p>The system does not react to every write. It reacts only when Truth crosses a workflow boundary requiring Intent creation.</p><h4>Event Source Mapping</h4><p>The stream mapping aggregates:</p><p>up to 50 records,<br>or up to 5 seconds.</p><p>This balances:</p><p>latency,<br>throughput,<br>Lambda cost,<br>queue pressure.</p><p>The system effectively performs micro-batching naturally.</p><h4>Replay Lambda</h4><p>The replay Lambda became the core reconciliation engine.</p><p>Responsibilities:</p><ul><li><p>inspect stream events,</p></li><li><p>discover pending rows,</p></li><li><p>identify retriable failures,</p></li><li><p>generate replayable Intent,</p></li><li><p>avoid duplicate queueing,</p></li><li><p>trigger autoscaling.</p></li></ul><p>This Lambda evolved into the operational heart of the platform.</p><h4>Queue Backlog Guard</h4><p>One subtle but extremely important design decision:</p><p>The replay Lambda checks queue visibility before re-enqueueing pending work.</p><p>Why?</p><p>Because replay itself can become destructive if uncontrolled.</p><p>Without a backlog guard:</p><p>the control plane could continuously duplicate Intent,<br>queue pressure would inflate,<br>workers would process stale state,<br>autoscaling would overreact.</p><p>This is a classic reconciliation trap.</p><p>The backlog guard prevented it.</p><h4>GPU ASG Kick</h4><p>The replay Lambda also became responsible for scaling GPU workers.</p><p>This matters because scale-to-zero architectures create a hidden problem:</p><p>The queue may contain work while compute remains asleep.</p><p>The replay Lambda solved this by:</p><p>emitting Intent,<br>then immediately setting desired ASG capacity.</p><p>That turned the replay engine into both:</p><p>a reconciliation layer,<br>and a control-plane orchestrator.</p><h2>8. Latency Transformation</h2><p>The shift from polling to event-driven reconciliation fundamentally changed responsiveness.</p><h3>Before</h3><p>Upload &#8594; wait for poll &#8594; queue &#8594; ASG scale &#8594; GPU boot</p><p>Total latency:</p><p>~3&#8211;20 minutes</p><p>depending on polling window timing.</p><h3>After</h3><p>Upload &#8594; stream event &#8594; immediate reconciliation &#8594; queue &#8594; ASG scale</p><p>Total latency:</p><p>~4&#8211;6 minutes</p><p>with remaining delay dominated almost entirely by:</p><p>EC2 startup,<br>model load,<br>GPU warm-up.</p><p>This is a very different operational profile.</p><p>The system stopped feeling batch-oriented.</p><p>It began behaving like a reactive platform.</p><h2>9. The First Major TBIE Failure</h2><h3>Intent Destroyed Too Early</h3><p>One of the earliest major incidents exposed why TBIE mattered.</p><h4>Symptom</h4><p>GPU workers experienced transient:</p><ul><li><p>S3 download failures,</p></li><li><p>temporary consistency races,</p></li><li><p>OOM conditions.</p></li></ul><p>But the worker still deleted the SQS message.</p><p>At the same time:</p><p>DynamoDB was updated with:</p><p>vlm_failed</p><p>The result:</p><p>Intent disappeared,<br>Truth claimed terminal failure,<br>automatic replay became impossible.</p><p>This was a severe reconciliation violation.</p><h4>The Core TBIE Violation</h4><p>Execution destroyed Intent before retries were exhausted.</p><p>That single decision broke replayability.</p><p>TBIE clarified the failure immediately.</p><p>The problem was not merely worker instability.</p><p>The problem was:</p><p>Execution invalidated Intent prematurely.</p><h4>The Fix</h4><p>The worker execution model changed.</p><p>Instead of binary success/failure, workers returned:</p><p>retry</p><ul><li><p>do NOT delete SQS message</p></li><li><p>do NOT write terminal Truth</p></li></ul><p>terminal_failure</p><ul><li><p>write durable failure state</p></li><li><p>delete Intent</p></li></ul><p>completed</p><ul><li><p>write success state</p></li><li><p>delete Intent</p></li></ul><p>This restored replay semantics.</p><h4>Why This Matters Beyond Parjanya</h4><p>Many distributed systems accidentally conflate:</p><p>&#8220;execution failed once&#8221; with<br>&#8220;execution is permanently impossible.&#8221;</p><p>Those are not equivalent.</p><p>TBIE forced the architecture to encode that distinction explicitly.</p><h2>10. Truth Pending, Intent Missing</h2><p>Another class of failures appeared repeatedly.</p><h3>Symptom</h3><p>Rows remained:</p><p>pending_vlm_enrichment</p><p>But:</p><ul><li><p>queues were empty,</p></li><li><p>GPU workers never started,</p></li><li><p>no replay existed.</p></li></ul><p>The system appeared healthy.</p><p>But nothing moved.</p><h3>What TBIE Revealed</h3><p>Truth and Intent were decoupled.</p><p>The architecture had assumed:</p><p>&#8220;If Truth says pending, Intent must already exist.&#8221;</p><p>That assumption was false.</p><p>Reconciliation cannot be assumed. It must be continuously enforced.</p><h3>The Replay Architecture</h3><p>This led to:</p><ul><li><p>replay scripts,</p></li><li><p>scheduled replay Lambdas,</p></li><li><p>retriable failure reset workflows,</p></li><li><p>queue reconstruction logic.</p></li></ul><p>The replay Lambda evolved into a continuously running reconciler.</p><p>This was the moment the architecture stopped being merely a pipeline.</p><p>It became a platform.</p><h2>11. Wrong Bucket, Right Key</h2><h3>A Perfect Distributed Systems Failure</h3><p>One of the most revealing incidents involved bucket mismatch.</p><h4>Symptom</h4><p>GPU workers repeatedly failed with:</p><p>s3_download_error</p><p>Yet:</p><ul><li><p>queue depth was growing,</p></li><li><p>autoscaling worked,</p></li><li><p>workers were alive,</p></li><li><p>previews existed.</p></li></ul><p>Everything looked operational.</p><h4>Root Cause</h4><p>The SQS payload contained:</p><p>the correct object key,<br>but the wrong bucket.</p><p>The preview existed.</p><p>Just not in the referenced bucket.</p><h4>Why This Was Architecturally Important</h4><p>The system was reliably executing the wrong instruction.</p><p>This is one of the hardest classes of distributed failures.</p><p>Nothing is technically broken.</p><p>The system is functioning exactly as instructed.</p><p>The instruction itself is invalid.</p><p>TBIE framed this correctly:</p><p>Intent must not merely exist. Intent must be correct and replayable.</p><h4>The Fix</h4><p>The architecture introduced:</p><ul><li><p>bucket source-of-truth rules,</p></li><li><p>preview-aware routing,</p></li><li><p>enqueue eligibility tightening,</p></li><li><p>RAW-aware preview validation,</p></li><li><p>replay resets for retriable failures.</p></li></ul><p>The fix was operationally deeper than changing one field.</p><p>It hardened the meaning of Intent itself.</p><h2>12. CORS Failures and Split Truth</h2><p>One of the most subtle incidents occurred at the ingestion boundary.</p><h3>Symptom</h3><p>Frontend uploads failed with browser CORS errors.</p><p>But backend APIs:</p><ul><li><p>generated presigned URLs,</p></li><li><p>wrote pending upload records,</p></li><li><p>and returned success responses.</p></li></ul><p>Truth looked correct.</p><p>Execution never happened.</p><h3>What Actually Failed</h3><p>The browser failed during:</p><p>OPTIONS preflight.</p><p>Execution never reached:</p><p>PUT upload.</p><h3>The TBIE Interpretation</h3><p>Truth existed. Intent existed. Execution failed before realization.</p><p>This became an important diagnostic heuristic:</p><p>When work is stuck:</p><p>Ask whether:</p><ul><li><p>Truth is missing,</p></li><li><p>Intent is missing,</p></li><li><p>or Execution cannot realize Intent.</p></li></ul><p>That framing simplified debugging enormously.</p><h2>13. Event-Driven Architecture Exposes Infrastructure Drift Faster</h2><p>As the architecture became more reactive, infrastructure drift became easier to detect.</p><p>This was unexpected.</p><h3>Example: Stale Worker Image Tag</h3><p>The ASG launch template still referenced:</p><p>:v20</p><p>while the actual system had moved to:</p><p>:v23</p><p>The ASG launched correctly. Cloud-init executed. Docker attempted to pull. The image no longer existed.</p><p>Workers never started.</p><h3>The Deeper Problem</h3><p>Terraform ignored user_data changes.</p><p>This created silent divergence between:</p><p>declared source-of-truth,<br>and actual runtime execution.</p><p>TBIE exposed this as an Execution drift problem.</p><p>Truth, Belief, and Intent were all correct.</p><p>Execution itself had drifted away from reality.</p><h3>The Architectural Lesson</h3><p>Infrastructure reproducibility is not optional.</p><p>Execution environments must remain tied to durable source-of-truth.</p><p>Otherwise replay becomes dangerous because:</p><p>the same Intent may produce different outcomes over time.</p><h2>14. AMI Drift and Runtime Incompatibility</h2><p>Another failure emerged at the AMI layer.</p><h3>Symptom</h3><p>Containers started. But model loading crashed.</p><p>The model weights existed. The processors did not.</p><p>The AMI bake omitted Python files required by:</p><p>trust_remote_code=True</p><p>The worker entered a crashloop.</p><h3>Why This Was Important</h3><p>Again:</p><p>Truth was correct. Intent was correct. Belief suggested workers existed.</p><p>Execution failed due to stale artifacts.</p><p>This is precisely why replayable systems require reproducible execution environments.</p><p>TBIE repeatedly reinforced this architectural truth.</p><h2>15. The Replay Lambda Became the Control Plane</h2><p>Originally, the replay Lambda was operational glue.</p><p>Eventually, it became the platform control plane.</p><p>Responsibilities expanded to include:</p><ul><li><p>pending reconciliation,</p></li><li><p>retriable failure resets,</p></li><li><p>tenant discovery,</p></li><li><p>queue backlog management,</p></li><li><p>autoscaling coordination,</p></li><li><p>replay orchestration,</p></li><li><p>dynamic routing.</p></li></ul><p>The replay layer became central infrastructure.</p><p>This was a critical architectural evolution.</p><h2>16. The IAM Incident</h2><h3>When the Control Plane Goes Blind</h3><p>One of the most dangerous incidents involved a missing IAM permission.</p><h4>Symptom</h4><p>The replay Lambda continuously crashed on:</p><p>sqs:GetQueueAttributes</p><p>for nearly 12 hours.</p><p>But:</p><ul><li><p>EventBridge still invoked it,</p></li><li><p>the schedule looked healthy,</p></li><li><p>the infrastructure appeared alive.</p></li></ul><p>Meanwhile:</p><ul><li><p>pending rows accumulated,</p></li><li><p>queues stopped reconciling,</p></li><li><p>autoscaling logic failed.</p></li></ul><h3>The TBIE Lesson</h3><p>The control plane had lost Belief.</p><p>Without Belief:</p><p>the replay engine could not safely emit Intent,<br>queue guards could not function,<br>orchestration collapsed.</p><p>The system looked operational while the reconciler was effectively dead.</p><h3>The Operational Insight</h3><p>A scheduled Lambda is not necessarily a healthy Lambda.</p><p>Control-plane observability matters more than worker observability.</p><p>Why?</p><p>Because worker failures are recoverable.</p><p>Control-plane blindness disables recovery itself.</p><h2>17. Dynamic Tenant Discovery</h2><p>As Parjanya moved toward beta onboarding, static tenant configuration became a bottleneck.</p><p>Originally:</p><p>The replay Lambda used static tenant lists.</p><p>Every new tenant required:</p><ul><li><p>Terraform changes,</p></li><li><p>environment updates,</p></li><li><p>redeploys.</p></li></ul><p>This violated the self-service model.</p><h3>The Evolution</h3><p>The architecture introduced:</p><ul><li><p>tenant registry writes during upload completion,</p></li><li><p>runtime tenant discovery,</p></li><li><p>dynamic reconciliation.</p></li></ul><p>The control plane became data-driven rather than configuration-driven.</p><p>This is a major architectural distinction.</p><p>Reactive systems scale operationally only when discovery becomes dynamic.</p><h2>18. Regrading and Policy Replay</h2><p>One of the most powerful consequences of TBIE was deterministic replay.</p><p>This became especially valuable during policy changes.</p><h3>Example</h3><p>The IQA policy evolved to reject:</p><ul><li><p>screenshots,</p></li><li><p>banners,</p></li><li><p>posters,</p></li><li><p>slides,</p></li><li><p>social cards,</p></li><li><p>infographics,</p></li><li><p>illustrations.</p></li></ul><p>The architecture needed to:</p><ul><li><p>reset VLM-derived Truth,</p></li><li><p>regenerate Intent,</p></li><li><p>rerun GPU enrichment,</p></li><li><p>rewrite curation outputs.</p></li></ul><p>This was not merely a retry.</p><p>It was a deterministic policy replay.</p><h3>Why This Matters</h3><p>Most ML systems struggle with:</p><p>&#8220;How do we reprocess historical data safely?&#8221;</p><p>TBIE already contained the answer.</p><p>Truth could be reset to a replay boundary. Intent could be regenerated. Execution remained stateless.</p><p>The system became replay-native.</p><p>This is a profound operational capability.</p><h2>19. Queue Retention and Weekend Gaps</h2><p>Another subtle operational issue:</p><p>Scale-to-zero architectures create temporal gaps.</p><h3>Scenario</h3><p>Users upload images Friday evening. GPU workers remain offline over the weekend.</p><p>If queue retention is too short:</p><p>Intent disappears before execution resumes.</p><p>Truth remains pending.</p><p>Intent vanishes.</p><p>This is catastrophic reconciliation drift.</p><h3>The Fix</h3><p>Queue retention was extended.</p><p>This ensured Intent outlived temporary execution dormancy.</p><p>An important TBIE lesson emerged:</p><p>Intent durability must exceed execution availability windows.</p><h2>20. Why Event-Driven Reconciliation Matters</h2><h3>Beyond AI</h3><p>Although Parjanya is an AI platform, the architectural lessons generalize broadly.</p><p>The same TBIE principles apply to:</p><p>distributed media systems,<br>payment processing,<br>ETL pipelines,<br>logistics systems,<br>asynchronous workflows,<br>microservice orchestration,<br>large-scale ingestion platforms.</p><p>The core challenge is universal:</p><p>How do you maintain alignment between:</p><p>durable truth,<br>intended work,<br>operational state,<br>and actual execution?</p><p>TBIE provides a vocabulary for reasoning about that alignment.</p><h2>21. The Shift from Pipeline to Platform</h2><p>This was perhaps the most important realization.</p><p>A pipeline moves data.</p><p>A platform:</p><ul><li><p>survives retries,</p></li><li><p>supports replay,</p></li><li><p>reconciles state continuously,</p></li><li><p>tolerates execution drift,</p></li><li><p>evolves policy safely,</p></li><li><p>supports operational introspection,</p></li><li><p>and remains debuggable under failure.</p></li></ul><p>The event-driven TBIE architecture pushed Parjanya decisively toward the latter.</p><p>The replay Lambda stopped being a utility.</p><p>It became the reconciliation brain of the system.</p><p>The architecture stopped being:</p><p>&#8220;process uploaded images.&#8221;</p><p>It became:</p><p>&#8220;maintain durable correctness while asynchronous distributed execution continuously changes.&#8221;</p><p>That is a very different engineering problem.</p><h2>22. The Operator&#8217;s Mental Model</h2><p>TBIE becomes most useful when it changes how incidents are diagnosed.</p><p>By the time Parjanya matured into an event-driven reconciliation system, the debugging approach itself had changed. Operators no longer began by asking whether &#8220;the queue is healthy&#8221; or whether &#8220;the GPU workers are running.&#8221; Those signals still mattered, but they were no longer treated as authoritative.</p><p>Instead, every investigation began with a much more precise question:</p><p>Is the system waiting because Intent is missing, or is Intent present but Execution cannot realize it?</p><p>That distinction dramatically narrowed the search space during incidents.</p><p>If Truth showed a growing backlog while Intent remained near zero, the issue was usually in reconciliation itself. Replay Lambda failure, queue emission failure, stale tenant discovery, or a blind control plane could all create this pattern. The queue might look empty and the autoscaling group might remain at zero, yet the real failure would not be in the workers. It would be in the system&#8217;s ability to regenerate Intent from Truth.</p><p>If Intent existed but Execution failed repeatedly, the investigation shifted toward realization problems instead: bucket routing mismatches, stale AMIs, launch-template drift, IAM gaps, runtime incompatibilities, model-loading failures, endpoint routing problems, or browser-side execution failures.</p><p>That diagnostic framing changed operations significantly. Incidents became easier to classify because TBIE separated the architecture into meaningful operational boundaries. Instead of treating the platform as one opaque pipeline, operators could isolate whether the failure belonged to Truth, Belief, Intent, or Execution.</p><p>The model also made one uncomfortable reality obvious: dashboards alone are not enough. A queue can look healthy while Truth continues accumulating backlog. Autoscaling can look correct while workers continuously crashloop. A scheduled Lambda can appear operational while silently failing every invocation because of an IAM permission gap.</p><p>TBIE did not eliminate debugging complexity. What it did was make debugging systematic.</p><h2>23. When the System Hangs at 02:00 AM</h2><p>Architectural diagrams are useful during design reviews.</p><p>Runbooks matter during incidents.</p><p>One of the most important evolutions in Parjanya v2.0 was realizing that reconciliation needed to exist not only in architecture, but also in operational practice. TBIE only became truly useful once there was a repeatable process for recovering the system under pressure.</p><p>The first step during any &#8220;hung VLM&#8221; investigation became identifying the TBIE boundary itself.</p><p>Truth consisted of the DynamoDB image rows and their workflow state. Intent consisted of SQS messages representing GPU work. Execution consisted of GPU workers consuming that Intent and writing enriched Truth back into DynamoDB. Belief consisted of queue depth, autoscaling state, visibility counts, worker health, and operational telemetry.</p><p>Once those boundaries were established, incident triage became much more structured.</p><p>Operators first checked Truth backlog. Were rows accumulating in pending_vlm_enrichment? If yes, the system still believed work should happen.</p><p>Next came Intent backlog. Did SQS contain replayable work items? If Truth backlog was high while Intent remained near zero, then reconciliation itself had failed.</p><p>Then came Execution health. Were GPU workers alive? Were containers actually starting? Were model loads succeeding? Were workers consuming messages or continuously failing before acknowledgement?</p><p>Several operational shortcuts emerged over time.</p><p>If the GPU log group was empty while ASG instances existed, the problem was often below the application layer entirely. Cloud-init failures, stale image tags, or broken launch templates frequently surfaced first through EC2 console output rather than through CloudWatch worker logs.</p><p>If the replay Lambda appeared scheduled but no queue activity existed, IAM permissions became the first thing to inspect. One of the most dangerous incidents in the system occurred precisely because the reconciliation Lambda could no longer read queue attributes, effectively blinding the control plane while the infrastructure superficially appeared healthy.</p><p>If rows repeatedly failed with S3 download errors while workers remained alive, the issue was often deterministic addressing rather than transient instability. Wrong-bucket references, preview routing mismatches, or endpoint configuration drift could all create workers that failed consistently while still appearing operational.</p><p>Over time, this changed the operational mindset of the platform. The goal stopped being &#8220;restart the workers and hope.&#8221; The goal became understanding exactly where reconciliation had broken down and then repairing the appropriate boundary.</p><p>That distinction is subtle, but extremely important.</p><p>A resilient platform is not the one that avoids incidents. It is the one that can recover from them methodically.</p><h2>24. Guardrails and Proactive Controls</h2><p>One of the clearest architectural patterns that emerged from Parjanya was that every major incident eventually needed to produce a permanent guardrail.</p><p>Without that discipline, incidents remain stories. With it, incidents become operational evolution.</p><p>The architecture gradually accumulated a large number of proactive controls:</p><p>Transient worker failures no longer delete Intent prematurely. Replay Lambdas continuously reconcile pending Truth. Reproducible lockfiles prevent dependency drift. Terraform validations reject invalid wildcard CORS patterns. Tenant discovery became dynamic rather than operator-maintained. Queue retention was extended to match real outage windows rather than idealized assumptions.</p><p>Many of these controls were not introduced because the architecture diagram required them. They emerged because production failures revealed where reconciliation could silently drift.</p><p>This is one of the strongest long-term lessons from the TBIE model.</p><p>Resilience is not achieved through one large design decision. It is accumulated gradually through operational guardrails.</p><p>The mature version of the system looked very different from the original one not because the core architecture changed dramatically, but because every important failure eventually became:</p><p>a validation rule,<br>a replay strategy,<br>a Terraform constraint,<br>a CI assertion,<br>a queue safeguard,<br>or an operational diagnostic.</p><p>That is how resilient systems evolve in practice.</p><p>They convert incidents into institutional memory.</p><h2>25. Maintenance as a Reliability Discipline</h2><p>One of the easiest mistakes in distributed systems is assuming resilience is something implemented once.</p><p>In reality, resilience is maintained continuously.</p><p>By the later stages of Parjanya v2.0, the team had accumulated a growing operational checklist precisely because many failures were caused not by dramatic outages, but by small forms of drift.</p><p>Replay logic and worker behavior needed to evolve together. GPU image tags needed to stay aligned with launch templates. Lockfiles had to remain committed when dependencies changed. Tenant buckets required CORS validation before onboarding. Queue retention needed to reflect actual business downtime windows. Backend API contracts and frontend types had to remain synchronized.</p><p>None of these tasks sound individually sophisticated.</p><p>But distributed systems rarely collapse from a single catastrophic event. They erode through gradual inconsistency.</p><p>That realization changed how the platform was maintained.</p><p>Operational discipline became part of the architecture itself.</p><p>The maintenance checklist was therefore not merely documentation. It was a recognition that reconciliation must continue throughout the entire lifecycle of the platform.</p><h2>26. Why TBIE Matters Beyond AI</h2><p>Although Parjanya is an AI platform, the architectural lessons generalize broadly.</p><p>The same TBIE principles apply to:</p><p>distributed media systems,<br>payment processing,<br>ETL pipelines,<br>logistics systems,<br>asynchronous workflows,<br>microservice orchestration,<br>large-scale ingestion platforms.</p><p>The core challenge is universal:</p><p>How do you maintain alignment between:</p><p>durable truth,<br>intended work,<br>operational state,<br>and actual execution?</p><p>TBIE provides a vocabulary for reasoning about that alignment.</p><h2>27. The Shift from Pipeline to Platform</h2><ol><li><p>Truth must remain durable and replayable</p></li></ol><p>If Truth cannot reconstruct the system after failures, the architecture becomes operationally fragile.</p><ol start="2"><li><p>Intent is more important than most systems realize</p></li></ol><p>Intent is replayability.</p><p>Destroying Intent prematurely destroys recovery.</p><ol start="3"><li><p>Event-driven systems expose hidden drift faster</p></li></ol><p>Reactive architectures surface infrastructure inconsistencies earlier.</p><p>This is painful initially.</p><p>But healthier long-term.</p><ol start="4"><li><p>Execution must remain reproducible</p></li></ol><p>Replay without reproducibility becomes dangerous.</p><ol start="5"><li><p>Control-plane observability matters more than worker observability</p></li></ol><p>Worker crashes are recoverable. Blind reconcilers are not.</p><ol start="6"><li><p>Queue depth alone is not truth</p></li></ol><p>Belief metrics require interpretation.</p><p>Approximate counts are operational signals, not durable truth.</p><ol start="7"><li><p>Policy replay should be designed intentionally</p></li></ol><p>Eventually every ML platform needs deterministic reprocessing.</p><p>Replay-native architectures handle this gracefully.</p><ol start="8"><li><p>Distributed systems fail by divergence</p></li></ol><p>Not by total outage.</p><p>The hardest bugs were:</p><p>wrong bucket,<br>stale AMI,<br>hidden CORS mismatch,<br>invisible IAM gap,<br>frozen replay,<br>missing Intent.</p><p>TBIE helped make those failures explainable.</p><h2>28. The Future Direction</h2><p>The current architecture already points toward several future evolutions:</p><ul><li><p>multi-stage event-driven pipelines,</p></li><li><p>adaptive batching,</p></li><li><p>warm GPU pools,</p></li><li><p>richer metrics export,</p></li><li><p>dynamic replay orchestration,</p></li><li><p>per-stage autoscaling,</p></li><li><p>event-sourced workflow history,</p></li><li><p>tenant-aware media delivery,</p></li><li><p>replayable policy evolution.</p></li></ul><p>Importantly:</p><p>These evolutions do not require rewriting the architecture.</p><p>They emerge naturally because reconciliation is already foundational.</p><p>That is one of the strongest signs that the architecture direction is correct.</p><h2>Closing Thoughts</h2><p>TBIE did not begin as an attempt to create a framework.</p><p>It emerged because distributed AI infrastructure repeatedly exposed the same class of operational failures:</p><p>work disappearing,<br>retries becoming impossible,<br>control planes drifting,<br>execution environments diverging,<br>queues losing meaning,<br>infrastructure behaving correctly against stale assumptions.</p><p>The model became useful because it created clarity.</p><p>Truth. Belief. Intent. Execution.</p><p>Once those boundaries became explicit:</p><p>replay became easier,<br>debugging became faster,<br>autoscaling became safer,<br>policy evolution became manageable,<br>and infrastructure failures became explainable.</p><p>The most important lesson from Parjanya v2.0 is not that event-driven architectures are faster.</p><p>The deeper lesson is:</p><p>Resilient distributed systems are fundamentally reconciliation systems.</p><p>The system that survives is not necessarily the one with the fastest workers.</p><p>It is the one that can continuously reconstruct:</p><p>what is true,<br>what work should exist,<br>what execution already happened,<br>and what still needs to be reconciled.</p><p>That is what ultimately transformed Parjanya from a pipeline into a platform.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png" width="1456" height="189" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:189,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[Prompt Debt: How We Doubled Throughput Without Changing the Model]]></title><description><![CDATA[A Parjanya v2.0 field note on inferencing, information waste, and why deleting things sometimes creates more value than adding them]]></description><link>https://blog.phagyul.ai/p/prompt-debt-how-we-doubled-throughput</link><guid isPermaLink="false">https://blog.phagyul.ai/p/prompt-debt-how-we-doubled-throughput</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Wed, 17 Jun 2026 04:16:19 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!h96B!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!h96B!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!h96B!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!h96B!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!h96B!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!h96B!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!h96B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_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;:1298886,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/202383039?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_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_!h96B!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!h96B!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!h96B!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!h96B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d3a4725-4e40-481b-bd3e-1c7c7aab5df3_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In May 2026, I found myself staring at a familiar engineering problem.</p><p>Parjanya&#8217;s Image Quality Assessment pipeline was approaching the limits of what our infrastructure could comfortably handle.</p><p>Inference workloads were growing.</p><p>Batch sizes were increasing.</p><p>Memory utilization was climbing.</p><p>And eventually, the system hit a wall.</p><p>A larger image.</p><p>A slightly bigger batch.</p><p>A little more context.</p><p>And then:</p><blockquote><p>CUDA Out of Memory.</p></blockquote><p>The obvious answer was straightforward.</p><p>Upgrade the hardware.</p><p>Move to larger GPUs.</p><p>Increase the budget.</p><p>Scale vertically.</p><p>That&#8217;s what I almost did.</p><p>Instead, I opened the prompt.</p><p>And that decision ended up saving far more money than a hardware upgrade would have.</p><div><hr></div><h2>The Assumption I Didn&#8217;t Question</h2><p>By this point in the Parjanya v2.0 journey, I had spent months thinking about infrastructure.</p><p>The previous two posts in this series covered:</p><ul><li><p>Multi-account AWS architecture</p></li><li><p>Terraform and operational discipline</p></li><li><p>CI/CD pipelines</p></li><li><p>IAM boundaries</p></li><li><p>Infrastructure scaling</p></li></ul><p>So when inference started becoming expensive, my instinct was predictable.</p><p>I looked at the hardware.</p><p>That&#8217;s what engineers do.</p><p>We assume the bottleneck lives where the graphs are red.</p><p>GPU memory usage was high.</p><p>Throughput was flattening.</p><p>Batch sizes were constrained.</p><p>The diagnosis seemed obvious.</p><p>But infrastructure metrics were only showing symptoms.</p><p>They weren&#8217;t showing the cause.</p><div><hr></div><h2>The Audit That Changed Everything</h2><p>Instead of pricing larger GPUs, I decided to audit the prompt itself.</p><p>At that point our VLM-based IQA system had evolved through multiple versions.</p><p>Each release added new capabilities:</p><ul><li><p>Better composition evaluation</p></li><li><p>Improved wildlife classification</p></li><li><p>More robust defect detection</p></li><li><p>Additional structured outputs</p></li><li><p>More nuanced confidence handling</p></li></ul><p>Every version added knowledge.</p><p>Almost nothing removed knowledge.</p><p>The prompt had become a living document.</p><p>Like most living documents, it accumulated debt.</p><p>When I finally measured it, the numbers surprised me.</p><p>The system prompt plus user context had grown to roughly:</p><p><strong>4,150 tokens</strong></p><p>Not because we needed 4,150 tokens.</p><p>Because nobody had challenged whether we still needed them.</p><div><hr></div><h2>What I Found</h2><p>The easiest way to describe it is this:</p><p>The prompt looked less like a carefully engineered system and more like a codebase that hadn&#8217;t been refactored in years.</p><p>There was useful logic.</p><p>There was historical baggage.</p><p>And there was a lot of dead code.</p><div><hr></div><h3>Unused Outputs</h3><p>One section calculated an overall quality score.</p><p>The model spent tokens reasoning about it.</p><p>The downstream system ignored it completely.</p><p>The actual acceptance and rejection decisions came from deterministic rules elsewhere in the pipeline.</p><p>The score existed because an earlier version needed it.</p><p>The current version didn&#8217;t.</p><p>Yet the prompt still carried the instructions.</p><div><hr></div><h3>Features That Never Shipped</h3><p>I found sections generating:</p><ul><li><p>search tags</p></li><li><p>mood descriptions</p></li><li><p>discovery metadata</p></li></ul><p>These outputs were originally intended for future content discovery features.</p><p>Those features never launched.</p><p>The instructions remained.</p><p>Every inference paid the cost.</p><p>Every single time.</p><div><hr></div><h3>Teaching the Model Things It Already Knew</h3><p>This was the biggest surprise.</p><p>Over time we&#8217;d added examples.</p><p>Then more examples.</p><p>Then explanations for the examples.</p><p>Then explanations explaining the explanations.</p><p>The prompt contained long sections describing:</p><ul><li><p>composition techniques</p></li><li><p>confidence scoring</p></li><li><p>framing recognition</p></li><li><p>classification behavior</p></li></ul><p>At one point those explanations were useful.</p><p>But the model wasn&#8217;t learning from scratch anymore.</p><p>The explanatory scaffolding had become informational overhead.</p><p>The rules mattered.</p><p>The essays explaining the rules did not.</p><div><hr></div><h2>I Started Thinking About It Like Technical Debt</h2><p>The moment everything clicked was when I stopped calling it prompt engineering.</p><p>This wasn&#8217;t prompt engineering.</p><p>This was refactoring.</p><p>The exact same process we apply to software.</p><p>In software we ask:</p><ul><li><p>Is this function still used?</p></li><li><p>Does this dependency still matter?</p></li><li><p>Is this abstraction providing value?</p></li><li><p>Can this code be simplified?</p></li></ul><p>I realized prompts deserve the same scrutiny.</p><p>A prompt is infrastructure.</p><p>It consumes resources.</p><p>It affects latency.</p><p>It affects throughput.</p><p>It affects cost.</p><p>And like any infrastructure, it accumulates debt.</p><p>I started calling this:</p><p><strong>Prompt Debt.</strong></p><div><hr></div><h2>What Stayed</h2><p>This is the part that surprised me most.</p><p>Almost all of the intelligence survived.</p><p>The capabilities remained intact.</p><p>The model still knew how to:</p><ul><li><p>recognize deliberate composition</p></li><li><p>distinguish artistic choices from technical defects</p></li><li><p>apply confidence-aware wildlife classification</p></li><li><p>detect focus issues</p></li><li><p>identify exposure problems</p></li><li><p>generate structured outputs</p></li><li><p>evaluate image quality</p></li></ul><p>We didn&#8217;t remove intelligence.</p><p>We removed repetition.</p><p>We removed explanation.</p><p>We removed historical residue.</p><p>The distinction matters.</p><div><hr></div><h2>The Numbers</h2><p>After the audit:</p><h3>System Prompt</h3><p>~700 tokens &#8594; ~360 tokens</p><h3>User Prompt</h3><p>~3,450 tokens &#8594; ~890 tokens</p><h3>Total Context</h3><p>~4,150 tokens &#8594; ~1,250 tokens</p><p>Approximately:</p><p><strong>70% reduction</strong></p><p>without changing:</p><ul><li><p>the model</p></li><li><p>the hardware</p></li><li><p>the infrastructure</p></li><li><p>the deployment architecture</p></li></ul><p>Only the prompt changed.</p><div><hr></div><h2>Why 70% Matters</h2><p>It&#8217;s tempting to see this as an academic optimization.</p><p>It wasn&#8217;t.</p><p>Those tokens had real operational consequences.</p><p>Every unnecessary token consumes:</p><ul><li><p>memory</p></li><li><p>compute</p></li><li><p>latency budget</p></li><li><p>throughput capacity</p></li></ul><p>On paper, a token looks small.</p><p>At scale, thousands of unnecessary tokens become infrastructure.</p><p>And infrastructure costs money.</p><p>Before the cleanup, our batching limits were constrained by context size.</p><p>After the cleanup, we could process roughly twice as many images within similar memory budgets.</p><p>The result was effectively:</p><p><strong>2x throughput without changing hardware.</strong></p><p>The kind of gain most teams expect from an expensive infrastructure project.</p><p>We got it from deleting text.</p><div><hr></div><h2>Every Token Has a Cost</h2><p>This became the biggest lesson of the entire exercise.</p><p>Engineers often think about infrastructure costs.</p><p>Few think about information costs.</p><p>Every token carries a burden.</p><p>A token occupies memory.</p><p>A token increases inference time.</p><p>A token competes for attention.</p><p>A token introduces complexity.</p><p>The question isn&#8217;t:</p><blockquote><p>&#8220;Can the model read this?&#8221;</p></blockquote><p>The question is:</p><blockquote><p>&#8220;Should the model be reading this at all?&#8221;</p></blockquote><p>Those are very different questions.</p><p>This was a practical reminder of a lesson I explored earlier in <em>Grounding Is Not a Prompt</em>. Models don&#8217;t become more faithful simply because we provide more instructions. What matters is the quality and relevance of information available at inference time. A smaller, denser prompt often outperforms a larger one filled with historical baggage and explanatory noise.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;b18987ef-e1f5-4c1b-8bb3-39710cb58f7b&quot;,&quot;caption&quot;:&quot;Source: How Well Do Large Language Models Truly Ground?&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Grounding Is Not a Prompt&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-02-07T02:21:22.979Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!HHAz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f120e84-49db-45ec-a506-edf56f9c4e73_1536x970.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/grounding-is-not-a-prompt&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:187075330,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><h2>The Broader Pattern</h2><p>The more I reflected on the exercise, the more it felt familiar.</p><p>This pattern appears everywhere.</p><p>Organizations accumulate meetings.</p><p>Software accumulates dependencies.</p><p>Infrastructure accumulates services.</p><p>Prompts accumulate instructions.</p><p>Over time, complexity grows through addition.</p><p>Rarely through subtraction.</p><p>Most systems become slower because nobody asks what can be removed.</p><p>Prompts are no different.</p><p>While reviewing the prompt, I kept thinking about a principle we previously discussed in <em>Databases, Caches and Queues: A Universal Rule for Distributed Systems</em>. Systems become resilient when information has clear ownership and purpose. The same principle applies to prompts. Every instruction should exist for a reason. If nobody consumes it, it becomes operational debt.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;a0f2bc2c-55c1-46a1-b16b-e699ad9c583a&quot;,&quot;caption&quot;:&quot;Modern distributed systems fail not because of scale, but because of misplaced responsibility. As systems grow asynchronous, replicated, and fault-tolerant, confusion often arises over what represents reality, what represents optimization, and what represents&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Databases, Caches and Queues: A universal Rule for Distributed Systems&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-02-01T03:44:43.149Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!FlV_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F678c2435-563e-447a-86c3-de6ba19a0970_800x533.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/databases-caches-and-queues-a-universal&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:186410680,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:4,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><h2>The Connection to Inferencing</h2><p>This experience fundamentally changed how I think about inference optimization.</p><p>Most conversations focus on:</p><ul><li><p>larger models</p></li><li><p>larger context windows</p></li><li><p>larger GPUs</p></li><li><p>more sophisticated hardware</p></li></ul><p>Those matter.</p><p>But they&#8217;re not always the first lever.</p><p>Sometimes the most effective optimization isn&#8217;t computational.</p><p>It&#8217;s informational.</p><p>Before changing the model, review the prompt.</p><p>Before upgrading the GPU, review the prompt.</p><p>Before increasing context windows, review the prompt.</p><p>The cheapest token is the one you never generate.</p><div><hr></div><h2>What Comes Next</h2><p>Prompt reduction was only one layer.</p><p>The next frontier involves serving optimization:</p><ul><li><p>prompt prefix caching</p></li><li><p>KV cache reuse</p></li><li><p>vLLM batching improvements</p></li><li><p>quantization strategies</p></li><li><p>memory-efficient inference</p></li></ul><p>Those areas still offer meaningful gains.</p><p>But they sit on top of a more fundamental principle.</p><p>Optimize information before optimizing infrastructure.</p><div><hr></div><h2>The Takeaway</h2><p>When the system first ran out of memory, I assumed we had a hardware problem.</p><p>What we actually had was an information problem.</p><p>The model wasn&#8217;t struggling because it lacked capacity.</p><p>It was struggling because we were making it carry unnecessary baggage.</p><p>That distinction changed how I think about AI systems.</p><p>We often assume progress requires adding something.</p><p>A larger model.</p><p>A larger GPU.</p><p>A larger context window.</p><p>A larger budget.</p><p>In this case, the breakthrough came from subtraction.</p><p>The model already knew enough.</p><p>The system simply needed less noise.</p><p>And that&#8217;s a lesson that extends far beyond prompts.</p><p>It&#8217;s a lesson about engineering itself.</p><div><hr></div><p><em>This concludes the initial Parjanya v2.0 engineering series. Across these three posts&#8212;from AWS account boundaries, to Terraform discipline, to prompt debt&#8212;the common theme has been surprisingly consistent: systems scale best when boundaries are clear, assumptions are explicit, and unnecessary complexity is removed. The challenge is rarely adding more. The challenge is knowing what to keep.</em></p><div><hr></div><h2>Further Reading</h2><p>If this article resonated with you, these related essays expand on the ideas discussed here:</p><ul><li><p><strong><a href="https://blog.phagyul.ai/p/grounding-is-not-a-prompt">Grounding Is Not a Prompt</a></strong> &#8212; Why better information retrieval often matters more than adding more instructions to a model.</p></li><li><p><strong><a href="https://blog.phagyul.ai/p/vlm-batch-inference-4-bit-quantization">VLM Batch Inference - 4 bit quantisation depth</a></strong> &#8212; The Hidden Cost of &#8220;Almost Fitting&#8221;</p></li><li><p><strong><a href="https://blog.phagyul.ai/p/context-engineering-and-context-debt">Context Engineering and Context Debt</a> &#8212; </strong><em><span data-color="rgb(54, 55, 55)" style="color: rgb(54, 55, 55);">a data investigation that revealed ~77% of my token spend was context accumulation waste, not productive reasoning. This is the framework I built to fix it &#8212; and the problem has a name: </span>Context Debt <span data-color="rgb(54, 55, 55)" style="color: rgb(54, 55, 55);">and the fix is:</span> Context Engineering <span data-color="rgb(54, 55, 55)" style="color: rgb(54, 55, 55);">.</span></em></p></li><li><p><strong><a href="https://blog.phagyul.ai/p/databases-caches-and-queues-a-universal">Databases, Caches and Queues: A Universal Rule for Distributed Systems</a></strong><a href="https://blog.phagyul.ai/p/databases-caches-and-queues-a-universal"> </a>&#8212; The Truth, Belief and Intent framework that inspired how we think about information flow across systems.</p></li><li><p><strong><a href="https://blog.phagyul.ai/p/tbie-in-practice-designing-resilient">TBIE in Practice: Designing Resilient AI Pipelines That Recover, Reconcile, and Re-run</a> - </strong>Reconciliation loop and TBIE model with case studies with Parjanya v2.0</p></li><li><p><strong><a href="https://blog.phagyul.ai/p/terraform-at-scale-what-actually">Terraform at Scale: What Actually Worked, What Didn&#8217;t, and the Cost of Trusting AI with Infrastructure</a></strong> &#8212; The previous post in this series, exploring operational discipline and infrastructure boundaries.</p></li><li><p><strong><a href="https://blog.phagyul.ai/p/why-we-use-three-aws-accounts-not">Why We Use Three AWS Accounts (Not Two) for Parjanya v2.0</a></strong><a href="https://blog.phagyul.ai/p/why-we-use-three-aws-accounts-not"> </a>&#8212; The architectural foundation that enabled the optimizations described here.</p></li></ul><div><hr></div><h2>Introducing the Inferencing Series</h2><p>This article marks the beginning of a new series exploring inferencing as a first-class engineering discipline. Much of the AI conversation today revolves around models, benchmarks, and training. Yet in production systems, the economics and behaviour of AI are often determined long after training is complete&#8212;during inference. The choices we make around prompts, context, quantization, batching, memory management, caching, retrieval, and serving architecture frequently have a greater impact on cost, latency, and reliability than changing the model itself.</p><p>Throughout this series, I&#8217;ll share lessons learned while building and operating Parjanya&#8217;s Visual Language Model (VLM) pipelines. Rather than focusing on LLM chat applications, the emphasis will be on real-world image understanding systems: image quality assessment, wildlife classification, structured extraction, multimodal reasoning, and the engineering decisions required to run them efficiently at scale. The goal is not simply to reduce costs, but to understand how information flows through an AI system and where meaningful optimization actually lives.</p><div><hr></div><h2>Why Start With Prompt Debt?</h2><p>Prompt Debt is an ideal starting point because it reveals a common misconception about AI systems: that performance improvements come primarily from adding more. More instructions. More examples. More context. More hardware. In practice, many mature VLM systems accumulate informational debt in the same way software accumulates technical debt&#8212;unused outputs, redundant instructions, abandoned features, and historical assumptions that continue consuming resources long after they stop creating value.</p><p>Future articles in the Inferencing Series will build on this foundation by exploring quantization, context engineering, grounding strategies, serving architectures, prompt caching, KV-cache optimization, batching, multimodal pipelines, and the operational realities of running VLM workloads in production. Prompt Debt is simply the first lens. The broader question&#8212;and the one that interests me most&#8212;is how to maximize signal while minimizing computational waste across the entire inferencing stack.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png" width="1456" height="189" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:189,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[Terraform at Scale: What Actually Worked, What Didn’t, and the Cost of Trusting AI with Infrastructure]]></title><description><![CDATA[A Parjanya v2.0 field note from migrating a real platform across AWS accounts, repositories, and automation layers]]></description><link>https://blog.phagyul.ai/p/terraform-at-scale-what-actually</link><guid isPermaLink="false">https://blog.phagyul.ai/p/terraform-at-scale-what-actually</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Tue, 16 Jun 2026 04:30:41 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!FmcI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F981e19f5-1c53-45d1-b071-7abbe56d44bb_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FmcI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F981e19f5-1c53-45d1-b071-7abbe56d44bb_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FmcI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F981e19f5-1c53-45d1-b071-7abbe56d44bb_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!FmcI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F981e19f5-1c53-45d1-b071-7abbe56d44bb_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!FmcI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F981e19f5-1c53-45d1-b071-7abbe56d44bb_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!FmcI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F981e19f5-1c53-45d1-b071-7abbe56d44bb_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FmcI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F981e19f5-1c53-45d1-b071-7abbe56d44bb_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/981e19f5-1c53-45d1-b071-7abbe56d44bb_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;:1502563,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/202230143?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F981e19f5-1c53-45d1-b071-7abbe56d44bb_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_!FmcI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F981e19f5-1c53-45d1-b071-7abbe56d44bb_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!FmcI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F981e19f5-1c53-45d1-b071-7abbe56d44bb_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!FmcI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F981e19f5-1c53-45d1-b071-7abbe56d44bb_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!FmcI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F981e19f5-1c53-45d1-b071-7abbe56d44bb_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>When people talk about Terraform, they often talk about Infrastructure as Code.</p><p>What I learned while building Parjanya v2.0 is that Terraform is really about something else:</p><p><strong>forcing operational discipline.</strong></p><p>Terraform didn&#8217;t magically simplify our infrastructure. It exposed assumptions, surfaced hidden dependencies, and forced us to formalize decisions we had previously gotten away with making informally.</p><p>As Parjanya evolved from a collection of scripts, console clicks, and one-off configurations into a multi-tenant image processing platform, Terraform became the backbone that allowed us to scale infrastructure without losing control.</p><p>It also introduced new challenges.</p><p>And when I layered AI-assisted engineering into the workflow, I discovered an entirely different category of problems worth documenting.</p><p>This post is the implementation companion to my previous article on why we chose a three-account AWS architecture for Parjanya v2.0.</p><p>That post explained the boundaries.</p><p>This one explains how we turned those boundaries into code.</p><div><hr></div><h2>The Reality of Operating Across Five Repositories</h2><p>Parjanya today spans five repositories.</p><p>Each exists for a reason.</p><ul><li><p><strong>parjanya-ml</strong> handles inference and model serving.</p></li><li><p><strong>parjanya-ops</strong> owns infrastructure and platform operations.</p></li><li><p><strong>parjanya-backend</strong> manages orchestration and APIs.</p></li><li><p><strong>parjanya-frontend</strong> serves tenant-facing experiences.</p></li><li><p><strong>parjanya-shared-libraries</strong> contains contracts and shared abstractions.</p></li></ul><p>The separation works well organizationally.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;2c65bc97-28aa-4849-96b3-84776f8019de&quot;,&quot;caption&quot;:&quot;After shipping Parjanya v1.0 through v1.3 (with 17+ patch releases), we&#8217;ve evolved from monolithic friction to a deliberate five-repository polyrepo architecture aligned with team structure and technical boundaries. This post documents our research-driven thought process, the specific tech stack (Nx frontend, FastAPI microservices, PyTorch + MIT-license&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Parjanya&#8217;s Polyrepo Architecture: Building Scalable AI/LLM Products with Organizational Autonomy (Part 1)&quot;,&quot;publishedBylines&quot;:[],&quot;post_date&quot;:&quot;2025-12-23T12:34:44.703Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!DlFL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa48be658-e370-4fcc-861a-5574afd8b22f_782x533.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/parjanyas-polyrepo-architecture-building&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:182407614,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>ML engineers don&#8217;t need to understand IAM condition keys.</p><p>Infrastructure engineers don&#8217;t need to navigate PyTorch dependencies.</p><p>Backend engineers don&#8217;t need to modify Terraform every time they ship a feature.</p><p>But Terraform exposed a challenge that few people talk about:</p><p><strong>cross-repository infrastructure dependencies.</strong></p><p>The moment one repository depends on infrastructure outputs defined in another, coordination becomes critical.</p><p>A renamed Terraform output in one repository can quietly break another repository that references it through remote state.</p><p>I&#8217;ve been bitten by this more than once.</p><p>Terraform didn&#8217;t prevent those mistakes.</p><p>What it did provide was visibility.</p><p>And visibility is often the difference between a recoverable issue and a production incident.</p><div><hr></div><h2>What Terraform Actually Improved</h2><p>A lot of Terraform discussions stay theoretical.</p><p>Here&#8217;s what it changed in practice for us.</p><h3>ECS and Warm Pools</h3><p>One of the first problems we tackled was cold-start latency.</p><p>Inference workloads running on ECS-backed EC2 instances would occasionally wait several minutes for capacity to become available.</p><p>To solve this, we implemented Auto Scaling Group warm pools.</p><p>The result wasn&#8217;t just faster startup times.</p><p>It gave us a repeatable way to define capacity behavior for different tenant tiers.</p><p>Instead of manually tuning infrastructure across environments, we could express those decisions through variables and deploy them consistently.</p><p>That may sound mundane.</p><p>But consistency becomes incredibly valuable once multiple environments, tenants, and deployment pipelines are involved.</p><div><hr></div><h3>Multi-Tenant S3 Isolation</h3><p>Parjanya is a multi-tenant platform.</p><p>Tenant isolation isn&#8217;t optional.</p><p>Terraform allowed us to codify S3 prefix-level isolation directly into IAM policies.</p><p>The most important outcome wasn&#8217;t the policy itself.</p><p>It was the reviewability.</p><p>A missing condition that could have exposed tenant object metadata became visible during code review instead of after deployment.</p><p>That&#8217;s one of Terraform&#8217;s underrated strengths:</p><p>It turns invisible infrastructure assumptions into visible diffs.</p><div><hr></div><h3>DynamoDB Tenant Boundaries</h3><p>The same pattern applied to DynamoDB.</p><p>Every tenant&#8217;s data is partitioned using tenant identifiers, with IAM enforcing access boundaries.</p><p>Could application code enforce those rules?</p><p>Yes.</p><p>Should application code be the only layer enforcing them?</p><p>Absolutely not.</p><p>Terraform helped us move those guarantees into infrastructure itself.</p><p>Even if application logic fails, IAM remains the final gatekeeper.</p><div><hr></div><h3>Event-Driven Infrastructure</h3><p>Parjanya&#8217;s processing pipeline relies heavily on EventBridge and SQS.</p><p>Before Terraform, environment drift was a recurring problem.</p><p>A queue configuration changed in Production but not Development.</p><p>An EventBridge rule existed in one environment but not another.</p><p>Over time these differences accumulate.</p><p>Terraform gave us repeatability.</p><p>The same modules, deployed consistently, dramatically reduced configuration divergence.</p><div><hr></div><h2>The Three-Account Migration</h2><p>The biggest Terraform project in Parjanya v2.0 wasn&#8217;t a service deployment.</p><p>It was infrastructure reorganization.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;78556e34-5bf1-4614-8cb0-f0c964a7944f&quot;,&quot;caption&quot;:&quot;When you&#8217;re building a startup, the default path is obvious:&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Why We Use Three AWS Accounts (Not Two) for Parjanya v2.0&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-06-15T04:34:11.507Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!QEIO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c5c405-f110-4c39-aa87-4a649cc75bf0_1536x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/why-we-use-three-aws-accounts-not&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:202074805,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>We migrated from a single AWS account into:</p><ul><li><p>Management / Tooling</p></li><li><p>Development</p></li><li><p>Production</p></li></ul><p>Terraform made that migration possible.</p><p>It did not make it easy.</p><div><hr></div><h3>Making State Account-Aware</h3><p>Our original infrastructure assumed everything lived in one account.</p><p>Provider configurations were implicit.</p><p>Cross-account roles didn&#8217;t exist.</p><p>Account boundaries didn&#8217;t exist.</p><p>The first step was making account ownership explicit.</p><p>That sounds simple until you realize every Terraform resource suddenly needs to know which AWS account it belongs to.</p><p>The work wasn&#8217;t intellectually difficult.</p><p>It was painstaking.</p><p>And this is where I learned an important lesson about AI-assisted engineering:</p><p>AI is surprisingly bad at repetitive infrastructure migrations unless it has complete context.</p><div><hr></div><h3>Migrating State Safely</h3><p>One of the most valuable Terraform commands I encountered during this process was:</p><p><code>terraform state mv</code></p><p>State migration sounds boring.</p><p>Until you realize a single mistake can cause Terraform to believe a production resource should be destroyed and recreated.</p><p>The migration process became an exercise in discipline:</p><p>Move state.</p><p>Run a plan.</p><p>Review carefully.</p><p>Repeat.</p><p>Slowly.</p><p>The temptation to batch changes is enormous.</p><p>Resisting that temptation saved us multiple times.</p><div><hr></div><h3>Cross-Account IAM</h3><p>The three-account architecture introduced a new category of complexity.</p><p>Trust relationships.</p><p>The Management account hosts shared tooling.</p><p>Development and Production need access to those resources.</p><p>Terraform became the mechanism for expressing those trust boundaries consistently.</p><p>What surprised me wasn&#8217;t the complexity of the IAM policies.</p><p>It was how much architectural thinking is required before writing any Terraform.</p><p>The tooling faithfully implements your design.</p><p>It does not validate whether the design itself is sensible.</p><div><hr></div><h3>Centralized State Management</h3><p>One decision I remain happy with is keeping Terraform state centralized within the Management account.</p><p>Development engineers can operate Development.</p><p>Production operators can manage Production.</p><p>But neither automatically gains access to every state file.</p><p>This separation aligns with the overall philosophy behind the architecture:</p><p>Boundaries first.</p><p>Convenience second.</p><div><hr></div><h2>Where AI Helped &#8212; And Where It Didn&#8217;t</h2><p>Throughout this migration I relied heavily on AI-assisted development.</p><p>Claude became part of the workflow.</p><p>Over time I learned that different models excel at very different tasks.</p><p>The results were revealing.</p><div><hr></div><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;172d4a1b-7754-4334-8b8f-aa5828ec4385&quot;,&quot;caption&quot;:&quot;A few months ago, I wrote about why I believed in a Haiku-first strategy: start with the cheapest and fastest model possible, then escalate only when the task genuinely becomes harder. That idea still makes sense in principle.&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Sonnet 4.6 Became My New Benchmark for Building an Infra-Heavy VLM Platform&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-05-11T04:33:51.000Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!OkJ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb255522-dac5-4f82-bedf-427ae147535f_1536x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/sonnet-46-became-my-new-benchmark&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:197172333,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><h3>Haiku: Fast But Dangerous for Infrastructure</h3><p>Haiku was excellent at generating boilerplate.</p><p>Variable files.</p><p>Module outputs.</p><p>Simple scaffolding.</p><p>But infrastructure isn&#8217;t just syntax.</p><p>Infrastructure is reasoning.</p><p>I repeatedly found that Haiku could generate valid Terraform that contained subtle security flaws.</p><p>The code looked correct.</p><p>The logic wasn&#8217;t.</p><p>That distinction matters.</p><p>A lot.</p><p>My conclusion became simple:</p><p><strong>Haiku should never be trusted with security-sensitive infrastructure decisions.</strong></p><div><hr></div><h3>Sonnet: The Daily Driver</h3><p>Most of our Terraform work happened with Sonnet.</p><p>For implementation tasks inside a repository, it performed extremely well.</p><p>Module structures.</p><p>Provider configurations.</p><p>Refactors.</p><p>General Terraform development.</p><p>Where it struggled was context.</p><p>A repository rename might affect multiple repositories.</p><p>A queue change might impact systems it couldn&#8217;t see.</p><p>The problem wasn&#8217;t model intelligence.</p><p>The problem was visibility.</p><p>The model can only reason about what you show it.</p><div><hr></div><h3>Opus: Better at Architecture Than Implementation</h3><p>I brought Opus into the process whenever decisions became architectural.</p><p>Questions like:</p><ul><li><p>Should this responsibility live in Management or Production?</p></li><li><p>How should artifacts flow between accounts?</p></li><li><p>What&#8217;s the cleanest trust model?</p></li></ul><p>These are trade-off questions.</p><p>Opus consistently handled them better than implementation-focused tasks.</p><p>The irony was that the more strategic the question became, the more useful the model became.</p><div><hr></div><h2>The Biggest Problem Wasn&#8217;t Terraform</h2><p>It Was Context.</p><p>This became one of the clearest lessons from Parjanya v2.0.</p><p>The hardest infrastructure problems weren&#8217;t provider bugs.</p><p>They weren&#8217;t Terraform limitations.</p><p>They weren&#8217;t AWS limitations.</p><p>They were context problems.</p><p>Infrastructure lived in one repository.</p><p>ML workloads lived in another.</p><p>Shared interfaces lived somewhere else.</p><p>Every repository understood part of the system.</p><p>No repository understood the entire system.</p><p>That&#8217;s why we started building supporting tooling and internal agents focused on context discovery and verification.</p><p>The challenge wasn&#8217;t generating code.</p><p>The challenge was understanding the system before generating code.</p><div><hr></div><h2>What Terraform Didn&#8217;t Solve</h2><p>It&#8217;s important to be honest about this.</p><p>Terraform isn&#8217;t a cure-all.</p><p>We still accumulated module sprawl.</p><p>We still dealt with drift.</p><p>We still had to manage secrets separately.</p><p>We still needed human judgment when reviewing large infrastructure changes.</p><p>Terraform gave us control.</p><p>It did not eliminate responsibility.</p><div><hr></div><h2>The Practical Lessons</h2><p>If I were starting again today, these are the lessons I&#8217;d carry forward.</p><p><strong>Use Terraform to enforce boundaries, not just provision resources.</strong></p><p><strong>Treat account architecture as an IAM problem first and a Terraform problem second.</strong></p><p><strong>Invest in cross-repository visibility before investing in more automation.</strong></p><p><strong>Choose AI models based on task type, not convenience.</strong></p><p><strong>Review infrastructure plans like code. Because they are.</strong></p><p><strong>Prioritize understanding the system before changing it.</strong></p><p>Most infrastructure failures aren&#8217;t caused by bad tooling.</p><p>They&#8217;re caused by incomplete context.</p><div><hr></div><h2>Looking Ahead</h2><p>The three-account architecture gave us the boundaries.</p><p>Terraform gave us the implementation.</p><p>But neither addressed another challenge that emerged as Parjanya&#8217;s inference workloads grew:</p><p>Cost.</p><p>Specifically, inference cost.</p><p>While we were optimizing infrastructure, another inefficiency was hiding in plain sight.</p><p>Our VLM system prompt had quietly grown to over 4,000 tokens.</p><p>Most of it wasn&#8217;t doing useful work.</p><p>Tomorrow&#8217;s post moves from infrastructure into inference engineering.</p><p>I&#8217;ll share how we reduced prompt size by nearly 70%, doubled throughput on the same hardware, and discovered that some of the most impactful optimizations don&#8217;t involve changing models at all.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;255188e9-f6ce-4a93-bb4d-47d72d38a327&quot;,&quot;caption&quot;:&quot;TL;DR: I noticed Haiku 4.5 being spawned as a subagent during an Opus 4.7 session. That observation opened a data investigation that revealed ~77% of my token spend was context accumulation waste, not productive reasoning. This is the framework I built to fix it &#8212; and the problem has a name:&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Context Engineering and Context Debt&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-05-20T06:06:57.000Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!dA7S!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcea4dfbb-67e2-4a62-af94-c33dac8db92a_1774x887.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/context-engineering-and-context-debt&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:198514119,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:3,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><h2>The Takeaway</h2><p>Terraform didn&#8217;t make Parjanya v2.0 successful.</p><p>What it did was force us to be explicit.</p><p>Explicit about ownership.</p><p>Explicit about trust boundaries.</p><p>Explicit about infrastructure decisions.</p><p>And perhaps most importantly, explicit about the assumptions we were making.</p><p>That&#8217;s the real value of Infrastructure as Code.</p><p>Not automation.</p><p>Clarity.</p><p>And clarity scales far better than heroics.</p><div><hr></div><p><em>This is part of my ongoing Parjanya v2.0 field notes, documenting the architectural, operational, and engineering decisions behind building a multi-tenant AI platform. In the next post, I&#8217;ll move beyond infrastructure and into inference optimization&#8212;where a prompt review ended up delivering more value than a hardware upgrade.</em></p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png" width="1456" height="189" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:189,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[Why We Use Three AWS Accounts (Not Two) for Parjanya v2.0]]></title><description><![CDATA[The infrastructure decision most startups postpone &#8212; and the one I almost did too]]></description><link>https://blog.phagyul.ai/p/why-we-use-three-aws-accounts-not</link><guid isPermaLink="false">https://blog.phagyul.ai/p/why-we-use-three-aws-accounts-not</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Mon, 15 Jun 2026 04:34:11 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!UKDk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8ba4f8-7108-45e5-8859-896188a41372_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you&#8217;re building a startup, the default path is obvious:</p><p>One AWS account.</p><p>Maybe two if you&#8217;re feeling disciplined.</p><p>One for development. One for production.</p><p>It sounds clean. It sounds sufficient.</p><p>For a while, I thought so too.</p><p>As Parjanya evolved into a multi-tenant image processing platform with real workloads, real customers, and increasingly complex infrastructure, I started asking a different question:</p><p><strong>What does the minimum viable production-grade AWS architecture actually look like?</strong></p><p>The answer wasn&#8217;t one account.</p><p>It wasn&#8217;t even two.</p><p>It was three.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UKDk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8ba4f8-7108-45e5-8859-896188a41372_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UKDk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8ba4f8-7108-45e5-8859-896188a41372_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!UKDk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8ba4f8-7108-45e5-8859-896188a41372_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!UKDk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8ba4f8-7108-45e5-8859-896188a41372_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!UKDk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8ba4f8-7108-45e5-8859-896188a41372_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!UKDk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8ba4f8-7108-45e5-8859-896188a41372_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5a8ba4f8-7108-45e5-8859-896188a41372_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;:1357909,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/202074805?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8ba4f8-7108-45e5-8859-896188a41372_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_!UKDk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8ba4f8-7108-45e5-8859-896188a41372_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!UKDk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8ba4f8-7108-45e5-8859-896188a41372_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!UKDk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8ba4f8-7108-45e5-8859-896188a41372_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!UKDk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8ba4f8-7108-45e5-8859-896188a41372_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Today Parjanya v2.0 runs on a three-account AWS structure:</p><ul><li><p>Management / Tooling</p></li><li><p>Development</p></li><li><p>Production</p></li></ul><p>It added complexity upfront.</p><p>It also removed entire categories of risk that I didn&#8217;t want to discover during an incident.</p><p>This post explains why I made that decision, what problems it solved, what I intentionally chose not to build yet, and how I think other SaaS teams should approach the same trade-offs.</p><div><hr></div><h2>The Setup We Started With</h2><p>Like most startups, we began with a single AWS account.</p><p>Everything lived there:</p><ul><li><p>Development resources</p></li><li><p>Production workloads</p></li><li><p>CI/CD pipelines</p></li><li><p>Container registries</p></li><li><p>Shared infrastructure</p></li></ul><p>The setup was fast.</p><p>The problem with fast is that it often hides risk.</p><p>Nothing feels wrong until the day an experiment, a permission mistake, or an infrastructure change unexpectedly affects production.</p><p>As we started formalising Parjanya v2.0, I realised I didn&#8217;t want to keep relying on discipline alone.</p><p>I wanted structural safety.</p><p>That&#8217;s when the three-account model emerged.</p><div><hr></div><h2>The Third Account Isn&#8217;t Staging</h2><p>Whenever I mention three accounts, people assume I mean:</p><ul><li><p>Dev</p></li><li><p>Staging</p></li><li><p>Prod</p></li></ul><p>That&#8217;s not what I built.</p><p>The structure is:</p><h3>Management / Tooling Account</h3><p>This account owns the operational plumbing:</p><ul><li><p>Container registry</p></li><li><p>Terraform state</p></li><li><p>CI/CD definitions</p></li><li><p>Cross-account IAM roles</p></li><li><p>Billing aggregation</p></li><li><p>Audit aggregation</p></li></ul><p>Importantly, <strong>it never runs application workloads.</strong></p><h3>Development Account</h3><p>This is where experimentation happens.</p><p>Infrastructure changes.</p><p>New features.</p><p>Testing.</p><p>Things break here by design.</p><h3>Production Account</h3><p>This runs live tenant workloads and customer-facing infrastructure.</p><p>Nothing experimental belongs here.</p><p>The critical insight is that the third account isn&#8217;t another environment.</p><p>It&#8217;s neutral territory.</p><p>It owns the things both Dev and Prod need, without forcing either environment to depend directly on the other.</p><div><hr></div><h2>The First Problem It Solves: Artifact Ownership</h2><p>Consider a simple CI/CD pipeline.</p><p>It builds a Docker image.</p><p>Where should that image live?</p><p>If the registry sits in Dev, then Production depends on Development.</p><p>If the registry sits in Prod, Development depends on Production.</p><p>Neither feels right.</p><p>The Management account solves this neatly.</p><p>CI builds once.</p><p>Pushes once.</p><p>Both Dev and Prod pull the exact same artifact.</p><p>No rebuilds.</p><p>No copies.</p><p>No divergence.</p><p>One image.</p><p>One source of truth.</p><p>Multiple promotions.</p><p>That sounds like a small detail until you&#8217;re debugging an issue and need absolute confidence that Production is running the same artifact that passed validation earlier.</p><div><hr></div><h2>The Real Reason: Blast Radius</h2><p>This is the reason that mattered most to me.</p><p>AWS accounts are the strongest isolation boundary AWS provides.</p><p>A broken IAM policy.</p><p>An accidental deletion.</p><p>A Terraform mistake.</p><p>A bad deployment.</p><p>These things cannot casually cross account boundaries.</p><p>That matters because Development should be chaotic.</p><p>People test things.</p><p>Infrastructure changes.</p><p>Experiments happen.</p><p>Failures are expected.</p><p>Production should not inherit that chaos.</p><p>With separate accounts, Dev can fail spectacularly and Prod remains untouched.</p><p>That&#8217;s a much stronger guarantee than &#8220;everyone promises to be careful.&#8221;</p><div><hr></div><h2>Credentials Become Safer by Default</h2><p>A surprisingly useful side effect is credential isolation.</p><p>When someone is working in the Dev account, their credentials only see Dev resources.</p><p>They aren&#8217;t merely discouraged from touching Production.</p><p>Production is outside their scope.</p><p>The same applies to automation.</p><p>The deployment pipeline for Dev assumes different roles than the deployment pipeline for Prod.</p><p>The separation isn&#8217;t cultural.</p><p>It&#8217;s structural.</p><p>And structural controls tend to survive stressful situations much better than process documents.</p><div><hr></div><h2>Cost Visibility Becomes Obvious</h2><p>Another benefit I underestimated was cost attribution.</p><p>Using AWS Organizations means every account naturally reports its own spending.</p><p>Development spend is visible.</p><p>Production spend is visible.</p><p>There&#8217;s no tagging strategy to maintain.</p><p>No allocation spreadsheets.</p><p>No cost archaeology.</p><p>When the AWS bill changes, I immediately know whether it was caused by:</p><ul><li><p>a production feature,</p></li><li><p>increased tenant activity,</p></li><li><p>or a development experiment that ran longer than intended.</p></li></ul><p>That clarity is surprisingly valuable.</p><div><hr></div><h2>What Lives Where</h2><p>The distribution is straightforward.</p><h3>Management Account</h3><ul><li><p>Container registry</p></li><li><p>Terraform backend</p></li><li><p>CI/CD pipelines</p></li><li><p>Cross-account IAM roles</p></li><li><p>Billing aggregation</p></li><li><p>Audit logging</p></li></ul><h3>Development Account</h3><ul><li><p>Full application stack</p></li><li><p>Synthetic tenant data</p></li><li><p>Reduced-scale services</p></li><li><p>Fast feedback loops</p></li><li><p>Manual automation triggers</p></li></ul><h3>Production Account</h3><ul><li><p>Live tenant workloads</p></li><li><p>Customer-facing services</p></li><li><p>Scheduled automation</p></li><li><p>Alerting</p></li><li><p>Full-scale infrastructure</p></li></ul><p>The key principle is simple:</p><p><strong>No application workloads run in the Management account.</strong></p><p>It exists to operate the platform, not host it.</p><div><hr></div><h2>The Deployment Flow</h2><p>The deployment path now looks like this:</p><ol><li><p>Code lands on the main branch.</p></li><li><p>CI/CD runs in the Management account.</p></li><li><p>The pipeline assumes a deployment role in Dev.</p></li><li><p>Integration tests run.</p></li><li><p>The same artifact is promoted into Prod.</p></li></ol><p>Production never builds code.</p><p>Production never owns source repositories.</p><p>Production simply runs validated artifacts.</p><p>That separation removes a surprising amount of operational risk.</p><div><hr></div><h2>What I Chose Not to Build Yet</h2><p>Architecture decisions are often more about what you don&#8217;t build than what you do.</p><h3>No Staging Environment</h3><p>Yet.</p><p>A true staging environment means maintaining a production-like replica.</p><p>That&#8217;s useful.</p><p>It&#8217;s also expensive.</p><p>At our current scale, good automated testing in Dev provides far more value than maintaining another full environment.</p><p>The architecture already supports a staging account.</p><p>I simply chose not to pay for it yet.</p><h3>No Tenant-Level VPC Isolation</h3><p>Today tenant isolation is logical rather than physical.</p><p>Data boundaries are enforced at the application and storage layers.</p><p>Per-tenant VPCs or accounts add stronger isolation, but also significant complexity.</p><p>Most SaaS companies don&#8217;t need that level of separation until enterprise customers explicitly require it.</p><p>We&#8217;re not there yet.</p><h3>No Dedicated Security Account</h3><p>AWS would ideally have:</p><ul><li><p>Management</p></li><li><p>Security</p></li><li><p>Dev</p></li><li><p>Prod</p></li></ul><p>with centralized immutable audit storage.</p><p>I agree with that architecture.</p><p>I also believe infrastructure maturity should follow business reality.</p><p>We&#8217;ll add a dedicated security account when compliance requirements justify it.</p><p>Not before.</p><div><hr></div><h2>My Rule of Thumb for Startups</h2><p>If you&#8217;re building a SaaS product and you&#8217;ve moved beyond proof-of-concept, my recommendation is straightforward:</p><h3>Start with Three Accounts</h3><p>Management.</p><p>Development.</p><p>Production.</p><p>The setup overhead is measured in hours.</p><p>The long-term safety benefits are measured in years.</p><h3>Don&#8217;t Rush Into Staging</h3><p>Build staging when your release process genuinely requires it.</p><p>Not because every architecture diagram on the internet includes one.</p><h3>Use AWS Organizations Early</h3><p>Retrofitting Organizations later is painful.</p><p>Starting with it is easy.</p><p>Future-you will be grateful.</p><h3>Treat the Management Account as Permanent Infrastructure</h3><p>Products evolve.</p><p>Tooling evolves.</p><p>The operational foundation should remain stable.</p><p>The Management account owns the plumbing, not the application.</p><div><hr></div><h2>Looking Ahead</h2><p>The current structure gives me a clear path forward.</p><p>When the platform grows, I can add:</p><ul><li><p>A staging account</p></li><li><p>A dedicated security account</p></li><li><p>Enterprise tenant accounts</p></li></ul><p>Each becomes an extension of the existing architecture rather than a redesign.</p><p>That&#8217;s exactly what I wanted.</p><div><hr></div><h2>The Takeaway</h2><p>The strongest boundary in AWS is the account boundary.</p><p>Use it deliberately.</p><p>For me, three accounts turned out to be the minimum structure that delivered:</p><ul><li><p>blast-radius isolation,</p></li><li><p>clean credential scoping,</p></li><li><p>predictable deployments,</p></li><li><p>and clear cost attribution.</p></li></ul><p>Not because it&#8217;s elegant on a diagram.</p><p>Because it makes operational mistakes dramatically less expensive.</p><p>Parjanya v2.0 is being built with longevity in mind.</p><p>The three-account architecture is one of the quiet decisions that makes everything else possible.</p><div><hr></div><p>The architecture looks clean on a diagram.</p><p>Reality was messier.</p><p>Moving Parjanya from a single AWS account to a three-account model meant refactoring Terraform state, redesigning IAM trust relationships, rebuilding deployment pipelines, and discovering that AI-generated infrastructure code is only as good as the context you give it.</p><p>Tomorrow, I&#8217;ll share the implementation story&#8212;what broke, what surprised us, and why the hardest part of infrastructure isn&#8217;t Terraform itself, but managing context across systems, repositories, and teams.</p><div><hr></div><p><em>This is part of my ongoing field notes from building Parjanya v2.0 &#8212; a multi-tenant image QA platform. I write about the architectural decisions, trade-offs, mistakes, and lessons learned while building it in public.</em></p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png" width="1456" height="189" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:189,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[Archetypes of the Southern Ocean]]></title><description><![CDATA[How the Falkland Islands, South Georgia and Antarctica Changed the Way I See Wildlife]]></description><link>https://blog.phagyul.ai/p/archetypes-of-the-southern-ocean</link><guid isPermaLink="false">https://blog.phagyul.ai/p/archetypes-of-the-southern-ocean</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Wed, 10 Jun 2026 15:55:54 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!kI5-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kI5-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kI5-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.png 424w, https://substackcdn.com/image/fetch/$s_!kI5-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.png 848w, https://substackcdn.com/image/fetch/$s_!kI5-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!kI5-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kI5-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.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;:1921499,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/201469626?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.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_!kI5-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.png 424w, https://substackcdn.com/image/fetch/$s_!kI5-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.png 848w, https://substackcdn.com/image/fetch/$s_!kI5-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!kI5-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97fe0392-4e38-4076-bd17-51ed46ad3c51_1535x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>A few weeks ago, one of the photographs from this series, <em>Vamana</em>, was selected as a finalist in the Black &amp; White category of the <a href="https://refocus-awards.com/people-vote-award/vamana">ReFocus Awards.</a></p><p>The image sparked an unexpected response. Friends who had seen it over the past several months kept asking the same questions:</p><div class="pullquote"><p><em><strong>&#8220;How was this created?&#8221;</strong></em></p><p><em><strong>&#8220;Was it made in-camera?&#8221;</strong></em></p><p><em><strong>&#8220;What were you trying to show?&#8221;</strong></em></p><p><em><strong>&#8220;Why does it feel mythological?&#8221;</strong></em></p></div><p>I promised to write about it when I first shared the image shortly after returning from Antarctica in October 2025. Like many unfinished promises to myself, it remained buried beneath work, travel, writing and countless photographs waiting to be processed.</p><p>The ReFocus recognition felt like the right moment to finally tell the story.</p><p>Because these photographs were never planned as a project.</p><p>They emerged gradually during the journey.</p><p>And like many of my favourite images, they began with a problem.</p><div><hr></div><h2>The Problem of Scale</h2><p>Antarctica, South Georgia and the Falkland Islands repeatedly confronted me with a challenge that a single photograph struggled to solve.</p><p>Scale.</p><p>A portrait could show an individual bird.</p><p>A landscape could show the colony.</p><p>But neither could convey what it felt like to stand there.</p><p>One of the earliest moments came on Steeple Jason Island in the Falklands.</p><p>Before landing, we had been briefed that we would be visiting one of the world&#8217;s largest Black-browed Albatross colonies.</p><p>I knew the numbers.</p><p>I had seen the photographs.</p><p>But numbers and photographs do not prepare you for the experience.</p><p>As I climbed the slope and looked across the colony, thousands upon thousands of albatrosses occupied the hillsides in every direction.</p><p>My instinct was to photograph an individual bird.</p><p>My second instinct was to photograph the colony.</p><p>Neither image felt complete.</p><p>The bird lacked context.</p><p>The landscape lacked intimacy.</p><p>I wanted both.</p><p>That was the moment the experiment began.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!opmB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a368b4-d573-4446-82e4-5ed5d4186d98_1920x1281.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!opmB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a368b4-d573-4446-82e4-5ed5d4186d98_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!opmB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a368b4-d573-4446-82e4-5ed5d4186d98_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!opmB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a368b4-d573-4446-82e4-5ed5d4186d98_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!opmB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a368b4-d573-4446-82e4-5ed5d4186d98_1920x1281.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!opmB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a368b4-d573-4446-82e4-5ed5d4186d98_1920x1281.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c6a368b4-d573-4446-82e4-5ed5d4186d98_1920x1281.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1209987,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/201469626?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a368b4-d573-4446-82e4-5ed5d4186d98_1920x1281.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!opmB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a368b4-d573-4446-82e4-5ed5d4186d98_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!opmB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a368b4-d573-4446-82e4-5ed5d4186d98_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!opmB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a368b4-d573-4446-82e4-5ed5d4186d98_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!opmB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a368b4-d573-4446-82e4-5ed5d4186d98_1920x1281.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Discovering Multiple Exposure</h2><p>The Canon R5C includes an in-camera multiple exposure mode.</p><p>It is a feature that many photographers know exists but few use regularly.</p><p>I had experimented with it before, but mostly as a creative exercise.</p><p>This time it felt useful.</p><p>Instead of creating a portrait and a landscape separately, I wondered whether I could combine them into a single frame.</p><p>Not digitally.</p><p>Not later in Photoshop.</p><p>But in-camera.</p><p>The goal wasn&#8217;t artistic abstraction.</p><p>At least not initially.</p><p>The goal was documentation.</p><p>I wanted to document how the place felt.</p><p>My settings remained remarkably simple throughout the project:</p><ul><li><p>Canon R5C</p></li><li><p>RF 100-500mm lens</p></li><li><p>Multiple Exposure mode</p></li><li><p>Continuous shooting</p></li><li><p>Additive/Luminance blending</p></li><li><p>Mostly 2 exposures per image (3 exposures only for <em>Vamana)</em></p></li></ul><p>Luminance blending proved especially important.</p><p>It allowed brighter areas from one frame to merge naturally with darker regions from another, creating layered images that retained structure without becoming visually chaotic.</p><p>The process quickly became addictive.</p><p>Instead of searching for a decisive moment, I began searching for relationships between moments.</p><div><hr></div><h2>Rajahamsa</h2><p>The first successful image from the experiment became what I later titled <em><strong>Rajahamsa</strong></em>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!o-Oe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F052d764e-26e6-4676-b3e2-c7ebd087756e_1920x1281.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!o-Oe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F052d764e-26e6-4676-b3e2-c7ebd087756e_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!o-Oe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F052d764e-26e6-4676-b3e2-c7ebd087756e_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!o-Oe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F052d764e-26e6-4676-b3e2-c7ebd087756e_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!o-Oe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F052d764e-26e6-4676-b3e2-c7ebd087756e_1920x1281.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!o-Oe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F052d764e-26e6-4676-b3e2-c7ebd087756e_1920x1281.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/052d764e-26e6-4676-b3e2-c7ebd087756e_1920x1281.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1175173,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/201469626?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F052d764e-26e6-4676-b3e2-c7ebd087756e_1920x1281.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!o-Oe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F052d764e-26e6-4676-b3e2-c7ebd087756e_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!o-Oe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F052d764e-26e6-4676-b3e2-c7ebd087756e_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!o-Oe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F052d764e-26e6-4676-b3e2-c7ebd087756e_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!o-Oe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F052d764e-26e6-4676-b3e2-c7ebd087756e_1920x1281.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>A Black-browed Albatross emerged from within its own colony.</p><p>The bird was simultaneously an individual and a multitude.</p><p>The more I looked at the image, the less it felt like a documentary photograph.</p><p>Something symbolic had appeared.</p><p>At the time I couldn&#8217;t fully explain it.</p><p>I only knew the image felt different.</p><p>It seemed to contain an idea rather than merely a subject.</p><p>Looking back now, I realize that was the first indication that the project was heading somewhere unexpected.</p><div><hr></div><h2>From Observation to Archetype</h2><p>The transformation happened gradually.</p><p>Not during editing.</p><p>Not even during shooting.</p><p>It happened while looking.</p><p>Many of the stories we encounter in childhood never truly leave us.</p><p>They remain dormant somewhere beneath conscious thought.</p><p>Standing among vast colonies of birds and seals at the edge of the world, those stories began resurfacing.</p><p>Not literally.</p><p>Symbolically.</p><p>The animals remained animals.</p><p>But they also began to resemble archetypes.</p><p>The same way clouds occasionally resemble faces.</p><p>Or mountains resemble sleeping giants.</p><p>The photographs were becoming bridges between observation and imagination.</p><div><hr></div><h2>Vamana</h2><p>The turning point arrived with a lone penguin(A&#271;el&#233;) standing alone an ice scape and there near by an immense colony of Adele and Rockhopper (I recall!)</p><p>Unlike the other images in the series, <em>Vamana</em> required three exposures.</p><p>An individual penguin.</p><p>The colony below.</p><p>The surrounding landscape.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!t4vK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc47892cc-1249-40a9-bca5-7f1144ef15c7_1920x1003.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!t4vK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc47892cc-1249-40a9-bca5-7f1144ef15c7_1920x1003.jpeg 424w, https://substackcdn.com/image/fetch/$s_!t4vK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc47892cc-1249-40a9-bca5-7f1144ef15c7_1920x1003.jpeg 848w, https://substackcdn.com/image/fetch/$s_!t4vK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc47892cc-1249-40a9-bca5-7f1144ef15c7_1920x1003.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!t4vK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc47892cc-1249-40a9-bca5-7f1144ef15c7_1920x1003.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!t4vK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc47892cc-1249-40a9-bca5-7f1144ef15c7_1920x1003.jpeg" width="1456" height="761" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c47892cc-1249-40a9-bca5-7f1144ef15c7_1920x1003.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:761,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1227283,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/201469626?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc47892cc-1249-40a9-bca5-7f1144ef15c7_1920x1003.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!t4vK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc47892cc-1249-40a9-bca5-7f1144ef15c7_1920x1003.jpeg 424w, https://substackcdn.com/image/fetch/$s_!t4vK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc47892cc-1249-40a9-bca5-7f1144ef15c7_1920x1003.jpeg 848w, https://substackcdn.com/image/fetch/$s_!t4vK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc47892cc-1249-40a9-bca5-7f1144ef15c7_1920x1003.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!t4vK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc47892cc-1249-40a9-bca5-7f1144ef15c7_1920x1003.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>When the image appeared on the camera screen, something immediately felt familiar.</p><p>A small figure.</p><p>An immeasurable world.</p><p>A paradox of scale.</p><p>It reminded me of Vamana, the dwarf incarnation who expands beyond expectation and measures the universe itself.</p><p>The connection was not deliberate.</p><p>It emerged after the photograph existed.</p><p>The mythology wasn&#8217;t guiding the image.</p><p>The image was awakening the mythology.</p><p>For the first time I began wondering whether these photographs might belong together as a series.</p><div><hr></div><h2>Jatayu</h2><p>If there is a photograph that convinced me the project was real, it was <em>Jatayu</em>.</p><p>Captured among the king penguin colonies of South Georgia, the image combines a chick&#8217;s portrait with thousands of penguins spread across a glacial valley.</p><p>The resulting figure feels monumental.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!T76a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51d3168e-52fc-474e-8ed8-f5d25b5d2ff0_1920x1281.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!T76a!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51d3168e-52fc-474e-8ed8-f5d25b5d2ff0_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!T76a!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51d3168e-52fc-474e-8ed8-f5d25b5d2ff0_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!T76a!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51d3168e-52fc-474e-8ed8-f5d25b5d2ff0_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!T76a!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51d3168e-52fc-474e-8ed8-f5d25b5d2ff0_1920x1281.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!T76a!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51d3168e-52fc-474e-8ed8-f5d25b5d2ff0_1920x1281.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/51d3168e-52fc-474e-8ed8-f5d25b5d2ff0_1920x1281.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1387963,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/201469626?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51d3168e-52fc-474e-8ed8-f5d25b5d2ff0_1920x1281.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!T76a!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51d3168e-52fc-474e-8ed8-f5d25b5d2ff0_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!T76a!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51d3168e-52fc-474e-8ed8-f5d25b5d2ff0_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!T76a!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51d3168e-52fc-474e-8ed8-f5d25b5d2ff0_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!T76a!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51d3168e-52fc-474e-8ed8-f5d25b5d2ff0_1920x1281.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Protective.</p><p>Almost watchful.</p><p>The glacier behind it only amplifies that sensation.</p><p>I remember staring at the rear LCD and immediately thinking:</p><p><strong>&#8220;That looks like Jatayu.&#8221;</strong></p><p>Not because it resembled any traditional depiction.</p><p>But because it carried the emotional weight I associated with the character.</p><p>Courage.</p><p>Guardianship.</p><p>Sacrifice.</p><p>For the first time, I stopped thinking about multiple exposure as a technique.</p><p>And started thinking about it as a language.</p><div><hr></div><h2>When Wildlife Becomes Myth</h2><p>One question I am often asked is whether these photographs were intended to illustrate Hindu mythology.</p><p>The answer is no.</p><p>At least not consciously.</p><p>I wasn&#8217;t searching for Vamana.</p><p>I wasn&#8217;t searching for Jatayu.</p><p>I wasn&#8217;t searching for Rajahamsa.</p><p>I was searching for ways to describe experiences that exceeded the limits of a single frame.</p><p>The mythology appeared later.</p><p>What fascinates me now is that this happened almost automatically.</p><p>Faced with extraordinary wildlife spectacles, my mind reached for archetypes I had inherited through stories.</p><p>Perhaps that is what myths have always done.</p><p>They give us a language for experiences that feel larger than ordinary reality.</p><div><hr></div><h2>Technical Notes</h2><p>All photographs in this series were created entirely in-camera using the Canon R5C.</p><p>No compositing was performed in post-processing.</p><p>The images rely on:</p><ul><li><p>Multiple Exposure mode</p></li><li><p>Continuous shooting</p></li><li><p>Luminance blending</p></li><li><p>Telephoto compression using the RF 100-500mm lens</p></li></ul><p>Most images use two exposures.</p><p><em>Vamana</em> uses three exposures.</p><p>What appears complex is actually the result of repeated experimentation in the field and a willingness to embrace unpredictability.</p><p>The final image often revealed itself only after the shutter sequence was complete.</p><div><hr></div><h2>Looking Back</h2><p>When I boarded the expedition vessel, I expected wildlife photography.</p><p>I did not expect a conversation with memory.</p><p>Yet that is ultimately what this project became.</p><p>The Southern Ocean presented extraordinary animals, extraordinary landscapes and extraordinary scale.</p><p>Multiple exposure allowed those experiences to coexist within a single frame.</p><p>And somewhere between observation and imagination, the birds became archetypes.</p><p>Not because they ceased being wildlife.</p><p>But because they became something more.</p><p>A reminder that every act of seeing is shaped by the stories we carry with us.</p><div><hr></div><p>more images from the series arrived unexpectedly, </p><h3>Matsya &#8594; Preservation of life</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fzMD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff40da258-5c03-4e04-bd89-fdd47f8f5d33_1920x1281.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fzMD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff40da258-5c03-4e04-bd89-fdd47f8f5d33_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fzMD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff40da258-5c03-4e04-bd89-fdd47f8f5d33_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fzMD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff40da258-5c03-4e04-bd89-fdd47f8f5d33_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fzMD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff40da258-5c03-4e04-bd89-fdd47f8f5d33_1920x1281.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!fzMD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff40da258-5c03-4e04-bd89-fdd47f8f5d33_1920x1281.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f40da258-5c03-4e04-bd89-fdd47f8f5d33_1920x1281.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:965530,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/201469626?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff40da258-5c03-4e04-bd89-fdd47f8f5d33_1920x1281.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fzMD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff40da258-5c03-4e04-bd89-fdd47f8f5d33_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fzMD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff40da258-5c03-4e04-bd89-fdd47f8f5d33_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fzMD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff40da258-5c03-4e04-bd89-fdd47f8f5d33_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fzMD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff40da258-5c03-4e04-bd89-fdd47f8f5d33_1920x1281.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>While photographing a Gentoo penguin colony in Antarctica, I created a multiple exposure that combined the landscape, the colony, and a solitary penguin. Later, as I revisited the frame, it reminded me of <strong>Matsya</strong>, the fish incarnation of Vishnu in Hindu mythology.</p><p>In the ancient story, Matsya appears during a great deluge and guides a vessel carrying life through the flood, ensuring continuity when the world stands on the edge of destruction. In this photograph, the expedition ship (our own Ortelius MV) rests in the distant background while the penguin emerges as a quiet, symbolic guide in the foreground. The resemblance was not planned in the field, but revealed itself later&#8212;one of those moments where photography becomes less about recording what is seen and more about discovering meaning within what was witnessed.</p><p>Whether coincidence or subconscious association, the image felt like a reminder that stories often exist before we recognize them. The camera records light; imagination completes the journey.</p><h3>Varaha &#8594; Restoration of the world</h3><p>By the end of the expedition, I had stopped looking for specific characters. Instead, I simply observed and waited for forms to emerge on their own. Varaha appeared unexpectedly&#8212;in the shape of ice, snow, and a colony scattered across the shoreline. In Hindu mythology, Varaha rescues the Earth from cosmic waters and restores balance to the world. Standing in Antarctica, a place that constantly reminds us of both fragility and endurance, I found the symbolism difficult to ignore. It became a fitting final archetype: not a story of survival alone, but of renewal.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1owV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6aca099-1339-472c-956c-e4b72e522df0_1920x1281.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1owV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6aca099-1339-472c-956c-e4b72e522df0_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1owV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6aca099-1339-472c-956c-e4b72e522df0_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1owV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6aca099-1339-472c-956c-e4b72e522df0_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1owV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6aca099-1339-472c-956c-e4b72e522df0_1920x1281.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!1owV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6aca099-1339-472c-956c-e4b72e522df0_1920x1281.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d6aca099-1339-472c-956c-e4b72e522df0_1920x1281.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1093809,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/201469626?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6aca099-1339-472c-956c-e4b72e522df0_1920x1281.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1owV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6aca099-1339-472c-956c-e4b72e522df0_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1owV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6aca099-1339-472c-956c-e4b72e522df0_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1owV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6aca099-1339-472c-956c-e4b72e522df0_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1owV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6aca099-1339-472c-956c-e4b72e522df0_1920x1281.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>I will be Continuing the search for new archetypes in new landscapes in the future</strong></p><div><hr></div><p>What began as an experiment has quietly become an ongoing creative pursuit. I now find myself actively searching for new characters and visual metaphors wherever I travel. They may emerge from different landscapes, different species, and different cultures, but the underlying idea remains the same: finding stories that exist somewhere between reality and imagination. More than anything, this project reminded me how much joy there is in playful exploration. I had an incredible amount of fun creating these images, and I look forward to discovering where the next character appears. You can follow my work <a href="https://www.instagram.com/jagadeeshrampam/">here</a> </p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png" width="1456" height="189" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:189,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[Building a Second Brain]]></title><description><![CDATA[Why memory, context and accumulated knowledge may matter more than bigger models.]]></description><link>https://blog.phagyul.ai/p/building-a-second-brain</link><guid isPermaLink="false">https://blog.phagyul.ai/p/building-a-second-brain</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Sun, 07 Jun 2026 03:51:12 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!JmrH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Over the years, I&#8217;ve accumulated thousands of notes.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JmrH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JmrH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!JmrH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!JmrH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!JmrH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JmrH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_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;:1900925,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200964585?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_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_!JmrH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!JmrH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!JmrH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!JmrH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f7e86d4-2dfd-4b80-bc74-f997eb2a05da_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The challenge was never collecting information.</p><p>The challenge was remembering it, connecting it and turning it into something useful.</p><p>Modern AI is remarkably capable.</p><p>Yet most systems remain surprisingly forgetful.</p><p>Every conversation begins from scratch.</p><p>Every project requires context to be reintroduced.</p><p>Every insight risks being lost in another folder, notebook or document.</p><p>The more I worked across research, photography, software, storytelling and archival work, the more obvious the problem became:</p><p><strong>Knowledge was accumulating faster than understanding.</strong></p><p>Instead of building another assistant, I started exploring a different idea.</p><p>What would a genuine second brain look like?</p><p>Not a chatbot.</p><p>Not a search engine.</p><p>Not a note-taking application.</p><p>A system that could:</p><p><strong>Observe &#8594; Remember &#8594; Understand &#8594; Create &#8594; Preserve</strong></p><p>A system capable of connecting ideas across years rather than conversations.</p><p>A system that becomes more valuable as its memory grows.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;0729728d-6b46-4c80-9cbf-808dec6605ae&quot;,&quot;caption&quot;:&quot;Source: How Well Do Large Language Models Truly Ground?&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Grounding Is Not a Prompt&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-02-07T02:21:22.979Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!HHAz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f120e84-49db-45ec-a506-edf56f9c4e73_1536x970.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/grounding-is-not-a-prompt&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:187075330,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><h2>From Information to Understanding</h2><p>Most AI systems operate on prompts.</p><p>A second brain should operate on context.</p><p>Every note should strengthen understanding.</p><p>Every project should enrich memory.</p><p>Every experiment should improve future decisions.</p><p>The objective is not simply to retrieve information.</p><p>The objective is to build accumulated intelligence.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;46b420b4-892c-4a6e-bda7-aacc59164cc1&quot;,&quot;caption&quot;:&quot;Most teams deploy AI as a single endpoint.&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Intelligent Model Orchestration for AI Agent Systems&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-02-12T06:05:38.014Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!X5Qv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb19fe57-9a3a-4370-bf3d-334da29e3c91_1536x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/intelligent-model-orchestration-for&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:187683979,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><h2>The Emergence of Smriti</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iABO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55d92d9b-829d-4905-bb20-7d985a5df33f_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iABO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55d92d9b-829d-4905-bb20-7d985a5df33f_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!iABO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55d92d9b-829d-4905-bb20-7d985a5df33f_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!iABO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55d92d9b-829d-4905-bb20-7d985a5df33f_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!iABO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55d92d9b-829d-4905-bb20-7d985a5df33f_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!iABO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55d92d9b-829d-4905-bb20-7d985a5df33f_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/55d92d9b-829d-4905-bb20-7d985a5df33f_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;:1466499,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200964585?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55d92d9b-829d-4905-bb20-7d985a5df33f_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_!iABO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55d92d9b-829d-4905-bb20-7d985a5df33f_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!iABO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55d92d9b-829d-4905-bb20-7d985a5df33f_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!iABO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55d92d9b-829d-4905-bb20-7d985a5df33f_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!iABO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55d92d9b-829d-4905-bb20-7d985a5df33f_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This thinking eventually evolved into a concept I now call:</p><p><strong>Parjanya&#8217;s Second Brain</strong></p><p>At its core sits <strong>Smriti</strong>.</p><p>Smriti is not simply another product.</p><p>It is the memory and intelligence layer that connects everything else.</p><p>A system designed to preserve context, connect knowledge and build long-term understanding.</p><p>Around this core are four complementary domains:</p><h3>Parjanya</h3><p>Visual Intelligence</p><p>Image quality assessment, visual understanding, benchmarking and insight generation.</p><h3>WilderhoodTV</h3><p>Creative Intelligence</p><p>Storytelling, production workflows, media creation and distribution.</p><h3>Smriti</h3><p>Rooted Intelligence</p><p>Memory, context, reflection and accumulated knowledge.</p><h3>Prakriti</h3><p>Archival Intelligence</p><p>Documenting and preserving wildlife, nature, heritage and field knowledge.</p><p>Together they form a connected intelligence ecosystem rather than a collection of independent products.</p><div><hr></div><h2>Why Context Matters</h2><p>The AI industry is understandably focused on models.</p><p>Bigger models.</p><p>Smarter models.</p><p>Faster models.</p><p>But I increasingly believe the next frontier may be something else.</p><p><strong>Context.</strong></p><p>Models will continue to improve.</p><p>What remains unique is the context we accumulate.</p><p>Our notes.</p><p>Our observations.</p><p>Our projects.</p><p>Our experiences.</p><p>Our decisions.</p><p>Our understanding of the world.</p><p>Without context, intelligence becomes generic.</p><p>With context, intelligence becomes personal.</p><div><hr></div><h2>Looking Ahead</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LiwH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58623d1c-e36b-4606-b1c6-4e80e9ce9229_1024x1536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LiwH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58623d1c-e36b-4606-b1c6-4e80e9ce9229_1024x1536.png 424w, https://substackcdn.com/image/fetch/$s_!LiwH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58623d1c-e36b-4606-b1c6-4e80e9ce9229_1024x1536.png 848w, https://substackcdn.com/image/fetch/$s_!LiwH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58623d1c-e36b-4606-b1c6-4e80e9ce9229_1024x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!LiwH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58623d1c-e36b-4606-b1c6-4e80e9ce9229_1024x1536.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!LiwH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58623d1c-e36b-4606-b1c6-4e80e9ce9229_1024x1536.png" width="1024" height="1536" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/58623d1c-e36b-4606-b1c6-4e80e9ce9229_1024x1536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1536,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1596533,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200964585?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58623d1c-e36b-4606-b1c6-4e80e9ce9229_1024x1536.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_!LiwH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58623d1c-e36b-4606-b1c6-4e80e9ce9229_1024x1536.png 424w, https://substackcdn.com/image/fetch/$s_!LiwH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58623d1c-e36b-4606-b1c6-4e80e9ce9229_1024x1536.png 848w, https://substackcdn.com/image/fetch/$s_!LiwH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58623d1c-e36b-4606-b1c6-4e80e9ce9229_1024x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!LiwH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58623d1c-e36b-4606-b1c6-4e80e9ce9229_1024x1536.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This is still an evolving idea.</p><p>The architecture will change.</p><p>The tools will change.</p><p>The models will change.</p><p>What remains constant is the underlying belief:</p><p><strong>Knowledge should not disappear. It should compound.</strong></p><p>The goal is not to automate thought.</p><p>The goal is to augment it.</p><p>To build a system that helps transform information into understanding, understanding into wisdom and wisdom into meaningful work.</p><div><hr></div><h3>Guiding Principle</h3><p><strong>Observe &#8594; Remember &#8594; Understand &#8594; Create &#8594; Preserve.</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_!8eky!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33ab7cb3-aee2-4839-af72-32d47e792ea4_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8eky!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33ab7cb3-aee2-4839-af72-32d47e792ea4_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!8eky!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33ab7cb3-aee2-4839-af72-32d47e792ea4_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!8eky!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33ab7cb3-aee2-4839-af72-32d47e792ea4_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!8eky!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33ab7cb3-aee2-4839-af72-32d47e792ea4_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!8eky!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33ab7cb3-aee2-4839-af72-32d47e792ea4_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/33ab7cb3-aee2-4839-af72-32d47e792ea4_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;:1332917,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200964585?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33ab7cb3-aee2-4839-af72-32d47e792ea4_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_!8eky!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33ab7cb3-aee2-4839-af72-32d47e792ea4_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!8eky!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33ab7cb3-aee2-4839-af72-32d47e792ea4_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!8eky!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33ab7cb3-aee2-4839-af72-32d47e792ea4_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!8eky!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33ab7cb3-aee2-4839-af72-32d47e792ea4_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png" width="1456" height="189" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:189,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[Valuing an Indian Octopus: Info Edge Through Damodaran’s Lens]]></title><description><![CDATA[Two engines. One balance sheet. A sum-of-the-parts valuation.]]></description><link>https://blog.phagyul.ai/p/valuing-an-indian-octopus-info-edge</link><guid isPermaLink="false">https://blog.phagyul.ai/p/valuing-an-indian-octopus-info-edge</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Fri, 05 Jun 2026 03:20:55 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!YTxS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c2f4773-364b-41d3-bff0-d5e495f6faed_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><p style="text-align: center;"><em><strong>DISCLAIMER: This article is part of my personal learning journey and is meant purely for educational and informational purposes. I have drawn insights from Prof. Aswath Damodaran&#8217;s publicly available teachings and financial information available in the public domain.</strong></em></p><p style="text-align: center;"><em><strong>While preparing this write-up, I referred to platforms such as Screener and AI-based study tools to better understand the concepts and validate publicly available data such as company filings and information available for investors from the company domain. The interpretations and conclusions shared here are entirely my own, and any errors or misunderstandings are solely my responsibility.</strong></em></p><p style="text-align: center;"><em><strong>This is not investment advice or a recommendation to buy, sell, or hold any securities. I encourage readers to do their own research and consult a SEBI-registered investment advisor before making any investment decisions.</strong></em></p></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YTxS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c2f4773-364b-41d3-bff0-d5e495f6faed_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YTxS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c2f4773-364b-41d3-bff0-d5e495f6faed_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!YTxS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c2f4773-364b-41d3-bff0-d5e495f6faed_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!YTxS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c2f4773-364b-41d3-bff0-d5e495f6faed_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!YTxS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c2f4773-364b-41d3-bff0-d5e495f6faed_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YTxS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c2f4773-364b-41d3-bff0-d5e495f6faed_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6c2f4773-364b-41d3-bff0-d5e495f6faed_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;:1486727,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200706956?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c2f4773-364b-41d3-bff0-d5e495f6faed_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_!YTxS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c2f4773-364b-41d3-bff0-d5e495f6faed_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!YTxS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c2f4773-364b-41d3-bff0-d5e495f6faed_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!YTxS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c2f4773-364b-41d3-bff0-d5e495f6faed_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!YTxS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c2f4773-364b-41d3-bff0-d5e495f6faed_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>Key Takeaways</h2><ul><li><p>Info Edge is best understood as two businesses under one roof: a dominant internet classifieds franchise and a highly successful venture investment engine.</p></li><li><p>Traditional valuation multiples can be misleading because a significant portion of the company&#8217;s value comes from listed and unlisted investments.</p></li><li><p>A sum-of-the-parts framework, inspired by Aswath Damodaran&#8217;s valuation approach, is the most appropriate way to analyze the company.</p></li><li><p>The core operating business appears to be a high-quality, cash-generative franchise with strong margins and durable competitive advantages.</p></li><li><p>At current prices, the stock appears to be trading around fair value rather than at a significant discount.</p></li><li><p>Future returns will likely depend on both the continued strength of the Naukri ecosystem and the success of the next generation of startup investments.</p></li></ul><div><hr></div><p>When I look at Info Edge, I do not see a normal listed company. I see two businesses stitched together: a dominant, cash-generating internet classifieds franchise led by Naukri, and a venture-style investment engine that has produced extraordinary value through stakes such as Eternal and PB Fintech.</p><p><strong>That is exactly why I think Info Edge is one of the best Indian case studies for applying Professor Aswath Damodaran's framework. Damodaran has repeatedly argued that cash, cross-holdings, and other non-operating assets should be valued separately from the operating business. In his discussions on holding companies and cross-holdings, he notes that the "sum of the parts" can often be greater than the whole when these assets are not properly accounted for. For a company like Info Edge, where listed and unlisted investments contribute materially to shareholder value, a sum-of-the-parts approach is not optional&#8212;it is essential.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></strong></p><p>In Info Edge&#8217;s case, that distinction is not academic. As of June 2026, the company itself had a market capitalization of roughly &#8377;65,000 crore, while a substantial part of its value sat in listed investments and a startup portfolio that management valued at nearly &#8377;37,000 crore.</p><blockquote><p><strong>So the right question is not, &#8220;Is Naukri expensive on earnings?&#8221;</strong></p></blockquote><p>The right question is:</p><blockquote><p><strong>How much am I paying for the core franchise after adjusting for Eternal, PB Fintech, and the next cohort of private investments?</strong></p></blockquote><div><hr></div><h2>Why Info Edge Is a Perfect case study for understanding Prof. Damodaran&#8217;s lens</h2><p>Damodaran&#8217;s valuation philosophy begins with a story and then forces the numbers to be consistent with that story.</p><p>My story for Info Edge is simple.</p><p>The first engine is a high-quality operating business with a durable moat in recruitment classifieds, strong operating leverage, and real free-cash-flow discipline.</p><p>The second engine is a capital allocator with a demonstrated ability to identify, back, and hold asymmetric winners for long periods.</p><p>That combination makes Info Edge unusual.</p><p>Many companies are either operating businesses or investment vehicles.</p><p><strong>Info Edge is both.</strong></p><blockquote><p>Naukri remains the core cash machine, but the market&#8217;s view of the company is also shaped by what happened with Zomato&#8212;now Eternal&#8212;and with Policybazaar through PB Fintech.</p></blockquote><p>This also explains why plain P/E ratios can mislead. Reported earnings often include large amounts of investment-related income and mark-to-market effects, creating accounting noise that distorts headline valuation multiples.</p><div><hr></div><h2>The Operating Story I Am Telling Myself</h2><p>When I strip away the investment book, I am left with a business that is significantly better than a typical Indian internet company.</p><p>FY25 standalone revenue was approximately &#8377;2,654 crore, operating profit was around &#8377;973 crore, and the starting EBIT margin in my model was roughly 36.7%.</p><p>That is not what a fragile, capital-hungry internet business looks like.</p><p>It looks like a platform business with real pricing power and low incremental capital intensity.</p><p>Info Edge&#8217;s own disclosures increasingly describe Naukri as evolving from a traditional job-search platform into a broader talent ecosystem. That matters because deeper workflow relevance typically strengthens both customer stickiness and monetization potential.</p><p>The cash-flow quality is equally important.</p><p>Free-cash-flow conversion remains strong, and cash generation has consistently supported both internal reinvestment and external venture investments.</p><p>That cash discipline sits at the center of my thesis.</p><p>In a Damodaran framework, earnings are only useful if they can be converted into cash and distributed or reinvested intelligently.</p><p>Info Edge passes that test far better than many businesses trading on technology narratives.</p><div><hr></div><h2>The Second Engine: Capital Allocation</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4SYu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b5880-a671-48a7-9aa2-3f81038eea1d_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4SYu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b5880-a671-48a7-9aa2-3f81038eea1d_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!4SYu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b5880-a671-48a7-9aa2-3f81038eea1d_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!4SYu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b5880-a671-48a7-9aa2-3f81038eea1d_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!4SYu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b5880-a671-48a7-9aa2-3f81038eea1d_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!4SYu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b5880-a671-48a7-9aa2-3f81038eea1d_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/234b5880-a671-48a7-9aa2-3f81038eea1d_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;:1728259,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200706956?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b5880-a671-48a7-9aa2-3f81038eea1d_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_!4SYu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b5880-a671-48a7-9aa2-3f81038eea1d_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!4SYu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b5880-a671-48a7-9aa2-3f81038eea1d_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!4SYu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b5880-a671-48a7-9aa2-3f81038eea1d_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!4SYu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b5880-a671-48a7-9aa2-3f81038eea1d_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The other half of the story is where Info Edge becomes truly distinctive.</p><p>Management disclosed that total invested capital across its startup platform stood at roughly &#8377;4,000 crore, while the fair market value of those investments approached &#8377;37,000 crore.</p><p>Those are extraordinary numbers.</p><p>More importantly, they fundamentally change how I think about the balance sheet.</p><p>This is not idle treasury cash.</p><p>This is a portfolio that has already produced two listed winners and still carries meaningful optionality from the rest of the investment book.</p><p>The listed winners are the easiest to value.</p><p>Using June 2026 market values, Info Edge&#8217;s stakes in Eternal and PB Fintech together were worth approximately &#8377;39,500 crore.</p><p>That single number explains why this company must be valued in pieces.</p><p>If the market capitalization is roughly &#8377;65,000 crore and the two listed holdings alone are worth nearly &#8377;40,000 crore, then the market is implicitly assigning the remaining value to the core operating franchises plus the unlisted portfolio.</p><div><hr></div><h2>How I Split the Business</h2><p>Damodaran&#8217;s treatment of cash and cross-holdings provides the right starting point.</p><p>First, value the parent company&#8217;s operating assets.</p><p>Second, value the holdings separately.</p><p>Third, decide whether those holdings deserve to be added at full value or at a discount because of taxes, opacity, or governance considerations.</p><p>For Info Edge, I split the company into three buckets:</p><ul><li><p>The core operating business: Naukri, 99acres, Jeevansathi, Shiksha, and other controlled operating assets.</p></li><li><p>The listed investment book: Eternal and PB Fintech.</p></li><li><p>The private portfolio: the broader startup portfolio, valued through probability-weighted assumptions and appropriate haircuts.</p></li></ul><p>Once I do that, the valuation becomes much clearer.</p><p>I no longer have to force one multiple to explain two fundamentally different economic engines.</p><div><hr></div><h2>My Core-Business DCF</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Noi3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce65570-e5fa-42fc-8931-5213c48f06f3_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Noi3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce65570-e5fa-42fc-8931-5213c48f06f3_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Noi3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce65570-e5fa-42fc-8931-5213c48f06f3_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Noi3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce65570-e5fa-42fc-8931-5213c48f06f3_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Noi3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce65570-e5fa-42fc-8931-5213c48f06f3_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Noi3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce65570-e5fa-42fc-8931-5213c48f06f3_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6ce65570-e5fa-42fc-8931-5213c48f06f3_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;:1290281,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200706956?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce65570-e5fa-42fc-8931-5213c48f06f3_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_!Noi3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce65570-e5fa-42fc-8931-5213c48f06f3_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Noi3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce65570-e5fa-42fc-8931-5213c48f06f3_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Noi3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce65570-e5fa-42fc-8931-5213c48f06f3_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Noi3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce65570-e5fa-42fc-8931-5213c48f06f3_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>I built three versions of the core-business valuation.</p><p>The first was a conventional FCFF model.</p><p>The second was a stricter Damodaran-style build with a higher cost of capital and explicit return-on-capital fade.</p><p>The third was an owner-earnings model that treats Info Edge more like a high-ROIC platform business with low maintenance reinvestment requirements.</p><p>The conventional FCFF model produced an intrinsic value range of:</p><p>&#8377;805.83 to &#8377;1,173.05 based on Bear to Bull scenario</p><p>The stricter Damodaran build produced:</p><p>&#8377;624.07-&#8377;675.71-&#8377;722.74(Bear-Base-Bull)</p><p>The owner-earnings model produced:</p><p>Bear&#8377;856.76, Base&#8377;978.00, Bull&#8377;1,150.75</p><p>I do not treat any one of these as the truth.</p><p>I treat them as a range generated by different but intellectually honest stories about the business.</p><p><strong>That is very much in the spirit of Damodaran: valuation is a disciplined conversation between narrative and numbers, not a hunt for a fake precision point estimate.</strong></p><div><hr></div><h2>What the Three Models Are Really Saying</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!avW1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26450a9e-e5a6-424d-9d5f-df0966ec01b5_1024x1536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!avW1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26450a9e-e5a6-424d-9d5f-df0966ec01b5_1024x1536.png 424w, https://substackcdn.com/image/fetch/$s_!avW1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26450a9e-e5a6-424d-9d5f-df0966ec01b5_1024x1536.png 848w, https://substackcdn.com/image/fetch/$s_!avW1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26450a9e-e5a6-424d-9d5f-df0966ec01b5_1024x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!avW1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26450a9e-e5a6-424d-9d5f-df0966ec01b5_1024x1536.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!avW1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26450a9e-e5a6-424d-9d5f-df0966ec01b5_1024x1536.png" width="1024" height="1536" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/26450a9e-e5a6-424d-9d5f-df0966ec01b5_1024x1536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1536,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1290071,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200706956?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26450a9e-e5a6-424d-9d5f-df0966ec01b5_1024x1536.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_!avW1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26450a9e-e5a6-424d-9d5f-df0966ec01b5_1024x1536.png 424w, https://substackcdn.com/image/fetch/$s_!avW1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26450a9e-e5a6-424d-9d5f-df0966ec01b5_1024x1536.png 848w, https://substackcdn.com/image/fetch/$s_!avW1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26450a9e-e5a6-424d-9d5f-df0966ec01b5_1024x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!avW1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26450a9e-e5a6-424d-9d5f-df0966ec01b5_1024x1536.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Taken together, these models say something simple.</p><p>Info Edge is not obviously cheap.</p><p>But it is also not wildly expensive if I believe the core operating franchise deserves a premium for moat, cash conversion, and capital allocation quality.</p><p>The overlap zone between my more realistic base cases falls roughly between &#8377;950 and &#8377;1,000 per share.</p><p>That sits remarkably close to where the market currently values the stock.</p><p>My conclusion is not that the stock is a bargain.</p><p>My conclusion is that the stock is trading around intrinsic value, with modest upside or downside depending on how optimistic I choose to be about the operating business and how much of the private investment book I am willing to recognize.</p><div><hr></div><h2>Why the Private Portfolio Cannot Be Ignored</h2><p>A lot of investors stop after marking Eternal and PB Fintech.</p><p>I think that is incomplete.</p><p>It is easy to value listed stakes and pretend the rest of the startup book is noise.</p><p>Management&#8217;s disclosures suggest otherwise.</p><p>At the same time, I do not want to value the private portfolio lazily.</p><p>For early-stage companies, the right framework resembles venture-capital valuation rather than traditional DCF analysis.</p><p>Estimate a plausible exit value.</p><p>Assign a probability of success.</p><p>Adjust for dilution.</p><p>Discount back at a sufficiently high required return.</p><p>That is why, in my own sum-of-the-parts framework, I do not add the startup portfolio at full value by default.</p><p>I use scenario-based weights and meaningful haircuts rather than assuming every fair-value mark will eventually translate into realized gains.</p><div><hr></div><h2>Promoter Skin, Moat, and Cash Discipline</h2><p>My three favourite lenses for evaluating businesses are:</p><ol><li><p>Moat</p></li><li><p>Promoter skin in the game</p></li><li><p>Free-cash-flow discipline</p></li></ol><p>Info Edge scores well on all three.</p><p>Promoter ownership remains meaningful at approximately 37.5%, with founder Sanjeev Bikhchandani individually holding about 24% of the company. This level of ownership creates strong alignment between management and minority shareholders, particularly in a business where long-term capital allocation is a major driver of value creation.</p><p>When founders continue to own a meaningful portion of the business after decades of operation, I generally have greater confidence that capital allocation decisions are being made with a long-term mindset.</p><p>On moat, the easiest evidence is visible in the economics of the core business.</p><p>A business generating EBIT margins north of 35%, producing strong free cash flow, and maintaining leadership in a category for years is rarely doing so by accident.</p><p>Those economics are often downstream manifestations of:</p><ul><li><p>Brand strength</p></li><li><p>Network effects</p></li><li><p>Embedded workflows</p></li><li><p>Customer inertia</p></li><li><p>Rational competition</p></li></ul><p>Naukri benefits from several of these simultaneously.</p><p>Employers want access to the largest candidate pool.</p><p>Candidates want access to the largest number of recruiters.</p><p>That creates a reinforcing flywheel that becomes increasingly difficult for competitors to replicate.</p><p>On cash-flow discipline, the story becomes even stronger.</p><p>The company has remained largely debt free while continuing to:</p><ul><li><p>Fund organic growth</p></li><li><p>Invest in adjacent businesses</p></li><li><p>Build a venture portfolio</p></li><li><p>Maintain balance-sheet flexibility</p></li></ul><p>That combination is surprisingly rare.</p><p>Many firms with venture portfolios lack a strong operating engine.</p><p>Many cash-generative firms struggle to identify high-return external investments.</p><p>Info Edge has demonstrated an ability to do both.</p><div><hr></div><h2>The Buy-Below Levels I Would Use</h2><p>Because the stock appears to be trading around fair value, I think price discipline matters more than enthusiasm.</p><p>Valuation should influence position sizing.</p><p>Quality tells me <em>what</em> to buy.</p><p>Valuation tells me <em>when</em> to buy.</p><p>My framework currently looks like this:</p><p>ZoneInterpretationBelow &#8377;850Strong Buy&#8377;850&#8211;&#8377;930Buy&#8377;930&#8211;&#8377;1,030Hold / WatchAbove &#8377;1,100Avoid aggressive additions</p><h3>Below &#8377;850</h3><p>At these levels, even relatively conservative valuation frameworks begin to show a meaningful margin of safety.</p><p>The investment case becomes less dependent on perfect execution and more dependent on simply avoiding major mistakes.</p><p>That is usually where I prefer to deploy capital.</p><h3>&#8377;850&#8211;&#8377;930</h3><p>The valuation starts tilting in my favor while still allowing room for execution risk.</p><p>The core franchise remains attractive and the optionality from investments is available at a more reasonable price.</p><h3>&#8377;930&#8211;&#8377;1,030</h3><p>This is approximately fair-value territory.</p><p>At these levels I would be comfortable holding existing positions but would not feel a strong urge to increase exposure.</p><h3>Above &#8377;1,100</h3><p>At these valuations, I would need a substantially more optimistic view regarding:</p><ul><li><p>Core business growth</p></li><li><p>Margin expansion</p></li><li><p>The next generation of startup winners</p></li><li><p>Long-term value creation from the investment portfolio</p></li></ul><p>Without that conviction, future returns become increasingly dependent on continued multiple expansion rather than fundamental value creation.</p><div><hr></div><h2>What Could Break My Thesis</h2><p>No valuation is complete without understanding what can go wrong.</p><p>There are four developments that would make me materially less constructive on Info Edge.</p><h3>1. Naukri Loses Pricing Power</h3><p>Naukri remains the economic anchor of the entire group.</p><p>If recruiters begin reducing spend, switching platforms, or finding better alternatives, the valuation of the entire business changes.</p><p>The investment portfolio may be exciting, but the operating franchise pays the bills.</p><p>A weakening recruitment moat would force me to revisit almost every assumption in my model.</p><h3>2. Adjacent Businesses Fail to Improve Economics</h3><p>The long-term narrative depends on businesses such as 99acres and other operating segments continuing to improve efficiency and monetization.</p><p>If these businesses fail to progress toward stronger economics, some of the optionality embedded in my valuation disappears.</p><p>The result would be lower growth assumptions and reduced confidence in margin expansion.</p><h3>3. Capital Allocation Discipline Deteriorates</h3><p>One of the biggest strengths of Info Edge has been its investment discipline.</p><p>Successful startup investors often face a dangerous temptation after early wins.</p><p>Past success can encourage larger bets, weaker underwriting standards, or excessive optimism.</p><p>If management begins prioritizing valuation marks over governance and business quality, I would immediately apply a larger discount to the investment portfolio.</p><p>The track record has earned credibility.</p><p>But credibility must continually be re-earned.</p><h3>4. A Prolonged Decline in Eternal or PB Fintech</h3><p>The market currently recognizes Info Edge not only as an operating company but also as a successful allocator of capital.</p><p>If Eternal and PB Fintech experience significant and prolonged declines, investors may stop assigning value to that allocator identity.</p><p>In that scenario, the market could increasingly focus only on the operating business while assigning lower value to the investment portfolio.</p><p>That would compress valuation multiples even if the underlying businesses remain fundamentally sound.</p><div><hr></div><h2>The Bigger Lesson</h2><p>One reason I enjoy studying Info Edge is that it demonstrates how valuation is often more about structure than forecasting.</p><p>Most investors spend their time debating whether revenue growth will be 12% or 15%.</p><p>In many situations, that is not where the real insight lies.</p><p>The real insight is understanding what exactly you are valuing.</p><p>Info Edge forces that discipline.</p><p>You cannot treat it as a simple internet stock.</p><p>You cannot treat it as a venture capital fund.</p><p>You cannot treat it as a holding company.</p><p>It is all three at the same time.</p><p>And that complexity creates both confusion and opportunity.</p><p>This is precisely the type of situation where Damodaran&#8217;s framework shines.</p><p>Separate the pieces.</p><p>Value each piece independently.</p><p>Then bring them back together.</p><p>Simple in principle.</p><p>Difficult in practice.</p><div><hr></div><h2>My Final Verdict</h2><p>When I put everything together, I keep arriving at the same conclusion.</p><p>Info Edge is a high-quality business with:</p><ul><li><p>A genuine moat</p></li><li><p>Meaningful promoter alignment</p></li><li><p>Strong free-cash-flow generation</p></li><li><p>Exceptional capital-allocation history</p></li><li><p>Significant optionality through its startup portfolio</p></li></ul><p>Those are characteristics I actively seek in long-term compounders.</p><p>However, quality alone does not make something cheap.</p><p>At roughly &#8377;1,010 per share, I believe the market already recognizes much of what makes Info Edge special.</p><blockquote><p>The Naukri franchise is appreciated.</p><p>The Eternal success story is appreciated.</p><p>The PB Fintech investment is appreciated.</p></blockquote><p><strong>A significant portion of the optionality is already reflected in the price.</strong></p><p>That leaves me with a conclusion that may sound less exciting but is probably more useful:</p><p><strong>Info Edge is not a deep-value opportunity today.</strong></p><p><strong>It is a high-quality business trading around intrinsic value.</strong></p><blockquote><p>Would I own it?</p></blockquote><p>Yes.</p><blockquote><p>Would I chase it aggressively?</p></blockquote><p>Probably not.</p><blockquote><p>Would I become significantly more interested if the market offered it closer to &#8377;850&#8211;&#8377;900?</p></blockquote><p>Absolutely.</p><p>If I were forced to summarize my view in a single sentence, it would be this:</p><blockquote><p><strong>Info Edge is one of the clearest examples in India of how Aswath Damodaran&#8217;s framework helps separate a great operating business from a great capital allocator living inside the same stock.</strong></p></blockquote><p>And that is precisely what makes it such a fascinating company to study.</p><div><hr></div><h3>Disclosure</h3><p>This article is intended solely for educational and research purposes and should not be construed as investment advice. The valuation frameworks, assumptions, and conclusions presented here reflect my personal analysis and may prove incorrect. Investors should conduct their own due diligence and consider their risk tolerance before making any investment decisions.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://aswathdamodaran.blogspot.com/2013/06/a-tangled-web-of-values-enterprise.html">https://aswathdamodaran.blogspot.com/2013/06/a-tangled-web-of-values-enterprise.html</a></p><div id="youtube2-R5vaEkbXgDs" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;R5vaEkbXgDs&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/R5vaEkbXgDs?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><h1><strong>DISCLAIMER</strong></h1><blockquote><blockquote><p>The content published in this post is intended <strong>solely for educational and informational purposes</strong>. I am <strong>not registered with SEBI</strong> as an investment advisor, research analyst, broker, or financial influencer, and nothing in this post should be construed as investment advice, stock recommendations, or solicitation to buy, sell, or hold any securities.</p></blockquote><blockquote><p>This analysis is part of my <strong>personal learning journey in finance and valuation</strong>, heavily influenced by academic frameworks and publicly available material from <strong>Aswath Damodaran</strong>, particularly his work on <strong>Cash, crossholdings, and others.</strong><br><br>The post reflects my own interpretation and application of these concepts as a finance student and practitioner, and any errors or assumptions are entirely my own.</p></blockquote><blockquote><p>The valuation models, assumptions, scenarios, and conclusions presented here are <strong>illustrative learning exercises</strong>, not predictions. They do not account for individual financial circumstances, risk tolerance, tax considerations, or investment objectives.</p></blockquote><blockquote><p>Readers are strongly encouraged to perform <strong>independent due diligence</strong> and/or consult a <strong>SEBI-registered financial professional</strong> before making any investment decisions. I shall not be responsible for any financial losses or outcomes resulting from reliance on this content.</p></blockquote></blockquote><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[Traditional Japan (Monochrome)]]></title><description><![CDATA[When I first arrived in Hokkaido, I was captivated by colour.]]></description><link>https://blog.phagyul.ai/p/traditional-japan-monochrome</link><guid isPermaLink="false">https://blog.phagyul.ai/p/traditional-japan-monochrome</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Mon, 01 Jun 2026 05:22:49 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!GRC8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I first arrived in Hokkaido, I was captivated by colour.</p><p>The crimson crowns of cranes against fresh snow. The blue hues of winter mornings. The warm glow of sunrise spilling across frozen landscapes.</p><p>Naturally, those scenes became the foundation of C1 &#8212; <em>Vibrant Hokkaido</em>.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;319cdc4e-6162-4579-a7c5-4869eafc3965&quot;,&quot;caption&quot;:&quot;Several months before travelling to Hokkaido, I found myself doing something I had not originally planned.&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Vibrant Hokkaido&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:12091074,&quot;name&quot;:&quot;Phagyul AI Systems Pvt Ltd&quot;,&quot;bio&quot;:&quot;Building rooted intelligence &#129504; &#127909; &#127793;&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69779d00-e8d0-4783-8d18-6eefd0dd0a36_82x82.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-05-31T02:39:22.000Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!yFHV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;cover_image_crop&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.phagyul.ai/p/vibrant-hokkaido&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:199934487,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7361555,&quot;publication_name&quot;:&quot;Jagadeesh Rampam&quot;,&quot;publication_logo_url&quot;:&quot;&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>But as the journey unfolded, I found myself increasingly drawn to something else.</p><p>Not colour.</p><p>Time.</p><p>The more I travelled through Hokkaido, the more I felt that many of its landscapes, traditions, and wildlife existed outside the rhythm of the modern world. A crane standing motionless in the snow, a sea eagle gliding across a winter valley, steam rising through an outdoor onsen&#8212;these scenes felt as though they could belong to today, fifty years ago, or perhaps even longer.</p><p>That feeling became the inspiration for C2.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GRC8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GRC8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!GRC8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!GRC8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!GRC8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!GRC8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b628b9cc-1106-44b7-a65b-be5d13591569_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;:2603084,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200075615?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_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_!GRC8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!GRC8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!GRC8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!GRC8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb628b9cc-1106-44b7-a65b-be5d13591569_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Why Monochrome?</h2><p>For me, monochrome was never about removing colour.</p><p>It was about removing time.</p><p>Colour often anchors a photograph to a specific moment. We recognise the palette of a season, the look of a particular era, or the visual characteristics of modern life.</p><p>Monochrome strips away those references.</p><p>What remains are the essential elements of a photograph:</p><ul><li><p>Light</p></li><li><p>Form</p></li><li><p>Texture</p></li><li><p>Atmosphere</p></li><li><p>Emotion</p></li></ul><p>More importantly, it allows a scene to feel timeless.</p><p>In Hokkaido, monochrome became the most natural way to express what I was experiencing. The enduring elegance of Japanese culture, the quiet beauty of winter landscapes, and the sense that many traditions continue largely unchanged despite the rapid pace of the world around them.</p><p>Rather than documenting Japan as it appeared before me, I wanted to create images that felt suspended between past and present.</p><div><hr></div><h2>Building C2</h2><p>The objective was not to create dramatic black-and-white photographs.</p><p>Instead, I wanted to create images that felt calm, restrained, and enduring.</p><p>The settings were designed to emphasize tonal separation rather than contrast alone. Snow remained soft and luminous. Shadows retained detail. Blacks provided structure without overwhelming the frame.</p><p>The result was a visual language inspired less by spectacle and more by permanence.</p><p>A crane became a silhouette against endless snow.</p><p>An eagle became a dark brushstroke against mountain ridges.</p><p>Steam transformed a crowded onsen into something almost dreamlike.</p><p>The photographs began to feel less like records of a journey and more like fragments of memory.</p><div><hr></div><h2>What I Found</h2><p>The most unexpected outcome was how much attention shifted from the subject to the feeling of the scene.</p><p>Without colour competing for attention, subtle details became more important:</p><p>The curve of a crane&#8217;s neck.</p><p>The delicate footprints pressed into fresh snow.</p><p>The layers of mist drifting through an onsen.</p><p>The patterns of winter forests beneath a soaring eagle.</p><p>Many photographs became simpler, yet somehow more evocative.</p><p>The absence of colour encouraged me to focus on what initially drew me to the frame rather than what made it visually striking.</p><div><hr></div><h2>The Images</h2><p>The red-crowned cranes became symbols of grace rather than colour.</p><p>Against the snow, they appeared almost sculptural&#8212;reduced to elegant lines, shapes, and movement.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IloJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c3e1b52-f26a-48c8-93b5-ba8c1668ad97_1281x1920.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IloJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c3e1b52-f26a-48c8-93b5-ba8c1668ad97_1281x1920.jpeg 424w, https://substackcdn.com/image/fetch/$s_!IloJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c3e1b52-f26a-48c8-93b5-ba8c1668ad97_1281x1920.jpeg 848w, https://substackcdn.com/image/fetch/$s_!IloJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c3e1b52-f26a-48c8-93b5-ba8c1668ad97_1281x1920.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!IloJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c3e1b52-f26a-48c8-93b5-ba8c1668ad97_1281x1920.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!IloJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c3e1b52-f26a-48c8-93b5-ba8c1668ad97_1281x1920.jpeg" width="1281" height="1920" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7c3e1b52-f26a-48c8-93b5-ba8c1668ad97_1281x1920.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1920,&quot;width&quot;:1281,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:158529,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200075615?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c3e1b52-f26a-48c8-93b5-ba8c1668ad97_1281x1920.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IloJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c3e1b52-f26a-48c8-93b5-ba8c1668ad97_1281x1920.jpeg 424w, https://substackcdn.com/image/fetch/$s_!IloJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c3e1b52-f26a-48c8-93b5-ba8c1668ad97_1281x1920.jpeg 848w, https://substackcdn.com/image/fetch/$s_!IloJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c3e1b52-f26a-48c8-93b5-ba8c1668ad97_1281x1920.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!IloJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c3e1b52-f26a-48c8-93b5-ba8c1668ad97_1281x1920.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The sea eagle soaring across Hokkaido&#8217;s mountains felt timeless, its silhouette echoing the rugged landscape beneath it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-Ate!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F384411bd-d294-4ece-baa0-c64a76408e0e_1920x1281.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-Ate!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F384411bd-d294-4ece-baa0-c64a76408e0e_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-Ate!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F384411bd-d294-4ece-baa0-c64a76408e0e_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-Ate!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F384411bd-d294-4ece-baa0-c64a76408e0e_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-Ate!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F384411bd-d294-4ece-baa0-c64a76408e0e_1920x1281.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!-Ate!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F384411bd-d294-4ece-baa0-c64a76408e0e_1920x1281.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/384411bd-d294-4ece-baa0-c64a76408e0e_1920x1281.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:711627,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200075615?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F384411bd-d294-4ece-baa0-c64a76408e0e_1920x1281.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-Ate!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F384411bd-d294-4ece-baa0-c64a76408e0e_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-Ate!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F384411bd-d294-4ece-baa0-c64a76408e0e_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-Ate!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F384411bd-d294-4ece-baa0-c64a76408e0e_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-Ate!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F384411bd-d294-4ece-baa0-c64a76408e0e_1920x1281.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The onsen scene revealed a different side of Japan. Visitors gathered quietly in rising steam while nature enveloped the entire experience, blurring the distinction between people and place.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JIyH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d7f60c3-03f6-4aa9-b7d8-631c9587ee34_1281x1920.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JIyH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d7f60c3-03f6-4aa9-b7d8-631c9587ee34_1281x1920.jpeg 424w, https://substackcdn.com/image/fetch/$s_!JIyH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d7f60c3-03f6-4aa9-b7d8-631c9587ee34_1281x1920.jpeg 848w, https://substackcdn.com/image/fetch/$s_!JIyH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d7f60c3-03f6-4aa9-b7d8-631c9587ee34_1281x1920.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!JIyH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d7f60c3-03f6-4aa9-b7d8-631c9587ee34_1281x1920.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!JIyH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d7f60c3-03f6-4aa9-b7d8-631c9587ee34_1281x1920.jpeg" width="1281" height="1920" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7d7f60c3-03f6-4aa9-b7d8-631c9587ee34_1281x1920.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1920,&quot;width&quot;:1281,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:416314,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200075615?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d7f60c3-03f6-4aa9-b7d8-631c9587ee34_1281x1920.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!JIyH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d7f60c3-03f6-4aa9-b7d8-631c9587ee34_1281x1920.jpeg 424w, https://substackcdn.com/image/fetch/$s_!JIyH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d7f60c3-03f6-4aa9-b7d8-631c9587ee34_1281x1920.jpeg 848w, https://substackcdn.com/image/fetch/$s_!JIyH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d7f60c3-03f6-4aa9-b7d8-631c9587ee34_1281x1920.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!JIyH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d7f60c3-03f6-4aa9-b7d8-631c9587ee34_1281x1920.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Even moments of intentional blur and abstraction began to feel more meaningful in monochrome, emphasizing atmosphere over description.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!V7M6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49782b78-6f32-44dd-90cc-a1980b9f1874_1920x1016.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!V7M6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49782b78-6f32-44dd-90cc-a1980b9f1874_1920x1016.jpeg 424w, https://substackcdn.com/image/fetch/$s_!V7M6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49782b78-6f32-44dd-90cc-a1980b9f1874_1920x1016.jpeg 848w, https://substackcdn.com/image/fetch/$s_!V7M6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49782b78-6f32-44dd-90cc-a1980b9f1874_1920x1016.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!V7M6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49782b78-6f32-44dd-90cc-a1980b9f1874_1920x1016.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!V7M6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49782b78-6f32-44dd-90cc-a1980b9f1874_1920x1016.jpeg" width="1920" height="1016" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49782b78-6f32-44dd-90cc-a1980b9f1874_1920x1016.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1016,&quot;width&quot;:1920,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:45630,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/200075615?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab7f6809-ed11-4501-9062-78c5667c7b5f_1920x1280.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!V7M6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49782b78-6f32-44dd-90cc-a1980b9f1874_1920x1016.jpeg 424w, https://substackcdn.com/image/fetch/$s_!V7M6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49782b78-6f32-44dd-90cc-a1980b9f1874_1920x1016.jpeg 848w, https://substackcdn.com/image/fetch/$s_!V7M6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49782b78-6f32-44dd-90cc-a1980b9f1874_1920x1016.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!V7M6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49782b78-6f32-44dd-90cc-a1980b9f1874_1920x1016.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Each image seemed less concerned with documenting what was there and more interested in conveying what it felt like to stand there.</p><div><hr></div><h2>What C2 Taught Me</h2><p>Photography often encourages us to capture moments.</p><p>Monochrome encouraged me to capture permanence.</p><p>It reminded me that some places possess a character that transcends a single season, a single journey, or even a single generation.</p><p>Hokkaido&#8217;s wildlife, landscapes, and traditions carry that quality.</p><p>By removing colour, I wasn&#8217;t simplifying the story.</p><p>I was revealing the part of it that felt enduring.</p><div><hr></div><p><strong>C2 &#8212; Traditional Japan (Monochrome)</strong> is my attempt to explore the timeless side of Hokkaido&#8212;a visual journey through landscapes, wildlife, and traditions that feel as relevant today as they might have decades ago, expressed through a monochrome palette that celebrates simplicity, atmosphere, and the enduring beauty of Japan.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png" width="1456" height="189" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:189,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[Vibrant Hokkaido]]></title><description><![CDATA[Several months before travelling to Hokkaido, I found myself doing something I had not originally planned.]]></description><link>https://blog.phagyul.ai/p/vibrant-hokkaido</link><guid isPermaLink="false">https://blog.phagyul.ai/p/vibrant-hokkaido</guid><dc:creator><![CDATA[Parjanya by Phagyul AI]]></dc:creator><pubDate>Sun, 31 May 2026 02:39:22 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!yFHV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Several months before travelling to Hokkaido, I found myself doing something I had not originally planned.</p><p>I wasn&#8217;t researching locations.</p><p>I wasn&#8217;t building shot lists.</p><p>I wasn&#8217;t even looking at wildlife photography.</p><p>Instead, I was revisiting old Japanese films and spending far too much time pausing anime scenes.</p><p>As someone who grew up watching anime, I had always been fascinated by how Japanese artists treated landscapes. Snow felt different. Forests felt different. Even ordinary roads seemed to carry a sense of atmosphere that was difficult to describe but immediately recognizable.</p><p>The colours were often richer than reality, yet never felt artificial.</p><p>The landscapes felt vibrant, but never loud.</p><p>Somewhere between memory and observation, a distinct visual language emerged.</p><p>Without realizing it, I had already started naming it in my head.</p><p><strong>Vibrant Hokkaido.</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_!yFHV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yFHV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!yFHV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!yFHV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!yFHV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!yFHV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f0427a49-7fc7-4368-a6d1-4513021ddccf_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;:2722916,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/199934487?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!yFHV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!yFHV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!yFHV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!yFHV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0427a49-7fc7-4368-a6d1-4513021ddccf_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>At the time, I thought it was a colour problem.</p><p>By the end of the trip, I realized it was a luminance problem.</p><p>And that distinction changed everything.</p><h2>Designing Hokkaido Before Seeing Hokkaido</h2><p>Long before boarding a flight to Japan, I started building two custom shooting profiles on my Canon EOS R5 Mark II.</p><p>The first became <strong>C1: Vibrant Hokkaido</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_!Lu7J!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0d2304-c8f7-41dc-9e98-d240ba503364_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Lu7J!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0d2304-c8f7-41dc-9e98-d240ba503364_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Lu7J!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0d2304-c8f7-41dc-9e98-d240ba503364_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Lu7J!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0d2304-c8f7-41dc-9e98-d240ba503364_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Lu7J!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0d2304-c8f7-41dc-9e98-d240ba503364_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Lu7J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0d2304-c8f7-41dc-9e98-d240ba503364_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bb0d2304-c8f7-41dc-9e98-d240ba503364_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;:2031280,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/199934487?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0d2304-c8f7-41dc-9e98-d240ba503364_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_!Lu7J!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0d2304-c8f7-41dc-9e98-d240ba503364_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Lu7J!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0d2304-c8f7-41dc-9e98-d240ba503364_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Lu7J!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0d2304-c8f7-41dc-9e98-d240ba503364_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Lu7J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0d2304-c8f7-41dc-9e98-d240ba503364_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>The second became <strong>C2: Traditional Japan</strong>.</p><p>The intention behind C1 was relatively straightforward. I wanted a profile that embraced the visual qualities I associated with modern Japanese landscape art and anime backgrounds&#8212;strong colour separation, rich blues, warm wildlife subjects and an overall sense of atmosphere.</p><p>The foundation was Canon&#8217;s Landscape Picture Style, but pushed further through additional contrast, saturation and colour tuning.</p><div class="pullquote"><p>The goal wasn&#8217;t realism.</p><p><strong>The goal was emotional realism.</strong></p></div><p>I wasn&#8217;t trying to reproduce exactly what I saw.</p><p>I was trying to reproduce what Hokkaido felt like in my imagination after years of consuming Japanese visual culture.</p><p>C2 was built for a completely different reason and deserves its own article, but in short, it was inspired by older Japanese cinema, monochrome photography and traditional aesthetics where form, shape and negative space matter more than colour.</p><p>At the time, both profiles felt complete.</p><p>I thought I had already solved the problem.</p><p>Hokkaido had other plans.</p><h2>The Surprise Waiting in the Snow</h2><p>One of the assumptions I carried into the trip was that colour would be the defining characteristic of the landscape.</p><p>After all, C1 was built around colour.</p><p>Yet once I started photographing winter scenes, I noticed something unexpected.</p><p>The strongest images weren&#8217;t necessarily the most colourful ones.</p><p>In fact, many of them contained remarkably little colour.</p><p>The fox crossing an icy road became one of those moments.</p><p>Initially, what attracted me to the scene was obvious.</p><p>A warm-toned fox against a cold blue landscape.</p><p>Classic colour contrast.</p><p>The kind of scene that fits perfectly within the original idea of Vibrant Hokkaido.</p><p>But as I reviewed the images later, I found myself paying less attention to the fox and more attention to the snow.</p><p>The snow wasn&#8217;t acting as background.</p><p>It was acting as structure.</p><p>The wind patterns across the frozen surface were creating visual pathways.</p><p>The lighter areas pulled the eye forward.</p><p>The darker areas acted as leading lines.</p><p>The fox wasn&#8217;t creating the composition.</p><p>The snow already had.</p><p>The fox was simply completing it.</p><p>That realization became one of the most important lessons of the trip.</p><h2>Snow Isn&#8217;t White</h2><p>Photographers often talk about exposing snow correctly.</p><p>What I discovered in Hokkaido was slightly different.</p><p>The challenge wasn&#8217;t exposure.</p><p>The challenge was preserving luminance relationships.</p><p>When we think about snow, we instinctively think about whiteness.</p><p>But Hokkaido snow rarely appears truly white.</p><p>It contains subtle blues.</p><p>Grey tones.</p><p>Cyan shifts.</p><p>Tiny variations that create depth and dimension.</p><p>Push everything toward pure white and the landscape becomes flatter.</p><p>Neutralize the colour too aggressively and winter loses its atmosphere.</p><p>The more I photographed, the more I realized that the visual identity of Hokkaido wasn&#8217;t being created by colour alone.</p><p>It was being created by the way snow carries light.</p><p>That became the foundation of what I eventually started calling <strong>Snow Luminance Control</strong>.</p><p>Not as a formal technique.</p><p>Not as a preset.</p><p>Simply as a way of seeing.</p><p>The objective became preserving those tonal transitions so that the snow itself could guide the viewer through the frame.</p><p>The fox remained important.</p><p>But the snow became the protagonist.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AwyP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabb68a72-1201-4e6f-ab18-ddea3c86791f_1920x1281.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AwyP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabb68a72-1201-4e6f-ab18-ddea3c86791f_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!AwyP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabb68a72-1201-4e6f-ab18-ddea3c86791f_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!AwyP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabb68a72-1201-4e6f-ab18-ddea3c86791f_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!AwyP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabb68a72-1201-4e6f-ab18-ddea3c86791f_1920x1281.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!AwyP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabb68a72-1201-4e6f-ab18-ddea3c86791f_1920x1281.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/abb68a72-1201-4e6f-ab18-ddea3c86791f_1920x1281.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1613127,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.phagyul.ai/i/199934487?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabb68a72-1201-4e6f-ab18-ddea3c86791f_1920x1281.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AwyP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabb68a72-1201-4e6f-ab18-ddea3c86791f_1920x1281.jpeg 424w, https://substackcdn.com/image/fetch/$s_!AwyP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabb68a72-1201-4e6f-ab18-ddea3c86791f_1920x1281.jpeg 848w, https://substackcdn.com/image/fetch/$s_!AwyP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabb68a72-1201-4e6f-ab18-ddea3c86791f_1920x1281.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!AwyP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabb68a72-1201-4e6f-ab18-ddea3c86791f_1920x1281.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>The Lightroom Problem</h2><p>Ironically, the next lesson arrived after I returned from the field.</p><p>Opening the RAW files inside Lightroom was a shock.</p><p>The images didn&#8217;t look anything like what I had seen on the back of the camera.</p><p>The carefully tuned colours from C1 seemed to disappear.</p><p>The atmosphere felt different.</p><p>The tonal relationships felt different.</p><p>For a while, I assumed the profile simply wasn&#8217;t working as intended.</p><p>That confusion continued until a conversation with Rahul Sachdev.</p><p>Rahul, a Canon Ambassador and someone whose field experience I deeply respect, pointed me toward something surprisingly simple.</p><p><strong>Match Camera.</strong></p><p>Once Lightroom and Photoshop were instructed to honour the in-camera rendering through Canon&#8217;s camera-matching profiles, the images immediately started resembling what I had designed and seen in the field.</p><p>It was one of those moments that seems obvious in hindsight.</p><p>I had spent months creating a visual language inside the camera, only to discover that my software workflow was quietly replacing it.</p><p>That lesson alone probably saved me countless hours of unnecessary editing.</p><div><hr></div><h2>The Limitations of Custom Modes</h2><p>As useful as the C1 and C2 workflow became, the trip also exposed some practical limitations.</p><p>One of the biggest frustrations involved crop settings.</p><p>Certain shooting configurations&#8212;particularly 1.6x crop workflows that proved useful for wildlife&#8212;did not always behave the way I expected once stored inside the custom modes.</p><p>Moving between C1, C2 and C3 often required additional verification to ensure the camera was actually operating the way I intended.</p><p>It wasn&#8217;t a deal-breaker.</p><p>But it was a reminder that custom modes are powerful shortcuts rather than perfect state-management systems.</p><p>The creative intent remains consistent.</p><p>The technical details still need supervision.</p><h2>Looking Back</h2><p>What started as an attempt to recreate a visual style inspired by anime eventually became something far more interesting.</p><p>I arrived in Hokkaido thinking about colour.</p><p>I left thinking about luminance.</p><p>The preset I designed before the trip survived.</p><p>But the reasoning behind it evolved.</p><p>Vibrant Hokkaido was never really about making colours stronger.</p><p>It was about allowing winter to remain expressive.</p><p>About preserving the subtle pathways hidden inside snow.</p><p>About understanding that a landscape can lead the eye long before a wildlife subject enters the frame.</p><p>The fox helped me recognize that.</p><p>The snow taught me why.</p><p>In the next post, I&#8217;ll explore the other half of this experiment&#8212;<strong>C2: Traditional Japan</strong>&#8212;a profile inspired not by modern anime aesthetics, but by older Japanese cinema, monochrome photography and the idea that sometimes removing colour reveals more than adding it ever could.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png" width="1456" height="189" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:189,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://parjanya.phagyul.ai/guide?utm_source=blog.phagyul.ai&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mmQN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 424w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 848w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1272w, https://substackcdn.com/image/fetch/$s_!mmQN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49c1df74-81d2-4a18-a37c-147f89b13cc3_2015x261.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p></p>]]></content:encoded></item></channel></rss>