rugmuncher-backend / backend /docs /adr /0002-why-five-databases.md
RMI Platform
feat(v3): ship new system β€” skip _legacy_main, mount v1 routers
3cf0daf
|
Raw
History Blame Contribute Delete
2.69 kB
# ADR-0002: Use 5 specialized databases instead of one general-purpose store
- **Status**: Accepted
- **Date**: 2026-06-21
- **Decider**: @cryptorugmunch
## Context
RMI stores data across multiple categories:
| Category | Volume | Access pattern | Query shape |
|----------|--------|----------------|-------------|
| User data, wallets, alerts (relational) | 252K rows | CRUD + joins | SQL |
| Cache, rate limits, labels (key-value) | 82K keys | O(1) get/set | key lookup |
| Analytics, cost tracking, legacy logs (columnar) | 83K rows (will grow) | Aggregate scans | SQL OLAP |
| Wallets, tokens, transfers (graph) | 20K nodes | Multi-hop traversal | Cypher |
| Embeddings, semantic search (vector) | 75 vectors | k-NN similarity | HNSW |
A single Postgres would not serve all five patterns efficiently:
- Graph queries in Postgres require recursive CTEs that scale O(nΒ²)
- Vector search in Postgres uses pgvector but is 10Γ— slower than Qdrant
- OLAP scans in Postgres lock transactional tables
- Cache in Postgres requires manual eviction policies
## Decision
Use five specialized databases:
1. **Postgres 16** β€” source of truth (relational data)
2. **Redis 7.2** β€” cache, rate limits, queues
3. **ClickHouse** β€” OLAP, cost tracking, deprecation logs
4. **Neo4j 5** β€” graph queries (cross-chain wallet flows)
5. **Qdrant** β€” vector search (RAG semantic retrieval)
Plus DuckDB for local analytics on the laptop (single-file, no server).
## Alternatives Considered
- **All Postgres (with extensions)**: pgvector + recursive CTEs + pg_partman. Rejected β€” graph perf unacceptable, OLAP competes with transactional load.
- **Single MongoDB**: Rejected β€” weak analytics, no vector search, no graph.
- **DynamoDB + S3 + Neptune**: Rejected β€” vendor lock-in, high cost, no vector.
- **Drop Neo4j, use ClickHouse**: Possible. Rejected for now β€” graph queries on 84K nodes are O(seconds), not O(minutes).
## Consequences
- **Positive**: Each DB does one job well. Optimized for its access pattern. Can scale independently.
- **Negative**:
- 5 things to back up, monitor, patch, version
- New engineer onboarding: must learn 5 DBs
- Cross-DB queries require application-level joins
- 5 different query languages (SQL, Redis commands, SQL/CH, Cypher, REST)
- **Mitigations**:
- DataBus facade unifies access (`app/databus/core.py`)
- Container memory limits set on all 5 DB containers
- Each DB has a runbook in `docs/runbooks/`
## Re-evaluation triggers
- Neo4j license change (currently community edition, free)
- Postgres + pgvector catching up to Qdrant perf (current gap: ~10Γ—)
- ClickHouse memory pressure requiring Memgraph substitution