1- # PostgreSQL Integration for MeshInfo
1+ # PostgreSQL Storage
22
3- This document describes the PostgreSQL dual-write implementation for MeshInfo.
4-
5- ## Overview
6-
7- MeshInfo now supports PostgreSQL as an alternative storage backend alongside JSON files. The implementation follows a ** dual-write pattern** where:
8-
9- 1 . All writes go to ** both** JSON files and PostgreSQL (when enabled)
10- 2 . Reads can come from ** either** JSON or PostgreSQL (configurable)
11- 3 . JSON files remain authoritative during the transition period
12- 4 . PostgreSQL failures never block JSON operations
3+ MeshInfo uses PostgreSQL as its storage backend. This document covers configuration, schema, and operational guidance.
134
145## Configuration
156
167Add the following to your ` config.toml ` :
178
189``` toml
1910[storage ]
20- read_from = " json "
21- write_to = [" json " , " postgres" ]
11+ read_from = " postgres "
12+ write_to = [" postgres" ]
2213
2314[storage .postgres ]
24- enabled = false
15+ enabled = true
2516host = " postgres"
2617port = 5432
2718database = " meshinfo"
2819username = " postgres"
29- password = " password "
30- min_pool_size = 5
31- max_pool_size = 20
20+ password = " your_password "
21+ min_pool_size = 1
22+ max_pool_size = 5
3223```
3324
3425### Configuration Options
3526
36- - ** ` read_from ` ** : ` "json" ` or ` "postgres" ` - Controls where data is loaded from on startup
37- - ** ` write_to ` ** : Array of ` ["json", " postgres"] ` - Controls which backends receive writes
38- - ** ` postgres.enabled ` ** : ` true ` or ` false ` - Master switch for PostgreSQL functionality
39- - ** ` postgres.host ` ** : Database server hostname
27+ - ** ` read_from ` ** : Must be ` "postgres" `
28+ - ** ` write_to ` ** : Must be ` ["postgres"] `
29+ - ** ` postgres.enabled ` ** : Must be ` true `
30+ - ** ` postgres.host ` ** : Database server hostname (use ` "localhost" ` if not using Docker)
4031- ** ` postgres.port ` ** : Database server port (default: 5432)
4132- ** ` postgres.database ` ** : Database name
4233- ** ` postgres.username ` ** : Database user
4334- ** ` postgres.password ` ** : Database password
44- - ** ` postgres.min_pool_size ` ** : Minimum connection pool size (default: 5 )
45- - ** ` postgres.max_pool_size ` ** : Maximum connection pool size (default: 20 )
35+ - ** ` postgres.min_pool_size ` ** : Minimum connection pool size (default: 1 )
36+ - ** ` postgres.max_pool_size ` ** : Maximum connection pool size (default: 5 )
4637
4738## Database Schema
4839
49- The PostgreSQL schema stores data in a relational structure while maintaining compatibility with the JSON format . Key tables include :
40+ The schema is automatically created on first run . Key tables:
5041
5142- ** ` nodes ` ** : Core node information (ID, name, hardware, status)
5243- ** ` node_positions ` ** : Historical position data
@@ -57,147 +48,48 @@ The PostgreSQL schema stores data in a relational structure while maintaining co
5748- ** ` chat_messages ` ** : All chat messages
5849- ** ` traceroutes ` ** : Complete traceroute history (JSONB payloads)
5950
60- The schema is automatically created on first run when PostgreSQL is enabled.
61-
62- ## Migration
63-
64- To migrate existing JSON data to PostgreSQL:
65-
66- ### Step 1: Enable PostgreSQL
67-
68- Update ` config.toml ` :
69- ``` toml
70- [storage .postgres ]
71- enabled = true
72- ```
73-
74- ### Step 2: Start PostgreSQL
75-
76- If using Docker Compose, PostgreSQL should already be running. Otherwise, start it:
77-
78- ``` bash
79- docker-compose up -d postgres
80- ```
81-
82- ### Step 3: Run Migration Script
83-
84- ``` bash
85- python scripts/migrate_json_to_postgres.py
86- ```
87-
88- The script will:
89- - Connect to PostgreSQL
90- - Create the database schema if needed
91- - Import all nodes, chat messages, telemetry, and traceroutes from JSON files
92- - Preserve all historical data
93- - Report progress and any errors
94-
95- ### Step 4: Enable Dual-Write
96-
97- Update ` config.toml ` to write to both backends:
98- ``` toml
99- [storage ]
100- read_from = " json"
101- write_to = [" json" , " postgres" ]
102-
103- [storage .postgres ]
104- enabled = true
105- ```
106-
107- ### Step 5: Verify Data Consistency
108-
109- - Monitor logs for any PostgreSQL write errors
110- - Spot-check the API to ensure data is identical
111- - Compare record counts between JSON and PostgreSQL
112-
113- ### Step 6: Switch to PostgreSQL Reads
114-
115- Once confident in data consistency, switch to direct PostgreSQL queries:
116- ``` toml
117- [storage ]
118- read_from = " postgres"
119- write_to = [" json" , " postgres" ]
120- ```
121-
122- ** Important** : When ` read_from: "postgres" ` , the API queries PostgreSQL directly without loading data into memory. This provides:
123- - Lower memory footprint
124- - Always up-to-date data from the database
125- - Better scalability for large datasets
126-
12751## Architecture
12852
12953### Write Flow
13054
131551 . MQTT message received
132562 . Data stored in memory (MemoryDataStore) for internal use
133573 . ** Real-time write to PostgreSQL** (non-blocking, errors logged)
134- 4 . Periodic write to JSON files (every 300 seconds by default)
13558
136- ### Read Flow (JSON mode)
59+ ### Read Flow
13760
138611 . Application starts
139- 2 . Data loaded from JSON files into memory
140- 3 . API serves from in-memory data structures
141- 4 . Fast response times with full dataset in RAM
142-
143- ### Read Flow (PostgreSQL mode)
144-
145- 1 . Application starts
146- 2 . PostgreSQL connection established (no data loaded into memory)
147- 3 . ** API queries PostgreSQL directly** for each request
62+ 2 . PostgreSQL connection established
63+ 3 . API queries PostgreSQL directly for each request
148644 . Lower memory footprint, always current data
149- 5 . Efficient queries with proper indexing
15065
15166### Error Handling
15267
15368- PostgreSQL write failures are logged but ** never block** application execution
154- - If PostgreSQL reads fail, the system automatically falls back to JSON
15569- Connection pool handles transient network issues
15670- Failed writes are logged for manual investigation
15771
158- ## Data Retention
159-
160- - ** JSON files** : Limited history (configurable via file-based rotation)
161- - ** PostgreSQL** : Unlimited history (all records preserved indefinitely)
162-
16372## Performance Considerations
16473
16574### Real-time Writes
16675
167- All writes to PostgreSQL happen in real-time as data arrives from MQTT. This ensures:
168- - Minimal data loss in case of application crash
169- - Up-to-date data in PostgreSQL at all times
170- - No batch write delays
76+ All writes happen in real-time as data arrives from MQTT, ensuring minimal data loss on crash.
17177
17278### Connection Pooling
17379
174- The implementation uses asyncpg connection pooling (5-20 connections by default) to handle concurrent writes efficiently .
80+ asyncpg connection pooling handles concurrent writes efficiently. Tune ` min_pool_size ` and ` max_pool_size ` based on your load .
17581
17682### Indexing
17783
178- Key indexes are created on:
179- - Node IDs
180- - Timestamps
181- - Foreign key relationships
182-
183- This ensures fast queries even with large datasets.
184-
185- ## Backwards Compatibility
186-
187- The implementation fully supports:
188-
189- 1 . ** Running without PostgreSQL** : Simply don't enable it in config
190- 2 . ** Downgrading to JSON-only** : Set ` postgres.enabled: false ` and restart
191- 3 . ** JSON as authoritative source** : Keep ` read_from: "json" ` during transition
84+ Key indexes are maintained on node IDs, timestamps, and foreign key relationships for fast queries even with large datasets.
19285
19386## Monitoring
19487
19588PostgreSQL operations are logged at INFO and ERROR levels:
19689
19790```
198- INFO: PostgreSQL connection pool established
199- INFO: Loaded 1234 nodes from PostgreSQL
200- ERROR: Failed to write node abc123 to PostgreSQL: connection timeout
91+ INFO: PostgreSQL mode: Data will be queried directly from database
92+ ERROR: Failed to write node abc123 to Postgres: connection timeout
20193```
20294
20395Monitor these logs to ensure healthy operation.
@@ -206,54 +98,39 @@ Monitor these logs to ensure healthy operation.
20698
20799### Connection Failures
208100
209- If PostgreSQL connection fails:
210- 1 . Check that PostgreSQL container is running
211- 2 . Verify connection settings in config.toml
212- 3 . Check network connectivity
213- 4 . Review PostgreSQL logs
101+ If PostgreSQL connection fails on startup, MeshInfo will log the error and exit. Check:
214102
215- The application will continue running with JSON-only mode.
103+ 1 . PostgreSQL container/service is running
104+ 2 . Connection settings in ` config.toml ` are correct (` host ` , ` port ` , ` username ` , ` password ` )
105+ 3 . Network connectivity between MeshInfo and the database
216106
217107### Data Inconsistencies
218108
219- To verify data consistency:
220-
221- 1 . ** Count records** :
222- ``` sql
223- SELECT COUNT (* ) FROM nodes;
224- SELECT COUNT (* ) FROM chat_messages;
225- SELECT COUNT (* ) FROM telemetry;
226- SELECT COUNT (* ) FROM traceroutes;
227- ```
228-
229- 2 . ** Compare with JSON** via API endpoints
109+ To verify record counts:
230110
231- 3 . ** Check for write errors** in application logs
111+ ``` sql
112+ SELECT COUNT (* ) FROM nodes;
113+ SELECT COUNT (* ) FROM chat_messages;
114+ SELECT COUNT (* ) FROM telemetry;
115+ SELECT COUNT (* ) FROM traceroutes;
116+ ```
232117
233- ### Migration Issues
118+ ### Migrating from JSON Storage
234119
235- If migration fails:
236- 1 . Check PostgreSQL logs for errors
237- 2 . Verify JSON files are valid and readable
238- 3 . Ensure sufficient disk space
239- 4 . Try migrating data types individually (modify script)
120+ If you are upgrading from an older version that used JSON file storage, a one-time migration script is available:
240121
241- ## Future Enhancements
122+ ``` bash
123+ docker exec -it meshinfo-meshinfo-1 python3 scripts/migrate_json_to_postgres.py
124+ ```
242125
243- Potential future improvements:
244- - Write-ahead log for failed PostgreSQL writes
245- - Automatic retry logic with exponential backoff
246- - Data validation and integrity checks
247- - Performance metrics and monitoring
248- - Support for read replicas
249- - Automatic failover between backends
126+ This reads your existing JSON data files and imports them into PostgreSQL. Run it once before switching to PostgreSQL-only mode.
250127
251128## Security
252129
253130- Use strong passwords for PostgreSQL
254- - Consider using SSL/TLS for database connections in production
131+ - Consider SSL/TLS for database connections in production
255132- Restrict database access via network policies
256- - Regular backups of PostgreSQL data
133+ - Set up regular PostgreSQL backups (e.g., ` pg_dump ` )
257134- Keep PostgreSQL updated with security patches
258135
259136## Support
0 commit comments