Subchapter 67.10
references/performance.mdMarkdown6 KBView on GitHub
Neptune uses r-series (memory-optimized) instances. The graph must fit in memory for best performance — Neptune caches the working set in the buffer pool.
| Instance | vCPU | RAM | Use for |
|---|---|---|---|
| db.r6g.large | 2 | 16 GB | Dev/test, small graphs |
| db.r6g.xlarge | 4 | 32 GB | Small production (< 10GB graph) |
| db.r6g.2xlarge | 8 | 64 GB | Medium production |
| db.r6g.4xlarge | 16 | 128 GB | Large graphs, complex traversals |
| db.r6g.8xlarge | 32 | 256 GB | Very large graphs |
Rule of thumb: provision RAM ≥ 2× your graph data size. If your graph is 20 GB, use at least a db.r6g.2xlarge (64 GB RAM).
| Factor | Serverless | Provisioned |
|---|---|---|
| Traffic pattern | Spiky, unpredictable | Steady, predictable |
| Cold start tolerance | Yes | N/A |
| Cost at low utilization | Lower (scales to ~0) | Higher (always-on) |
| Latency predictability | Variable | Consistent |
| Max capacity | 128 NCUs | Instance-bound |
Use Serverless for: dev/test environments, infrequent batch jobs, new projects with unknown traffic.
Use provisioned for: production apps with SLA requirements, sustained load.
Add read replicas to scale read throughput and reduce load on the primary:
aws neptune create-db-instance \
--db-instance-identifier neptune-reader-1 \
--db-instance-class db.r6g.xlarge \
--engine neptune \
--db-cluster-identifier your-cluster \
--tags Key=created_by,Value=neptune-skill Key=generation_model,Value=<model-id>Route read queries to the reader endpoint — Neptune load-balances across all replicas automatically.
// Filters the SOURCE set first (Seattle people), then traverses — fewer edges:
g.V().hasLabel('Person').has('city', 'Seattle').out('KNOWS') // friends of Seattle people
// Filters the TARGET after traversal — a DIFFERENT result set, not just slower:
g.V().hasLabel('Person').out('KNOWS').has('city', 'Seattle') // Seattle-dwelling friendsFilter placement changes which vertices the predicate applies to (source
vs. target), so it affects correctness, not just performance. When a predicate
applies to the source vertex, push it before out() to shrink the working set
early; do not move a has() across a traversal step if that would change which
vertices it filters.
// ❌ Traverses full graph, returns 10
g.V().hasLabel('Person').repeat(out('KNOWS')).times(3).limit(10)
// ✅ Limits fan-out at each step
g.V().hasLabel('Person').limit(100)
.repeat(out('KNOWS').limit(10))
.times(3)
.limit(10)// Without simplePath(), traversal can loop forever in cyclic graphs
g.V().has('Account', 'id', 'A1')
.repeat(out('SENT_TO').simplePath()) // simplePath prevents revisiting
.times(5)
.values('id')// Add .profile() to any traversal
g.V().hasLabel('Person').out('KNOWS').out('KNOWS').profile()
// Key metrics to watch:
// traversedEdges — high = too much fan-out
// elementCount — high = too many vertices loaded
// duration — per step, identifies bottleneckServerless scales to near-zero when idle. For dev/test clusters that run 8 hours/day, cost is ~60-70% lower than always-on provisioned instances.
Neptune uses SSD-backed distributed storage billed per GB-month. Storage auto-grows — there is no manual allocation.
Reader replicas can use a different (smaller) instance class than the writer. This is a common cost optimization — use a large writer for writes and smaller readers for read-heavy workloads. Avoid over-provisioning readers for infrequent read workloads — Neptune Serverless is often cheaper.
Key metrics:
GremlinRequestsPerSec — query throughput
GremlinErrors — error rate
BufferCacheHitRatio — target > 95%; below this = working set exceeds RAM
CPUUtilization — sustained > 80% = need larger instance
FreeableMemory — low = need more RAM
DBClusterReplicaLag — replication lag to read replicas# Alert on low cache hit ratio
aws cloudwatch put-metric-alarm \
--alarm-name NeptuneBufferCacheHitRatioLow \
--metric-name BufferCacheHitRatio \
--namespace AWS/Neptune \
--statistic Average \
--period 300 \
--threshold 90 \
--comparison-operator LessThanThreshold \
--evaluation-periods 3 \
--alarm-actions arn:aws:sns:...troubleshooting (slow queries), querying (optimization patterns)