12 KiB
S3 Migration Guide
Complete guide for migrating existing Brainy data to the new optimized system, with special considerations for shared S3 buckets.
🎯 Overview
When upgrading to Brainy v0.36.0+ with the new optimization system, you can migrate existing data without starting from scratch. This guide covers migration strategies, shared bucket considerations, and best practices.
✅ Key Points
- No data loss - All existing data is preserved and enhanced
- Automatic optimization - System applies all optimizations during migration
- Backward compatible - Can read data from any previous version
- Zero-downtime options - Multiple strategies for production systems
🔄 Migration Methods
Method 1: Backup & Restore (Recommended)
The safest and most reliable migration approach.
// Step 1: Export from existing Brainy instance
const oldBrainy = new BrainyData({ /* existing config */ })
const backupData = await oldBrainy.backup()
// Step 2: Save backup (optional)
import fs from 'fs'
fs.writeFileSync('brainy-backup.json', JSON.stringify(backupData))
// Step 3: Create new optimized instance
import { createAutoBrainy } from '@soulcraft/brainy'
const newBrainy = createAutoBrainy({
bucketName: 'my-optimized-vectors'
})
// Step 4: Restore data with optimizations
const result = await newBrainy.restore(backupData, {
clearExisting: true
})
console.log(`Migrated ${result.nounsRestored} vectors successfully`)
Benefits:
- ✅ Clean migration with no conflicts
- ✅ Can test before switching production
- ✅ Rollback option available
- ✅ Works with any storage backend
Method 2: In-Place Upgrade
Upgrade existing data without moving it.
import { createAutoBrainy } from '@soulcraft/brainy'
// Point to existing data location
const brainy = createAutoBrainy({
bucketName: 'existing-bucket' // Same as old instance
})
// System automatically:
// 1. Detects existing data format
// 2. Rebuilds optimized HNSW index
// 3. Applies semantic partitioning
// 4. Enables all optimizations
// First operation triggers optimization
const results = await brainy.search([0.1, 0.2, 0.3], 10)
Benefits:
- ✅ No data movement required
- ✅ Immediate optimization benefits
- ✅ Minimal downtime
Limitations:
- ⚠️ Requires exclusive access during initial optimization
- ⚠️ No rollback without backup
Method 3: Sparse Data Import
For migrating raw data without vectors.
// Import data without vectors (they'll be regenerated)
const sparseData = {
nouns: [
{
id: 'doc-1',
metadata: {
text: 'Machine learning algorithms',
noun: 'Thing',
category: 'technology'
}
// No vector field - will be auto-generated
}
],
verbs: [],
version: '1.0.0'
}
const brainy = createAutoBrainy()
const result = await brainy.importSparseData(sparseData)
Benefits:
- ✅ Smaller backup files
- ✅ Ensures vectors use latest embedding model
- ✅ Good for data format migrations
🗄️ Shared S3 Bucket Considerations
When multiple Brainy instances share the same S3 bucket, special care is needed during migration.
Understanding Shared Bucket Architecture
shared-bucket/
├── nouns/ # Vector data
├── verbs/ # Relationships
├── metadata/ # Additional metadata
├── index/ # HNSW index data
├── statistics/ # System statistics
├── change-log/ # Change tracking with instance IDs
└── locks/ # Distributed locks for coordination
Built-in Safety Features
-
Distributed Locking
- Prevents concurrent modifications
- 30-second TTL with automatic cleanup
- Coordinates between multiple instances
-
Instance Tracking
// Each modification includes instance identification { timestamp: 1234567890, operation: 'add', instanceId: 'process-123' // or 'browser' } -
Conflict Detection
- Change logs track all modifications
- Enables conflict resolution
- Maintains data consistency
⚠️ Potential Issues with Shared Buckets
| Issue | Impact | Solution |
|---|---|---|
| Namespace Collision | Different apps overwrite data | Use unique prefixes |
| Index Corruption | Multiple rebuilds conflict | Coordinate migrations |
| Lock Contention | Performance degradation | Stagger instance updates |
| Statistics Conflicts | Incorrect metrics | Use distributed locking |
📋 Migration Strategies for Shared Buckets
Strategy 1: Dedicated Namespace (Recommended)
Create isolation using bucket subfolders.
// Each application uses its own namespace
const brainy = createAutoBrainy({
bucketName: 'shared-bucket/app-name/v2',
region: 'us-east-1'
})
// Data structure becomes:
// shared-bucket/
// app-name/
// v2/
// nouns/
// verbs/
// ...
Strategy 2: Blue-Green Migration
Run old and new systems in parallel.
// Phase 1: Create new optimized instance in separate bucket
const newBrainy = createAutoBrainy({
bucketName: 'optimized-vectors',
region: 'us-east-1'
})
// Phase 2: Sync data from old to new
const backupData = await oldBrainy.backup()
await newBrainy.restore(backupData)
// Phase 3: Run both systems in parallel
// - Old system: Handles writes
// - New system: Handles reads (testing)
// Phase 4: Switch traffic to new system
// Phase 5: Decommission old system
Strategy 3: Rolling Migration
Gradually migrate instances with zero downtime.
// Step 1: Set read-only mode on secondary instances
const readOnlyInstances = instances.map(instance => {
instance.setReadOnly(true)
return instance
})
// Step 2: Migrate primary write instance
const primaryBrainy = createAutoBrainy({
bucketName: 'shared-bucket',
learningEnabled: true
})
// Step 3: Gradually migrate read instances
for (const instance of readOnlyInstances) {
const optimized = createAutoBrainy({
bucketName: 'shared-bucket',
readOnlyMode: true
})
// Replace old instance with optimized
}
Strategy 4: Coordinated In-Place Migration
Migrate with careful coordination.
async function coordinatedMigration() {
// Step 1: Announce maintenance window
console.log('Starting coordinated migration...')
// Step 2: Stop all write operations
const instances = await getAllInstances()
instances.forEach(i => i.setReadOnly(true))
// Step 3: Wait for in-flight operations
await new Promise(resolve => setTimeout(resolve, 5000))
// Step 4: Perform migration
const brainy = createAutoBrainy({
bucketName: 'shared-bucket',
autoConfigureEnvironment: true,
learningEnabled: true
})
// Step 5: Verify migration
const stats = await brainy.getStatistics()
console.log(`Migrated ${stats.nounCount} vectors`)
// Step 6: Resume operations
instances.forEach(i => i.setReadOnly(false))
}
🛡️ Best Practices
1. Pre-Migration Checklist
- Backup existing data using
backup()method - Test migration with subset of data
- Monitor S3 costs during migration (increased API calls)
- Plan maintenance window if using shared bucket
- Verify credentials for S3 access
- Check available storage for temporary duplication
2. Performance Monitoring
// Monitor migration progress and performance
const brainy = createAutoBrainy({ /* config */ })
// Check optimization status
setInterval(async () => {
const metrics = brainy.getPerformanceMetrics()
console.log({
vectorsProcessed: metrics.indexSize,
searchLatency: metrics.averageSearchTime,
cacheHitRate: metrics.cacheHitRate,
memoryUsage: metrics.memoryUsage
})
}, 10000)
3. Handling Large Datasets
For datasets over 1M vectors:
// Use scenario-based configuration
const brainy = await createQuickBrainy('enterprise', {
bucketName: 'large-vectors',
region: 'us-east-1'
})
// Or manual configuration for fine control
const brainy = createAutoBrainy({
expectedDatasetSize: 5000000,
maxMemoryUsage: 16 * 1024 * 1024 * 1024, // 16GB
targetSearchLatency: 500,
s3Config: {
bucketName: 'large-vectors',
region: 'us-east-1'
}
})
4. Rollback Plan
Always maintain ability to rollback:
// Before migration
const backupData = await oldBrainy.backup()
fs.writeFileSync('backup-{timestamp}.json', JSON.stringify(backupData))
// If rollback needed
const oldBrainy = new BrainyData({ /* old config */ })
await oldBrainy.restore(backupData, { clearExisting: true })
📊 Expected Performance Improvements
After migration with optimizations:
| Dataset Size | Before | After | Improvement |
|---|---|---|---|
| 10k vectors | ~200ms | ~50ms | 4x faster |
| 100k vectors | ~2s | ~200ms | 10x faster |
| 1M vectors | ~10s | ~500ms | 20x faster |
| Memory Usage | 100% | 25-30% | 70-75% reduction |
| S3 API Calls | 100% | 10-50% | 50-90% reduction |
🔍 Troubleshooting
Common Issues and Solutions
| Problem | Cause | Solution |
|---|---|---|
| "Lock timeout" errors | Multiple instances competing | Stagger migration timing |
| High memory usage | Large dataset loading | Enable compression, reduce cache |
| Slow initial searches | Index rebuilding | Wait for optimization to complete |
| S3 rate limiting | Too many concurrent operations | Reduce batch sizes |
| Missing vectors | Sparse data import | Ensure embedding function available |
Debug Logging
Enable detailed logging during migration:
// Set environment variable
process.env.BRAINY_DEBUG = 'true'
const brainy = createAutoBrainy({
bucketName: 'my-bucket',
// Logs will show optimization decisions
})
Verification Steps
After migration, verify success:
async function verifyMigration(brainy) {
// 1. Check data integrity
const stats = await brainy.getStatistics()
console.log(`Vectors: ${stats.nounCount}`)
console.log(`Relationships: ${stats.verbCount}`)
// 2. Test search performance
const testVector = [0.1, 0.2, 0.3]
const start = Date.now()
const results = await brainy.search(testVector, 10)
console.log(`Search time: ${Date.now() - start}ms`)
// 3. Verify optimizations active
const metrics = brainy.getPerformanceMetrics()
console.log(`Cache hit rate: ${metrics.cacheHitRate}`)
console.log(`Compression ratio: ${metrics.compressionRatio}`)
return stats.nounCount > 0 && results.length > 0
}
🎯 Quick Decision Guide
Choose your migration approach:
graph TD
A[Start Migration] --> B{Shared S3 Bucket?}
B -->|Yes| C{Can Stop All Instances?}
B -->|No| D[Use Backup & Restore]
C -->|Yes| E[In-Place Migration]
C -->|No| F{Need Zero Downtime?}
F -->|Yes| G[Blue-Green Migration]
F -->|No| H[Rolling Migration]
D --> I[Complete]
E --> I
G --> I
H --> I
💡 Tips for Success
- Start Small: Test with 1% of data first
- Monitor Metrics: Use
getPerformanceMetrics()frequently - Use Read-Only Mode: For instances that only search
- Plan S3 Costs: Migration causes temporary spike in API calls
- Keep Backups: Always maintain rollback capability
- Leverage Auto-Config: Let system optimize automatically
- Document Process: Record settings for reproducibility
🔗 Related Documentation
- Large-Scale Optimizations - Understanding the optimization system
- Auto-Configuration Guide - How automatic optimization works
- Storage Optimization - S3 and storage best practices
- Production Migration Guide - General production deployment
🆘 Getting Help
- GitHub Issues: Report migration problems
- Discussions: Share migration experiences
- Documentation: Check other guides for specific features
Ready to migrate? Start with a backup, test thoroughly, and enjoy 10-20x performance improvements! 🚀