Database Migrations Guide
This guide documents the database schema changes and migration process for Hyperscape.Overview
Hyperscape uses Drizzle ORM for database schema management and migrations. The database stores persistent game data including characters, inventory, skills, bank, and world state. Database: PostgreSQL (production), SQLite (local development fallback) Migration Tool: Drizzle Kit Migration Location:packages/server/src/database/migrations/
Recent Migrations
Migration 0029: Crafting Skill (PR #698)
Date: 2026-01-30 Changes:- All existing characters get crafting level 1, XP 0
- New characters start with crafting level 1, XP 0
- No data loss or character reset required
Migration 0030: Fletching Skill (PR #699)
Date: 2026-01-31 Changes:- All existing characters get fletching level 1, XP 0
- New characters start with fletching level 1, XP 0
- No data loss or character reset required
Migration 0031: Runecrafting Skill (PR #703)
Date: 2026-01-31 Changes:- All existing characters get runecrafting level 1, XP 0
- New characters start with runecrafting level 1, XP 0
- No data loss or character reset required
Complete Skill Schema
Thecharacters table now includes 17 skills (34 columns total):
Combat Skills (14 columns)
Gathering Skills (6 columns)
Production Skills (14 columns)
Running Migrations
Automatic Migration (Development)
Migrations run automatically when the server starts in development mode:Manual Migration (Production)
For production deployments, run migrations manually before deploying:Generate New Migration
When you modify the schema inpackages/server/src/database/schema.ts:
packages/server/src/database/migrations/.
Push Schema Changes (Development Only)
For rapid iteration in development, push schema changes directly without migrations:Migration Best Practices
1. Always Use IF NOT EXISTS
2. Provide Default Values
All new columns should have sensible defaults:3. Test Migrations Locally First
Before deploying:-
Reset local database:
-
Start fresh and verify migration:
- Check migration logs in console
-
Verify schema in database:
4. Keep Migrations Small and Focused
Each migration should do ONE thing:- ✅ Add crafting skill columns
- ❌ Add crafting skill columns + modify inventory table + add new items
5. Document Breaking Changes
If a migration requires data transformation or has breaking changes, document it:Schema Conventions
Naming
- Tables: Lowercase, plural (e.g.,
characters,items,bank_items) - Columns: camelCase (e.g.,
craftingLevel,fletchingXp) - Indexes:
{table}_{column}_idx(e.g.,characters_username_idx) - Foreign Keys:
{table}_{column}_fkey(e.g.,bank_items_characterId_fkey)
Skill Columns
Each skill has two columns:{skill}Level- Current level (1-99){skill}Xp- Current XP (0-200,000,000)
Data Types
- Levels:
integer(1-99) - XP:
integer(0-200,000,000) - IDs:
text(UUIDs or custom IDs) - Timestamps:
timestamp(with timezone) - Booleans:
boolean - JSON:
jsonb(for complex data like equipment stats)
Migration History
Skills Migrations
Other Notable Migrations
Rollback Procedure
Drizzle does not support automatic rollbacks. To rollback a migration:1. Identify the Migration
Find the migration file inpackages/server/src/database/migrations/.
2. Write Reverse SQL
Create a reverse migration manually:3. Apply Reverse Migration
4. Update Migration Journal
Editpackages/server/src/database/migrations/meta/_journal.json to remove the migration entry.
⚠️ Warning: Manual rollbacks can cause data loss. Always backup before rolling back.
Adding a New Skill
To add a new skill to the database:1. Update Schema
Editpackages/server/src/database/schema.ts:
2. Generate Migration
0032_add_herblore_skill.sql.
3. Review Migration
Check the generated SQL:4. Test Migration
5. Update Repository Code
UpdateCharacterRepository.ts to load/save new skill:
6. Commit Migration
Commit both the schema change and generated migration:Database Reset (Development)
To completely reset your local database:Production Deployment
Pre-Deployment Checklist
- All migrations tested locally
- Schema changes reviewed
- Default values set for new columns
- Backward compatibility verified
- Rollback plan documented
Deployment Steps
-
Backup Database:
-
Run Migrations:
-
Verify Schema:
-
Deploy Application:
- Monitor Logs: Check for migration errors or schema issues.
Rollback Plan
If deployment fails:-
Restore Database:
-
Revert Code:
- Redeploy Previous Version
Migration Troubleshooting
Migration Already Applied
Symptom: Migration fails with “column already exists” error. Cause: Migration was already applied but journal not updated. Fix: UseIF NOT EXISTS in migrations (already done for all skill migrations).
Migration Fails Midway
Symptom: Some columns added, others failed. Cause: SQL error in migration file. Fix:- Check error message for specific SQL issue
- Fix migration file
- Manually drop partially-added columns
- Re-run migration
Schema Out of Sync
Symptom: Code expects columns that don’t exist in database. Cause: Migrations not run after pulling updates. Fix:Wrong Default Value
Symptom: New characters have incorrect starting skill levels. Cause: Default value in migration doesn’t match game logic. Fix: Create a new migration to update the default:Schema Documentation
Characters Table
Primary Key:id (text, UUID)
Core Columns:
username- Character name (unique)userId- Owner’s user ID (foreign key)createdAt- Creation timestamplastLogin- Last login timestampisAgent- Boolean flag for AI agents
x,y,z- World position (real)rotationX,rotationY,rotationZ,rotationW- Quaternion rotation
health- Current HP (integer)maxHealth- Max HP (integer)combatLevel- Calculated combat level (integer)attackStyle- Current attack style (text)autoRetaliate- Auto-retaliate flag (boolean)
- See Complete Skill Schema above
equippedWeapon,equippedShield,equippedHelmet, etc. (text, item IDs)
coins- Coin pouch amount (integer)avatarUrl- VRM avatar URL (text)walletAddress- Blockchain wallet (text)templateConfig- AI agent template (jsonb)
Inventory Table
Primary Key:id (text, UUID)
Columns:
characterId- Owner character ID (foreign key)itemId- Item type ID (text)quantity- Stack size (integer, >= 1)slot- Inventory slot (integer, 0-27)metadata- Item metadata (jsonb)
- Unique:
(characterId, slot)- One item per slot - Check:
quantity >= 1- No zero-quantity items
Bank Items Table
Primary Key:id (text, UUID)
Columns:
characterId- Owner character ID (foreign key)itemId- Item type ID (text)quantity- Stack size (integer)slot- Bank slot (integer, 0-479)tab- Bank tab (integer, 0-8)isPlaceholder- Placeholder flag (boolean)
- Unique:
(characterId, slot)- One item per slot
Drizzle Kit Commands
Generate Migration
Create a new migration from schema changes:src/database/migrations/
Apply Migrations
Run pending migrations:Push Schema (Dev Only)
Push schema changes directly without migrations:Introspect Database
Generate schema from existing database:Studio (Database GUI)
Open Drizzle Studio to browse database:https://local.drizzle.studio
Environment Variables
Development
Production
- Neon - Serverless PostgreSQL
- Supabase - PostgreSQL with extras
- Railway - PostgreSQL + hosting
- Fly.io - PostgreSQL + hosting
Migration File Format
File Naming
Format:{number}_{description}.sql
Examples:
0029_add_crafting_skill.sql0030_add_fletching_skill.sql0031_add_runecrafting_skill.sql
File Structure
--> statement-breakpoint is required between statements for Drizzle to parse correctly.
Meta Files
Drizzle generates metadata files inmigrations/meta/:
_journal.json- Migration history{number}_snapshot.json- Schema snapshot after migration
Common Migration Patterns
Add Skill Columns
Add Table
Add Index
Add Constraint
Modify Column
Data Integrity
Foreign Keys
All foreign keys useON DELETE CASCADE to maintain referential integrity:
Constraints
Inventory Quantity:Performance Considerations
Indexes
Add indexes for frequently queried columns:JSONB Columns
Use JSONB for complex data that doesn’t need relational queries:- Flexible schema
- No joins required
- GIN indexes for fast queries
- Can’t enforce constraints
- Harder to query specific fields
See Also
- README.md - Project documentation
- CLAUDE.md - Development guidelines
- SKILLS.md - Skills system overview
- Drizzle ORM Docs - Official documentation