Database Seeding Plan
Last Updated: 2026-01-21
Purpose: Define what data should be seeded in production vs. development/test environments
Overview
Database seeding ensures that essential global data is available to all users. This document defines what should and should not be seeded, and how seeding should be implemented.
What to Seed (Production)
These items should be seeded in all environments (production, staging, development):
Global Content (userId = null)
-
Global Achievements ✅
- Achievement definitions available to all users
- Seeded via:
seed-gamification.ts - Idempotent: Uses upsert by
key
-
Global Shop Items ✅
- Items available in the shop for all users
- Seeded via:
seed-gamification.ts - Idempotent: Uses upsert by
key
-
Global Challenges ✅
- Challenge templates available to all users
- Seeded via:
seed-gamification.ts - Idempotent: Uses upsert by
key
-
Global Bounties ✅
- Bounty templates available to all users
- Seeded via:
seed-gamification.ts - Idempotent: Uses upsert by
key
-
Global Opponents (for battles) ✅
- Opponent templates for gamification battles
- Seeded via:
seed-gamification.ts - Idempotent: Uses upsert by
key
-
Global Journal Questions ✅
- Default journal questions available to all users
- Seeded via:
seed.ts(main seed function) - Idempotent: Checks for existing questions before creating
-
Exercise Catalog (Global Exercises) ✅
- Common exercises available to all users (userId = null)
- Seeded via:
seed-exercises.tsorseed.ts - Idempotent: Checks for existing exercises by name and userId = null
-
Seasonal Event Templates ✅
- Template seasonal events for holidays and seasonal celebrations
- Status: Complete
- Seeded via:
seed-seasonal-events.ts - Idempotent: Uses upsert by
key - Includes: Christmas, New Year, Valentine's Day, Easter, Summer, Halloween, Thanksgiving
-
One-time Event Templates ✅
- Template one-time events for milestones and special celebrations
- Status: Complete
- Seeded via:
seed-one-time-events.ts - Idempotent: Uses upsert by
key - Includes: Launch event, user count milestones, XP milestones, beta celebration
-
Default Week Settings Templates ⚠️
- Default week settings that new users can copy
- Status: Deferred - WeekSettings is user-specific (userId unique), not suitable for global templates
- Alternative: Consider creating example week settings documentation or admin interface for copying settings
What NOT to Seed (Production)
These items should never be seeded in production:
-
Users ❌
- Production databases should start clean
- Users register through the normal registration flow
- Exception: Development/test environments may seed demo users
-
User-Specific Data ❌
- Tasks, training sessions, journal entries
- Perimeter tasks, projects, deadlines
- People, relationships, interactions
- All data tied to a specific userId
-
User Gamification Data ❌
- User XP, coins, level, achievements earned
- User-owned items, collections, gear
- All gamification data tied to a specific userId
Seeding Implementation
Seed Script Structure
server/prisma/
├── seed.ts # Main seed script (production seeds only)
├── seed-dev.ts # Development/test seeds (demo user, test data)
├── seed-exercises.ts # Exercise catalog seeding
├── seed-gamification.ts # Gamification data seeding
├── seed-seasonal-events.ts # Seasonal event templates seeding
└── seed-one-time-events.ts # One-time event templates seeding
Seed Commands
{
"scripts": {
"prisma:seed": "tsx prisma/seed.ts", // Production seeds only (includes all seed scripts)
"prisma:seed:dev": "tsx prisma/seed-dev.ts", // Dev/test seeds
"prisma:seed:exercises": "tsx prisma/seed-exercises.ts", // Exercises only
"prisma:seed:gamification": "tsx prisma/seed-gamification.ts", // Gamification only
"prisma:seed:seasonal-events": "tsx prisma/seed-seasonal-events.ts", // Seasonal events only
"prisma:seed:one-time-events": "tsx prisma/seed-one-time-events.ts", // One-time events only
"prisma:seed:all": "tsx prisma/seed.ts && tsx prisma/seed-gamification.ts" // All production seeds
}
}
Idempotency Requirements
All seed scripts must be idempotent - safe to run multiple times:
- Use
upsertoperations where possible - Check for existing records before creating
- Use unique keys/identifiers (e.g., achievement
key, exercisename+userId) - Never delete existing data (only create/update)
Seed Script Pattern
async function seedGlobalData() {
console.log('Seeding global data...');
// Check if already seeded
const existing = await prisma.achievement.findFirst({
where: { key: 'FIRST_LOGIN', userId: null }
});
if (existing) {
console.log(' ✓ Global data already seeded, skipping...');
return;
}
// Seed data using upsert
await prisma.achievement.upsert({
where: { key: 'FIRST_LOGIN' },
update: {},
create: { /* ... */ }
});
console.log(' ✓ Global data seeded successfully');
}
Development/Test Seeding
For development and testing, additional seed scripts can create:
-
Demo User (development only)
- Email:
demo@arcos.local - Password:
demo123 - Pre-populated with sample data for testing
- Email:
-
Test Users (testing only)
- Created via separate test utilities
- Clearly marked for easy cleanup
- Pattern:
test-*@example.com
Creating Test Users
Test users should be created via test utilities, not seed scripts:
// server/src/utils/test-helpers.ts
export async function createTestUser(email: string): Promise<User> {
// Creates test user with pattern: test-*@example.com
// Automatically cleaned up in test teardown
}
Deployment Seeding
Production Deployment
# Run production seeds only (no users, no demo data)
pnpm prisma db seed
Development Setup
# Run production seeds
pnpm prisma db seed
# Run development seeds (demo user, test data)
# Note: Development seeds should be separate from production seeds
# See seed.ts for current implementation
Docker Deployment
# In docker-compose.yml or deployment script
docker compose exec server pnpm prisma db seed
Seed Script Checklist
When creating or updating seed scripts:
- Script is idempotent (safe to run multiple times)
- Uses
upsertor checks for existing records - Only seeds global data (userId = null where applicable)
- Does not seed users or user-specific data
- Includes clear console logging
- Handles errors gracefully
- Documented in this file
Current Seed Status
| Category | Status | Script | Idempotent |
|---|---|---|---|
| Global Achievements | ✅ Complete | seed-gamification.ts | ✅ Yes |
| Global Shop Items | ✅ Complete | seed-gamification.ts | ✅ Yes |
| Global Challenges | ✅ Complete | seed-gamification.ts | ✅ Yes |
| Global Bounties | ✅ Complete | seed-gamification.ts | ✅ Yes |
| Global Opponents | ✅ Complete | seed-gamification.ts | ✅ Yes |
| Global Journal Questions | ✅ Complete | seed.ts | ✅ Yes |
| Exercise Catalog | ✅ Complete | seed-exercises.ts | ✅ Yes |
| Seasonal Event Templates | ✅ Complete | seed-seasonal-events.ts | ✅ Yes |
| One-time Event Templates | ✅ Complete | seed-one-time-events.ts | ✅ Yes |
| Default Week Settings | ⚠️ Deferred | - | - |
Future Enhancements
- Separate seed modules for each category
- Seed validation to ensure data integrity
- Seed rollback capability (if needed)
- Seed versioning to track changes
- Admin interface for managing seed data
Notes
- The current
seed.tsmixes production seeds with demo user creation - This should be refactored to separate production seeds from dev/test seeds
- Demo user creation should be moved to
seed-dev.ts - All production seeds should be idempotent and safe to run in production