Okto Grafx, Ladybug and Neo4j solve different deployment and integration needs. Compare the capabilities, the boundaries and the work each can help you do.
Updated September 13, 2026 · Capabilities, not benchmarks
EMBEDDED PYTHON
Okto Grafx
For local applications that need flexible or typed graphs, composed native queries, exact values, hybrid retrieval and independent local readers and writers.
Evaluate dialect differences, pre-alpha maturity and the upgrade contract.Explore the contracts EMBEDDED ANALYTICS
Ladybug
For embedded graph analysis with rich typed data, multiple language bindings and file or external-store integrations.
Plan around its documented writable database ownership model.Ladybug documentation SHARED GRAPH SERVICE
Neo4j
For applications that connect to a graph server and need broad Cypher tooling, drivers and optional enterprise operations.
Account for server operations and CE, EE and library boundaries.Neo4j editions
Fit descriptions are architectural assessments from the cited contracts, not measured product rankings.
THE FEATURE MATRIX
Compare the details. Keep the boundaries visible.
Native features, extensions and edition-specific capabilities are labeled directly. “Not established” means the review did not verify an equivalent contract.
Reading this comparison
Grafx cells use qualified 0.0.6 development source, including the September 13 native regression and final installed Pulse qualification. These features are separate from the published 0.0.5 package. Ladybug uses 0.20.3 with 16 executed comparison scenarios plus official rolling documentation. Neo4j uses current self-managed documentation: CE is Community; EE is Enterprise. Rolling documentation is not a version-frozen conformance test; Neo4j execution remains deferred. The latest qualification reports supersede pending labels in earlier chronological checkpoints.
Not availablePartialMeetsNot applicable
Flags refer to the capability in each row. Yellow includes narrower scope, an extension, a separate library or edition-dependent availability. Gray marks descriptive attributes that are not scored. A capability not established by this review is not treated as proof of absence; read the cell and its source.
On smaller screens, scroll horizontally to compare all three products.
Feature comparison: validated Grafx 0.0.6 development, Ladybug 0.20.3 and current Neo4j self-managed editions
CAPABILITY
Okto Grafx0.0.6 · qualified development
Ladybug0.20.3 · bounded execution + docs
Neo4jCurrent docs · CE / EE
Architecture & transactions
Embedded Python database
Meets
Embedded Python library. In-memory or persistent local storage; no database server.
Concurrent connections share one writable Database object. Direct file owners: one writable object OR multiple read-only objects. See the multiwrite note below.
Ordered clauses, correlated OPTIONAL MATCH, EXISTS, bounded named paths and up to 64 UNION / UNION ALL branches. All 3,896 required V3 cases pass; one explicit upstream lists-of-maps divergence prevents a full conformance claim.
Cypher dialect with macros and typed graphs. The pinned 0.20.3 execution refused selected scoped CALL forms and produced different path multiplicities; neither dialect is established as a superset.
Explicit typed tables coexist with flexible unlabeled nodes, dynamic properties and native ANY values. Node labels and relationship types may share a name; identities remain qualified by store, table and kind.
Structured property graph with declared node and relationship tables. Typed nested columns are supported; this is a different model from flexible, unlabeled entities.
Zero, one or multiple versioned labels on one stable node identity. CREATE/MERGE, SET/REMOVE, membership, retained history, copy and transfer/resume preserve labels. Physical typed constraints still apply.
The pinned 0.20.3 multiple-label scenario refused label SET. Existing node IDs stayed unchanged; this result concerns mutable labels, not all graph update support.
Returning and unit writing CALL, explicit/wildcard/leading-WITH imports, nested reads and updating UNION. Private branch effects share one outer statement rollback boundary; no inner commits.
DATE, LOCALTIME, TIME, LOCALDATETIME, DATETIME and DURATION with constructors, clocks, arithmetic and durable native values. Equality keys are supported; ordered indexes for these families are refused.
Native DATE, timestamp families and INTERVAL. The pinned date scenario matched the expected calendar value; families and timezone semantics still require mapping.
DECIMAL(p,s), up to 38 digits, with exact arithmetic, aggregates, ordering and typed equality-index seeks. Native history/copy and decimal128 columnar exchange preserve precision/scale. No decimal ordered index.
Native DECIMAL. The pinned storage scenario preserved 1.2500 as DECIMAL(12,4), using an explicitly declared CAST adaptation without a floating-point intermediate.
Typed LIST/MAP/ARRAY/STRUCT with nested nullability and exact descriptors, plus heterogeneous ANY values and lists of maps. Native, text and columnar consumers preserve supported types; collection property indexes are refused.
Homogeneous lists of simple property types can be stored. General maps, heterogeneous collections and lists containing null are not supported as stored properties.
Trusted typed read/write/unit procedures with native value/entity signatures, nested calls and explicit transaction-scoped query/schema authority. Revocation and shared budgets apply; external side effects are not rolled back.
Python and C++ user-defined functions are documented. An equivalent transaction-scoped writing/schema procedure authority contract was not established in this review.
Custom JVM procedures with READ, WRITE, SCHEMA and DBMS modes. Registration, permissions and execution contracts differ from embedded Python callbacks.
Native snapshot-bound weighted BM25 over node/relationship properties, with atomic analyzer/options replacement. New searches use the current analyzer with their owning data snapshot.
Bounded prefix, exact phrases, persisted token positions and ordered proximity (slop). No phrase/prefix combination, character offsets, stemming or stopword configuration.
Lucene query syntax includes quoted exact matches and analyzers. Its visibility and returned evidence differ from the Grafx snapshot and token-position contract.
Bounded CSV/JSONL/SQLite plus optional Arrow, Pandas, Polars, Parquet and NetworkX. Exact decimal and typed nested transport preserve descriptors with atomic imports; supported consumers and refusals are explicit.
Attached local catalogs, aliases, permissions and workspace resolution. Each transaction belongs to one store; no cross-store joins, edges or distributed COMMIT.
Resumable fresh-store transfer and bounded existing-target copy with durable receipts and optional endpoint closure. Qualified consumers preserve multiple labels, flexible/no-PK identities, relationship groups and expanded types. Historical transfer requires explicit current-only semantics.
Opt-in as-of reads, versions and graph/schema/property diffs; optional temporal index, retention, pins and quiescent physical compaction. Captures history from activation; no valid time or full bitemporality.
CDC is available in Enterprise and specified Aura tiers. Change capture does not establish native arbitrary historical graph snapshots or equivalent diffs.
Python API, JSON CLI inventories/search, JS/TS subprocess recipe and script-free offline HTML snapshots. No native network driver or interactive GUI. Pulse supplies its own UI/MCP.
These additions are included in the 0.0.6 comparison above. They have completed local acceptance and remain separate from the published 0.0.5 package.
NATIVE + CONSUMER QUALIFICATION
Current qualification covers the expanded language, labels, exact types, trusted procedures and their consumers. The installed label-format matrix records 36 native scenarios and 36 transfer worker checks. New native formats require compatible participants; a passing development build is not a release or production-maturity guarantee. Read the upgrade contract.
01
A graph that can change shape
Classify the same entity with multiple labels, add flexible properties and keep typed models where your application needs strict constraints. Preserve identity through label changes, history and copies.
Flexible storage does not bypass physical typed constraints. Nested values and ANY properties do not imply arbitrary property-index support.
Express correlated lookups, EXISTS, named paths, conditional MERGE actions and returning or unit writing subqueries. Combine up to 64 UNION branches under one statement rollback boundary.
Scoped imports, resource bounds and native error semantics apply. No inner transaction commits or promise that every vendor query runs unchanged.
Store exact decimal amounts, calendar and duration values, and typed nested records. Carry supported descriptors through native history, copies, JSON/text and Arrow/Pandas/Polars/Parquet exchange.
Decimal precision is bounded at 38 digits. Consumer support varies by type; decimal ordered indexes and collection property indexes are refused explicitly.
Register typed procedures that read, write or create permitted schema within the owning transaction. Share query budgets and pass native entities and values without losing their identity.
Callbacks are trusted application code, not sandboxed plugins. Authority expires with its invocation; external side effects have no rollback guarantee.
Inspect retained nodes, relationships and schema at a commit or timestamp. Compare changes between two commits.
Opt-in from activation; bounded retention. Diffs compare retained commits from the same store. System time only, not valid-time or full bitemporal queries.
System-time history is not full bitemporality. Native HTTP/MCP services, distributed transactions and HA replication remain outside Grafx’s delivered engine scope.
A DECISION YOU CAN VERIFY
Start with your workload.
Validate your queries, read/write ownership, retrieval quality, recovery and upgrade behavior. No common-dataset benchmark was run for this comparison, so it makes no speed or throughput ranking.