Graph Engines
Graph Engines
Compare Ryugraph and FalkorDB wrappers
What You'll Learn
- Engine Comparison - Ryugraph vs FalkorDB capabilities
- Choosing an Engine - When to use which
- Performance Characteristics - Speed and memory tradeoffs
- Migration Between Engines - Switching wrappers
# Cell 1 — ParametersUSERNAME = "_FILL_ME_IN_" # Set your email before running# Cell 2 — Connectfrom graph_olap import GraphOLAPClientfrom graph_olap_schemas import WrapperTypeclient = GraphOLAPClient(username=USERNAME)
# Cell 3 — Provisionfrom notebook_setup import provisionpersonas, conn = provision(USERNAME)analyst = personas["analyst"]admin = personas["admin"]ops = personas["ops"]client = analyst
# Find the tutorial mapping by name (not by index — parallel CI has multiple)mappings = client.mappings.list()tutorial_mappings = [m for m in mappings if "tutorial-customer-graph" in m.name]mapping = tutorial_mappings[0] if tutorial_mappings else mappings.items[0]MAPPING_ID = mapping.idprint(f"Using mapping: {mapping.name} (id={MAPPING_ID})")Engine Overview
Ryugraph and FalkorDB
from graph_olap_schemas import WrapperType
# The WrapperType enum defines the available graph enginesprint("Available engine types:")print(f" - {WrapperType.RYUGRAPH} (in-memory, optimised for graph algorithms)")print(f" - {WrapperType.FALKORDB} (Redis-based, persistent, production-ready)")
# Ryugraph: Pure in-memory graph engine# - Fastest query execution for analytics workloads# - Rich native algorithm library (PageRank, community detection, etc.)# - Full NetworkX algorithm support# - Data lives only while the instance is running## FalkorDB: Redis-backed graph database# - Persistent storage via Redis# - Good for production serving and dashboards# - Subset of native algorithms (BFS, shortest path)# - Cypher query compatibilityFeature Comparison
Capabilities and limitations
# Terminate the shared provision instance to free capacity# (this notebook creates its own Ryugraph + FalkorDB instances)try: shared_instance = client.instances.list(search="tutorial-instance", status="running") for inst in shared_instance.items: if "tutorial-instance" in inst.name: client.instances.terminate(inst.id) print(f"Terminated shared instance {inst.id} ({inst.name})") import time; time.sleep(3)except Exception as e: print(f"Note: {e}")
# Create a Ryugraph instance (in-memory, fast algorithms)ryugraph_instance = client.instances.create_and_wait( mapping_id=MAPPING_ID, name="tutorial-ryugraph", wrapper_type=WrapperType.RYUGRAPH, timeout=300, ttl="PT1H",)print(f"Ryugraph instance: {ryugraph_instance.id} status={ryugraph_instance.status}")
# Create a FalkorDB instance (Redis-backed, persistent)falkordb_instance = client.instances.create_and_wait( mapping_id=MAPPING_ID, name="tutorial-falkordb", wrapper_type=WrapperType.FALKORDB, timeout=300, ttl="PT1H",)print(f"FalkorDB instance: {falkordb_instance.id} status={falkordb_instance.status}")
# Both engines support Cypher queries through the same connection interfaceconn_ryu = client.instances.connect(ryugraph_instance.id)conn_fdb = client.instances.connect(falkordb_instance.id)print(f"\nConnected to both engines")Algorithm Availability
Algorithms are per-instance, not per-engine type
# Algorithm discovery is per-instance via the connection object# There is NO client.instances.available_algorithms() method.
# --- Ryugraph algorithms ---ryu_native = conn_ryu.algo.algorithms()ryu_nx = conn_ryu.networkx.algorithms()
print("=== Ryugraph: Native Algorithms ===")for algo in sorted(ryu_native, key=lambda a: a["name"] if isinstance(a, dict) else a): name = algo["name"] if isinstance(algo, dict) else algo print(f" - {name}")
print(f"\n=== Ryugraph: NetworkX Algorithms ({len(ryu_nx)} available) ===")# Show first 10 for brevityfor algo in sorted(ryu_nx, key=lambda a: a["name"] if isinstance(a, dict) else a)[:10]: name = algo["name"] if isinstance(algo, dict) else algo print(f" - {name}")if len(ryu_nx) > 10: print(f" ... and {len(ryu_nx) - 10} more")
# --- FalkorDB algorithms ---fdb_native = conn_fdb.algo.algorithms()fdb_nx = conn_fdb.networkx.algorithms()
print(f"\n=== FalkorDB: Native Algorithms ===")for algo in sorted(fdb_native, key=lambda a: a["name"] if isinstance(a, dict) else a): name = algo["name"] if isinstance(algo, dict) else algo print(f" - {name}")
print(f"\n=== FalkorDB: NetworkX Algorithms ({len(fdb_nx)} available) ===")for algo in sorted(fdb_nx, key=lambda a: a["name"] if isinstance(a, dict) else a)[:10]: name = algo["name"] if isinstance(algo, dict) else algo print(f" - {name}")if len(fdb_nx) > 10: print(f" ... and {len(fdb_nx) - 10} more")
# Expected: Ryugraph typically has more native algorithms than FalkorDB.# Both engines expose NetworkX algorithms, but the exact list may differ.Choosing the Right Engine
Decision framework
Decision framework: which engine to use?
┌─────────────────────────┬─────────────────┬─────────────────┐ │ Criterion │ Ryugraph │ FalkorDB │ ├─────────────────────────┼─────────────────┼─────────────────┤ │ Storage │ In-memory only │ Redis-persisted │ │ Query speed │ Fastest │ Fast │ │ Native algorithms │ Many │ Subset (BFS, │ │ │ (PageRank, etc) │ shortest path) │ │ NetworkX algorithms │ Full support │ Full support │ │ Persistence │ None │ Yes │ │ Best for │ Analytics, │ Production │ │ │ exploration │ serving, apps │ │ Horizontal scaling │ No │ Yes (Redis) │ └─────────────────────────┴─────────────────┴─────────────────┘
Rule of thumb:
- Exploring data or running heavy algorithms? → Ryugraph
- Building a dashboard or serving API queries? → FalkorDB
- Need persistence across restarts? → FalkorDB
- Need maximum algorithm coverage? → Ryugraph
Key Takeaways
- Use
WrapperType.RYUGRAPHorWrapperType.FALKORDBwithclient.instances.create_and_wait() - Ryugraph is in-memory with the richest native algorithm set; FalkorDB is Redis-backed and persistent
- Algorithm availability is per-instance: use
conn.algo.algorithms()andconn.networkx.algorithms() - Both engines share the same Cypher query interface via
conn.query() - Choose Ryugraph for analytics/exploration, FalkorDB for production serving
# Cleanup: terminate instances created in this notebookfor inst in [ryugraph_instance, falkordb_instance]: try: client.instances.terminate(inst.id) print(f"Terminated instance {inst.id}") except Exception as e: print(f"Instance cleanup: {e}")