Files
pgsql-jellyfin/docs/database/postgres-migration-guide.md
T
wjones c76853a442 PostgreSQL: Production fixes—UPSERT, remote backup, auth logs
- Fix: Atomic UPSERT for BaseItemProviders (resolves duplicate key errors during concurrent metadata refresh; clears navigation property to prevent EF Core tracking conflicts)
- Add: Remote PostgreSQL backup support (removes localhost-only restriction; works with pg_dump/pg_restore for both local and remote DBs)
- Add: Configurable backup disable option (`disable-backups`)
- Fix: Query timeout and performance (documented `command-timeout` config, added performance index scripts)
- Fix: Authentication errors now log as warnings with clear messages (ExceptionMiddleware), reducing log noise
- Fix: SyncPlay authorization handler validates user before lookup, logs warnings for unauthenticated/unknown users (returns 403/404)
- Fix: Database deadlock detection logs warnings and allows EF Core auto-retry
- Add: Configurable LibraryMonitorDelay (min 30s, default 60s)
- Fix: SQLite migration filtering—skip SQLite-only migrations on PostgreSQL
- Chore: Suppress StyleCop warnings (SA1137, etc.) for project consistency
- Docs: 21 documentation files added/updated (config, backup, performance, troubleshooting, session summary)
- All changes are backward compatible and production-ready
2026-03-03 16:35:27 -05:00

5.3 KiB

PostgreSQL Database Provider - Migration Guide

Overview

The Jellyfin.Database.Providers.Postgres project has been successfully created as a PostgreSQL alternative to the SQLite provider. This document outlines the key changes and migration path.

Project Structure

src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/
├── Jellyfin.Database.Providers.Postgres.csproj
├── PostgresDatabaseProvider.cs
├── ModelBuilderExtensions.cs
├── GlobalSuppressions.cs
├── Properties/
│   └── AssemblyInfo.cs
├── ValueConverters/
│   └── DateTimeKindValueConverter.cs
├── Migrations/
│   └── PostgresDesignTimeJellyfinDbFactory.cs
└── README.md

Key Differences from SQLite Provider

1. Database Provider Attribute

[JellyfinDatabaseProviderKey("Jellyfin-PostgreSQL")]

2. Connection String Builder

  • SQLite: SqliteConnectionStringBuilder
  • PostgreSQL: NpgsqlConnectionStringBuilder

3. Connection Options

SQLite:

  • DataSource (file path)
  • Cache mode
  • Journal mode
  • Pragma settings

PostgreSQL:

  • Host, Port
  • Database name
  • Username, Password
  • Connection pooling
  • Timeout settings

4. Optimization Commands

SQLite:

PRAGMA wal_checkpoint(TRUNCATE)
PRAGMA optimize
VACUUM

PostgreSQL:

VACUUM ANALYZE

5. Data Purge

SQLite:

DELETE FROM "table";

PostgreSQL:

TRUNCATE TABLE "table" CASCADE;

6. Backup/Restore

  • SQLite: File-based backup (Copy jellyfin.db)
  • PostgreSQL: Use pg_dump and pg_restore tools

Configuration Example

appsettings.json

{
  "Database": {
    "Provider": "Jellyfin-PostgreSQL",
    "CustomProviderOptions": {
      "Options": [
        { "Key": "host", "Value": "localhost" },
        { "Key": "port", "Value": "5432" },
        { "Key": "database", "Value": "jellyfin" },
        { "Key": "username", "Value": "jellyfin" },
        { "Key": "password", "Value": "your_password" }
      ]
    }
  }
}

Migration from SQLite to PostgreSQL

1. Export Data from SQLite

# Use a tool like pgloader or write custom migration scripts
sqlite3 jellyfin.db .dump > jellyfin_dump.sql

2. Transform SQL (if needed)

SQLite-specific SQL may need transformation for PostgreSQL compatibility:

  • INTEGER PRIMARY KEY → SERIAL PRIMARY KEY
  • DATETIME → TIMESTAMP
  • Boolean values (0/1 → false/true)

3. Import to PostgreSQL

# Create database
createdb -U jellyfin jellyfin

# Import (after transformation)
psql -U jellyfin -d jellyfin -f transformed_dump.sql

4. Update Configuration

Point Jellyfin to PostgreSQL using the configuration above.

Creating Migrations

cd src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres

# Add migration
dotnet ef migrations add MigrationName --context JellyfinDbContext

# Apply migrations
dotnet ef database update --context JellyfinDbContext

Package Dependencies

  • Npgsql.EntityFrameworkCore.PostgreSQL 9.0.2 (with EF Core 10 override)
  • Microsoft.EntityFrameworkCore 10.0.3
  • Microsoft.EntityFrameworkCore.Relational 10.0.3
  • Microsoft.EntityFrameworkCore.Design 10.0.3
  • Microsoft.EntityFrameworkCore.Tools 10.0.3

Note: When Npgsql 10.x is released, update Directory.Packages.props.

Testing

Unit Tests

Tests should be added to verify:

  1. Connection string building
  2. Migration application
  3. CRUD operations
  4. Transaction handling

Integration Tests

  1. Test against real PostgreSQL instance
  2. Verify data type mappings
  3. Test concurrent access
  4. Performance benchmarks

Known Limitations

  1. Version Compatibility: Using Npgsql 9.x with EF Core 10.x (temporary)
  2. Backup/Restore: Not implemented within provider (use PostgreSQL tools)
  3. Migrations: Will need to be generated fresh (not ported from SQLite)

Advantages of PostgreSQL

  1. Multi-user Support: Better concurrent access handling
  2. ACID Compliance: Full transaction support
  3. Scalability: Better performance with large datasets
  4. JSON Support: Native JSONB type for complex data
  5. Replication: Built-in master-slave replication
  6. Extensions: PostGIS, full-text search, etc.

Next Steps

  1. Generate Initial Migration

    dotnet ef migrations add InitialCreate --context JellyfinDbContext
    
  2. Test with Development Database

    • Set up local PostgreSQL
    • Apply migrations
    • Test Jellyfin functionality
  3. Performance Testing

    • Compare query performance vs SQLite
    • Optimize indexes
    • Tune PostgreSQL configuration
  4. Documentation

    • Update user documentation
    • Add deployment guides
    • Create troubleshooting guide
  5. CI/CD Integration

    • Add PostgreSQL to test pipeline
    • Test migrations in CI
    • Performance regression tests

Support

For issues specific to the PostgreSQL provider:

  1. Check PostgreSQL logs: /var/log/postgresql/
  2. Enable EF Core logging in Jellyfin
  3. Verify PostgreSQL version compatibility (12+)
  4. Check connection string in configuration

References