When a database becomes unavailable, the first question is obvious: what is down? The harder question is: what else could be affected, and how can we explain the connection?
That question led me to build TraceGraph, a graph-powered incident-impact investigation prototype for Graph Hacks 2026, using FalkorDB as the source of truth for service dependencies.
- Code: TraceGraph on GitHub
- Demo: https://drive.google.com/file/d/14Ei0qs_gRllNWaGJ_bcJq3BEHmF2OVZB/view?usp=sharing
The problem: impact is about relationships
A software system is not just a list of services. The API gateway may depend on the order service, which depends on inventory, which depends on a database. If that database fails, the impact can travel through several layers.
Looking at each component separately doesn't make those connections easy to see. TraceGraph models the dependencies explicitly and follows them to answer a focused question: if this component becomes unavailable, which other components have a dependency path to it?
The project uses synthetic demo data. It does not connect to production telemetry or confirm real outages; it demonstrates how graph relationships can support an explainable investigation.
Model the dependencies in FalkorDB
TraceGraph represents each application, service, worker, database, or queue as a Component node. A directed DEPENDS_ON edge records the dependency direction:
A --> B
This means A depends on B. Therefore, if B fails, A is a potential impact when a directed path exists from A to B.
For example:
Customer Web App
-> API Gateway
-> Order Service
-> Inventory Service
-> Inventory DB
This direction is the core design decision. A component's dependencies are not the same as the components that depend on it. TraceGraph needs to traverse dependents towards the failed component to explain potential impact.
The query that powers the investigation
The backend uses a parameterized Cypher query to find paths with between one and five dependency edges:
MATCH path = (affected:Component)-[:DEPENDS_ON*1..5]->
(failed:Component {name: $name})
WHERE affected.name <> failed.name
RETURN affected.name AS affected_name,
[node IN nodes(path) | node.name] AS dependency_path
ORDER BY affected_name
Here's what matters in this query:
-
DEPENDS_ON*1..5traverses one to five edges, bounding the search depth for this prototype. -
$nameidentifies the selected failed component as a separate query parameter instead of interpolating user text into the query. -
nodes(path)returns the component sequence, which becomes the evidence shown to the user. - The failed component is excluded from its own impact list.
Python then groups paths by affected component and removes duplicate paths. The displayed impact count is the number of distinct affected components, not the number of paths.
What the demo shows
The UI lets a user select a component and optionally ask a natural-language question. For example:
What happens if Inventory DB goes down?
In the sample graph, TraceGraph identifies five potentially affected components: Inventory Service, Order Service, API Gateway, Customer Web App, and Analytics Worker. It also displays the dependency path behind each result.
A second scenario helps check the edge direction. If Order Service is selected as unavailable, the demo graph identifies API Gateway and Customer Web App as potential impacts. Inventory Service and other dependencies that Order Service uses are not automatically classified as affected by its failure.
Architecture: keep each part focused
I kept the implementation small and split it into clear responsibilities:
-
Streamlit (
ui.py) displays the component selector, question input, impact summary, and evidence paths. -
FastAPI (
app/main.py) provides endpoints includingGET /components,GET /impact/{component_name},POST /ask, andGET /health. -
Question handling (
app/agent.py) resolves a component mentioned in the question. Without an API key, local name matching keeps the demo runnable. Optional Groq tool calling can request graph-backed tools. -
Graph tools (
app/tools.py) expose component listing and impact tracing as explicit functions. -
FalkorDB (
app/database.py) stores the nodes and edges, runs Cypher, and returns the paths used in the answer.
The language model, when configured, helps resolve the question and request a tool. Python validates and executes the tool call. The impact result still comes from FalkorDB rather than being invented by the model. Without Groq credentials, the local resolver works as a fallback.
Docker Compose runs FalkorDB, the FastAPI backend, and Streamlit as separate services. For local development, the published ports are bound to 127.0.0.1.
Testing the behavior, not just the screen
I added checks for the graph data, agent behavior, and graph-backed impact results. The tests cover the expected Inventory DB impact set, dependency direction for Order Service, unknown-component handling, and a representative multi-hop path.
My local test run completed with 8 tests passing. The integration tests are opt-in and need a running FalkorDB instance, so the result is meaningful only when those tests are enabled and the database is reachable.
During development I hit a couple of useful bugs. One test assertion treated a list of paths like a dictionary; inspecting the actual data shape showed that the assertion—not the query—was wrong. I also created a Python module under the wrong folder, which caused an import error until I moved it into the root app package.
Those errors reinforced two habits: inspect the actual value at a boundary, and make sure Python package paths match the imports the code uses. Running Docker locally also helped me understand how a UI, API, and graph database communicate as separate services.
What I would improve next
TraceGraph is a prototype, not a production incident platform. Its dependency graph is synthetic and manually defined, it doesn't ingest metrics or logs, and a path indicates a possible dependency impact rather than a verified outage. Its text-based evidence paths could also be complemented by an interactive graph view.
Next, I would connect the model to a service catalog or deployment metadata source, test more branching and hop-limit scenarios, add graph visualization, and evaluate results against known incident cases. A production deployment would also need appropriate authentication, access controls, persistent data, and operational monitoring.
Run TraceGraph locally
You'll need Docker Desktop with Docker Compose. From the project root:
git clone https://github.com/Shreyansh2025/tracegraph-falkordb-hackathon.git
cd tracegraph-falkordb-hackathon
docker compose up --build
Then open:
- UI: http://localhost:8501
- API docs: http://localhost:8000/docs
- Health check: http://localhost:8000/health
The repository README explains environment configuration and how to run the tests. Keep secrets in a local .env file; never commit API keys.
The main thing I learned
A graph is most useful here when it does real work. FalkorDB is not just storing data for a diagram: its directed relationships and traversal determine which components are returned and supply the path behind each result. The UI makes that result easy to inspect, while optional AI assistance helps people ask questions and initiate graph-backed operations.
Building TraceGraph gave me hands-on practice with graph modeling, Cypher, FastAPI, Streamlit, Docker Compose, test debugging, and explaining the limits of a prototype. The next challenge is connecting the model to real dependency data and proving that its results remain useful on more realistic incident scenarios.
AI assistance disclosure
AI coding assistance was used to help scaffold, debug, review, test, and document parts of the project. I ran the application and tests locally, reviewed the code, and remain responsible for understanding and explaining its behavior, graph model, query, and limitations.
Top comments (0)