Neo4j logoEcosystem

Count the Homes of One Entity

Pick a single entity in your organization — `Customer`, `Patient`, `Instrument`, whatever your domain calls the thing everything else hangs off — and count where it physically lives. In a serious estate the count is rarely below four. It is a label in Neo4j. It is a table in a warehouse. It is a subject in a schema registry. It is a model in a transformation project, a form in a capture system, a class in an application's JSON Schema.

Count the Homes of One Entity

Pick a single entity in your organization — Customer, Patient, Instrument, whatever your domain calls the thing everything else hangs off — and count where it physically lives. In a serious estate the count is rarely below four. It is a label in Neo4j. It is a table in a warehouse. It is a subject in a schema registry. It is a model in a transformation project, a form in a capture system, a class in an application's JSON Schema.

One meaning, several physical shapes, each with its own dialect for expressing constraints. That is the landscape a graph database sits inside, and it explains why "how do we manage the graph schema" is almost never the real question. The real question is where meaning lives when it must hold across systems that agree on nothing else.

First, the neighbourhood right next to the database

The CoreModels Neo4j connector is deliberately built out of Neo4j's own materials rather than alongside them.

Extraction uses what the ecosystem already ships. CALL apoc.meta.schema() — the APOC library's sampled schema inventory — produces the required meta_schema artifact. SHOW CONSTRAINTS produces the optional constraints artifact, which refines the sampled uniqueness and existence flags with what the database is genuinely enforcing, including node-key constraints that imply both. Two statements, runnable from Neo4j Browser or cypher-shell, no installation.

Enforcement flows back through the ecosystem's own primitive: a generated Cypher script of uniqueness and existence constraints plus indexes, written IF NOT EXISTS, the same statements a careful DBA would hand-write — produced from a governed definition instead of from memory. Where editions differ, the script says so: property-existence constraints require Neo4j Enterprise, and that note is in the file rather than in a footnote nobody reads.

This matters because ecosystem tools outlive integrations. APOC and Cypher constraints will be documented and understood by every Neo4j engineer you hire. An integration that speaks them is one your team can reason about with knowledge it already has. It has a practical consequence too: the parser tolerates shape variation across APOC versions — a bare object, a {"value": ...} wrapper, or a single-row array all parse — and we say out loud that APOC output details vary, so validate against your version on a first run.

Then, one connector among many

Zoom out and Neo4j is one of thirteen vendor connectors, sitting behind exactly the same verbs as dbt, Snowflake, Databricks Unity Catalog, Google BigQuery, Microsoft Fabric, AWS Glue, Confluent Schema Registry, Airbyte, Apache Airflow, Salesforce, REDCap and cBioPortal. The vendor key neo4j is a segment in the route; swap it for snowflake and the same import, audit, re-audit, generate, history, badge and status verbs answer.

That symmetry is structural, not cosmetic. Every connector parses into one neutral estate model — datasets with fields, normalized checks, and lineage — and every connector is pure: it parses artifacts, maps native types, generates artifacts and contributes its own audit rules, and never touches graph storage itself. All the graph writing happens in shared, vendor-neutral services. That is why the audit engine that catches a retyped Snowflake column is the same engine, unmodified, that catches a retyped Neo4j property.

The design question we had to get right was whether a graph could pass through a table-shaped neutral model without being flattened into something it is not. The answer is the relationship mapping: an outgoing typed relationship becomes a governed reference, named after the relationship type, pointing at its target label — the graph-native foreign key, kept first-class. Incoming directions are not duplicated on the target side, and relationship-type entries from APOC are counted and skipped because the node-side view already carries them. Where the graph is genuinely more expressive than the neutral model — multi-target relationships, points, durations — the difference is recorded as metadata and lossiness rather than quietly discarded. Neutrality does not mean pretending every system is the same. It means translating faithfully and declaring what did not fit.

What the graph's meaning composes with

Once a Neo4j schema is governed, it stops being graph-team-only knowledge. The same governed model encodes out to the languages the rest of the estate speaks: JSON Schema for the application team, SQL DDL for the warehouse, Avro and Protobuf for the streaming platform, LinkML and OWL for the semantics and ontology crowd, ShEx, JSON-LD, and data-contract formats. We implement these open specifications as published — the Bitol Open Data Contract Standard, Apache Ossie's semantic model, LinkML — because the point of standing on a standard is that your meaning leaves in a form other tools accept without a translation layer you have to maintain. We implement them; we do not speak for the people who maintain them.

It composes across vendors, too. The vendor identity of every governed node is itself recorded as a mapping — the standard neo4j, the URI being the label — so the graph's own vocabulary survives every export. When two estates hold the same physical relation, a reconciliation verb links them as one entity with reciprocal same-as assertions written through the same carrier, so the connection is a recorded fact rather than a naming coincidence. And when a governed node should carry an ontology term, an advisory lookup against the public EMBL-EBI Ontology Lookup Service proposes candidate IRIs that a human then binds — through that same carrier, which is why a binding made once shows up in the LinkML and OWL exports without further work.

Why neutrality is the load-bearing choice

It would have been easier to build a Neo4j-shaped governance tool. We did not, because meaning outlives runtimes. Teams re-platform warehouses, swap streaming vendors, and add a graph database midway through a program. Every one of those migrations is a governance catastrophe if the governance lived inside one vendor's catalog. A neutral model is the only position from which "the Customer entity" stays one thing while its physical homes multiply and change underneath it.

Neutrality also keeps the incentives honest. We have no stake in which database wins. The Neo4j connector's job is to make Neo4j better at being Neo4j — enforced constraints, documented meaning, auditable drift — not to wrap it, proxy it, or sit in front of its query path. In retrieval-heavy architectures that division gets sharper rather than blurrier: the graph operationalizes traversal and indexing, while the governed model holds what the structure means, and each side is checked against the other on a cadence you set. Your graph database was never meant to be the system of record for meaning across an estate it cannot see.

Our Neo4j quickstart shows the whole exchange: two exported artifacts in, a governed model and a Cypher constraint script out.