<?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: Harsh Chauhan</title>
    <description>The latest articles on DEV Community by Harsh Chauhan (@very_h4rsh).</description>
    <link>https://dev.to/very_h4rsh</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%2F3971581%2Fb90a8b65-cfe1-4ef9-9ffd-1221ba5dd3c8.jpeg</url>
      <title>DEV Community: Harsh Chauhan</title>
      <link>https://dev.to/very_h4rsh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/very_h4rsh"/>
    <language>en</language>
    <item>
      <title>The newest deploy is almost never the cause. So I gave on-call a graph.</title>
      <dc:creator>Harsh Chauhan</dc:creator>
      <pubDate>Mon, 19 Oct 2026 03:33:30 +0000</pubDate>
      <link>https://dev.to/very_h4rsh/the-newest-deploy-is-almost-never-the-cause-so-i-gave-on-call-a-graph-5d0g</link>
      <guid>https://dev.to/very_h4rsh/the-newest-deploy-is-almost-never-the-cause-so-i-gave-on-call-a-graph-5d0g</guid>
      <description>&lt;h2&gt;
  
  
  The newest deploy is almost never the cause. So I gave on-call a graph. (On-call Brain, Graph Hacks by WeMakeDevs x FalkorDB)
&lt;/h2&gt;

&lt;p&gt;It's 3 am. Your phone says &lt;code&gt;checkout p99 latency above 2s&lt;/code&gt;. You open the deploy log and look at the newest change: a search deploy from eight minutes ago. You roll it back. Nothing changes.&lt;/p&gt;

&lt;p&gt;The real cause was a config change on the payments gateway forty minutes earlier. Checkout calls payments, payments calls the gateway, and someone cut its connection pool from 200 to 20. A list of deploys can't tell you that. &lt;strong&gt;A graph of how your services connect can.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That became &lt;strong&gt;On-call Brain&lt;/strong&gt;, my entry to Graph Hacks by WeMakeDevs and FalkorDB.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/eriObL8LlsQ" rel="noopener noreferrer"&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%2F0k4kxqkpkaq0dvvkbvye.jpg" alt="Watch the demo video" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Click to watch the 4-minute demo: the web app, Slack, Claude Code over MCP, and the graph in FalkorDB Browser.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Three agents (triage, investigator, comms) work every incident over one FalkorDB graph of the company: services and their dependencies over time, owners, on-call rotations, changes, docs, tickets, chat and past incidents.&lt;/li&gt;
&lt;li&gt;Every answer comes with proof: the evidence path, the suspects ruled out and why, and the Cypher behind each step, with FalkorDB's own timing and query plan.&lt;/li&gt;
&lt;li&gt;When a human confirms a cause, it becomes memory, and the next similar incident is solved in half the steps.&lt;/li&gt;
&lt;li&gt;It's an MCP server first (33 tools), with a Claude Code plugin, Slack and an alert webhook, plus a web UI. Live at &lt;a href="https://13-127-186-74.sslip.io/" rel="noopener noreferrer"&gt;https://13-127-186-74.sslip.io/&lt;/a&gt;, with every graph on FalkorDB Cloud.&lt;/li&gt;
&lt;li&gt;On 200 generated incidents it finds the planted cause 186 times. A plain change log finds it zero times.&lt;/li&gt;
&lt;/ul&gt;

&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%2Finu9qaw9l5mvj3kcp13u.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%2Finu9qaw9l5mvj3kcp13u.png" alt="The answer: cause, confidence, evidence path, who is paged" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Product thinking: who is this for?
&lt;/h2&gt;

&lt;p&gt;The user is the engineer on call, half awake, with one question: what do I do right now? That shaped every decision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Answer first, proof one click away.&lt;/strong&gt; The screen leads with the cause, how sure it is, who is paged and the fix. "Show me why" holds the graph and the queries for when you want to check.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go where they already work.&lt;/strong&gt; On-call engineers live in their editor, Slack and their alerting tool, so the core product is an MCP server. The web page is one window onto it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Humans close the loop.&lt;/strong&gt; The agents propose; only a person can confirm a cause. That confirmation is what the system learns from.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be honest about confidence.&lt;/strong&gt; "Very likely: 4 of 5 suspects ruled out" says why, and a cause the graph can't support is labelled "needs a human" instead of guessed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&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%2F76ij003mwllx9h5xlwia.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%2F76ij003mwllx9h5xlwia.png" alt="Architecture: four surfaces call one tool registry; the agents decide with Claude or a rules planner; tenant graphs, a coordination graph and UDF libraries live on FalkorDB Cloud" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every graph tool is defined once, in one registry, and served three ways: to the agents, over MCP and over HTTP. The agents never call each other. They read and write one shared incident board in the graph, so any agent can be restarted mid-incident and pick up where it left off. Claude Opus 5.5 chooses each step and writes a one-line reason; without an API key, a deterministic planner does the same job, which is also what the tests run against.&lt;/p&gt;

&lt;p&gt;FalkorDB is the only database. Besides one graph per company, it holds a coordination graph (locks, rate limits and the LLM budget) and two libraries of functions that run inside the database. More on why below.&lt;/p&gt;

&lt;h2&gt;
  
  
  The graph model
&lt;/h2&gt;

&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%2Fgk64caqhzp44vwp2njhj.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%2Fgk64caqhzp44vwp2njhj.png" alt="Graph model: services with time-bounded, keyed dependencies and owners; changes; alerts; incidents with hypotheses and evidence; runbooks and documents" width="800" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most important design choice is that &lt;strong&gt;edges carry time&lt;/strong&gt;. &lt;code&gt;DEPENDS_ON&lt;/code&gt;, &lt;code&gt;OWNS&lt;/code&gt; and &lt;code&gt;ON_CALL&lt;/code&gt; all have validity windows, and nothing is ever deleted. When checkout stopped calling legacy-billing three days ago, that edge got a &lt;code&gt;valid_to&lt;/code&gt;. Every query asks what was true at the moment of the alert. Each company gets its own graph in FalkorDB, so memory and knowledge never mix between tenants.&lt;/p&gt;

&lt;p&gt;Facts carry a second time too: &lt;code&gt;recorded_at&lt;/code&gt;, when the graph learned them. If CI reports a change after the incident opened, the agents still use it, and the answer lists it as "learned late" instead of pretending it was known all along.&lt;/p&gt;

&lt;h2&gt;
  
  
  The query that does most of the work
&lt;/h2&gt;

&lt;p&gt;Finding suspects is a temporal multi-hop walk: start at the alerting service, follow up to six dependency hops, keep a path only if every edge on it was live at alert time, then take the recent changes on the services reached, nearest first. In plain Cypher:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;i:&lt;/span&gt;&lt;span class="n"&gt;Incident&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;id:&lt;/span&gt; &lt;span class="n"&gt;$incident_id&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:TRIGGERED_BY&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;a:&lt;/span&gt;&lt;span class="n"&gt;Alert&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:FIRED_ON&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;o:&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;MATCH&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:DEPENDS_ON&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;s:&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;IN&lt;/span&gt; &lt;span class="nf"&gt;relationships&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
          &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;r.valid_from&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;a.at&lt;/span&gt; &lt;span class="n"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r.valid_to&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="ow"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;r.valid_to&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a.at&lt;/span&gt;&lt;span class="ss"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="ss"&gt;))&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;hops&lt;/span&gt;
&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;c:&lt;/span&gt;&lt;span class="n"&gt;Change&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:CHANGED&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;c.at&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;a.at&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;$window&lt;/span&gt; &lt;span class="ow"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;c.at&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;a.at&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;c.id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s.id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hops&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;hops&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c.at&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That version has a cost: the &lt;code&gt;WHERE&lt;/code&gt; filters paths after FalkorDB has expanded them, so the walk still wanders into every retired dependency's subtree. The product version flips it around. It starts from the few changes in the window (a range index on &lt;code&gt;Change.at&lt;/code&gt;), then calls a JavaScript function that runs inside FalkorDB and walks only live edges, stopping as soon as it has reached every changed service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;o0&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="ow"&gt;IN&lt;/span&gt; &lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="n"&gt;o0&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;folded&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
     &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;o:&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="py"&gt;reach:&lt;/span&gt; &lt;span class="n"&gt;oncall.live_reach&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alert_at&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;IN&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;h.s.id&lt;/span&gt;&lt;span class="ss"&gt;])}]&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;walks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A test checks that it returns exactly the same rows as the plain form. It's as fast at 1,000 services and 2 to 4 times faster at 2,500.&lt;/p&gt;

&lt;p&gt;Each suspect is then checked: is there a live path from the alert to its service, and did errors appear along it, in order, after the change? For the first incident:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Suspect&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;search deploy (newest change)&lt;/td&gt;
&lt;td&gt;ruled out&lt;/td&gt;
&lt;td&gt;no dependency path from checkout to search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;legacy-billing deploy&lt;/td&gt;
&lt;td&gt;ruled out&lt;/td&gt;
&lt;td&gt;checkout's dependency on it was retired 3 days ago&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pricing deploy&lt;/td&gt;
&lt;td&gt;ruled out&lt;/td&gt;
&lt;td&gt;rolled back before the alert&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cart deploy&lt;/td&gt;
&lt;td&gt;ruled out&lt;/td&gt;
&lt;td&gt;cart showed no errors after it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;payments-gw config change&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;cause&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;errors travel payments-gw, payments, checkout&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Legacy-billing is the interesting one: it deployed and threw errors right before the alert, so any rule that watches errors blames it. Only the retired edge rules it out.&lt;/p&gt;

&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%2Fy83i1ht28wjmre5dedft.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%2Fy83i1ht28wjmre5dedft.png" alt="Show me why: the incident subgraph and the Cypher behind each step" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory you can measure
&lt;/h2&gt;

&lt;p&gt;Confirming a cause writes &lt;code&gt;CAUSED_BY&lt;/code&gt; and a runbook back into the graph. Three days later, refunds slows down. Recall is structural, not textual: it finds resolved incidents whose cause sat on the new alert's live dependency path. The checkout incident matches, because the same gateway sits upstream of refunds, and its fix is tested first. For a fair comparison the same alert also runs on a copy of the graph that never saw the first incident:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Investigator steps&lt;/th&gt;
&lt;th&gt;Suspects tested&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;With memory&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Without memory&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&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%2Fgi9qft2gzqlmukqkn3k9.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%2Fgi9qft2gzqlmukqkn3k9.png" alt="Solved from memory: 3 investigator steps instead of 6" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Three alerts, one incident
&lt;/h2&gt;

&lt;p&gt;Checkout, refunds and subscriptions alert within four minutes. Triage projects the alerting services and the upstream services that went red into a scratch graph and runs &lt;strong&gt;WCC&lt;/strong&gt; (weakly connected components) to decide which alerts are one incident. A postgres-orders change explains all three and leads; a subscriptions deploy explains only one, so it's kept as "also possible" rather than thrown away. Criticality for paging comes from &lt;strong&gt;PageRank&lt;/strong&gt; on a point-in-time projection of the live dependencies.&lt;/p&gt;

&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%2Fu0in34950vzqrqvice9n.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%2Fu0in34950vzqrqvice9n.png" alt="Three alerts, one incident" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The company brain
&lt;/h2&gt;

&lt;p&gt;Docs, decision records, postmortems, tickets and chat sit in the same graph, linked to the services, changes and people they mention. "Who owns kafka?" returns the team, who is on call now and the sources, with an older decision record flagged as superseded. A follow-up like "and who is on call for it?" works because each conversation is stored in the graph too. No model runs here: full-text search finds the documents, and the graph decides what's current and what to cite.&lt;/p&gt;

&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%2Fpr7t5ymvvc7qwmuuozum.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%2Fpr7t5ymvvc7qwmuuozum.png" alt="Ask the brain: who owns kafka, with sources" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond the web page
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code plugin:&lt;/strong&gt; ask "what breaks if postgres-orders goes down?" and Claude picks the blast-radius tool by itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slack:&lt;/strong&gt; &lt;code&gt;/oncall who owns payments-gw?&lt;/code&gt; answers inline, and &lt;code&gt;/oncall incident subscriptions latency&lt;/code&gt; runs the agents and posts the result with Confirm and Wrong cause buttons.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhook:&lt;/strong&gt; an alerting tool posts the alert, the agents run headless, and the status update comes back.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Going all in on FalkorDB
&lt;/h2&gt;

&lt;p&gt;Late in the hackathon I moved the live site's graphs to FalkorDB Cloud and went through the docs looking for every place the database could do the work instead of my code. What changed:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;FalkorDB feature&lt;/th&gt;
&lt;th&gt;What it does here&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;FalkorDB Cloud&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Every graph of the live site, in the same AWS region as the app: 1.2 ms median per query. The same code runs on a local FalkorDB; only the connection string changes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A graph for coordination&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud allows graph commands but not Redis's &lt;code&gt;SET&lt;/code&gt;, &lt;code&gt;INCR&lt;/code&gt; or &lt;code&gt;EVAL&lt;/code&gt;, so the run lock, rate limits and LLM budget are &lt;code&gt;Lease&lt;/code&gt; and &lt;code&gt;Counter&lt;/code&gt; nodes. A UNIQUE constraint on &lt;code&gt;Lease.key&lt;/code&gt; is the mutex: 16 racing clients, exactly one winner.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;User-defined functions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The blast-radius and suspect walks are JavaScript functions (&lt;code&gt;oncall.live_upstream&lt;/code&gt;, &lt;code&gt;oncall.live_reach&lt;/code&gt;) that skip dead edges as they walk.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;FLEX&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;FalkorDB's own function library. &lt;code&gt;flex.text.jaroWinkler&lt;/code&gt; turns a typo like &lt;code&gt;kafak&lt;/code&gt; into "did you mean svc:kafka?", on every surface.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Constraints&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;UNIQUE ids on every label. &lt;code&gt;DEPENDS_ON&lt;/code&gt; and &lt;code&gt;OWNS&lt;/code&gt; must carry &lt;code&gt;valid_from&lt;/code&gt; (MANDATORY), so the database refuses an undated dependency. Each dependency has a UNIQUE key, so 12 racing writers with no lock still create one edge.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;algo.maxFlow&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;"Is there a way around this service?" counts the routes that share no dependency edge.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;GRAPH.PROFILE&lt;/code&gt; / &lt;code&gt;EXPLAIN&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A Plan button on every query in the trace, and each step shows FalkorDB's own run time and whether the plan came from its cache. A test runs &lt;code&gt;EXPLAIN&lt;/code&gt; on every named query and fails on any full-label scan nobody has justified.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;GRAPH.COPY&lt;/code&gt; + &lt;code&gt;RENAME&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A company is seeded on a staging graph and swapped in whole, so nobody ever reads a half-built graph.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Free tier keeps nothing across a restart, so a watchdog checks once a minute and puts back the constraints, the functions and the demo company.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running it in public
&lt;/h2&gt;

&lt;p&gt;The app runs on one ARM instance on AWS, in Docker behind Caddy for HTTPS, with no SSH and secrets in SSM. The graphs live on FalkorDB Cloud in the same region. A public demo with a real model behind it needs guardrails: per-client rate limits, a cap on concurrent runs, daily and hourly token budgets (past them the rules planner takes over and says so), request size limits, security headers, and a token on every outside write. Every issue the security scans found is fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does the graph actually matter?
&lt;/h2&gt;

&lt;p&gt;An eval of 200 generated incidents, each with a planted cause zero to three hops upstream, decoys of every kind, unrelated errors, silent hops and cascade victims:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Found the planted cause&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;On-call Brain&lt;/td&gt;
&lt;td&gt;186/200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Change log that also watches errors&lt;/td&gt;
&lt;td&gt;134/200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keyword match on the alert name&lt;/td&gt;
&lt;td&gt;57/200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Newest change in the window&lt;/td&gt;
&lt;td&gt;0/200&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Design decisions and trade-offs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decision&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;th&gt;Trade-off&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Time on every dependency and ownership edge&lt;/td&gt;
&lt;td&gt;answers depend on what was true at alert time&lt;/td&gt;
&lt;td&gt;every query carries a time filter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agents share a board in the graph, not memory&lt;/td&gt;
&lt;td&gt;restartable, inspectable, every step logged&lt;/td&gt;
&lt;td&gt;one extra read per decision (1 to 2 ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Structural recall instead of text embeddings&lt;/td&gt;
&lt;td&gt;incident titles all look alike; where the cause sat is what matters&lt;/td&gt;
&lt;td&gt;needs a dependency graph to exist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Algorithms on scratch projections&lt;/td&gt;
&lt;td&gt;PageRank and WCC must ignore retired edges&lt;/td&gt;
&lt;td&gt;a copy per run (small graphs, fast)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hot walks as functions inside FalkorDB&lt;/td&gt;
&lt;td&gt;they drop dead edges while walking instead of after&lt;/td&gt;
&lt;td&gt;JavaScript to keep in step with a plain-Cypher twin (a test compares them)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coordination in a graph, not Redis keys&lt;/td&gt;
&lt;td&gt;Cloud has no &lt;code&gt;SET&lt;/code&gt;/&lt;code&gt;INCR&lt;/code&gt;; one database to run&lt;/td&gt;
&lt;td&gt;a lock is a query and a constraint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deterministic planner beside the LLM&lt;/td&gt;
&lt;td&gt;works without a key, testable, a safe fallback&lt;/td&gt;
&lt;td&gt;two code paths to keep in step&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MCP first, web second&lt;/td&gt;
&lt;td&gt;engineers live in editors and chat&lt;/td&gt;
&lt;td&gt;more surfaces to secure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model time explicitly.&lt;/strong&gt; Retiring an edge instead of deleting it was the single most useful decision.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Let the database enforce safety.&lt;/strong&gt; Every read runs as &lt;code&gt;GRAPH.RO_QUERY&lt;/code&gt;, so a read tool can't write even if its query is wrong, and constraints refuse bad data whoever writes it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent review catches what the builder can't.&lt;/strong&gt; Every round of separate code, security and design review found real issues, including two-minute hangs under load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FalkorDB details worth knowing:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;shortestPath&lt;/code&gt; works in &lt;code&gt;WITH&lt;/code&gt; and &lt;code&gt;RETURN&lt;/code&gt;, not in &lt;code&gt;MATCH&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A variable-length bound can't be a parameter (&lt;code&gt;*1..$depth&lt;/code&gt; fails), so the hop limit is a function argument.&lt;/li&gt;
&lt;li&gt;A MANDATORY constraint is checked the moment the edge is created, before any &lt;code&gt;SET&lt;/code&gt; in the same query, so the required property goes inside the &lt;code&gt;MERGE&lt;/code&gt; pattern.&lt;/li&gt;
&lt;li&gt;Create constraints only when they're missing, never while writes are running.&lt;/li&gt;
&lt;li&gt;On 4.22, two &lt;code&gt;GRAPH.UDF LOAD REPLACE&lt;/code&gt; calls close together under traffic can crash the server. Load a library once, and replace it only when its code changed.&lt;/li&gt;
&lt;li&gt;FalkorDB Cloud allows a fixed list of commands. Design for graph commands only and it just works.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'd improve next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tell "red because of this change" apart from "red at the same moment for another reason": most of the eval's misses are that case.&lt;/li&gt;
&lt;li&gt;A path for incidents with no change behind them, such as pure capacity problems.&lt;/li&gt;
&lt;li&gt;Real ingest from CI/CD, monitoring and chat into the write tools that already exist (&lt;code&gt;record_change&lt;/code&gt;, &lt;code&gt;record_doc&lt;/code&gt;, &lt;code&gt;record_message&lt;/code&gt;, &lt;code&gt;record_ticket&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Per-user auth on the public API, and runbook confidence that decays with age.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Demo video: &lt;a href="https://youtu.be/eriObL8LlsQ" rel="noopener noreferrer"&gt;https://youtu.be/eriObL8LlsQ&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Live: &lt;a href="https://13-127-186-74.sslip.io/" rel="noopener noreferrer"&gt;https://13-127-186-74.sslip.io/&lt;/a&gt; (press "Simulate an incident")&lt;/li&gt;
&lt;li&gt;Recorded runs, no server: &lt;a href="https://harz05.github.io/oncall-brain/" rel="noopener noreferrer"&gt;https://harz05.github.io/oncall-brain/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Code, graph model and every Cypher query: &lt;a href="https://github.com/harz05/oncall-brain" rel="noopener noreferrer"&gt;https://github.com/harz05/oncall-brain&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Built with Python, FastAPI and FalkorDB, with Claude Opus 5.5 planning at runtime and Claude Code as my coding assistant. Thanks to WeMakeDevs and FalkorDB for Graph Hacks.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>devchallenge</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>How I got into GSoC'26 with CERN-HSF</title>
      <dc:creator>Harsh Chauhan</dc:creator>
      <pubDate>Sun, 14 Jun 2026 09:32:13 +0000</pubDate>
      <link>https://dev.to/very_h4rsh/how-i-got-into-gsoc26-with-cern-hsf-362i</link>
      <guid>https://dev.to/very_h4rsh/how-i-got-into-gsoc26-with-cern-hsf-362i</guid>
      <description>&lt;p&gt;Hi all!! I'm Harsh Chauhan currently an Engineering Physics undergrad at IIT Dharwad. I'll be using this space to document my GSoC journey and everything around it. This is my first time writing a blog, so please bear with me :p.&lt;/p&gt;

&lt;p&gt;So to start with the good news, my proposal on &lt;a href="https://summerofcode.withgoogle.com/programs/2026/projects/NE74dwRu" rel="noopener noreferrer"&gt;ML Inference on Heterogeneous Architectures using SOFIE&lt;/a&gt; got accepted for Google Summer of Code 2026 with &lt;a href="https://hepsoftwarefoundation.org/activities/gsoc.html" rel="noopener noreferrer"&gt;CERN-HSF&lt;/a&gt; and as I'm writing this I'm already in Week 3 of the coding phase. I'm currently working under my mentors &lt;a href="https://sparks.web.cern.ch/moneta-lorenzo" rel="noopener noreferrer"&gt;Dr. Lorenzo Moneta&lt;/a&gt; (Senior Applied Physicist at CERN) and &lt;a href="https://ch.linkedin.com/in/sanjiban-sengupta" rel="noopener noreferrer"&gt;Sanjiban Sengupta&lt;/a&gt; (Doctoral Student at CERN and previous GSoC'21 contributor with CERN).&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;So what's the project about??&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GSoC and where does CERN-HSF fit in?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How it started?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finding my footing at CERN-HSF&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Three proposals, one deadline&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;D-Day: Results&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;My two cents&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's next?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  So what's the project about??
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/ML4EP/SOFIE" rel="noopener noreferrer"&gt;SOFIE&lt;/a&gt; (&lt;strong&gt;S&lt;/strong&gt;ystem for &lt;strong&gt;O&lt;/strong&gt;ptimized &lt;strong&gt;F&lt;/strong&gt;ast &lt;strong&gt;I&lt;/strong&gt;nference code &lt;strong&gt;E&lt;/strong&gt;mit) is part of CERN's &lt;a href="https://root.cern/" rel="noopener noreferrer"&gt;ROOT framework&lt;/a&gt;, developed under ML4EP, a CERN &lt;a href="https://ep-dep-sft.web.cern.ch/" rel="noopener noreferrer"&gt;SFT&lt;/a&gt; group effort focused on building common ML software tools for high-energy physics. It takes trained ML models and generates fast, dependency light C++ code to run inference on them, which is useful when you need to deploy models inside large physics analysis pipelines. So far SOFIE has mostly targeted CPUs and my project is about extending it to run on GPUs using the alpaka framework, which lets the same code run across different hardware backends like NVIDIA and AMD. The goal is to make ML inference in ROOT faster and portable across heterogeneous architectures.&lt;/p&gt;

&lt;p&gt;I'll go into the actual technical goals, the operators, their fusion and benchmarking in a later blog once I cover the coding phase in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  GSoC and where does CERN-HSF fit in?
&lt;/h2&gt;

&lt;p&gt;If you're reading till here, I'm assuming you probably already know what GSoC is, but for any readers who might be new to this: Google Summer of Code is a program where students contribute to open-source projects over the summer, each paired with mentors from a participating organization. You write a project proposal and if it gets accepted, you spend a few months building it out with guidance from your mentors.&lt;/p&gt;

&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.amazonaws.com%2Fuploads%2Farticles%2Fi358ady2fcu1ujf529pb.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.amazonaws.com%2Fuploads%2Farticles%2Fi358ady2fcu1ujf529pb.gif" alt="img1" width="480" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CERN-HSF is one of those organizations, and it's an umbrella org, meaning it brings together a bunch of high-energy physics projects from places like &lt;strong&gt;CERN, Fermilab, DESY, MIT and several universities&lt;/strong&gt; under one roof. And honestly, just the idea of contributing to software used at CERN is kind of exciting for me. Coming from a physics background, I've been hearing and reading about CERN forever (from professors casually mentioning it to watching Veritasium videos about it), so getting to contribute here still feels a little surreal, this is the place where the web was born and the Higgs boson was discovered. ROOT, the framework my project sits under, is one of its biggest sub-projects.&lt;/p&gt;

&lt;p&gt;One thing that makes CERN-HSF a bit different from a lot of other orgs is how selection works. It's not just about how many contributions you rack up. The process is more phase-wise: you reach out to mentors, complete an evaluation task they assign and then, if that goes well, you write a proposal. Your prior contributions do play a role, but the eval task and the proposal carry real weight. I'll get into how that actually played out for me further down.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it started?
&lt;/h2&gt;

&lt;p&gt;I first heard about GSoC at the end of my freshman year, through a friend who had gotten in and was contributing over the summer. It stuck in my head as something I wanted to do.&lt;/p&gt;

&lt;p&gt;By sophomore year I had it in mind, but I'll be honest, I never really committed to it. I was into development at the time and had started learning WebRTC, so I set up a few org projects locally like &lt;strong&gt;Rocket.Chat, Plone and Jitsi&lt;/strong&gt; and poked around here and there. But around midsems I couldn't stay consistent and I just let it go. TBH, part of me leaned on the excuse that it was only sophomore year and I had time.&lt;/p&gt;

&lt;p&gt;Looking back, that was a bit silly of me. Even just trying and drafting a proposal that might not get accepted is worth a lot, because you learn where you fall short and what to fix. &lt;strong&gt;If there's one thing I'd tell anyone reading this, it's that the attempt itself teaches you more than waiting for the "right year" ever will. As cliche as it may sound, you break stuff, learn and figure it out!!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding my footing at CERN-HSF
&lt;/h2&gt;

&lt;p&gt;Around January this year, I started seriously researching orgs again. This time I came across the umbrella orgs like &lt;strong&gt;CERN-HSF, ML4Sci and NumFOCUS&lt;/strong&gt;. CERN-HSF stood out to me because of the sheer range of its past projects, everything from webdev, agentic AI, ML to compiler research, with a lot of them coming straight from experiments like ATLAS and CMS.&lt;/p&gt;

&lt;p&gt;The 2026 projects started dropping around February 3rd, so I began going through them. There were a lot, around 40 announced initially and I spent the next couple of weeks reading through codebases and the research papers behind the projects that caught my eye. A few stood out were: firstly ofc the one &lt;a href="https://hepsoftwarefoundation.org/gsoc/2026/proposal_ML4EP_SOFIE_ALPAKA.html" rel="noopener noreferrer"&gt;I'm working on now&lt;/a&gt;, the &lt;a href="https://hepsoftwarefoundation.org/gsoc/2026/proposal_ML4EP_SOFIE_PYTORCH_KERAS.html" rel="noopener noreferrer"&gt;Keras and PyTorch parsers project&lt;/a&gt; (both under SOFIE), &lt;a href="https://hepsoftwarefoundation.org/gsoc/2026/proposal_OMNIFOLD.html" rel="noopener noreferrer"&gt;OmniFold&lt;/a&gt; and &lt;a href="https://hepsoftwarefoundation.org/gsoc/2026/proposal_NegativeWeightsMCFM.html" rel="noopener noreferrer"&gt;MCFM&lt;/a&gt;, which is a Monte Carlo event generator.&lt;/p&gt;

&lt;p&gt;The mentor contact window ran from February 19th to March 16th. My timing wasn't ideal because my midsems landed right at the end of February, so I got stuck for a bit and started mailing mentors a little later than I'd have liked. In total I reached out to around 7 to 10 mentors for eval tasks.&lt;/p&gt;

&lt;p&gt;Once a mentor responds, they assign you an evaluation task. For my project, this started with a preliminary exercise to get my environment set up and get familiar with SOFIE, followed by a small toy implementation where I implemented a few operators and wrote tests for them on the GPU.&lt;/p&gt;

&lt;p&gt;The hardest part wasn't the implementation itself, it was getting everything to build and set up locally. Fixing those build issues by digging through the docs taught me a lot and that same setup and understanding is what made contributing to the ROOT repo afterwards much smoother. The implementation came a bit easier since I'd done deep learning last semester, so &lt;strong&gt;if you're aiming for an ML-related project, having built even tiny things and messed around with existing ones beforehand helps more than you'd expect.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Three proposals, one deadline
&lt;/h2&gt;

&lt;p&gt;By this point I had to draft three proposals at once, &lt;strong&gt;MCFM, OmniFold and the SOFIE ML Inference one&lt;/strong&gt;, all while quizzes were going on :/ It was a lot to juggle.&lt;/p&gt;

&lt;p&gt;For MCFM, a good chunk of the proposal came directly from my eval task. While doing it I'd found an issue building the project through CMake which I fixed locally and flagged it to the mentor, so I documented that along with my results. That one ended up around 12 pages and got feedback from the mentor.&lt;/p&gt;

&lt;p&gt;For the SOFIE ML Inference proposal, my mentor gave guidance on the expected length and content, and I got review feedback on my draft. That came out to about 6 pages. Along with this, I was also contributing in ROOT and interacting with my mentors and other maintainers since March. For OmniFold I didn't get much feedback and mostly submitted what I had.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A few things I took away about writing proposals:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Keep the deliverables clean and the timeline realistic. &lt;strong&gt;Better to have clear core deliverables plus some stretch goals than to overscope everything upfront&lt;/strong&gt;, since the actual scope tends to evolve as the project progresses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Look at past accepted proposals. They give you a real sense of structure and depth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add small code snippets, a rough framework plan, or diagrams where you can. &lt;strong&gt;Showing a skeleton of what you're thinking lands better than just saying "I'll do this and that."&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's more to it, but it's not worth stressing over right now, proposal writing really only comes into the picture in the last month or so.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you'd like to see how they actually turned out, here are my three proposals: &lt;a href="https://drive.google.com/file/d/1EWDSJ_ODL-0xmfy0PcVIFfaj0CFwFxt_/view?usp=sharing" rel="noopener noreferrer"&gt;SOFIE ML Inference&lt;/a&gt;, &lt;a href="https://drive.google.com/file/d/1bNguRNdlrze9mPSl8MeBaw9_qrkkzte9/view?usp=sharing" rel="noopener noreferrer"&gt;MCFM&lt;/a&gt; and &lt;a href="https://drive.google.com/file/d/1IY2nVxNcUGhiWyYd71PAiX2AAeON1pKy/view?usp=sharing" rel="noopener noreferrer"&gt;OmniFold&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  D-Day: Results
&lt;/h2&gt;

&lt;p&gt;Results came out on April 30th, right at 11:30 PM. My endsems were going on that week and I distinctly remember stressing about it at around 3 AM that morning, because I had my Condensed Matter Physics endsem the same day. Meanwhile, I was also up surfing the GSoC subreddit, discussing with others and basically stressing together with a bunch of strangers.&lt;/p&gt;

&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.amazonaws.com%2Fuploads%2Farticles%2F2grteng7l62ffyads8ey.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.amazonaws.com%2Fuploads%2Farticles%2F2grteng7l62ffyads8ey.png" alt="Acceptance-mail" width="781" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the time came, I opened my GSoC profile page and saw my ML Inference on Heterogeneous Architectures project accepted. It happened sooner than I expected and telling my friends and everyone after was overwhelming, to say the least.&lt;/p&gt;

&lt;h2&gt;
  
  
  My two cents
&lt;/h2&gt;

&lt;p&gt;If there's one thing I'd want you to take away, it's this: &lt;strong&gt;don't let the big orgs intimidate you out of trying&lt;/strong&gt;. CERN-HSF felt way out of my league at first and I think a lot of people talk themselves out of even attempting it because of that fear. But it's worth the shot. Worst case, you learn a ton along the way.&lt;/p&gt;

&lt;p&gt;And honestly, that's something I've only started realizing myself. I'm still pretty new to all of this, but even in this short time, I've felt how much getting into open source pushes you to grow as a developer. You learn to read unfamiliar codebases, work with maintainers, take feedback and collaborate with people across the world and that sticks with you regardless of whether you get selected.&lt;/p&gt;

&lt;p&gt;I'll probably write a separate, more detailed blog on the contributions and application side of things, so I'll keep this short for now.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;Right now I'm already into the coding phase, working with my mentors, raising PRs and discussing the plan forward in our weekly syncs as we go. I'm planning to keep blogging through the program and documenting my work along the way, which should also help me when the final evaluation comes around.&lt;/p&gt;

&lt;p&gt;For those of you who made it till the end, thank you very much!! If you're considering GSoC, especially with a big org, I hope this was useful.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A few blogs that helped me figure out how to write this one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://sanjiban.hashnode.dev/getting-into-gsoc21-with-cern-hsf" rel="noopener noreferrer"&gt;Sanjiban Sengupta's GSoC'21 blog&lt;/a&gt; (now one of my mentors!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://medium.com/@viveknigam3003/getting-into-gsoc-20-with-cern-hsf-d7ec866c0533" rel="noopener noreferrer"&gt;Vivek Nigam's GSoC'20 journey&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&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.amazonaws.com%2Fuploads%2Farticles%2F14e9nj8vdi51sa5y3okz.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.amazonaws.com%2Fuploads%2Farticles%2F14e9nj8vdi51sa5y3okz.gif" alt="end" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I'll be covering the project's technical side and how the coding phase is going in upcoming posts, so stay tuned for more. Until next time!! :p&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>gsoc</category>
    </item>
  </channel>
</rss>
