Property Sharding with Neo4j Kubernetes Operator¶
Property Sharding is an advanced Neo4j feature that separates graph structure (nodes and relationships) from properties, enabling better scalability for property-heavy workloads by distributing properties across multiple databases.
Overview¶
Property Sharding decouples data into:
- Graph Shard: Single database containing nodes and relationships WITHOUT properties
- Property Shards: Multiple databases containing properties distributed via hash function
- Virtual Database: Logical database presenting unified view of graph + property shards
Prerequisites¶
System Requirements¶
Neo4j Version Requirements:
- Minimum: Neo4j 2025.12-enterprise (introduced in 2025.12)
- Note: Property sharding is an enterprise-only feature and requires valid licensing
- Not available on Aura
Cluster Infrastructure Requirements:
- Minimum Servers: 2 servers minimum (3+ recommended for HA graph shard primaries)
- Recommended Servers: 3-7 servers (odd numbers provide better consensus characteristics)
- Maximum Recommended: 20+ servers for very large deployments
Resource Requirements per Server:
| Component | Minimum (Basic) | Recommended (Production) | Notes |
|---|---|---|---|
| Memory | 4GB total | 8GB+ total | 4GB minimum, 8GB+ recommended |
| CPU | 1 core | 2+ cores | Cross-shard queries are CPU intensive |
| Storage | 10GB | 100GB+ | Depends on data volume and shard count |
| Network | 1Gbps | 10Gbps+ | Low latency critical for transaction log sync |
Additional Requirements:
- Authentication: Admin secret required (property sharding requires authenticated cluster access)
- Storage Class: Persistent storage class must be specified (e.g.,
standard,fast-ssd) - Kubernetes Version: 1.32+ (the operator's minimum; see Installation)
- Network Policy: Allow inter-pod communication on discovery and bolt ports
- Cypher Version: sharded databases are created with Cypher 25 as their default language (the operator sets it on the whole sharded family); the rest of the server is governed by
spec.serverDefaultCypherLanguage
Performance Considerations:
- Memory Overhead: 20-30% additional memory required for shard coordination
- CPU Overhead: 20-30% additional CPU required for cross-shard operations
- Storage Growth: Linear growth with number of property shards
- Network Traffic: 2-3x increase in inter-server communication
Capacity Planning Guidelines:
Development/Testing:
topology:
servers: 3
resources:
requests:
memory: 4Gi # Absolute minimum for dev/test
cpu: 2000m # 2 cores for cross-shard queries
limits:
memory: 8Gi # Recommended for production
cpu: 2000m
Production:
topology:
servers: 3 # or 5+ for larger datasets
resources:
requests:
memory: 4Gi # Minimum for dev/test
cpu: 2000m # Cross-shard performance
limits:
memory: 8Gi # Recommended for production
cpu: 4000m # Handle peak loads
High-Performance Production:
topology:
servers: 7 # Better distribution
resources:
requests:
memory: 8Gi # Production recommendation
cpu: 4000m # Maximum throughput
limits:
memory: 20Gi # Peak load handling
cpu: 6000m # Burst capability
Quick Start¶
✅ Tested Configuration: The examples below have been tested with Neo4j 2025.12-enterprise on Kubernetes clusters with the specified resource requirements. Property sharding cluster creation typically completes in 2-3 minutes with proper resources.
0. Prerequisites¶
Before creating a property sharding cluster, create the required admin secret:
kubectl create secret generic neo4j-admin-secret \
--from-literal=username=neo4j \
--from-literal=password=your-secure-password
1. Create Property Sharding Enabled Cluster¶
apiVersion: neo4j.neo4j.com/v1beta1
kind: Neo4jEnterpriseCluster
metadata:
name: property-sharding-cluster
namespace: default
spec:
acceptLicenseAgreement: "eval"
image:
repo: neo4j
tag: 2025.12-enterprise # Property sharding requires 2025.12+
# Authentication required for property sharding
auth:
adminSecret: neo4j-admin-secret
topology:
servers: 3 # 3+ recommended for HA graph shard primaries
storage:
size: 10Gi
className: standard # Storage class must be specified
resources:
requests:
memory: 4Gi # Minimum 4GB for dev/test environments
cpu: 2000m # 2+ cores required for cross-shard queries
limits:
memory: 8Gi # Recommended 8GB for production
cpu: 4000m # Higher CPU for shard coordination overhead (20-30% increase)
# Enable property sharding
propertySharding:
enabled: true
config:
# Required configuration (applied automatically if not specified)
internal.dbms.sharded_property_database.enabled: "true"
internal.dbms.sharded_property_database.allow_external_shard_access: "false"
# Performance tuning (optional)
db.tx_log.rotation.retention_policy: "7 days"
internal.dbms.sharded_property_database.property_pull_interval: "10ms"
2. Create Sharded Database¶
apiVersion: neo4j.neo4j.com/v1beta1
kind: Neo4jShardedDatabase
metadata:
name: products-sharded-db
namespace: default
spec:
# Reference to property sharding enabled cluster
clusterRef: property-sharding-cluster
# Virtual database name (what users connect to)
name: products
# The sharded family's default Cypher language. Required, and "25" is the only
# accepted value: the graph shard and every property shard inherit it from
# this, the parent database, whatever spec.serverDefaultCypherLanguage says.
defaultCypherLanguage: "25"
# Property sharding configuration
propertySharding:
propertyShards: 4 # Number of property shards
# Graph shard topology (stores nodes/relationships)
graphShard:
primaries: 3
secondaries: 2
# Property shard topology (stores properties)
propertyShardTopology:
replicas: 2
# Database creation options
wait: true # Wait for creation to complete
ifNotExists: true # Don't fail if database exists
Seeding from Backups (Optional)¶
Use seedURI for a single backup location that contains shard-suffixed artifacts
(for example, products-g000 and products-p000). Use seedURIs for per-shard
URIs when seeding from dumps or multiple locations.
spec:
seedURI: "s3://backups/products/"
seedConfig:
restoreUntil: "2025-06-01T10:30:00Z"
seedCredentials:
secretRef: "seed-credentials"
Configuration Reference¶
PropertyShardingSpec (Neo4jEnterpriseCluster)¶
| Field | Type | Required | Description |
|---|---|---|---|
enabled |
boolean | Yes | Enable property sharding support on cluster |
config |
map[string]string | No | Advanced property sharding configuration |
Required Configuration Settings¶
When propertySharding.enabled is true, these settings are automatically applied:
config:
internal.dbms.sharded_property_database.enabled: "true"
internal.dbms.sharded_property_database.allow_external_shard_access: "false"
Sharding does not set the server's default Cypher language. Neo4j docs
suggest db.query.default_language=CYPHER_25, but it is not needed: a sharded
database's graph shard and property shards inherit the parent database's
language, not the server's, and the operator creates every sharded database
with SET DEFAULT LANGUAGE CYPHER 25. The server default is yours to
set with spec.serverDefaultCypherLanguage, as on any other cluster.
Upgrading a sharding cluster
If you are upgrading a sharding cluster from v1.16.x or earlier, see the Upgrade Guide.
Optional Performance Tuning¶
config:
# Transaction log retention (critical for shard sync)
db.tx_log.rotation.retention_policy: "7 days"
# Property pull interval
internal.dbms.sharded_property_database.property_pull_interval: "10ms"
# Memory configuration
server.memory.heap.max_size: "8G"
server.memory.pagecache.size: "4G"
PropertyShardingConfiguration (Neo4jShardedDatabase)¶
| Field | Type | Required | Description |
|---|---|---|---|
propertyShards |
int32 | Yes | Number of property shards (1-1000) |
graphShard |
DatabaseTopology | Yes | Topology for graph shard |
propertyShardTopology |
PropertyShardTopology | Yes | Replica topology for property shards |
DatabaseTopology¶
| Field | Type | Description |
|---|---|---|
primaries |
int32 | Number of primary replicas |
secondaries |
int32 | Number of secondary replicas |
PropertyShardTopology¶
| Field | Type | Description |
|---|---|---|
replicas |
int32 | Number of replicas per property shard |
Best Practices¶
Cluster Sizing¶
Development/Testing:
- 2 servers minimum (3+ recommended for HA graph shard primaries)
- 4GB heap per server (absolute minimum for property sharding)
- 8GB+ total RAM per server (recommended for stable production operation)
- Property shards: 2-4
Production:
- 3+ servers recommended (HA graph shard primaries)
- 4-8GB+ heap per server (4GB minimum, 8GB for production)
- 20GB+ total RAM per server (accounting for system overhead)
- 2+ CPU cores per server (cross-shard query requirements)
- Property shards: 4-16 (start conservatively)
Property Distribution Strategy¶
Property distribution across shards is automatic; the operator does not provide per-property controls.
Shard Count Recommendations¶
| Dataset Size | Property Shards | Reasoning |
|---|---|---|
| < 1M nodes | 2-4 | Minimal overhead |
| 1M-10M nodes | 4-8 | Balanced distribution |
| 10M-100M nodes | 8-16 | Better parallelization |
| 100M+ nodes | 16-32 | Maximum distribution |
Note: Resharding requires an offline neo4j-admin database copy and recreating the database; the operator does not automate resharding.
Monitoring and Observability¶
Cluster Status¶
Check if property sharding is ready:
Look for:
Sharded Database Status¶
Check sharded database health:
Key status fields:
status:
phase: Ready
shardingReady: true
graphShard:
name: products-g000
ready: true
state: online
propertyShards:
- name: products-p000
ready: true
state: online
virtualDatabase:
name: products
ready: true
Database Operations¶
Connect to the virtual database:
Query the virtual database (automatically routes to appropriate shards):
// Connect to virtual database
:use products
// Standard queries work transparently
MATCH (n:Product) RETURN n.name, n.description LIMIT 10;
// Create data (properties distributed automatically)
CREATE (p:Product {
id: "12345", // Stays in graph shard
name: "Widget", // Stays in graph shard
description: "...", // Goes to property shard
metadata: "{...}" // Goes to property shard
});
Check individual shards:
// Graph shard (nodes/relationships only)
:use system
SHOW DATABASES
WHERE name STARTS WITH "products-g"
// Property shards (properties only)
SHOW DATABASES
WHERE name STARTS WITH "products-p"
Troubleshooting¶
Common Issues¶
1. Version Mismatch
Solution: Upgrade to Neo4j 2025.12 or later.2. Insufficient Memory
Error: property sharding requires minimum 4GB memory for basic operation, got XXXMB (recommended: 8GB+)
resources:
requests:
memory: 4Gi # Minimum requirement
limits:
memory: 8Gi # Recommended for production
3. Insufficient CPU Resources
Solution: Increase CPU allocation for cross-shard query performance:resources:
requests:
cpu: 2000m # Recommended minimum for cross-shard queries
limits:
cpu: 4000m # Allow burst capacity
4. Invalid Server Count
Solution: Set at least 2 servers, and consider 3+ for HA graph shard primaries: topology:
servers: 3 # 3+ recommended for HA graph shard primaries
# Consider 7 servers for larger datasets
5. Cluster Not Configured for Property Sharding
Solution: EnsurepropertySharding.enabled: true on the referenced cluster and that it is Ready.
Debugging Commands¶
# Check cluster configuration
kubectl describe neo4jenterprisecluster property-sharding-cluster
# Check sharded database events
kubectl describe neo4jshardeddatabase products-sharded-db
# View operator logs
kubectl logs -n neo4j-operator-system -l control-plane=controller-manager --tail=-1
# Check individual database status
kubectl exec property-sharding-cluster-server-0 -- \
cypher-shell -u neo4j -p password "SHOW DATABASES"
# Check virtual database
kubectl exec property-sharding-cluster-server-0 -- \
cypher-shell -u neo4j -p password "SHOW DATABASES"
Backup and Recovery¶
Note: There is no backupConfig on Neo4jShardedDatabase. Use an explicit Neo4jBackup
with spec.instanceRef (the cluster) + spec.shardedDatabase set to the
Neo4jShardedDatabase resource name (e.g. products-sharded-db) — the operator
resolves the logical database name (spec.name, e.g. products) from that resource.
A single backup captures every shard consistently in one neo4j-admin database backup
invocation via a {logical-name}* glob — you do not list the individual shard
databases (products-g000, products-p000, …). Because of the glob, the backup is
refused while any other database's name starts with the logical name (for example
products-archive beside products), naming it: rename or drop that database, or
pick a logical name no other database begins with.
ℹ️ An all-databases backup (
spec.allDatabases) catalogues each sharded family's per-shard artifacts instatus.history[].shardedFamilies(family names also inshardedDatabasesExcluded, with a warning event) — so one all-databases backup is a restorable source for sharded databases too. The all-databases restore loop recreates standard databases only; recover each sharded family by re-applying itsNeo4jShardedDatabasewithspec.seedBackupRefpointing at that same backup (addspec.seedSourceDatabaseto restore under a different name) — notNeo4jRestore. This holds for cloud storage. On a PVC only a run whose shards are all full backups can seed a sharded database, and an all-databases backup's runs after the first hold differentials — so on a PVC, back each sharded database up with its ownshardedDatabase-scopedNeo4jBackup, which takes full backups there (Restoring a sharded database).
apiVersion: neo4j.neo4j.com/v1beta1
kind: Neo4jBackup
metadata:
name: sharded-backup
namespace: default
spec:
instanceRef: property-sharding-cluster # the owning Neo4jEnterpriseCluster
shardedDatabase: products-sharded-db # the Neo4jShardedDatabase RESOURCE name (all shards in one run)
storage:
type: pvc # one of: pvc | s3 | gcs | azure
pvc:
name: sharded-backup-storage
storageClassName: standard
size: 50Gi
schedule: "0 2 * * *" # optional cron; omit for one-shot
retention:
maxCount: 10
options:
backupType: AUTO # on a PVC, AUTO takes full backups of a sharded database
validate: true # optional per-shard recoverability check
The per-shard .backup artifacts produced by the run are recorded in
status.history[].shardArtifacts[] (one entry per shard, e.g. products-g000,
products-p000). When options.validate: true, per-shard recoverability is
surfaced under status.history[].validation.
Restoring a sharded database¶
To restore a sharded database from a backup, seed a new Neo4jShardedDatabase
via spec.seedBackupRef (referencing this Neo4jBackup CR), or perform a
destructive in-place restore with spec.replaceExisting: true + spec.force: true
(see the field reference above). The seed is the backup's latest successful run.
From a PVC, every shard of that run must be a full backup. The operator serves the PVC to Neo4j over HTTP, and over HTTP Neo4j seeds a sharded database only from a full backup of each shard. A differential cannot be turned into one either: merging a shard's chain loses the sharding information the seed needs. So:
- On a PVC,
backupType: AUTO(the default) takes a full backup of a sharded database on every run, so every run can seed one. Each run's shard types are instatus.history[].shardArtifacts[].type. (backupType: DIFFis refused for a sharded database: Neo4j does not back up property shards differentially. In cloud storage,AUTOwrites a differential of the graph shard and full property shards, which seed directly.) - An all-databases backup (
spec.allDatabases) keepsAUTOas usual, because oneneo4j-adminrun covers every database. Its sharded families' runs after the first hold differentials, and raise the same warning. To restore a sharded database from a PVC, back it up with its ownNeo4jBackup(spec.shardedDatabase). - A
seedBackupRefwhose latest run holds a differential shard fails at once, naming the shards. It retries: once a full run of that backup lands, the database seeds from it.
From cloud storage, differentials seed directly: Neo4j reads the whole chain
from the bucket. To seed under a different spec.name than the backed-up
database, set spec.seedSourceDatabase to the backed-up name: Neo4j matches
the seed's shards by name. (From a PVC, the operator maps the shards to the new
name itself.) The cluster's server pods fetch it themselves, so they need the
backup's credentials Secret — and, for MinIO or another S3-compatible store, its
endpoint. Put them on the cluster (spec.extraEnvFrom, spec.env), or annotate
the cluster with neo4j.com/auto-inherit-seed-creds: "true" and the operator
adds both, at the cost of one rolling restart. Without either, the database fails
and names what is missing.
Performance and Sizing¶
Queries hitting only the graph shard (structure + graph properties) are fastest; cross-shard queries touching property shards add latency proportional to result-set size. For sizing, see the dedicated Resource Sizing guide. Sharded clusters benefit from low-latency networking (<10ms inter-pod for transaction-log sync, <5ms for query responsiveness) — co-locate pods in the same zone where possible.
Storage planning: total ≈ graph-shard size + (property-shards × avg property data per shard) + ~20% transaction-log + index overhead. Each property shard has its own transaction log; size accordingly.
Migration from Standard Databases¶
Property sharding cannot be enabled on existing databases. Migration approaches:
- Create new sharded database and migrate data
- Export/import with property distribution
- Application-level migration with dual-write
Limitations¶
- No in-operator resharding: Resharding requires offline
neo4j-admin database copyand recreation - Neo4j version: Requires 2025.12+ enterprise
- Cypher version: sharded databases are Cypher 25 (set by the operator); other databases follow
spec.serverDefaultCypherLanguage - No online resharding: Plan shard count carefully
- Increased complexity: More monitoring and operational overhead