<?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: Aakash Sai Ram</title>
    <description>The latest articles on DEV Community by Aakash Sai Ram (@aakash_sairam_115284fbc3).</description>
    <link>https://dev.to/aakash_sairam_115284fbc3</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%2F4150535%2Fbe863008-335e-4c12-9b12-897f6add3d6f.png</url>
      <title>DEV Community: Aakash Sai Ram</title>
      <link>https://dev.to/aakash_sairam_115284fbc3</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aakash_sairam_115284fbc3"/>
    <language>en</language>
    <item>
      <title>How IncidentIQ Puts Hindsight at the Center of Incident Response</title>
      <dc:creator>Aakash Sai Ram</dc:creator>
      <pubDate>Tue, 29 Sep 2026 17:30:32 +0000</pubDate>
      <link>https://dev.to/aakash_sairam_115284fbc3/how-incidentiq-puts-hindsight-at-the-center-of-incident-response-5f08</link>
      <guid>https://dev.to/aakash_sairam_115284fbc3/how-incidentiq-puts-hindsight-at-the-center-of-incident-response-5f08</guid>
      <description>&lt;h2&gt;
  
  
  When the Architecture Is the Product
&lt;/h2&gt;

&lt;p&gt;I've worked on systems where memory was an afterthought—a &lt;code&gt;localStorage&lt;/code&gt; key, a session variable, a note appended to a ticket. In every case, the agent's usefulness capped out at the boundaries of a single conversation. The moment someone new opened a session, the slate was clean. IncidentIQ is an attempt to build something different: a system where the agent's memory is a first-class architectural component, not an afterthought, and where the entire application is organized around how information moves from past incidents into future ones.&lt;/p&gt;

&lt;p&gt;This is the story of how we designed that system.&lt;/p&gt;

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

&lt;p&gt;IncidentIQ is an incident response command center backed by a pnpm monorepo: a Vite + React frontend, an Express 5 API, PostgreSQL with Drizzle ORM for persistence, and &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;Hindsight&lt;/a&gt; as the memory layer. The application has four views: a &lt;strong&gt;Dashboard&lt;/strong&gt; showing live incident state and agent activity; a &lt;strong&gt;New Incident&lt;/strong&gt; form where engineers file signals and the agent immediately surfaces relevant historical patterns; a &lt;strong&gt;Before vs. After&lt;/strong&gt; comparison screen showing what changes when memory is present; and an &lt;strong&gt;Agent Memory&lt;/strong&gt; gallery where the full memory store is browsable and searchable.&lt;/p&gt;

&lt;p&gt;Every part of the application connects to the memory layer either on the write path (when incidents close) or the read path (when new incidents arrive). That symmetry was intentional from the start.&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%2Fzc3gc7pq0yb14qdqp7su.jpg" 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%2Fzc3gc7pq0yb14qdqp7su.jpg" alt="System architecture: Engineer → React frontend → Express 5 API → PostgreSQL/Drizzle, with Hindsight connected to the API via retain() and recall()" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;IncidentIQ system architecture. Hindsight handles memory independently of the primary database.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Core Architectural Decision
&lt;/h2&gt;

&lt;p&gt;The critical design question was where the memory boundary should sit. Options ranged from storing resolution notes in the same PostgreSQL database as incidents (simple, cheap, no semantic search), to passing the entire incident history as context in every LLM prompt (expensive, context-limited), to using a dedicated memory layer that handles indexing, retrieval, and scoping independently of the application database.&lt;/p&gt;

&lt;p&gt;We chose the third approach, using &lt;a href="https://vectorize.io/what-is-agent-memory" rel="noopener noreferrer"&gt;Hindsight's agent memory model&lt;/a&gt;. The reasons were concrete: keyword search over structured notes fails as soon as the wording differs between the original incident and the new one. A &lt;code&gt;checkout-api&lt;/code&gt; latency incident described as "elevated p95 response time" should match a memory titled "connection pool exhaustion cascade"—not because those phrases overlap lexically, but because the semantic context is the same. That kind of retrieval requires vector-indexed storage, which Hindsight provides without us building the infrastructure.&lt;/p&gt;

&lt;p&gt;The application database (PostgreSQL via Drizzle) holds structured incident records. Hindsight holds the semantic memory store. They're separate on purpose. Incidents are structured data with known fields—id, service, severity, status, timestamps. Memories are semantic artifacts designed for fuzzy retrieval. Conflating them in the same store would either require building retrieval on top of a relational schema or imposing relational rigidity on semantic content.&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%2Fn4cyn6s1bzctz8hqqkdq.jpg" 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%2Fn4cyn6s1bzctz8hqqkdq.jpg" alt="The memory retain/recall lifecycle: from incident resolution through the 4-step modal to Hindsight's memory store, and back via recall on new incident intake" width="768" height="1376"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Memory lifecycle in IncidentIQ. Retain happens at resolution; recall happens at intake. Both are scoped by service name.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How Information Flows Through the System
&lt;/h2&gt;

&lt;p&gt;The write path is driven by the resolution modal. When an engineer closes an incident, they walk through four steps: root cause, resolution action, lesson learned, and a confirmation to retain that lesson as agent memory. The lesson field is the critical one—it's what reaches Hindsight.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.tsx — memory shape: what Hindsight retains per resolved incident&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// scopes future recalls to this service&lt;/span&gt;
  &lt;span class="nl"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Severity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// root cause description&lt;/span&gt;
  &lt;span class="nl"&gt;lesson&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// forward-looking instruction for the agent&lt;/span&gt;
  &lt;span class="nl"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// how many times Hindsight has recalled this memory&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;service&lt;/code&gt; field is the scope key. Every retain call includes it. Every recall call filters by it. A memory from &lt;code&gt;payments-worker&lt;/code&gt; does not surface when the next incident is &lt;code&gt;checkout-api&lt;/code&gt;, even if the symptoms overlap.&lt;/p&gt;

&lt;p&gt;The read path executes on every incident intake. Before the agent generates analysis, the system runs a recall against the memory store scoped to the service of the incoming incident. The matching memories surface in the analysis panel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AnalysisPanel — shows recall badge when memories are retrieved&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;submitted&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"memory-badge"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BrainCircuit&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; 3 memories recalled
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;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 analysis text then references the recalled context directly: "This signal matches a known saturation pattern in the service dependency layer. Start by checking the last deploy and the nearest shared resource."&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%2Ftqbzh0sjd6cqqzw3dbfl.jpg" 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%2Ftqbzh0sjd6cqqzw3dbfl.jpg" alt="Agent Memory gallery showing searchable memory cards with service pills, severity dots, lesson sections, and recall hit counts" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Agent Memory gallery. Engineers browse and search the full memory store. Recall hit counts show which patterns recur most.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Before vs. After
&lt;/h2&gt;

&lt;p&gt;The comparison view makes the behavioral difference explicit. You give it an incident signal for a specific service and run both paths side by side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without memory:&lt;/strong&gt; "Check application logs, restart the affected pods, and increase the timeout if the issue persists." Generic, non-actionable, treats the incident as novel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With memory:&lt;/strong&gt; "Pause the retry amplification, then compare connection-pool saturation against the remembered deploy pattern for checkout-api." Specific, service-grounded, immediately testable.&lt;/p&gt;

&lt;p&gt;The comparison view quantifies this as a quality score—28% without memory, 92% with. Those numbers reflect how closely the response anchors to a testable first hypothesis. The specific values come from the comparison UI's scoring logic built into the application.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Resolution Workflow Drives Everything
&lt;/h2&gt;

&lt;p&gt;The 4-step modal is the engine of the memory layer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ResolveModal — four-step memory capture on incident close&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setStep&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1=RootCause, 2=Resolution, 3=Lesson, 4=Retain&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;submitResolve&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;step&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;setStep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;step&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="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootCause&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lesson&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;Each step is gated. You cannot advance without filling in the current field. The friction is intentional—incomplete lessons produce low-quality recalls. The final step ("Retain Memory") confirms that the lesson will be active for the next incident on that service.&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%2Fr6q4hkms5ljdra7qgdql.jpg" 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%2Fr6q4hkms5ljdra7qgdql.jpg" alt="The 4-step resolution workflow: Root Cause → Resolution → Lesson Learned → Retain Memory, feeding into Hindsight's service-scoped memory store" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The four-step resolution modal drives all memory writes. The lesson field—separate from root cause—is what reaches Hindsight.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Architecture is memory design.&lt;/strong&gt; The decision about where memory lives—in the application database or in a dedicated semantic store—determined everything downstream. Once we committed to Hindsight as a first-class layer, the data flow became clearer: structured data in PostgreSQL, semantic memory in Hindsight, no crossover.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope every retain call at the most specific reliable key.&lt;/strong&gt; Service name was the right scope for this system. Broader scoping (e.g., all incidents globally) produced too many false recall matches. Narrower scoping (e.g., by specific endpoint) produced too few. Service name sits at the right granularity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The four-step modal has a real cost.&lt;/strong&gt; Engineers pushed back on the extra steps when first encountering the resolution flow. The payback takes a few weeks of incidents before the recalled lessons become noticeably useful. That lag is a genuine UX tradeoff, not a solved problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separate the write schema from the read schema.&lt;/strong&gt; The PostgreSQL incident schema and the Hindsight memory schema serve different retrieval patterns. Trying to unify them would have produced a system good at neither structured queries nor semantic retrieval.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The architecture of IncidentIQ is an argument: when &lt;a href="https://vectorize.io/what-is-agent-memory" rel="noopener noreferrer"&gt;agent memory&lt;/a&gt; is treated as a first-class system component—with its own storage, its own retrieval semantics, and its own write path—the agent becomes genuinely useful rather than generically capable. The &lt;a href="https://hindsight.vectorize.io/" rel="noopener noreferrer"&gt;Hindsight documentation&lt;/a&gt; covers the retain/recall mechanics in detail. The key architectural insight is simpler: information only compounds if the system is designed to collect it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>automation</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
