Skip to content

Upgrading

club follows semantic versioning. The database schema is applied idempotently on every startup, so upgrading is typically as simple as pulling a new image and restarting — there are no manual migration commands.

Before You Upgrade

  1. Read the release notes for the version you are upgrading to. Check for breaking changes or special migration instructions.

  2. Back up your data. See Backup & Restore for instructions. At minimum, back up the metadata store (database).

  3. Test in a staging environment if possible, especially for major version upgrades.


Upgrade Steps

  1. Back up your data:

    Terminal window
    # SQLite
    sqlite3 /data/club.db ".backup /backups/club-pre-upgrade.db"
    # Filesystem blobs
    tar -czf /backups/packages-pre-upgrade.tar.gz -C /data packages/
  2. Pull the new image:

    Terminal window
    docker pull club:latest
    # Or pin to a specific version:
    docker pull club:1.2.0
  3. Stop the current container:

    Terminal window
    docker compose down
  4. Start with the new image:

    Terminal window
    docker compose up -d
  5. Verify the upgrade:

    Terminal window
    # Check health
    curl https://packages.example.com/api/v1/health
    # Check version in response
    curl -s https://packages.example.com/api/v1/health | jq .version
    # Tail logs for any errors during schema application
    docker compose logs club --tail 50

If using a specific version tag in your docker-compose.yml, update it:

services:
club:
image: club:1.2.0 # Update version here

Schema Behavior

Idempotent, Not Versioned

club does not use a versioned migration table. Instead, the entire schema is expressed as a list of idempotent statements that run on every server startup:

  • CREATE TABLE IF NOT EXISTS ...
  • CREATE INDEX IF NOT EXISTS ...
  • ALTER TABLE ... ADD COLUMN ... (with duplicate-column errors caught)
  • CREATE VIRTUAL TABLE IF NOT EXISTS ... USING fts5(...)

There is no schema_migrations table. There are no numbered script files. Every boot re-applies the full schema; the IF NOT EXISTS clauses and column-exists guards make this safe.

What This Means for Upgrades

ScenarioBehavior
New tables added in the new versionCreated on first boot of the new binary
New columns added to existing tablesAdded via ALTER TABLE on first boot
New indexesCreated on first boot
Column renames or dropsRequire explicit, release-specific data migration code — see release notes
Unchanged schemaNo-op; schema statements re-run but nothing changes

You do not run a “migrate” command before or after upgrading. The server applies the schema during boot, before it starts accepting requests.


Rollback Procedure

If an upgrade causes issues, you can roll back to the previous version.

  1. Stop the server:

    Terminal window
    docker compose down
    # or: systemctl stop club
  2. Restore the database from backup:

    Terminal window
    # SQLite
    cp /backups/club-pre-upgrade.db /data/club.db
    # PostgreSQL
    pg_restore -h db.example.com -U club -d club /backups/club-pre-upgrade.dump
  3. Restore blob storage if needed:

    Terminal window
    tar -xzf /backups/packages-pre-upgrade.tar.gz -C /data
  4. Switch back to the previous version:

    Terminal window
    # Docker
    # Edit docker-compose.yml to use the previous image tag
    docker compose up -d
    # From source
    git checkout v1.1.0
    dart build cli -t packages/club_server/bin/server.dart -o build/server
    sudo cp build/server/bundle/bin/server /usr/local/bin/club
    systemctl start club
  5. Verify the rollback:

    Terminal window
    curl https://packages.example.com/api/v1/health

Any packages published or tokens created after the upgrade are lost with the database restore. This is why backing up before upgrading is critical.


Version Pinning

For production deployments, always pin to a specific version rather than using latest:

docker-compose.yml
services:
club:
image: club:1.2.0 # Pin to specific version

This prevents accidental upgrades and ensures reproducible deployments. Update the version tag deliberately after testing.