diff --git a/docker/grafana/Dockerfile.grafana b/docker/grafana/Dockerfile.grafana
index ff2c3a9..00cf957 100644
--- a/docker/grafana/Dockerfile.grafana
+++ b/docker/grafana/Dockerfile.grafana
@@ -1,7 +1,4 @@
 FROM grafana/grafana-oss:10.4.2
 
-# Install the Redis datasource plugin
-RUN grafana-cli plugins install redis-datasource
-
 # Copy the datasource configuration
 COPY docker/grafana/datasources.yml /etc/grafana/provisioning/datasources/datasources.yml
\ No newline at end of file
diff --git a/docker/grafana/datasources.yml b/docker/grafana/datasources.yml
index 35bd6dc..19d426b 100644
--- a/docker/grafana/datasources.yml
+++ b/docker/grafana/datasources.yml
@@ -7,4 +7,16 @@ datasources:
     isDefault: true
     editable: true
     jsonData:
-      httpMethod: POST
\ No newline at end of file
+      httpMethod: POST
+  - name: postgres
+    type: postgres
+    access: proxy
+    url: postgres:5432
+    jsonData:
+      database: meshtastic
+      sslmode: "disable"
+    user: postgres
+    secureJsonData:
+      password: postgres
+    isDefault: false
+    editable: true
\ No newline at end of file
diff --git a/docker/postgres/init.sql b/docker/postgres/init.sql
index 92321fb..7d16017 100644
--- a/docker/postgres/init.sql
+++ b/docker/postgres/init.sql
@@ -28,3 +28,27 @@ CREATE TABLE IF NOT EXISTS client_details
     role        VARCHAR,
     mqtt_status VARCHAR default 'none'
 );
+
+CREATE TABLE IF NOT EXISTS node_graph
+(
+    node_id                 VARCHAR PRIMARY KEY,
+    last_sent_by_node_id    VARCHAR,
+    last_sent_at            TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    broadcast_interval_secs INTEGER,
+    FOREIGN KEY (node_id) REFERENCES client_details (node_id)
+);
+
+CREATE TABLE IF NOT EXISTS node_neighbors
+(
+    id          SERIAL PRIMARY KEY,
+    node_id     VARCHAR,
+    neighbor_id VARCHAR,
+    snr         FLOAT,
+    FOREIGN KEY (node_id) REFERENCES client_details (node_id),
+    FOREIGN KEY (neighbor_id) REFERENCES node_graph (node_id),
+    UNIQUE (node_id, neighbor_id)
+);
+
+CREATE INDEX idx_node_neighbors_node_id ON node_neighbors (node_id);
+CREATE INDEX idx_node_neighbors_neighbor_id ON node_neighbors (neighbor_id);
+CREATE UNIQUE INDEX idx_unique_node_neighbor ON node_neighbors (node_id, neighbor_id);
diff --git a/exporter/processors.py b/exporter/processors.py
index a1ead5a..21d29d5 100644
--- a/exporter/processors.py
+++ b/exporter/processors.py
@@ -472,7 +472,47 @@ class NeighborInfoAppProcessor(Processor):
         logger.debug("Received NEIGHBORINFO_APP packet")
         neighbor_info = NeighborInfo()
         neighbor_info.ParseFromString(payload)
-        pass
+        self.update_node_graph(neighbor_info, client_details)
+        self.update_node_neighbors(neighbor_info, client_details)
+
+    def update_node_graph(self, neighbor_info: NeighborInfo, client_details: ClientDetails):
+        def operation(cur, conn):
+            cur.execute("""
+                INSERT INTO node_graph (node_id, last_sent_by_node_id, broadcast_interval_secs)
+                VALUES (%s, %s, %s)
+                ON CONFLICT (node_id) 
+                DO UPDATE SET 
+                    last_sent_by_node_id = EXCLUDED.last_sent_by_node_id,
+                    broadcast_interval_secs = EXCLUDED.broadcast_interval_secs,
+                    last_sent_at = CURRENT_TIMESTAMP
+            """, (client_details.node_id, neighbor_info.last_sent_by_id, neighbor_info.node_broadcast_interval_secs))
+            conn.commit()
+
+        self.execute_db_operation(operation)
+
+    def update_node_neighbors(self, neighbor_info: NeighborInfo, client_details: ClientDetails):
+        def operation(cur, conn):
+            new_neighbor_ids = [str(neighbor.node_id) for neighbor in neighbor_info.neighbors]
+            if new_neighbor_ids:
+                placeholders = ','.join(['%s'] * len(new_neighbor_ids))
+                cur.execute(f"""
+                    DELETE FROM node_neighbors 
+                    WHERE node_id = %s AND neighbor_id NOT IN ({placeholders})
+                """, (client_details.node_id, *new_neighbor_ids))
+            else:
+                cur.execute("DELETE FROM node_neighbors WHERE node_id = %s", (client_details.node_id,))
+
+            for neighbor in neighbor_info.neighbors:
+                cur.execute("""
+                    INSERT INTO node_neighbors (node_id, neighbor_id, snr)
+                    VALUES (%s, %s, %s)
+                    ON CONFLICT (node_id, neighbor_id) 
+                    DO UPDATE SET snr = EXCLUDED.snr
+                """, (client_details.node_id, str(neighbor.node_id), float(neighbor.snr)))
+
+            conn.commit()
+
+        self.execute_db_operation(operation)
 
 
 @ProcessorRegistry.register_processor(PortNum.ATAK_PLUGIN)