A PostgreSQL 18 extension implementing a high-performance native Labelled Property Graph (LPG) store via a custom Table Access Method, enabling graph queries directly inside PostgreSQL without a separate database.
pg_eddy delivers adjacency-aware graph storage inside PostgreSQL. Instead of storing graph data as heap tables and scanning B-tree indexes on every hop, pg_eddy uses a custom AM that places node adjacency information adjacent to node data on disk — enabling O(degree) per-hop traversal without index lookups.
Why pg_eddy over Neo4j or Apache AGE?
- One system to operate: single backup, single monitoring stack, single connection pool
- Full ACID transactions: spanning both graph and relational data in the same transaction
- Faster multi-hop queries: adjacency-follow design is 2–5× faster than AGE on MATCH patterns
- Incremental view maintenance: optional integration with pg-trickle for incrementally-maintained graph views
For a detailed feature breakdown and release history, see CHANGELOG.md. For the complete roadmap with phases, exit criteria, and design rationale, see plans/implementation_plan.md.
- PostgreSQL 18.x
- Rust 1.85+ (with
cargo) cargo-pgrx0.18
# Clone the repository
git clone https://github.com/trickle-labs/pg-eddy.git
cd pg-eddy
# Install cargo-pgrx (if not already installed)
OPENSSL_NO_VENDOR=1 cargo install cargo-pgrx --version 0.18.0 --locked
# Initialize pgrx with your PostgreSQL 18 installation
cargo pgrx init --pg18 /usr/lib/postgresql/18/bin/pg_config
# Build the extension
cd pg_eddy
cargo build --features pg18
# Run tests
cargo pgrx test pg18
# Install into your PostgreSQL instance
cargo pgrx install --release --features pg18Add to postgresql.conf:
shared_preload_libraries = 'pg_eddy'Then restart PostgreSQL:
pg_ctl restartCREATE EXTENSION pg_eddy;
SELECT pg_eddy.health_check(); -- Should return 'pg_eddy OK'SELECT pg_eddy.create_node(
ARRAY['Person'],
'{"name": "Alice", "age": 30}'::jsonb
); -- Returns node_id
SELECT pg_eddy.create_node(
ARRAY['Person'],
'{"name": "Bob", "age": 28}'::jsonb
);SELECT pg_eddy.get_node(1);
-- Returns: {"name": "Alice", "age": 30}SELECT pg_eddy.node_count();
-- Returns: 2┌─────────────────────────────────────────────────────────┐
│ Client Layer │
│ pgEddy.cypher(query, params) │ SQL / SPI interface │
└───────────────────┬─────────────────────────────────────┘
│
┌───────────────────▼─────────────────────────────────────┐
│ OpenCypher Query Engine │
│ Lexer → Parser → AST → Logical Plan → Physical Plan │
│ Pattern rewriting · Filter pushdown · Index selection │
└───────────────────┬─────────────────────────────────────┘
│
┌───────────────────▼─────────────────────────────────────┐
│ Native Graph Storage AM │
│ Node Store (custom pages) │ Edge Store (CSR pages) │
│ Property Store (inline + overflow) │
│ Label Index (B-tree) │ Rel-type Index (B-tree) │
│ Property Index (B-tree per indexed property) │
└───────────────────┬─────────────────────────────────────┘
│
┌───────────────────▼─────────────────────────────────────┐
│ Reactivity Layer (optional — pg_trickle) │
│ Graph stream tables: MATCH views, path aggregates │
│ IVM engine · DAG scheduler · CDC change capture │
└─────────────────────────────────────────────────────────┘
cd pg_eddy
cargo pgrx test pg18cd pg_eddy
cargo pgrx run pg18Then in psql:
CREATE EXTENSION pg_eddy;
SELECT pg_eddy.health_check();cd pg_eddy
cargo clippy --features pg18See justfile for common development tasks:
just build # Build the extension
just test # Run tests
just lint # Run clippy
just run # Start a development PostgreSQL instancepg_eddy targets 2–5× faster multi-hop MATCH patterns than Apache AGE on graphs that fit in shared_buffers. Per-hop traversal is O(degree) via adjacency-follow (no index lookups).
Honest trade-offs:
- Neo4j on in-memory graphs: ~5–10× faster (native memory access vs PostgreSQL buffer manager)
- For I/O-bound graphs: both systems are I/O-dominated; the gap narrows to 2–3×
- See plans/implementation_plan.md for benchmarking strategy
- CHANGELOG.md — release notes and feature highlights
- plans/implementation_plan.md — complete design document, storage layout, query engine architecture, and phased roadmap
- CONTRIBUTING.md — contribution guidelines
- Source code: pg_eddy/src/ — organized by layer (storage, catalog, cypher, etc.)
We welcome contributions! Please see CONTRIBUTING.md for guidelines, and plans/implementation_plan.md for the current phase and next priorities.
| Component | Version | Status |
|---|---|---|
| PostgreSQL | 18.x | Required |
| pgrx | 0.18 | Required |
| Rust Edition | 2024 | Required |
| Linux | Debian 11+, Ubuntu 20.04+ | Tested |
| macOS | 12+ (Intel/ARM) | Expected to work |
| Windows | WSL2 | Expected to work |
pg_eddy is licensed under the Apache License 2.0. See LICENSE for details.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Security: See SECURITY.md for responsible disclosure
pg_eddy's design draws inspiration from:
- Neo4j's native store: adjacency-aware layout and singly-linked relationship chains
- PostgreSQL's AM API: MVCC, WAL, buffer management, index integration
- OpenCypher spec: query language and TCK conformance target
- pg-trickle: incremental view maintenance and CDC integration patterns
See plans/implementation_plan.md for the detailed technical roadmap with phase gates, exit criteria, and strategic rationale.