Files
pgsql-jellyfin/docs/DATABASE_SCHEMA_CREATION.md
T
wjones a3eb4b1b57 Add automatic PostgreSQL database creation and migration
- Added Jellyfin.Database.Providers.Postgres project with full EF Core migration support for PostgreSQL.
- Implemented automatic database creation and privilege assignment on startup.
- Generated initial migration and model snapshot for PostgreSQL schema.
- Updated build, test, and dependency files to include PostgreSQL provider and Npgsql packages.
- Added PowerShell script for generating and testing PostgreSQL migrations.
- No changes to application logic outside database provider/migration infrastructure.
2026-02-22 18:51:24 -05:00

7.5 KiB

Database Schema Creation - How It Works

Yes! The Database Schema is Created Automatically

Jellyfin has a sophisticated migration system that automatically creates all database tables when you first run it with a new database provider.

How It Works

1. First-Time Initialization (New Installation)

When Jellyfin starts for the first time:

// From JellyfinMigrationService.cs lines 113-118
var databaseCreator = dbContext.Database.GetService<IDatabaseCreator>() as IRelationalDatabaseCreator;
if (!await databaseCreator.ExistsAsync().ConfigureAwait(false))
{
    await databaseCreator.CreateAsync().ConfigureAwait(false);
}

What happens:

  1. Checks if database exists
  2. If not, creates the database
  3. Creates the __EFMigrationsHistory table to track applied migrations
  4. Seeds initial migration records

2. Migration Application

The JellyfinMigrationService manages two types of migrations:

A. Database Migrations (EF Core Schema Migrations)

These create the actual tables, columns, indexes, and constraints.

SQLite: Has 75+ migration files (as of current version)

  • Located in: src\Jellyfin.Database\Jellyfin.Database.Providers.Sqlite\Migrations\
  • Examples:
    • 20200514181226_AddActivityLog.cs
    • 20200613202153_AddUsers.cs
    • 20241020103111_LibraryDbMigration.cs

PostgreSQL: Currently has NO migration files yet ⚠️

B. Code Migrations (Data Migrations)

These handle data transformations and post-schema setup tasks.

// From JellyfinMigrationService.cs lines 459-460
var migrator = _jellyfinDbContext.GetService<IMigrator>();
await migrator.MigrateAsync(_databaseMigrationInfo.Key).ConfigureAwait(false);

3. Migration Stages

Migrations run in specific stages during startup:

public enum JellyfinMigrationStageTypes
{
    PreStartup,
    CoreInitialisation,  // <- Database schema created here
    PostStartup
}

CoreInitialisation Stage is where:

  • EF Core migrations are applied
  • Database schema (tables) is created
  • Indexes and constraints are added

Current PostgreSQL Status

⚠️ Important: PostgreSQL Migrations Need to Be Generated

The PostgreSQL provider is missing EF Core migration files. This means:

What's Missing:

  • No .cs migration files in src\Jellyfin.Database\Jellyfin.Database.Providers.Postgres\Migrations\
  • Schema won't be created automatically for PostgreSQL
  • First run will fail or create empty database

What Exists:

  • PostgresDesignTimeJellyfinDbFactory.cs - Design-time factory for generating migrations
  • PostgreSQL provider implementation
  • Connection and configuration code

How to Generate PostgreSQL Migrations

You need to generate the initial migration that creates all tables:

# Navigate to the PostgreSQL provider project
cd src\Jellyfin.Database\Jellyfin.Database.Providers.Postgres

# Generate initial migration (creates all tables)
dotnet ef migrations add InitialCreate --context JellyfinDbContext --output-dir Migrations

# Or, copy and adapt migrations from SQLite provider
# This is more complex but ensures parity with SQLite schema

Alternative: Runtime Schema Creation (Development Only)

For development/testing, you could modify the code to use EnsureCreated():

// WARNING: Only for development - bypasses migration system
await dbContext.Database.EnsureCreatedAsync().ConfigureAwait(false);

⚠️ Don't use in production - this bypasses the migration history system.

What Gets Created

When migrations run properly, they create these tables:

Core Tables (from JellyfinDbContext.cs)

  • Users - User accounts
  • Permissions - User permissions
  • Preferences - User preferences
  • AccessSchedules - Access time restrictions
  • ActivityLogs - Activity/audit logs
  • ApiKeys - API authentication keys
  • Devices - Client devices
  • DeviceOptions - Device-specific settings
  • DisplayPreferences - UI display settings
  • ItemDisplayPreferences - Item-specific display settings
  • CustomItemDisplayPreferences - Custom item preferences
  • ImageInfos - Image metadata
  • TrickplayInfos - Video preview thumbnails metadata
  • MediaSegments - Video chapter/intro/credits data

Library Tables (from BaseItemRepository)

  • BaseItems - Media library items (movies, shows, etc.)
  • AncestorIds - Item hierarchy relationships
  • AttachmentStreamInfos - Subtitle/attachment metadata
  • Chapters - Video chapter information
  • ItemValues - Genre/Studio/Artist tags
  • ItemValuesMap - Tag-to-item relationships
  • MediaStreamInfos - Audio/video stream metadata
  • UserData - Watch history, ratings, favorites

System Tables

  • __EFMigrationsHistory - Tracks applied migrations

Verifying Schema Creation

After Jellyfin Starts Successfully

SQLite:

sqlite3 data/jellyfin.db ".tables"

PostgreSQL:

psql -U jellyfin -d jellyfin -c "\dt"

You should see all the tables listed above.

Checking Migration History

PostgreSQL:

SELECT * FROM "__EFMigrationsHistory" ORDER BY "MigrationId";

This shows which migrations have been applied.

Troubleshooting

Error: "Table does not exist"

Cause: Migrations haven't been applied

Solution:

  1. Check logs for migration errors
  2. Verify database connection
  3. Ensure migrations exist in the provider assembly
  4. Manually run: dotnet ef database update

PostgreSQL: No Tables Created

Cause: PostgreSQL provider has no migration files

Solution: Generate migrations:

cd src\Jellyfin.Database\Jellyfin.Database.Providers.Postgres
dotnet ef migrations add InitialCreate --context JellyfinDbContext

Migration Fails

Cause: Database permissions, connection issues, or corrupt migration

Solution:

  1. Check database user has CREATE TABLE permissions
  2. Verify connection string
  3. Check logs: <config-dir>/logs/
  4. Restore from backup if available

Best Practices

For Development

  1. Keep migrations in sync between providers
  2. Test migrations before deploying
  3. Backup database before applying migrations
  4. Use source control for migration files

For Production

  1. Never use EnsureCreated() - always use migrations
  2. Backup before upgrades that include migrations
  3. Test migrations in staging environment first
  4. Monitor logs during first startup with new database

For Contributors

If adding new tables/columns:

  1. Update JellyfinDbContext with new DbSets
  2. Generate migrations for ALL providers (SQLite, PostgreSQL)
  3. Test migration on clean database
  4. Include migration in pull request

Migration Workflow

Startup → Check Database Exists → Create if Missing
    ↓
Load Migration History
    ↓
Find Pending Migrations (compare applied vs available)
    ↓
Apply Each Migration in Order:
    - Database Migrations (schema changes)
    - Code Migrations (data transformations)
    ↓
Update Migration History
    ↓
Continue Jellyfin Startup

Summary

Question: Is there code to create the database and tables?

Answer: YES!

  • Database creation: Automatic via IDatabaseCreator
  • Table schema: Via EF Core migrations
  • Migration tracking: Via __EFMigrationsHistory
  • Automatic application: Via JellyfinMigrationService
  • ⚠️ PostgreSQL: Requires migration files to be generated first

The system is fully automatic once migrations exist for your database provider. SQLite is ready to go. PostgreSQL needs its migrations generated using the dotnet ef migrations add command.