← Back to Home

Neo4j to AWS Neptune: Customer Data Migration Story

2022-2023 Migration • 13 min read
Graph Databases • Cost Optimization • Data Migration • Real-World

In 2022, we faced a decision: our Neo4j bill was growing faster than our features. We were storing millions of customer touchpoints in a graph database, and as that graph scaled, licensing costs scaled with it. By early 2023, we had migrated to AWS Neptune and saved $25K annually while maintaining the same reliability and performance.

This is the technical story of what we did, what went wrong, and what we'd do differently.

The Cost Problem

Neo4j's pricing model is based on instance size (RAM). As our customer touchpoint graph grew, we had to continuously upgrade:

The trajectory was clear: costs would keep accelerating. We needed an alternative.

Why AWS Neptune?

Neptune made sense because:

The Math: Neptune instance (r5.2xlarge) cost us ~$8K/year. Neo4j was $8K/month. Easy decision.

The Migration Process (2022-2023)

Phase 1: Assessment (Week 1)

We started by understanding what we were migrating:

Phase 2: Testing (Weeks 2-3)

We launched a Neptune test instance and:

  1. Exported 10% of our Neo4j graph to CSV
  2. Transformed the data (Neo4j properties → Gremlin format)
  3. Loaded into Neptune test instance
  4. Ported our 30+ Cypher queries to Gremlin
  5. Ran side-by-side queries, compared results exactly

Gotcha we found: Gremlin handles graph traversals differently than Cypher. Some queries needed complete rewrites.

Phase 3: Full Data Migration (Week 4)

Once we were confident, we migrated the full graph:

Step 1: Stop writes to Neo4j
Step 2: Export all nodes and edges to S3 (CSV format)
Step 3: Validate export (row counts, checksums)
Step 4: Neptune bulk load from S3 (~2 hours for 150GB)
Step 5: Run validation queries on Neptune
Step 6: Compare customer touchpoint counts (must match exactly)
      

Migration took one weekend. Zero data loss.

Phase 4: Application Code Migration (Weeks 5-6)

The application layer needed updates:

Phase 5: Parallel Running (Weeks 7-8)

We ran both databases simultaneously for 2 weeks:

This gave us huge confidence. We found (and fixed) edge cases that would have broken production.

Phase 6: Cutover (Friday, Week 9)

On Friday evening, we switched:

  1. Verified Neptune had latest data
  2. Stopped writes to Neo4j (read-only mode)
  3. Updated application to read from Neptune
  4. Monitored error rates and latency for 30 minutes (heightened alerting)
  5. Kept Neo4j running as a fallback (for 2 weeks, just in case)

Cutover was clean. No incidents. We turned off Neo4j after 2 weeks of successful production use.

Results

Cost Savings

Performance & Reliability

What Went Wrong (And How We Fixed It)

Issue 1: Gremlin Query Performance

Problem: One critical query (finding customer relationships 3+ hops away) was 30% slower in Gremlin.

Solution: Added materialized paths (pre-computed common traversals, cached in Redis). Query latency dropped below SLA.

Issue 2: Timeout on Large Traversals

Problem: Queries on the deepest parts of the graph (6+ hops) would occasionally timeout.

Solution: Increased Neptune query timeout, added pagination (break large traversals into smaller queries).

Issue 3: Data Type Mismatches

Problem: Some Neo4j properties (dates, IDs) had subtle type differences when loaded into Neptune.

Solution: Explicit type casting during data transformation, validation queries before cutover.

What We'd Do Differently

Lessons Learned

1. Managed Services Win Over Time

Neptune requires zero ops effort. Neo4j required constant tuning. The TCO gap is huge.

2. Data Validation is Non-Negotiable

We validated customer touchpoint counts at every stage. This caught issues before they affected customers.

3. Parallel Running Prevents Disasters

Running both systems let us find bugs in isolation. Cutover was boring—the best kind.

4. Graph Query Languages Are Not Interchangeable

Cypher and Gremlin express the same problems differently. You can't just translate syntax; you need to rethink logic.

Conclusion

The Neo4j to Neptune migration was one of the best ROI projects we did. $25K annual savings, zero data loss, better uptime, less operational burden.

If you're running Neo4j and your license costs are climbing, Neptune is worth serious evaluation. The migration is non-trivial but absolutely doable with the right process.

← Back to HomeRead More Articles