<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: N3MO</title>
    <description>The latest articles on DEV Community by N3MO (@n3mo-dev).</description>
    <link>https://dev.to/n3mo-dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3977637%2Fd80db94a-7cb8-46fc-a3ba-84fcd9d42bc3.png</url>
      <title>DEV Community: N3MO</title>
      <link>https://dev.to/n3mo-dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/n3mo-dev"/>
    <language>en</language>
    <item>
      <title>Automatically Answering "What Does This PR Break?" Building Blast Radius Analysis Into GitHub Reviews</title>
      <dc:creator>N3MO</dc:creator>
      <pubDate>Tue, 21 Jul 2026 09:42:59 +0000</pubDate>
      <link>https://dev.to/n3mo-dev/automatically-answering-what-does-this-pr-break-building-blast-radius-analysis-into-github-308g</link>
      <guid>https://dev.to/n3mo-dev/automatically-answering-what-does-this-pr-break-building-blast-radius-analysis-into-github-308g</guid>
      <description>&lt;p&gt;(this is an open core project so please visit to the github repositry to contribute any contribution would be helpful)&lt;/p&gt;

&lt;h1&gt;
  
  
  Automatically Answering "What Does This PR Break?" Building Blast Radius Analysis Into GitHub Reviews
&lt;/h1&gt;

&lt;p&gt;Every large codebase has the same recurring question in code review: &lt;em&gt;what else does this change touch?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Text search misses indirect dependencies. Unit tests only catch what they were written to catch. And in a codebase with thousands of files, nobody can hold the full dependency graph in their head.&lt;/p&gt;

&lt;p&gt;I built N3MO to answer this automatically, and recently shipped the feature I think matters most: it now posts the answer directly as a PR comment.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;When a PR opens, N3MO:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parses the diff to find every symbol added, deleted, or modified&lt;/li&gt;
&lt;li&gt;Traces each symbol through a call graph built from the repo's AST&lt;/li&gt;
&lt;li&gt;Posts a structured report as a PR comment direct callers, total downstream impact, per-symbol status&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No dashboard to check. No separate tool to open. It shows up exactly where review already happens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why AST parsing instead of grep
&lt;/h2&gt;

&lt;p&gt;Text search finds &lt;em&gt;textual&lt;/em&gt; matches. It can't tell you that a renamed function is called indirectly through three layers of abstraction, or that a modified return type breaks a caller two files away that never appears in a simple search.&lt;/p&gt;

&lt;p&gt;N3MO builds a real structural map: parse each file into an AST (Tree-sitter, 27 languages), extract symbol definitions and call sites, and store the graph in Postgres using recursive CTEs to trace transitive dependencies. That's what lets it answer "what breaks if I change this?" with certainty instead of a guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance at scale
&lt;/h2&gt;

&lt;p&gt;Indexing needs to work on real codebases, not toy examples. Current benchmarks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TensorFlow (14.6k files, 480k+ edges): ~14 minutes cold-start&lt;/li&gt;
&lt;li&gt;Re-indexing after a PR is incremental only changed files get re-parsed, so it stays fast on subsequent runs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Security model
&lt;/h2&gt;

&lt;p&gt;Since this runs on private repos, code never leaves the user's environment. Indexing happens in place, and nothing is sent to an external server for analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it's at
&lt;/h2&gt;

&lt;p&gt;N3MO has been in daily active use by ~8k developers via the local CLI/MCP integration (Cursor, Claude Desktop). The SaaS/PR-comment feature is newer and is what I'm actively building toward — turning individual CLI usage into a tool teams adopt for code review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it on your repo
&lt;/h2&gt;

&lt;p&gt;Log in, connect your repository, and a &lt;strong&gt;15-day free trial&lt;/strong&gt; activates automatically. Follow the setup steps and N3MO runs on every PR from that point on — indexing in place, re-indexing only what changed, nothing leaving your repo.&lt;/p&gt;

&lt;p&gt;If you work in a codebase where "what depends on this?" comes up often in review, I'd genuinely like feedback:[n3mo.shop]&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwgq6ey01p944vvvhczos.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwgq6ey01p944vvvhczos.png" alt=" " width="800" height="410"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpfuwzh3v47p0h98b1fag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpfuwzh3v47p0h98b1fag.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>saas</category>
      <category>python</category>
      <category>github</category>
    </item>
    <item>
      <title>I made my portfolio website today , please give feedbacks</title>
      <dc:creator>N3MO</dc:creator>
      <pubDate>Sat, 18 Jul 2026 13:20:20 +0000</pubDate>
      <link>https://dev.to/n3mo-dev/i-made-my-portfolio-website-today-please-give-feedbacks-272p</link>
      <guid>https://dev.to/n3mo-dev/i-made-my-portfolio-website-today-please-give-feedbacks-272p</guid>
      <description>&lt;p&gt;I have been busy working on my project (&lt;a href="https://github.com/RajX-dev/N3MO" rel="noopener noreferrer"&gt;https://github.com/RajX-dev/N3MO&lt;/a&gt;), Which you can also check, but yeah whenever I got free time I worked on making my portfolio site right now unable to buy the domain I want but yeah it's this - &lt;a href="https://rajx-dev.vercel.app/" rel="noopener noreferrer"&gt;https://rajx-dev.vercel.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>portfolio</category>
      <category>beginners</category>
    </item>
    <item>
      <title>today ran my own tool over the whole django repo it indexed it in 2.5 minutes and generated a whole graph for each function i searched, its always awesome to look at something you build on your own works. T-T</title>
      <dc:creator>N3MO</dc:creator>
      <pubDate>Wed, 15 Jul 2026 15:49:35 +0000</pubDate>
      <link>https://dev.to/n3mo-dev/today-ran-my-own-tool-over-the-whole-django-repo-it-indexed-it-in-25-minutes-and-generated-a-whole-4j61</link>
      <guid>https://dev.to/n3mo-dev/today-ran-my-own-tool-over-the-whole-django-repo-it-indexed-it-in-25-minutes-and-generated-a-whole-4j61</guid>
      <description></description>
      <category>django</category>
      <category>python</category>
      <category>showdev</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>AI agents are hallucinating on your monorepo. Here is why I used PostgreSQL to fix it.</title>
      <dc:creator>N3MO</dc:creator>
      <pubDate>Tue, 14 Jul 2026 04:52:04 +0000</pubDate>
      <link>https://dev.to/n3mo-dev/ai-agents-are-hallucinating-on-your-monorepo-here-is-why-i-used-postgresql-to-fix-it-2hio</link>
      <guid>https://dev.to/n3mo-dev/ai-agents-are-hallucinating-on-your-monorepo-here-is-why-i-used-postgresql-to-fix-it-2hio</guid>
      <description>&lt;p&gt;We need to talk about the elephant in the room: &lt;strong&gt;AI coding agents are failing on massive codebases.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whether you are using Cursor, Claude, or Windsurf, if you point an LLM at a 30,000-file enterprise monorepo and ask, &lt;em&gt;"What breaks if I rename this utility function?"&lt;/em&gt;, the AI will likely hallucinate. Why? Because LLMs rely on flat-file text search (&lt;code&gt;grep&lt;/code&gt;) or semantic vector embeddings, neither of which actually understand the structural &lt;strong&gt;call graph&lt;/strong&gt; of your code.&lt;/p&gt;

&lt;p&gt;To fix this, developers have started building local AST (Abstract Syntax Tree) parsers. But I noticed a fatal flaw in the popular ones: &lt;strong&gt;they were dumping the entire AST graph into static JSON files.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;If you try to load a 500,000-edge JSON graph into memory to traverse a dependency tree, your machine is going to choke. &lt;/p&gt;

&lt;p&gt;I knew there had to be a better way to scale this, so I built &lt;strong&gt;&lt;a href="https://github.com/RajX-dev/N3MO" rel="noopener noreferrer"&gt;N3MO&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The N3MO Approach: PostgreSQL + Recursive CTEs
&lt;/h3&gt;

&lt;p&gt;Instead of relying on fragile JSON files, I decided to treat source code like enterprise data. N3MO uses Tree-sitter to parse 27 different programming languages into ASTs, but instead of keeping them in memory, it batch-inserts the symbols and function calls directly into &lt;strong&gt;PostgreSQL&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Why Postgres? Because of &lt;strong&gt;Recursive CTEs&lt;/strong&gt; (&lt;code&gt;WITH RECURSIVE&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Instead of writing a slow Breadth-First Search algorithm in Python to figure out the "blast radius" of a function change, N3MO pushes the traversal directly down to the C-optimized database engine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- A simplified version of how N3MO calculates blast radius in milliseconds&lt;/span&gt;
&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="k"&gt;RECURSIVE&lt;/span&gt; &lt;span class="n"&gt;impact_chain&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source_symbol_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ARRAY&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;source_symbol_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;calls&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;resolved_symbol_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;

    &lt;span class="k"&gt;UNION&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt;

    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_symbol_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_symbol_id&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;calls&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;
    &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;impact_chain&lt;/span&gt; &lt;span class="n"&gt;ic&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resolved_symbol_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_symbol_id&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;ic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_symbol_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;ANY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By leveraging Postgres cycle guards (c.source_symbol_id = ANY(ic.path)) to prevent infinite recursive loops, N3MO can trace the blast radius of a function across tens of thousands of files in under 50 milliseconds.&lt;/p&gt;

&lt;p&gt;Connecting it back to AI (MCP)&lt;br&gt;
Once the code graph was living in Postgres, I built an MCP (Model Context Protocol) server. Now, when Claude or Cursor looks at my code, it doesn't just read text—it queries the PostgreSQL database to understand the exact, deterministic call graph before it refactors anything.&lt;/p&gt;

&lt;p&gt;Join the Community&lt;br&gt;
N3MO is completely open-source. We are actively looking for contributors to help us add more Tree-sitter languages, optimize our database migrations (Alembic), and build out the AI layer.&lt;/p&gt;

&lt;p&gt;⭐ Check out the code: &lt;a href="https://github.com/RajX-dev/N3MO" rel="noopener noreferrer"&gt;https://github.com/RajX-dev/N3MO&lt;/a&gt;&lt;br&gt;
💬 Talk Architecture: &lt;a href="https://discord.gg/cTgZKHf2G" rel="noopener noreferrer"&gt;https://discord.gg/cTgZKHf2G&lt;/a&gt;&lt;br&gt;
If you are tired of your LLM agents hallucinating, drop the JSON files and come use a real database.&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>ai</category>
      <category>database</category>
    </item>
    <item>
      <title>I am tired because of today's condition of project market</title>
      <dc:creator>N3MO</dc:creator>
      <pubDate>Thu, 09 Jul 2026 12:01:52 +0000</pubDate>
      <link>https://dev.to/n3mo-dev/i-am-tired-because-of-todays-condition-of-project-market-1b1h</link>
      <guid>https://dev.to/n3mo-dev/i-am-tired-because-of-todays-condition-of-project-market-1b1h</guid>
      <description>&lt;p&gt;I have been posting everywhere Hacker news, reddit , devto every possible platform.&lt;br&gt;
I am Raj shekhar, a fourth year college student , I have been working on a project for the last 7 months, like i had a huge problem that i tried solving and while solving the problem i realized that this can be turn into a huge Dev tool that everyone can use , so i made it work like everyday almost while having the semester exams in between (for context i am a electrical engineering student and I dont even like electrical, I am a tech lover) so I have to focus on the exams also, while i was building it, I never though it will be become this complex and its pretty helpful also  it become a huge thing.&lt;/p&gt;

&lt;p&gt;Now when it come to post the project on the internet every kid in his home making some cheap vibe coded app/website, the market is filled with garbage projects written by ai, I am not saying that i havent used any AI but I have used it to debug the code and cleaning the repo and for readme. But my point is these people are making some cheap things with just prompting producing same slop and posting everywhere , whereas people like me who worked hard in solving complex problem getting sideline because of these slop posts and slop projects.&lt;/p&gt;

&lt;p&gt;ill be just attaching the github profile not the project because I am so done , if you like give a visit and understand the project give me legit feedback I want to know if its good or bad , my placements are like 1 month away I cant promote the SaaS anymore if this post will get sideline again ill just stop writing. &lt;/p&gt;

&lt;p&gt;Github profile- &lt;a href="https://github.com/RajX-dev" rel="noopener noreferrer"&gt;https://github.com/RajX-dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>python</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Ai agents kept get in the loop of hallucination, so i resolved it</title>
      <dc:creator>N3MO</dc:creator>
      <pubDate>Fri, 03 Jul 2026 13:42:41 +0000</pubDate>
      <link>https://dev.to/n3mo-dev/ai-agents-kept-get-in-the-loop-of-hallucination-so-i-resolved-it-14ef</link>
      <guid>https://dev.to/n3mo-dev/ai-agents-kept-get-in-the-loop-of-hallucination-so-i-resolved-it-14ef</guid>
      <description>&lt;p&gt;I love using AI coding agents. But recently, I noticed a frustrating pattern when asking them to execute complex, multi-file refactors. &lt;/p&gt;

&lt;p&gt;I would ask an agent to modify a core utility function—let's call it &lt;code&gt;validate_session()&lt;/code&gt;. The agent would enthusiastically rewrite the function, and then confidently hallucinate dependencies. It would tell me it updated files that didn't exist, or completely miss the downstream API endpoints that relied on the old function signature.&lt;/p&gt;

&lt;p&gt;The problem wasn't the LLM's intelligence. The problem was how it was retrieving context.&lt;/p&gt;

&lt;p&gt;When an AI agent (or even a human developer) searches a codebase, we rely on vector embeddings or basic substring matching (&lt;code&gt;grep&lt;/code&gt;). But code isn't just a collection of text documents. It's a highly structured, relational graph.&lt;/p&gt;

&lt;p&gt;When you modify &lt;code&gt;validate_session()&lt;/code&gt;, you don't care where the string "validate_session" appears in a random markdown file. You care about:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What function calls it?&lt;/li&gt;
&lt;li&gt;What functions call &lt;em&gt;that&lt;/em&gt; function?&lt;/li&gt;
&lt;li&gt;What is the ultimate downstream impact?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I needed something that didn't guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Map
&lt;/h2&gt;

&lt;p&gt;I realized that if I wanted to truly understand the transitive blast radius of a change, I needed to parse the actual structure of the code, not just text.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;N3MO&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of relying on embeddings, N3MO uses &lt;strong&gt;Tree-sitter&lt;/strong&gt; (the exact same parsing engine GitHub uses) to parse source code into Abstract Syntax Trees (ASTs) locally. &lt;/p&gt;

&lt;p&gt;It takes those ASTs and maps every function, class, and method into a queryable relational database. There are zero LLM calls during the indexing phase—it is pure, deterministic static analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaling it Up
&lt;/h2&gt;

&lt;p&gt;Initially, I tested it on small projects. But I wanted to see if a relational graph could handle enterprise scale without falling over.&lt;/p&gt;

&lt;p&gt;So, I threw the &lt;strong&gt;TensorFlow codebase&lt;/strong&gt; at it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Files:&lt;/strong&gt; 14,611&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Symbols extracted:&lt;/strong&gt; 79,523&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relational edges mapped:&lt;/strong&gt; 480,851&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;N3MO parsed and indexed the entire repository into a queryable local graph in just &lt;strong&gt;14.06 minutes&lt;/strong&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Built for Engineers, Not Just Bots
&lt;/h2&gt;

&lt;p&gt;I didn't just build this for AI. I built it to act as a &lt;strong&gt;structural insurance policy&lt;/strong&gt; for human engineering teams.&lt;/p&gt;

&lt;p&gt;Now, instead of running a slow &lt;code&gt;grep&lt;/code&gt; and getting hundreds of noisy text matches, you can use N3MO to completely map your repository:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The CLI:&lt;/strong&gt; Run &lt;code&gt;n3mo impact "validate_session"&lt;/code&gt; in your terminal to instantly see the full blast radius before you touch the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD PR Bots:&lt;/strong&gt; Hook N3MO into GitHub Actions. On every Pull Request, N3MO automatically calculates the blast radius of the modified files and drops a markdown report directly into the PR comments. You know exactly what will break &lt;em&gt;before&lt;/em&gt; you merge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Visualizer:&lt;/strong&gt; Boot up the local dashboard and visually explore the orbiting call graph to untangle massive legacy repos.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Giving the Map Back to the AI
&lt;/h2&gt;

&lt;p&gt;Of course, once I had a deterministic graph, I couldn't resist giving it to the AI agents that inspired it in the first place.&lt;/p&gt;

&lt;p&gt;I wrapped the N3MO engine in a native &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; server. Now, when I use Cursor or Claude Desktop, the agent can actively query the N3MO server alongside its normal workflow. &lt;/p&gt;

&lt;p&gt;Instead of guessing context, the agent asks N3MO: &lt;em&gt;"What is the transitive blast radius?"&lt;/em&gt; And N3MO hands back the exact, verifiable relational graph. No more hallucinations. Just surgical, structural precision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it out
&lt;/h2&gt;

&lt;p&gt;I'm building N3MO in public, and it currently supports deep semantic call graph mapping for Python, JS/TS, and Java (with structural parsing for 24 other languages). &lt;/p&gt;

&lt;p&gt;If you want to stop guessing what your code touches whether you are a human or an AI give it a shot.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://github.com/RajX-dev/N3MO" rel="noopener noreferrer"&gt;Star N3MO on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
🌐 &lt;strong&gt;&lt;a href="https://n3mo.shop" rel="noopener noreferrer"&gt;Visit the Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
# Get started instantly
pip install n3mo
n3mo index /path/to/your/repo
n3mo query callers "my_function" --depth 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>ai</category>
      <category>architecture</category>
    </item>
    <item>
      <title>I cloned the repo. I was lost. So I built the map.</title>
      <dc:creator>N3MO</dc:creator>
      <pubDate>Sat, 27 Jun 2026 01:30:00 +0000</pubDate>
      <link>https://dev.to/n3mo-dev/i-cloned-the-repo-i-was-lost-so-i-built-the-map-2i10</link>
      <guid>https://dev.to/n3mo-dev/i-cloned-the-repo-i-was-lost-so-i-built-the-map-2i10</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmrykzp4evxfga6eu1smo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmrykzp4evxfga6eu1smo.png" alt=" " width="800" height="519"&gt;&lt;/a&gt;So there I was. A GSoC project I actually wanted to work on.&lt;/p&gt;

&lt;p&gt;Cloned the repo. Opened VS Code.&lt;/p&gt;

&lt;p&gt;Hundreds of files. Thousands of functions. Zero context.&lt;/p&gt;

&lt;p&gt;I tried grepping. I tried scrolling. I opened random files hoping something would click.&lt;/p&gt;

&lt;p&gt;Nothing clicked.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem wasn't skill. It was orientation.
&lt;/h2&gt;

&lt;p&gt;I knew how to write code. I didn't know &lt;em&gt;this&lt;/em&gt; code.&lt;/p&gt;

&lt;p&gt;There's no onboarding doc that tells you: "function A calls function B which depends on module C." You're supposed to figure that out. Manually. By reading everything.&lt;/p&gt;

&lt;p&gt;That's not how I work. That's probably not how you work either.&lt;/p&gt;

&lt;p&gt;So instead of contributing to that project, I started building something else.&lt;/p&gt;




&lt;h2&gt;
  
  
  What if the codebase could explain itself?
&lt;/h2&gt;

&lt;p&gt;Not an AI that hallucinates what your code does. Something that actually reads it. Parses it. Maps every function, every call, every dependency statically.&lt;/p&gt;

&lt;p&gt;No guessing. No LLM making things up. Just: here's what exists, here's what calls what.&lt;/p&gt;

&lt;p&gt;That became N3MO.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it actually does
&lt;/h2&gt;

&lt;p&gt;You point it at a repo. It indexes everything.&lt;/p&gt;

&lt;p&gt;Django's 3,021 files indexed in ~2.5 minutes. 43,000+ symbols. 181,000+ call edges.&lt;/p&gt;

&lt;p&gt;Every function knows what calls it. Every module knows what it imports. You can ask "where is this used?" and get an actual answer, not a guess.&lt;/p&gt;

&lt;p&gt;It ships as a PyPI package, a GitHub App, an MCP server that works inside Cursor and Claude Desktop, and a REST API. All from the same engine.&lt;/p&gt;




&lt;h2&gt;
  
  
  The GSoC project I never contributed to
&lt;/h2&gt;

&lt;p&gt;I never sent that PR.&lt;/p&gt;

&lt;p&gt;But the problem it gave me turned into something I'm still building a year later.&lt;/p&gt;

&lt;p&gt;Sometimes the codebase you can't understand is more valuable than the one you can.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;code&gt;pip install n3mo&lt;/code&gt; or &lt;a href="https://n3mo.shop" rel="noopener noreferrer"&gt;n3mo.shop&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>python</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Python was my first language. I forgot about it for years. Then I built a code intelligence engine with it.</title>
      <dc:creator>N3MO</dc:creator>
      <pubDate>Sun, 21 Jun 2026 13:14:25 +0000</pubDate>
      <link>https://dev.to/n3mo-dev/python-was-my-first-language-i-forgot-about-it-for-years-then-i-built-a-code-intelligence-engine-24el</link>
      <guid>https://dev.to/n3mo-dev/python-was-my-first-language-i-forgot-about-it-for-years-then-i-built-a-code-intelligence-engine-24el</guid>
      <description>&lt;p&gt;Python was the first language I ever wrote code in.&lt;/p&gt;

&lt;p&gt;I was a beginner. Ran some scripts. Never built anything meaningful. Then college started and I moved to Java and C++ — Python was forgotten.&lt;/p&gt;

&lt;p&gt;Years later, everyone's talking about ML and AI. Python is the language of the moment. I'm not into ML, but I picked it back up.&lt;/p&gt;




&lt;h2&gt;
  
  
  The moment that started everything
&lt;/h2&gt;

&lt;p&gt;I was trying to get into GSoC. Found a project I liked, cloned the repo, opened the codebase.&lt;/p&gt;

&lt;p&gt;Hundreds of files. Thousands of functions. Zero context.&lt;/p&gt;

&lt;p&gt;I didn't know what called what, what was connected to what, what I could safely touch. I closed the tab.&lt;/p&gt;

&lt;p&gt;That feeling — of being lost in someone else's code — became the problem I couldn't let go.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;N3MO&lt;/strong&gt; is a local-first code intelligence engine. It parses your codebase, builds a call graph with symbols and relationships, stores everything in Postgres, and lets you query it.&lt;/p&gt;

&lt;p&gt;Written entirely in Python. Built with tree-sitter for parsing, psycopg2 for Postgres, networkx for the graph layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Numbers that matter
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Indexes Django: 3,021 files, 43k+ symbols, 181k+ call edges&lt;/li&gt;
&lt;li&gt;Cold index time: dropped from ~23 minutes to ~2.5 minutes after a SQL optimization (SPLIT_PART rewrite)&lt;/li&gt;
&lt;li&gt;Available as a PyPI package, MCP server (Cursor/Claude Desktop), GitHub App with webhook reindexing
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;n3mo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;Python was the right choice. Not because of ML. Because the ecosystem — tree-sitter bindings, Postgres drivers, graph libraries — was all there.&lt;/p&gt;

&lt;p&gt;Every problem I hit, there was a library for it. Every optimization I needed, Python didn't get in the way.&lt;/p&gt;

&lt;p&gt;The language that gave me my first &lt;code&gt;print("hello world")&lt;/code&gt; ended up being the one I shipped something real with.&lt;/p&gt;




&lt;p&gt;Repo + docs: &lt;a href="https://github.com/RajX-dev/N3MO" rel="noopener noreferrer"&gt;github.com/RajX-dev/N3MO&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tags: &lt;code&gt;python&lt;/code&gt; &lt;code&gt;opensource&lt;/code&gt; &lt;code&gt;programming&lt;/code&gt; &lt;code&gt;beginners&lt;/code&gt; &lt;code&gt;showdev&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1b4wf4ett9xmc8k0338g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1b4wf4ett9xmc8k0338g.gif" alt=" " width="560" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>productivity</category>
      <category>ai</category>
    </item>
    <item>
      <title>I indexed the entire Django codebase and traced 317 blast-radius references. Here's what I learned building the tool.</title>
      <dc:creator>N3MO</dc:creator>
      <pubDate>Thu, 18 Jun 2026 01:43:52 +0000</pubDate>
      <link>https://dev.to/n3mo-dev/i-indexed-the-entire-django-codebase-and-traced-317-blast-radius-references-heres-what-i-learned-1iac</link>
      <guid>https://dev.to/n3mo-dev/i-indexed-the-entire-django-codebase-and-traced-317-blast-radius-references-heres-what-i-learned-1iac</guid>
      <description>&lt;p&gt;A few months ago I was mid-refactor on a Python codebase and &lt;code&gt;grep -r&lt;/code&gt; gave me 12 results. I changed the function, ran the tests, and broke 4 things grep hadn't caught. Classic.&lt;/p&gt;

&lt;p&gt;That afternoon I started building N3MO.&lt;/p&gt;

&lt;h3&gt;
  
  
  What N3MO does
&lt;/h3&gt;

&lt;p&gt;N3MO answers one question: &lt;strong&gt;"what breaks if I change this?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It parses your repository's ASTs using Tree-sitter, stores every symbol and call edge in PostgreSQL, then walks the call graph using recursive CTEs to return the full transitive blast radius of any function, method, or class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;n3mo
n3mo index
n3mo impact &lt;span class="s2"&gt;"authenticate_user"&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;◈ IMPACT ANALYSIS
──────────────────────────────────────────────────
Target: authenticate_user

◉ Direct Callers (3 symbols)
 ▸ login_endpoint       api/auth.py:12
 ▸ refresh_token        api/token.py:23
 ▸ validate_session     middleware/auth.py:89

◎ Ripple Effects (5 symbols)
 ╰─▸ POST /login        routes.py:67
 ╰─▸ admin_login        admin/views.py:34
 ╰─▸ require_auth       decorators.py:12

──────────────────────────────────────────────────
Total impacted: 8 references │ depth ≤ 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why Postgres as the graph store
&lt;/h3&gt;

&lt;p&gt;The obvious question: why not Neo4j or a dedicated graph DB?&lt;/p&gt;

&lt;p&gt;A few reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It's already in most stacks.&lt;/strong&gt; Asking a team to spin up a new DB just for code intelligence is friction. Asking them to run &lt;code&gt;n3mo setup&lt;/code&gt; (which starts a Docker container) is much less.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recursive CTEs are powerful enough.&lt;/strong&gt; PostgreSQL's &lt;code&gt;WITH RECURSIVE&lt;/code&gt; handles arbitrary-depth graph traversal cleanly. For the query volumes involved (this is a dev tool, not a production API), it's fast enough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The data is relational.&lt;/strong&gt; Symbols have names, files, line numbers, types. Calls have callers and callees. This is a table, not a document or a property graph.
The schema is roughly:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;  &lt;span class="c1"&gt;-- function, class, method&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;calls&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;caller_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;callee_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The blast radius query uses a recursive CTE to walk &lt;code&gt;calls&lt;/code&gt; from a given symbol outward to arbitrary depth.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Django benchmark
&lt;/h3&gt;

&lt;p&gt;I needed a real-world test case — not a toy repo. Django is public, large, and well-structured. Here's what indexing it looked like:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Files&lt;/td&gt;
&lt;td&gt;3,021&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Symbols&lt;/td&gt;
&lt;td&gt;~43,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Call edges&lt;/td&gt;
&lt;td&gt;~181,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cold index time&lt;/td&gt;
&lt;td&gt;~11 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Impact query on &lt;code&gt;dispatch&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;317 references, &amp;lt;2s&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The biggest optimization came from fixing the call name matching query. Initial version used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;call_name&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was doing a full table scan on every symbol lookup. Replaced with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;SPLIT_PART&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;call_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cut indexing time from ~23 minutes to ~11 minutes on Django.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other things N3MO does
&lt;/h3&gt;

&lt;p&gt;Beyond the CLI, there are a few integrations I built:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub App webhook&lt;/strong&gt; — installs on a repo, runs on every PR, posts a markdown blast radius report as a PR comment. Useful for catching unintended impact before merge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP server&lt;/strong&gt; — N3MO exposes a Model Context Protocol server so AI coding tools (Cursor, Claude Desktop, Windsurf) can query the codebase structure before suggesting refactors. The idea is that if an agent knows &lt;code&gt;dispatch&lt;/code&gt; has 317 downstream callers, it won't casually rename it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interactive graph UI&lt;/strong&gt; — &lt;code&gt;--graph&lt;/code&gt; flag launches a vis.js visualizer in your browser with a depth slider and node highlighting. Click a node to deep-link into your local IDE.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's next
&lt;/h3&gt;

&lt;p&gt;The tool is technically complete. The current focus is on getting real teams using it and finding the rough edges.&lt;/p&gt;

&lt;p&gt;If you work on a large Python codebase and want to try it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;n3mo
n3mo setup   &lt;span class="c"&gt;# starts Postgres in Docker&lt;/span&gt;
n3mo index   &lt;span class="c"&gt;# parse and store&lt;/span&gt;
n3mo impact &lt;span class="s2"&gt;"your_function"&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub App and full source: &lt;a href="https://github.com/RajX-dev/N3MO" rel="noopener noreferrer"&gt;github.com/RajX-dev/N3MO&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AGPL-3.0. Free for open source and projects under 15k LOC.&lt;/p&gt;




</description>
      <category>python</category>
      <category>postgres</category>
      <category>devtools</category>
    </item>
    <item>
      <title>How I cut Django indexing from 23 minutes to 11 minutes with one SQL change</title>
      <dc:creator>N3MO</dc:creator>
      <pubDate>Wed, 10 Jun 2026 11:56:37 +0000</pubDate>
      <link>https://dev.to/n3mo-dev/how-i-cut-django-indexing-from-23-minutes-to-11-minutes-with-one-sql-change-5of</link>
      <guid>https://dev.to/n3mo-dev/how-i-cut-django-indexing-from-23-minutes-to-11-minutes-with-one-sql-change-5of</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;I'm building N3MO — an open source code intelligence &lt;br&gt;
engine that maps Python codebases into a knowledge &lt;br&gt;
graph stored in PostgreSQL.&lt;/p&gt;

&lt;p&gt;When I tested it on Django (3,021 Python files, &lt;br&gt;
181,000+ function calls), the full index took &lt;br&gt;
23 minutes. Extraction was 8 minutes. Linking &lt;br&gt;
was 15 minutes.&lt;/p&gt;

&lt;p&gt;Linking was the bottleneck.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why linking was slow
&lt;/h2&gt;

&lt;p&gt;N3MO's linking phase resolves which function calls &lt;br&gt;
which. The original query used LIKE:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call_name&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%%.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This matches calls like &lt;code&gt;module.function&lt;/code&gt; or &lt;br&gt;
&lt;code&gt;self.function&lt;/code&gt; by checking if the call name &lt;br&gt;
ends with the function name.&lt;/p&gt;

&lt;p&gt;The problem: a leading wildcard LIKE query &lt;br&gt;
cannot use indexes. PostgreSQL has to compare &lt;br&gt;
every call against every symbol.&lt;/p&gt;

&lt;p&gt;For Django: 181,000 calls × 43,000 symbols = &lt;br&gt;
7.8 billion comparisons. That's why it took &lt;br&gt;
15 minutes.&lt;/p&gt;
&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;Replace LIKE with SPLIT_PART:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;SPLIT_PART&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SPLIT_PART splits the call name at '.' and takes &lt;br&gt;
the last part. &lt;code&gt;module.function&lt;/code&gt; becomes &lt;code&gt;function&lt;/code&gt;. &lt;br&gt;
Then it's an exact match — which CAN use indexes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;Before: 23 minutes&lt;br&gt;
After: 11 minutes&lt;br&gt;
Speedup: 2x faster from one line change&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;When you have a performance problem in SQL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leading wildcard LIKE = no index possible&lt;/li&gt;
&lt;li&gt;SPLIT_PART + exact match = index friendly&lt;/li&gt;
&lt;li&gt;Always check if your WHERE clause can use indexes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;N3MO is open source: github.com/RajX-dev/N3MO&lt;/p&gt;

</description>
      <category>django</category>
      <category>performance</category>
      <category>postgres</category>
      <category>sql</category>
    </item>
  </channel>
</rss>
