<?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: Sahasra Kondapuram</title>
    <description>The latest articles on DEV Community by Sahasra Kondapuram (@sahasra_k).</description>
    <link>https://dev.to/sahasra_k</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%2F4147795%2Fad368e12-b817-4bbe-9357-404b913553c9.png</url>
      <title>DEV Community: Sahasra Kondapuram</title>
      <link>https://dev.to/sahasra_k</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sahasra_k"/>
    <language>en</language>
    <item>
      <title>How Hindsight Helped Our Backend Recall Past Incidents</title>
      <dc:creator>Sahasra Kondapuram</dc:creator>
      <pubDate>Wed, 30 Sep 2026 06:52:20 +0000</pubDate>
      <link>https://dev.to/sahasra_k/how-hindsight-helped-our-backend-recall-past-incidents-474k</link>
      <guid>https://dev.to/sahasra_k/how-hindsight-helped-our-backend-recall-past-incidents-474k</guid>
      <description>&lt;p&gt;*&lt;em&gt;How We Built the Backend for WorkMemory AI&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
An engineering incident may be solved in a few hours, but the useful knowledge from that incident can easily disappear afterward.&lt;/p&gt;

&lt;p&gt;While working on WorkMemory AI, I focused on the backend that connects the incident dashboard with the memory and investigation workflow. The goal was simple: when an engineer reports a problem, the backend should provide a structured way to store that incident and prepare it for future investigation and organizational memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Is WorkMemory AI?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;WorkMemory AI is an incident-response assistant designed around a simple idea:&lt;/p&gt;

&lt;p&gt;«An engineer should not always have to start from zero when a similar incident has happened before.»&lt;/p&gt;

&lt;p&gt;In a software team, information about incidents can be spread across tickets, documentation, chats, troubleshooting notes, and deployment discussions.&lt;/p&gt;

&lt;p&gt;For example, imagine that a Payment API starts returning HTTP 500 errors after a deployment.&lt;/p&gt;

&lt;p&gt;An engineer might eventually discover that an environment configuration was incorrect. Months later, a similar problem occurs.&lt;/p&gt;

&lt;p&gt;Without an organized memory system, the second investigation may begin almost from scratch.&lt;/p&gt;

&lt;p&gt;WorkMemory AI is designed to connect these two situations by treating previous engineering incidents as useful organizational knowledge.&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%2F0jsqztiq5kktp08fis16.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%2F0jsqztiq5kktp08fis16.jpg" alt=" " width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 1: WorkMemory AI dashboard for recording and investigating engineering incidents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Role: Backend&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My main focus was the backend.&lt;/p&gt;

&lt;p&gt;The backend is built using Node.js and Express.js. It provides API endpoints that the frontend can use to submit incidents and request an investigation.&lt;/p&gt;

&lt;p&gt;The basic architecture is:&lt;/p&gt;

&lt;p&gt;React + Vite Frontend&lt;br&gt;
          |&lt;br&gt;
          v&lt;br&gt;
Node.js + Express Backend&lt;br&gt;
          |&lt;br&gt;
          +---- Incident API&lt;br&gt;
          |&lt;br&gt;
          +---- Investigation API&lt;br&gt;
          |&lt;br&gt;
          v&lt;br&gt;
Memory / AI Integration Layer&lt;/p&gt;

&lt;p&gt;I wanted the frontend to remain independent from the internal implementation of the memory layer.&lt;/p&gt;

&lt;p&gt;The React application only needs to communicate with the backend API. Provider-specific logic can stay inside backend services.&lt;/p&gt;

&lt;p&gt;Designing the Incident API&lt;/p&gt;

&lt;p&gt;The first important endpoint is:&lt;/p&gt;

&lt;p&gt;POST /api/incidents&lt;/p&gt;

&lt;p&gt;It receives an incident from the frontend.&lt;/p&gt;

&lt;p&gt;The backend first checks whether incident data was actually provided:&lt;/p&gt;

&lt;p&gt;router.post("/incidents", async (req, res) =&amp;gt; {&lt;br&gt;
  try {&lt;br&gt;
    const incident = req.body;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (!incident || Object.keys(incident).length === 0) {
  return res.status(400).json({
    error: "Incident data is required"
  });
}

const memory = await saveToHindsight(incident);

return res.status(201).json({
  message: "Incident stored",
  memory
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;} catch (error) {&lt;br&gt;
    console.error("Error storing incident:", error);&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return res.status(500).json({
  error: "Failed to store incident",
  details: error.message
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;This structure gives the API a clear responsibility:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Receive the incident.&lt;/li&gt;
&lt;li&gt;Validate the request.&lt;/li&gt;
&lt;li&gt;Send the incident to the memory service.&lt;/li&gt;
&lt;li&gt;Return a response to the frontend.&lt;/li&gt;
&lt;li&gt;Handle errors without crashing the server.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Figure 2: Testing the incident API from the backend.&lt;/p&gt;

&lt;p&gt;Keeping Memory Logic Separate&lt;/p&gt;

&lt;p&gt;One of the backend design decisions I found useful was keeping the memory-provider logic separate from the API routes.&lt;/p&gt;

&lt;p&gt;Instead of putting every external API request directly inside "incidentRoutes.js", the route calls a service:&lt;/p&gt;

&lt;p&gt;const {&lt;br&gt;
  saveToHindsight,&lt;br&gt;
  investigateWithMemory&lt;br&gt;
} = require("../services/hindsightService");&lt;/p&gt;

&lt;p&gt;The route therefore doesn't need to know how the memory system is implemented.&lt;/p&gt;

&lt;p&gt;The service acts as an adapter between the application and the memory layer.&lt;/p&gt;

&lt;p&gt;In the current project version, this adapter is implemented as a test layer so that the rest of the application can be developed and tested independently.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;async function saveToHindsight(incident) {&lt;br&gt;
  console.log("\n[HINDSIGHT] Incident received:");&lt;br&gt;
  console.log(JSON.stringify(incident, null, 2));&lt;/p&gt;

&lt;p&gt;return {&lt;br&gt;
    status: "stored",&lt;br&gt;
    source: "temporary-hindsight-adapter",&lt;br&gt;
    incident&lt;br&gt;
  };&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;This was useful during development because I could test the complete API workflow before connecting the production memory implementation.&lt;/p&gt;

&lt;p&gt;The Investigation Endpoint&lt;/p&gt;

&lt;p&gt;The second important backend endpoint is:&lt;/p&gt;

&lt;p&gt;POST /api/incidents/investigate&lt;/p&gt;

&lt;p&gt;Its purpose is different from incident creation.&lt;/p&gt;

&lt;p&gt;Instead of simply storing an incident, it represents the investigation stage.&lt;/p&gt;

&lt;p&gt;The route validates the request and calls the investigation service:&lt;/p&gt;

&lt;p&gt;router.post("/incidents/investigate", async (req, res) =&amp;gt; {&lt;br&gt;
  try {&lt;br&gt;
    const incident = req.body;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (!incident || Object.keys(incident).length === 0) {
  return res.status(400).json({
    error: "Incident data is required"
  });
}

const result = await **investigateWithMemory(incident);**

return res.status(200).json(result);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;} catch (error) {&lt;br&gt;
    console.error("Error investigating incident:", error);&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return res.status(500).json({
  error: "Failed to investigate incident",
  details: error.message
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;The current investigation adapter returns a structured response:&lt;/p&gt;

&lt;p&gt;async function investigateWithMemory(incident) {&lt;br&gt;
  console.log("\n[HINDSIGHT] Investigation requested:");&lt;br&gt;
  console.log(JSON.stringify(incident, null, 2));&lt;/p&gt;

&lt;p&gt;return {&lt;br&gt;
    message: "Investigation endpoint is working",&lt;br&gt;
    incident,&lt;br&gt;
    similarIncidents: [],&lt;br&gt;
    analysis: {&lt;br&gt;
      status: "pending",&lt;br&gt;
      message: "Connect Hindsight Recall and the LLM layer next."&lt;br&gt;
    }&lt;br&gt;
  };&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;This also made the development process easier because the frontend could be connected to the investigation endpoint before the complete memory and LLM layers were finished.&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%2Fup2oakfy5cs43f91plcp.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%2Fup2oakfy5cs43f91plcp.jpg" alt=" " width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 4: Investigation endpoint returning a structured backend response.&lt;/p&gt;

&lt;p&gt;Why Use an Adapter?&lt;/p&gt;

&lt;p&gt;The adapter pattern became important for this project.&lt;/p&gt;

&lt;p&gt;A frontend should not have to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;where the memory service is hosted,&lt;/li&gt;
&lt;li&gt;how authentication works,&lt;/li&gt;
&lt;li&gt;how memory requests are formatted,&lt;/li&gt;
&lt;li&gt;how recall is performed,&lt;/li&gt;
&lt;li&gt;or what happens when the external service fails.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those responsibilities belong in the backend.&lt;/p&gt;

&lt;p&gt;The intended production flow is:&lt;/p&gt;

&lt;p&gt;New Incident&lt;br&gt;
     |&lt;br&gt;
     v&lt;br&gt;
Backend API&lt;br&gt;
     |&lt;br&gt;
     v&lt;br&gt;
Memory Layer&lt;br&gt;
     |&lt;br&gt;
     v&lt;br&gt;
Recall Relevant Past Incidents&lt;br&gt;
     |&lt;br&gt;
     v&lt;br&gt;
LLM Investigation&lt;br&gt;
     |&lt;br&gt;
     v&lt;br&gt;
Investigation Result&lt;br&gt;
     |&lt;br&gt;
     v&lt;br&gt;
Frontend&lt;/p&gt;

&lt;p&gt;This separation means that the application can evolve without rewriting the frontend whenever the memory implementation changes.&lt;/p&gt;

&lt;p&gt;A Simple Example&lt;/p&gt;

&lt;p&gt;Consider this incident:&lt;/p&gt;

&lt;p&gt;Title:&lt;br&gt;
Payment API 500 Error&lt;/p&gt;

&lt;p&gt;Service:&lt;br&gt;
Payment API&lt;/p&gt;

&lt;p&gt;Environment:&lt;br&gt;
Production&lt;/p&gt;

&lt;p&gt;Description:&lt;br&gt;
Payment API started returning 500 errors after deployment.&lt;/p&gt;

&lt;p&gt;Severity:&lt;br&gt;
High&lt;/p&gt;

&lt;p&gt;The frontend sends this information to:&lt;/p&gt;

&lt;p&gt;POST /api/incidents&lt;/p&gt;

&lt;p&gt;The backend validates the request and passes the incident to the memory service.&lt;/p&gt;

&lt;p&gt;Later, an engineer could submit a similar incident to:&lt;/p&gt;

&lt;p&gt;POST /api/incidents/investigate&lt;/p&gt;

&lt;p&gt;The intended memory workflow would then look for relevant previous engineering experiences.&lt;/p&gt;

&lt;p&gt;For example, a previous incident might have revealed that an incorrect deployment environment variable caused a similar Payment API failure.&lt;/p&gt;

&lt;p&gt;The important idea is not that the previous incident automatically proves the current root cause.&lt;/p&gt;

&lt;p&gt;Instead, it gives the engineer a useful starting point:&lt;/p&gt;

&lt;p&gt;«“A similar problem happened before. Here is what the team learned then.”»&lt;/p&gt;

&lt;p&gt;The engineer can then verify that information against the current system.&lt;/p&gt;

&lt;p&gt;Backend Error Handling&lt;/p&gt;

&lt;p&gt;Another area I focused on was basic error handling.&lt;/p&gt;

&lt;p&gt;For example, if an empty request reaches the API, the backend returns:&lt;/p&gt;

&lt;p&gt;return res.status(400).json({&lt;br&gt;
  error: "Incident data is required"&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;If an unexpected problem occurs while processing the request:&lt;/p&gt;

&lt;p&gt;return res.status(500).json({&lt;br&gt;
  error: "Failed to store incident",&lt;br&gt;
  details: error.message&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;This makes API failures easier to understand during development and testing.&lt;/p&gt;

&lt;p&gt;The server also uses environment variables through "dotenv":&lt;/p&gt;

&lt;p&gt;require("dotenv").config();&lt;/p&gt;

&lt;p&gt;This allows configuration such as the server port and future external-service credentials to remain outside the source code.&lt;/p&gt;

&lt;p&gt;The Backend Stack&lt;/p&gt;

&lt;p&gt;The backend uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Express.js&lt;/li&gt;
&lt;li&gt;CORS&lt;/li&gt;
&lt;li&gt;dotenv&lt;/li&gt;
&lt;li&gt;REST API endpoints&lt;/li&gt;
&lt;li&gt;A separate memory-service adapter&lt;/li&gt;
&lt;li&gt;React/Vite frontend integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is developed using Git, GitHub, and VS Code.&lt;/p&gt;

&lt;p&gt;Figure 5: Running the WorkMemory AI backend locally.&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%2F4xunx1i0kl6cbzni3tcb.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%2F4xunx1i0kl6cbzni3tcb.jpg" alt=" " width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Separate application logic from external services&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Putting provider-specific code inside a separate service makes the main API routes easier to understand and maintain.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build the API boundary first&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Having clear endpoints such as "/api/incidents" and "/api/incidents/investigate" made it easier to connect the frontend and develop the rest of the system incrementally.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Memory and storage solve different problems&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A normal incident record answers:&lt;/p&gt;

&lt;p&gt;«“What incident did we record?”»&lt;/p&gt;

&lt;p&gt;A memory system is intended to answer:&lt;/p&gt;

&lt;p&gt;«“Have we experienced something relevant before?”»&lt;/p&gt;

&lt;p&gt;That distinction is one of the main ideas behind WorkMemory AI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Build incrementally&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We did not need every part of the system to be complete before testing the backend.&lt;/p&gt;

&lt;p&gt;The API, frontend, and memory adapter could be tested separately and then connected progressively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. AI should support engineering judgment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even when the memory and LLM layers are connected, their output should be treated as investigation context rather than unquestionable truth.&lt;/p&gt;

&lt;p&gt;A previous incident can be similar without having exactly the same root cause.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Comes Next&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The next stage for the backend is completing the real Hindsight integration so that incidents can be retained as persistent engineering memories and relevant memories can be recalled during investigation.&lt;/p&gt;

&lt;p&gt;The investigation layer can then pass recalled context to an LLM to generate a structured explanation and recommended next steps.&lt;/p&gt;

&lt;p&gt;The intended final workflow is:&lt;/p&gt;

&lt;p&gt;Engineer reports incident&lt;br&gt;
          ↓&lt;br&gt;
Backend receives incident&lt;br&gt;
          ↓&lt;br&gt;
Incident is retained as organizational knowledge&lt;br&gt;
          ↓&lt;br&gt;
A similar incident appears later&lt;br&gt;
          ↓&lt;br&gt;
Backend recalls relevant past experience&lt;br&gt;
          ↓&lt;br&gt;
LLM analyzes the recalled context&lt;br&gt;
          ↓&lt;br&gt;
Engineer receives investigation context&lt;br&gt;
          ↓&lt;br&gt;
New learning can become future memory&lt;/p&gt;

&lt;p&gt;This creates a continuous learning loop instead of treating every incident as an isolated event.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most interesting part of building WorkMemory AI was realizing that an incident should not simply end when the immediate problem is fixed.&lt;/p&gt;

&lt;p&gt;The real value can continue afterward if the useful experience is captured and made available when a similar problem appears.&lt;/p&gt;

&lt;p&gt;My contribution to that idea was building the backend boundary that connects the frontend, incident workflow, and memory layer.&lt;/p&gt;

&lt;p&gt;The current backend gives us a clean foundation for that workflow, while the memory and LLM layers can be extended behind the service boundary.&lt;/p&gt;

&lt;p&gt;The idea we want to carry forward is simple:&lt;/p&gt;

&lt;p&gt;«Solve the incident once. Preserve what was learned. Make the next investigation start with that knowledge.»&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%2Fadgycsiitnp2c64x1f4d.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%2Fadgycsiitnp2c64x1f4d.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Project&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GitHub: &lt;br&gt;
&lt;a href="https://github.com/sahasra09k-spec/WorkMemory-AI" rel="noopener noreferrer"&gt;https://github.com/sahasra09k-spec/WorkMemory-AI&lt;/a&gt;&lt;br&gt;
Demo:&lt;a href="https://photos.app.goo.gl/h1fkWCBvU2xqh2dD9" rel="noopener noreferrer"&gt;https://photos.app.goo.gl/h1fkWCBvU2xqh2dD9&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hindsight: &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;https://github.com/vectorize-io/hindsight&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hindsight Documentation: &lt;a href="https://hindsight.vectorize.io/" rel="noopener noreferrer"&gt;https://hindsight.vectorize.io/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
