- JWT authentication with Supabase integration - Role-based access control (Admin, Owner, Staff, Auditor) - Universal database adapter (Prisma/Supabase/MongoDB support) - User management with hierarchical permissions - Redis caching service (configured but optional) - Comprehensive API documentation - Production-ready NestJS architecture - Migration scripts for provider switching - Swagger/OpenAPI documentation
3.2 KiB
3.2 KiB
Database Migration Scenarios
Scenario 1: PostgreSQL → PostgreSQL (Different Provider)
Examples: Supabase → AWS RDS, Google Cloud SQL, Railway, Neon, PlanetScale
What Changes:
- ✅ Connection string only
- ✅ Keep all Prisma code unchanged
- ✅ Keep all SQL queries unchanged
Migration Steps:
# 1. Update connection string
DATABASE_URL="postgresql://user:pass@new-provider.com:5432/db"
# 2. Run Prisma migration
npx prisma migrate deploy
# 3. Update environment variables
SUPABASE_URL="" # Remove
SUPABASE_SERVICE_ROLE_KEY="" # Remove
Code Changes Required:
// Before (Supabase)
const { data } = await this.supabase.from('users').select('*');
// After (Any PostgreSQL + Prisma)
const data = await this.prisma.user.findMany();
Effort: 1-2 days Risk: Very Low
Scenario 2: PostgreSQL → MySQL/MariaDB
Examples: Supabase → AWS RDS MySQL, PlanetScale MySQL
What Changes:
- ⚠️ Schema syntax differences
- ⚠️ Data type mappings
- ✅ Prisma handles most differences
Migration Steps:
// Update datasource in schema.prisma
datasource db {
provider = "mysql" // Changed from postgresql
url = env("DATABASE_URL")
}
// Some field types may need updates
model User {
id String @id @default(cuid()) // uuid() → cuid() for MySQL
// ... rest unchanged
}
Effort: 3-5 days Risk: Low-Medium
Scenario 3: PostgreSQL → MongoDB
Examples: Supabase → MongoDB Atlas, AWS DocumentDB
What Changes:
- ❌ Complete schema redesign
- ❌ Relational → Document model
- ❌ All queries need rewriting
Migration Complexity:
// Before (Relational)
const user = await this.prisma.user.findUnique({
where: { id },
include: { receipts: true, staff: true }
});
// After (Document)
const user = await this.mongodb.collection('users').findOne({
_id: ObjectId(id)
});
// Receipts and staff would be embedded documents or separate collections
Effort: 2-4 weeks Risk: High
Scenario 4: Keep Database, Replace Supabase Services
Examples: Keep PostgreSQL, replace Auth/Storage with AWS/Firebase
Service Replacements:
Authentication:
// Before: Supabase Auth
await supabase.auth.signInWithOtp({ email });
// After: AWS Cognito
await cognito.initiateAuth({ email });
// After: Firebase Auth
await firebase.auth().sendSignInLinkToEmail(email);
// After: Auth0
await auth0.passwordlessStart({ email });
File Storage:
// Before: Supabase Storage
await supabase.storage.from('receipts').upload(fileName, file);
// After: AWS S3
await s3.upload({ Bucket: 'receipts', Key: fileName, Body: file });
// After: Google Cloud Storage
await storage.bucket('receipts').file(fileName).save(file);
// After: Cloudinary
await cloudinary.uploader.upload(file, { public_id: fileName });
Real-time:
// Before: Supabase Realtime
supabase.from('users').on('*', callback).subscribe();
// After: Socket.IO
io.on('user_updated', callback);
// After: AWS AppSync
await appSync.subscribe({ subscription: USER_UPDATED });
// After: Pusher
pusher.subscribe('users').bind('updated', callback);
Effort: 1-3 weeks per service Risk: Medium