The astro-basics project features a sophisticated database abstraction layer that enables seamless switching between database providers without code changes or complex configuration. Switch between Supabase (PostgreSQL) and Turso (LibSQL) with a single command while maintaining full backward compatibility.
Overview
Section titled “Overview”The database switching system provides:
- One-command switching between database providers
- Automatic backups before any configuration changes
- Zero breaking changes to existing code
- Real-time provider detection without server restart
- Interactive setup wizard for non-technical users
🔄 Easy Switching
Switch databases with npm run db:switch:turso or npm run db:switch:supabase - automatic
backups included.
🛡️ Safe Operations
Built-in backup/restore system prevents configuration loss. Roll back anytime with npm run db:restore.
🎯 Auto-Detection
Smart provider detection automatically uses the best available database based on your configuration.
🧙♂️ Setup Wizard
Interactive wizard guides you through database setup with step-by-step instructions.
Quick Start
Section titled “Quick Start”Check Current Status
Section titled “Check Current Status”npm run db:statusThis shows your current database configuration, active provider, and available options.
Switch Database Provider
Section titled “Switch Database Provider”npm run db:switch:tursonpm run db:switch:supabaseEach switch automatically:
- Creates a backup of your current configuration
- Tests connectivity to the new database
- Updates your environment variables
- Confirms successful switch
First-Time Setup
Section titled “First-Time Setup”If you’re setting up databases for the first time:
npm run db:wizardThe interactive wizard will:
- Guide you through choosing database providers
- Help you obtain necessary credentials
- Test connections automatically
- Configure your
.envfile
Architecture
Section titled “Architecture”Database Abstraction Layer
Section titled “Database Abstraction Layer”The system uses a unified interface that abstracts database-specific implementations:
// All code uses the same interface regardless of providerimport { getDatabase } from '#libs/database'
const db = getDatabase()const events = await db.getEvents({ limit: 10 })Key Components:
src/libs/database/- Modular abstraction layer (v2.0.0)index.ts- Public API entry pointfactory.ts- Provider auto-detection and instantiationproviders/turso/- Turso implementation (delegation pattern)providers/supabase/- Supabase implementation (delegation pattern)shared/- Shared utilities (field validation, security)
src/libs/database-types.ts- Unified TypeScript interfacessrc/libs/database.ts- Backward compatibility re-exports
Architecture Benefits:
- Modular Design: Feature-specific modules (events, users, clients, orders)
- Delegation Pattern: Provider classes delegate to operation classes
- Scalability: Easy to add new features without touching existing code
- Maintainability: Each module has single responsibility
Learn more: Database Architecture Guide
Provider Selection Logic
Section titled “Provider Selection Logic”The system automatically selects databases using this priority:
- Explicit Choice -
DATABASE_PROVIDER=turso|supabasein.env - Supabase - If Supabase credentials are configured
- Turso - If Turso credentials are configured
- Error - If no providers are available
Configuration
Section titled “Configuration”Environment Variables
Section titled “Environment Variables”# Supabase ConfigurationSUPABASE_URL=https://your-project-id.supabase.coSUPABASE_ANON_KEY=eyJ... # For client operationsSUPABASE_SERVICE_ROLE_KEY=eyJ... # For server operations (required)
# Optional: Explicit provider selectionDATABASE_PROVIDER=supabase# Turso ConfigurationTURSO_DATABASE_URL=libsql://your-database-name.turso.ioTURSO_AUTH_TOKEN=eyJ...
# Optional: Explicit provider selectionDATABASE_PROVIDER=turso# Configure both providers# SupabaseSUPABASE_URL=https://your-project-id.supabase.coSUPABASE_SERVICE_ROLE_KEY=eyJ...
# TursoTURSO_DATABASE_URL=libsql://your-database-name.turso.ioTURSO_AUTH_TOKEN=eyJ...
# Choose which one to use (or omit for auto-detection)DATABASE_PROVIDER=supabaseAvailable Commands
Section titled “Available Commands”Database Management
Section titled “Database Management”# Core Commandsnpm run db:status # Show current configuration and statusnpm run db:wizard # Interactive setup for new usersnpm run db:manage # Advanced database management CLI
# Database Switching (with automatic backups)npm run db:switch:turso # Switch to Turso databasenpm run db:switch:supabase # Switch to Supabase database
# Backup Operationsnpm run db:backup # Create configuration backup onlynpm run db:restore # Restore from previous backup
# Validation & Healthnpm run db:schema # Validate database schema compatibilityAdvanced Management CLI
Section titled “Advanced Management CLI”The npm run db:manage command provides additional operations:
# Test database connectionsnpm run db:manage test
# Run comprehensive health checksnpm run db:manage health
# List all tables in current databasenpm run db:manage tables
# Interactive switching with promptsnpm run db:manage switchDatabase Providers
Section titled “Database Providers”Supabase (PostgreSQL)
Section titled “Supabase (PostgreSQL)”Best for:
- Real-time subscriptions
- Advanced PostgreSQL features
- Row-level security (RLS)
- Built-in authentication integration
Configuration:
- Requires
SUPABASE_URLandSUPABASE_SERVICE_ROLE_KEY - Uses service role for server-side operations
- Supports real-time features and complex queries
Turso (LibSQL)
Section titled “Turso (LibSQL)”Best for:
- Low latency applications
- Edge deployment
- SQLite compatibility
- Simple data models
Configuration:
- Requires
TURSO_DATABASE_URLandTURSO_AUTH_TOKEN - Distributed SQLite with edge replication
- Fast read operations with eventual consistency
Common Use Cases
Section titled “Common Use Cases”Development Team Workflow
Section titled “Development Team Workflow”Perfect for teams working with different database preferences:
# Each developer chooses their preferred databasenpm run db:wizard
# Select Turso for fast local development# or Supabase for advanced features# Test with Tursonpm run db:switch:tursonpm run dev# Run your tests...
# Switch and test with Supabasenpm run db:switch:supabasenpm run dev# Run your tests...
# Restore original setupnpm run db:restoreProduction Deployment
Section titled “Production Deployment”For production environments, set explicit provider:
# Production .envDATABASE_PROVIDER=supabase # or turso# ... other production configsThis prevents auto-detection issues and ensures consistent behavior.
Safety Features
Section titled “Safety Features”Automatic Backups
Section titled “Automatic Backups”Every switching operation automatically:
- Backs up current configuration to
.env.backup - Tests new database connectivity before switching
- Validates the switch after completion
- Provides rollback option if issues occur
Rollback Protection
Section titled “Rollback Protection”If something goes wrong during switching:
# Automatic rollbacknpm run db:restore
# Manual rollback if neededcp .env.backup .envnpm run db:status # Verify restorationDry Run Mode
Section titled “Dry Run Mode”Preview changes without applying them:
# See what would happen without making changesnode scripts/switch-database.js --to turso --dry-runTroubleshooting
Section titled “Troubleshooting”For quick issues, try these common solutions:
🔧 Configuration Issues
“Database not configured” error: bash npm run db:status # Check what's missing npm run db:wizard # Run setup wizard
🔗 Connection Problems
Connection failures during switching: bash npm run db:manage test # Test connections npm run db:manage health # Run diagnostics
🎯 Provider Detection
Wrong provider selected: bash # Set explicit provider in .env echo "DATABASE_PROVIDER=turso" >> .env
🚨 Emergency Recovery
Something went wrong: bash npm run db:restore # Rollback to previous config
Comprehensive Troubleshooting
Section titled “Comprehensive Troubleshooting”For detailed problem diagnosis and resolution, see our Complete Database Troubleshooting Guide:
- Error Message Diagnosis - Step-by-step solutions for all common errors
- Provider-Specific Issues - Turso and Supabase specific problem resolution
- Switching Operation Failures - Backup, rollback, and recovery procedures
- Development Environment Issues - Module imports, hot reload, production differences
- Performance Optimization - Speed and memory issue resolution
- Advanced Debugging Tools - Detailed diagnostic techniques
Integration with Existing Code
Section titled “Integration with Existing Code”API Endpoints
Section titled “API Endpoints”All existing API endpoints automatically work with both databases:
import { getDatabase } from '#libs/database'
export const GET: APIRoute = async () => { const db = getDatabase() // Automatically uses active provider const data = await db.getEvents({ limit: 10 })
return new Response( JSON.stringify({ success: true, provider: db.getProviderName(), // Shows which DB is active data, }) )}Astro Components
Section titled “Astro Components”Dashboard components automatically adapt to the active provider:
---import { getDatabase } from '#libs/database'import type { Event } from '#libs/database-types'
let events: Event[] = []try { const db = getDatabase() events = await db.getEvents({ limit: 50 })} catch (error) { console.error('Database error:', error)}---
<div> { events.map(event => ( <div key={event.id}> <h3>{event.name}</h3> <p>{event.description}</p> </div> )) }</div>Best Practices
Section titled “Best Practices”Development
Section titled “Development”- Use
tursofor fast local development - Lower latency for frequent operations - Switch to
supabasefor testing advanced features - Real-time, RLS, advanced queries - Check
npm run db:statuswhen joining projects - Understand current configuration
Production
Section titled “Production”- Set
DATABASE_PROVIDERexplicitly - Prevent auto-detection issues - Use service role keys for Supabase - Never use anonymous keys server-side
- Monitor with
npm run db:manage health- Regular health checks
- Document database choices per environment - Clear team guidelines
- Use backup/restore for experiments - Safe configuration testing
- Share setup with
npm run db:wizard- Consistent team onboarding
Performance Considerations
Section titled “Performance Considerations”The abstraction layer is designed for minimal overhead:
- < 5ms additional latency measured in production
- Zero performance impact on database operations themselves
- Provider-specific optimizations preserved through abstraction
- Connection pooling and caching handled by underlying providers
Security Notes
Section titled “Security Notes”.env.backupfiles excluded from git automatically- Service role keys are server-side only for Supabase operations
- Credential validation before switching prevents invalid configurations
- Database switching requires filesystem access - consider for production deployment
Migration Path
Section titled “Migration Path”Existing Projects
Section titled “Existing Projects”If you have an existing project using only Turso or Supabase:
- Install the abstraction layer (already done in astro-basics)
- Update imports to use
getDatabase()instead of direct clients - Test existing functionality to ensure compatibility
- Configure second database when ready to switch
The system is designed to be 100% backward compatible - existing code continues working without changes.
Schema Compatibility
Section titled “Schema Compatibility”Validate schema compatibility between providers:
npm run db:schema # Check current schemanpm run db:manage tables # List available tablesBoth providers should have compatible table structures for seamless switching.
Advanced Features
Section titled “Advanced Features”Real-time Provider Switching
Section titled “Real-time Provider Switching”Unlike traditional database switching that requires server restarts, this system supports real-time switching:
// Database provider changes automatically without restartconst db = getDatabase() // Always returns currently configured providerProvider-Aware Error Handling
Section titled “Provider-Aware Error Handling”The system provides context-aware error messages:
try { const db = getDatabase() await db.insertClient(data)} catch (error) { // Error includes provider information for better debugging console.error(`Database operation failed (${db.getProviderName()}):`, error)}Schema Validation
Section titled “Schema Validation”Built-in schema validation ensures compatibility:
# Validate schema before switchingnpm run db:schema
# Reports:# - Missing tables# - Column mismatches# - Type incompatibilities# - Required migrationsFuture Enhancements
Section titled “Future Enhancements”The database abstraction system is designed to support:
- Additional providers (MySQL, MongoDB, etc.)
- Migration generation tools
- Schema synchronization between providers
- Advanced backup strategies (scheduled, remote storage)
- Performance monitoring and optimization
Getting Help
Section titled “Getting Help”If you encounter issues with the database switching system:
- Check status:
npm run db:statusfor current configuration - Test connections:
npm run db:manage testfor connectivity issues - Health check:
npm run db:manage healthfor comprehensive diagnostics - Reset configuration:
npm run db:wizardto start fresh
For detailed troubleshooting, see the comprehensive troubleshooting guide in the project documentation.
The database switching system transforms database management from a complex, error-prone process into a simple, safe operation that any team member can perform confidently. Whether you’re a solo developer or part of a large team, the system adapts to your workflow while maintaining the flexibility to switch providers as your needs evolve.