# SQLite Migration Summary

## Changes Made

The backend has been migrated from PostgreSQL to SQLite for both local development and production (Fly.io).

### Benefits of SQLite

1. **Simplified Deployment** - No separate database service needed
2. **Lower Cost** - Save ~$15/month (no Postgres hosting)
3. **Easier Development** - No need to install/run PostgreSQL locally
4. **Single File Database** - Easy backups and migrations
5. **Perfect for this use case** - Low concurrent writes, simple queries

## Modified Files

### Dependencies
- **package.json**
  - Removed: `pg`, `@types/pg`
  - Added: `better-sqlite3`, `@types/better-sqlite3`

### Database Configuration
- **src/config/database.ts**
  - Changed from `drizzle-orm/node-postgres` to `drizzle-orm/better-sqlite3`
  - Uses `DATABASE_PATH` instead of `DATABASE_URL`
  - Enabled WAL mode for better concurrent access

- **src/config/env.ts**
  - Changed `DATABASE_URL` to `DATABASE_PATH`
  - Default: `./data/gallus_cms.db`

- **src/db/schema.ts**
  - Changed from `pgTable` to `sqliteTable`
  - Changed `uuid()` to `text()` with `crypto.randomUUID()`
  - Changed `jsonb()` to `text(..., { mode: 'json' })`
  - Changed `timestamp()` to `integer(..., { mode: 'timestamp' })`
  - Changed `boolean()` to `integer(..., { mode: 'boolean' })`
  - Uses `sql\`(unixepoch())\`` for default timestamps

- **drizzle.config.ts**
  - Changed dialect from `postgresql` to `sqlite`
  - Uses `DATABASE_PATH` instead of `DATABASE_URL`

### Environment Files
- **.env** and **.env.example**
  - Changed `DATABASE_URL=postgresql://...` to `DATABASE_PATH=./data/gallus_cms.db`
  - Changed `GIT_WORKSPACE_DIR=/tmp/gallus-repo` to `./data/workspace`

### Docker Configuration
- **Dockerfile**
  - Added build tools for `better-sqlite3` native module (python3, make, g++)
  - Added `sqlite` CLI tool
  - Creates `/app/data` directory for database
  - Sets `DATABASE_PATH=/app/data/gallus_cms.db`
  - Proper permissions for non-root user

- **fly.toml**
  - Added `DATABASE_PATH` and `GIT_WORKSPACE_DIR` to [env]
  - Changed volume mount from `gallus_repo_workspace` to `gallus_data`
  - Mount destination: `/app/data` (contains both DB and git workspace)

### Documentation
- **README.md** - Updated setup instructions
- **DEPLOYMENT.md** - Removed Postgres setup, updated volume creation
- **SQLITE_MIGRATION.md** - This file!

## Local Development

### Setup
```bash
# Dependencies already installed
pnpm install

# Create data directory (done)
mkdir -p data

# Database will be created automatically at ./data/gallus_cms.db
```

### Generate and Run Migrations
```bash
# Generate migration files from schema
pnpm run db:generate

# Run migrations to create tables
pnpm run db:migrate
```

### Start Development Server
```bash
pnpm run dev
```

The database file will be created at `./data/gallus_cms.db` on first run.

## Production (Fly.io)

### Volume Setup
```bash
# Create single volume for both database and git workspace
flyctl volumes create gallus_data --size 2 --region ams
```

### Environment Variables
Set in fly.toml (non-sensitive):
- `DATABASE_PATH=/app/data/gallus_cms.db`
- `GIT_WORKSPACE_DIR=/app/data/workspace`

Set as secrets (sensitive):
- All other env vars (OAuth credentials, tokens, etc.)

### Deployment
```bash
flyctl deploy
```

Database will be created automatically on first start. No need for separate database service!

## Database Location

### Local Development
- **Database:** `./data/gallus_cms.db`
- **WAL files:** `./data/gallus_cms.db-wal`, `./data/gallus_cms.db-shm`
- **Git workspace:** `./data/workspace/`

### Production (Fly.io)
- **Database:** `/app/data/gallus_cms.db` (on volume)
- **Git workspace:** `/app/data/workspace/` (on volume)
- **Volume name:** `gallus_data` (2GB)

## Backup Strategy

### Manual Backup
```bash
# Local
cp data/gallus_cms.db data/gallus_cms.backup.db

# Production (Fly.io)
flyctl ssh console
sqlite3 /app/data/gallus_cms.db ".backup /app/data/backup.db"
# Then copy back: flyctl ssh sftp get /app/data/backup.db
```

### Automated Backup (Optional)
Consider setting up a cron job or Fly.io machine to periodically:
1. Create SQLite backup
2. Upload to S3/Backblaze/etc.

## Performance Notes

SQLite is perfect for this use case because:
- **Low write concurrency** - Single admin user making changes
- **Read-heavy** - Mostly reading content for publish operations
- **Small dataset** - Events, gallery images, content sections
- **Simple queries** - No complex joins or aggregations

WAL mode is enabled for:
- Better concurrent read access
- Safer writes (crash recovery)
- Improved performance

## Migration from Existing Data

If you had PostgreSQL data to migrate:

1. Export from Postgres:
```sql
\copy events TO 'events.csv' CSV HEADER;
\copy gallery_images TO 'gallery.csv' CSV HEADER;
-- etc.
```

2. Import to SQLite:
```sql
.mode csv
.import events.csv events
.import gallery.csv gallery_images
-- etc.
```

## Known Limitations

1. **No native UUID type** - Using TEXT with UUID format
2. **No native JSON type** - Using TEXT with JSON serialization (Drizzle handles this)
3. **No native TIMESTAMP** - Using INTEGER with Unix epoch (Drizzle handles this)
4. **Single writer** - Only one write transaction at a time (not an issue for this use case)

## Troubleshooting

### "Database is locked" error
- WAL mode should prevent this
- Check if multiple processes are accessing the database
- Ensure proper file permissions

### Native module build errors
- Make sure build tools are installed: `apt-get install python3 make g++` (Linux)
- On Alpine: `apk add python3 make g++`
- Try rebuilding: `pnpm rebuild better-sqlite3`

### Database file not found
- Check `DATABASE_PATH` is set correctly
- Ensure `data/` directory exists
- Check file permissions

## Next Steps

1. ✅ Update dependencies
2. ✅ Update database configuration
3. ✅ Update schema
4. ✅ Update Docker configuration
5. ⏳ Generate migrations: `pnpm run db:generate`
6. ⏳ Run migrations: `pnpm run db:migrate`
7. ⏳ Test development server: `pnpm run dev`
8. ⏳ Test publish flow
9. ⏳ Deploy to Fly.io

The migration is complete! Just need to generate/run migrations and test.
