Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring Data Neo4j tenant lookup: constrain before traversing

Last updated: 1 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

A tenant-scoped graph read should select a bounded root through an index before expanding relationships.

The traversal starts at the predicate

A dispatch screen fetches one shipment and its latest events. Matching every Shipment node and filtering the tenant late can traverse much more graph than the response needs. Store tenantId and shipmentId on the root and back the pair with a uniqueness constraint. That enforces the business key and gives the planner an indexed entry point. Tenant identity still comes from authentication, not a caller's free-form query parameter.

Measure the plan

Use EXPLAIN and PROFILE on the actual query and data distribution. Check for an index seek on the constrained root, row counts after each relationship expansion, and unexpected eager operations. An index does not guarantee a good plan for an unbounded variable-length path. Require a maximum hop count and output cap.

Test duplicate and cross-tenant cases

Insert the same shipmentId under two tenants and confirm both work. Attempt a duplicate within one tenant and require rejection. Request one tenant's shipment using another tenant's principal and assert no node or relationship properties escape.

Implementation sketch

cypher
CREATE CONSTRAINT shipment_tenant_key IF NOT EXISTS
FOR (shipment:Shipment)
REQUIRE (shipment.tenantId, shipment.shipmentId) IS UNIQUE;

MATCH (shipment:Shipment {tenantId: $tenantId, shipmentId: $shipmentId})
MATCH (shipment)-[:HAS_CHECKPOINT]->(checkpoint:Checkpoint)
RETURN checkpoint ORDER BY checkpoint.recordedAt DESC LIMIT 47;

Cost and verification

The constraint costs storage and write maintenance, while avoiding scans on bounded reads. Relationship fan-out can still dominate; index the entry point and cap the expansion.

Common Mistakes

  • Do not use an internal graph ID as tenant authorization.
  • Do not assume an indexed root makes an unlimited traversal cheap.
  • Do not trust a tenant ID supplied by the requester without binding it to the principal.

Read next

Spring Data Neo4j custom query: return one coherent root record, Spring JWT tenant claims: reject missing or malformed ownership before conversion, Spring Data MongoDB tenant uniqueness: enforce it in an index.

spring
spring-boot
data-transactions
neo4j-indexed-tenant-lookup
Storage details