At least 10 must-have queries are available as concrete paths or aggregates that guide node, relationship and index decisions.
Property Graph Schema Design
Prerequisite
What needs to be finished first
Preparation
What needs to be ready before start
Whiteboard or diagram tool (arrows.app, draw.io, Cypher Workbench); sandbox DB (Neo4j Aura Free, Memgraph, Neptune Local); sample data CSVs; migration tool (Liquibase Graph, Neo4j Migrations); issue tracker.
One graph modeler (lead); one to two engineers who will later write queries; one domain expert for terms and cardinalities; one data-source owner for sample data.
Use cases and query patterns; estimated data volumes (nodes, relationships, growth); SLA for latency and throughput; selected graph store; source systems and ETL status.
4-8 h initial, then iterative hour slices
Sandbox DB ready. Sample data in CSV. Top 10 queries prepared as pseudo-Cypher. Whiteboard with columns: Use Case, Query, Node, Relationship, Property, Index.
Core question
The one question this method answers
Which node labels, relationship types, properties and indexes create a schema that answers prioritized queries performantly and scales with data growth?
Flow
Marker: Phase
| Step | Duration | Action | Hint |
|---|---|---|---|
1Phase 1: Query inventory | 45-60 min | Formulate all use-case queries as concrete Cypher/Gremlin sketches. Per query: expected latency, frequency, filter criteria, path depth. Prioritize top 10. | If queries remain vague ("show all relationships"), go back to use-case level. Generic queries lead to generic, often wrongly indexed schemas. |
2Phase 2: Nodes and relationships | 60-90 min | Identify entities as node labels (singular, PascalCase). Identify relationships as directed relationship types (UPPER_CASE, verb). Document cardinality and path role per relationship. | If an attribute has many unique values and filtering matters (for example tags), it can become its own node instead of a property. Pure property filters on cardinality > 10k become slow without index. |
3Phase 3: Properties and data types | 45-60 min | List properties per node and relationship: name, type (string/int/datetime/list), required/optional, default. Mark temporal validity, source and confidence as separate properties. | Properties on relationships are powerful (for example weight, validFrom), but unindexed in many engines. Anyone filtering on relationship property should check engine docs. |
4Phase 4: Indexes and constraints | 30-45 min | Identify the start point in the graph for each top query. Set indexes there (unique constraints for IDs, range indexes for filters, fulltext for search). Document constraints for data integrity. | Index without query is overhead. Query without constraint is risk. At least every top-10 query must have an index-supported start point. |
5Phase 5: Validation in sandbox | 60-90 min | Create schema in sandbox DB (CREATE CONSTRAINT, CREATE INDEX). Import sample data. Run top-10 queries, check EXPLAIN/PROFILE. Document latency and plan quality. | If EXPLAIN shows AllNodesScan, an index is missing or query must be reformulated. Never go to production without plan check. |
6Phase 6: Migration script | 30-45 min | Capture schema in migration file (idempotent, with version number). Sample queries as test suite. Export schema diagram. Commit both to repo. | Schema in diagram is communication; schema in migration is truth. Anyone maintaining only a diagram has a schema nobody can reproduce. |
Artifact
What comes out at the end
Repo directory with schema diagram (arrows.app export, PNG, JSON), node-and-relationship catalog (markdown table), migration script (idempotent), sample data loader, sample queries suite and index plan with rationale.
Migration files numbered (V001__init.cypher, V002__add_team.cypher). Diagram JSON next to code. Schema version stored in DB as (:SchemaMeta {version: '1.2.0'}). Breaking changes as major increment.
- arrows.app for diagrams (JSON export)
- Cypher Workbench (Neo4j) with schema designer
- draw.io with property-graph stencils
- Liquibase Graph or Neo4j Migrations for versioning
property-graph-schema-design-working-template.md
Compact working template for Property Graph Schema Design with context, input, output artifacts, and next step.
Property Graph Schema Design Canvas
Context
What is this method used for?
Core question
Which question should be answered at the end?
Input
Which data, observations, or materials are available?
Working area
- Area 1:
- Area 2:
- Area 3:
- Relationships / patterns:
Output artifacts
- Schema diagram:
- Node and relationship catalog:
- Index plan:
- Migration scripts:
- Sample queries:
Open questions
- ...
Next step
Owner, date, success signal.
Example output
Concrete filled scenario, fictional example
property-graph-schema-design-beispiel.md
Concrete filled scenario, fictional example
Property Graph Schema - Service Dependency Graph (v0.4, 2026-05-18)
Top queries (excerpt):
- Q1: Direct downstream dependencies of a service. Latency target < 50 ms.
- Q2: Transitive dependencies up to depth 3. < 200 ms.
- Q5: All services of a team with their DB cluster. < 100 ms.
Nodes:
Service {name (unique), tier, status, createdAt}Team {name (unique), email}Database {name (unique), type, region}
Relationships:
(Service)-[:DEPENDS_ON {weight, since}]->(Service)(Team)-[:OWNS]->(Service)(Service)-[:USES]->(Database)
Indexes:
- UNIQUE CONSTRAINT on Service.name, Team.name, Database.name
- RANGE INDEX on Service.tier (used by Q3)
Plan check Q2 (depth 3): NodeIndexSeek + VarLengthExpand, 45 ms at 12k nodes / 38k edges. OK.
Migration: V004__add_database.cypher. Schema version in DB updated to 0.4.
Pitfalls
Recognize symptoms and steer against them
Schema without query reference
Schema looks clean in diagrams, but EXPLAIN shows AllNodesScan on top queries.
Plan check per top query in Phase 5. Sharpen indexes or adapt schema shape (for example promote property to node). Design schema next to queries, not detached.
Too generic relationship types
All relationships are called RELATED_TO or LINK; queries must filter on properties, performance suffers.
Name relationships with verb semantics (DEPENDS_ON, OWNS, USES). At least one relationship type per domain statement.
Properties on wrong layer
Frequently filtered values sit as properties in nodes with 100k+ instances, no index, query slow.
Model high-cardinality filter properties as nodes or add RANGE/POINT/FULLTEXT index. Check engine docs for index types.
No constraint, duplicate data
Multiple service nodes with same name, paths duplicated, queries inconsistent.
UNIQUE CONSTRAINTS on natural IDs before first data import. ETL fails on violation, data quality remains intact.
Diagram diverges from migration
Schema in arrows.app diagram shows four nodes, database has five. Nobody knows current state.
Migration script is source of truth. Diagram is generated from migrations before release or kept synchronized by pull request. Inconsistencies as CI check.
Manual schema migrations
Schema changes are applied manually in every environment, staging and prod diverge.
Use tooling such as Liquibase Graph or Neo4j Migrations. Idempotent Cypher files with version number. CI rolls migration into test and staging DB.
Stop criteria
Done signals checkable in under a minute
Finished the runsheet?
Go to the profile for purpose, similar methods, and sources or continue to the next method in the catalog.