Skip to content

Latest commit

 

History

History
168 lines (124 loc) · 6.77 KB

File metadata and controls

168 lines (124 loc) · 6.77 KB

Platform Storage Strategy

Executive Summary

Recommendation: Use graceful degradation with platform-specific optimizations and automatic adapter selection.

// Single API for all platforms
import { createDatabase } from '@framers/sql-storage-adapter';

const db = await createDatabase({ 
  priority: ['indexeddb', 'sqljs'],  // Auto-detects best adapter
});

Platform Matrix: Pros & Cons

🌐 Web (Browser)

Adapter Pros Cons Best For
IndexedDB (NEW) ✅ Native browser storage API
✅ Async, non-blocking
✅ 50MB-1GB+ quota
✅ sql.js wrapper (full SQL support)
✅ Persistent across sessions
❌ Uses sql.js WASM (500KB load)
❌ IndexedDB quotas vary by browser
❌ Not a separate SQL engine (sql.js + IDB persistence)
Primary choice for web
Offline PWAs
Privacy-first apps
sql.js ✅ Full SQLite in WASM
✅ In-memory fast reads
✅ Optional IDB persistence
✅ Zero dependencies
❌ 500KB WASM load
❌ Slow writes to IDB
❌ Single-threaded
Fallback for web
Edge functions
LocalStorage ✅ 5-10MB simple API ❌ Synchronous (blocks UI)
❌ String-only
❌ No transactions
NOT RECOMMENDED

Winner: IndexedDB adapter (sql.js + IndexedDB persistence wrapper)

  • sql.js provides SQL execution (WASM SQLite)
  • IndexedDB provides browser-native persistence (stores SQLite file as blob)
  • Auto-save batching minimizes IDB overhead
  • Works offline, respects privacy
  • Note: This is sql.js with IndexedDB persistence, not a separate SQL engine

🖥️ Electron (Desktop)

Adapter Pros Cons Best For
better-sqlite3 FASTEST (native C++)
✅ Full SQLite features
✅ WAL mode for concurrency
✅ Synchronous API (no async overhead)
✅ Mature, battle-tested
❌ Requires native compilation
❌ Must rebuild for Electron ABI
❌ Large binary (~5MB)
Primary choice for Electron
Production desktop apps
sql.js ✅ No rebuild needed
✅ Cross-platform WASM
❌ 3-5x slower than native
❌ Async overhead
Quick prototyping
CI/CD without build tools
IndexedDB ✅ Available in Electron renderer ❌ Slower than better-sqlite3
❌ Unnecessary abstraction
❌ Use better-sqlite3 instead

Winner: better-sqlite3

  • Native performance is unbeatable for desktop
  • Electron already handles native modules
  • Fallback to sql.js if build fails

📱 Mobile (Capacitor: iOS/Android)

Adapter Pros Cons Best For
@capacitor-community/sqlite BEST native SQLite on mobile
✅ iOS: Core Data integration
✅ Android: Native SQLite
✅ Encryption support
✅ Multi-threaded
❌ Capacitor-specific
❌ Requires native plugins
Primary choice for mobile
Capacitor apps only
IndexedDB ✅ Available in WebView
✅ Works without Capacitor
❌ Slower than native
❌ Limited mobile quota
❌ Browser quirks on mobile
PWA-style mobile apps
Ionic without Capacitor
sql.js ✅ Universal fallback ❌ WASM overhead on mobile
❌ Battery drain
Emergency fallback only

Winner: @capacitor-community/sqlite for Capacitor apps, IndexedDB for web-based mobile


☁️ Cloud (Node.js, Serverless)

Adapter Pros Cons Best For
PostgreSQL BEST for multi-user
✅ Connection pooling
✅ JSONB, full-text search
✅ Horizontal scaling
✅ Cloud-native (RDS, Supabase, Neon)
❌ Requires hosted DB
❌ Network latency
❌ Cost at scale
Primary choice for cloud
Multi-tenant SaaS
Real-time sync
better-sqlite3 ✅ Fast for single-user
✅ No external DB needed
✅ Simple deployment
❌ File-based (hard to scale)
❌ No network access
❌ Single-writer limitation
Personal cloud instances
Dev/staging
sql.js (ephemeral) ✅ Serverless edge (Cloudflare Workers)
✅ No cold start for DB
❌ In-memory only
❌ State lost on restart
Stateless functions
Cache layer

Winner: PostgreSQL for production, better-sqlite3 for dev/staging


Graceful Degradation Strategy

Priority Cascade by Platform

const PLATFORM_PRIORITIES: Record<Platform, AdapterKind[]> = {
  web: ['indexeddb', 'sqljs'],                    // NEW: IndexedDB first
  electron: ['better-sqlite3', 'sqljs'],          // Native first
  capacitor: ['capacitor', 'indexeddb', 'sqljs'], // Native mobile > WebView IDB
  node: ['better-sqlite3', 'postgres', 'sqljs'],  // Native > Cloud > WASM
  cloud: ['postgres', 'better-sqlite3', 'sqljs'], // Cloud-first
};

Automatic Detection

function detectPlatform(): Platform {
  if (typeof window !== 'undefined') {
    if (window.Capacitor?.isNativePlatform?.()) return 'capacitor';
    if (window.indexedDB) return 'web';
  }
  if (typeof process !== 'undefined') {
    if (process.versions?.electron) return 'electron';
    if (process.env.DATABASE_URL) return 'cloud';
    return 'node';
  }
  return 'unknown';
}

Usage Examples

Web Application

import { IndexedDbAdapter } from '@framers/sql-storage-adapter';

const db = new IndexedDbAdapter({
  dbName: 'my-app-db',
  autoSave: true,
  saveIntervalMs: 5000,
});

await db.open();
await db.run('CREATE TABLE sessions (id TEXT PRIMARY KEY, data TEXT)');

Desktop Application (Electron)

import { createDatabase } from '@framers/sql-storage-adapter';
import path from 'path';

const db = await createDatabase({
  filePath: path.join(app.getPath('userData'), 'app.db'),
});

await db.open();

Mobile Application (Capacitor)

import { createDatabase } from '@framers/sql-storage-adapter';

const db = await createDatabase({
  priority: ['capacitor', 'indexeddb'],
});

Cloud Application (Node.js)

import { createDatabase } from '@framers/sql-storage-adapter';

const db = await createDatabase({
  postgres: { connectionString: process.env.DATABASE_URL },
});

Summary Table

Platform Primary Fallback Notes
Web IndexedDB sql.js Browser-native persistence
Electron better-sqlite3 sql.js Native performance
Capacitor capacitor IndexedDB Native mobile > WebView
Node better-sqlite3 Postgres Local-first, cloud optional
Cloud Postgres better-sqlite3 Multi-tenant requires Postgres

TL;DR: Use IndexedDB for web, better-sqlite3 for desktop, capacitor for mobile, Postgres for cloud. The adapter automatically selects the best option based on your runtime environment.