Skip to main content

Rollback from v3 to v2

The scripts below reverse the built-in Nexus 3.0 database upgrade for PostgreSQL and SQL Server. Nexus automatically captures a v2 rollback checkpoint during the first upgrade, before queue initialization or regular migrations change the database. You do not need to remember to run a separate capture script. The rollback restores the v2 schema and saved settings while retaining messages and job history written since the upgrade.

A database rollback cannot undo work already processed, external side effects, or broker changes. To restore the exact pre-upgrade database contents, restore the full v2 backup instead. Coordinate that restore with application data and brokers so that already processed work is not unintentionally repeated.

Download the scripts​

DatabaseScriptSettings at the top of the file
PostgreSQLv3-to-v2-postgres.sqltarget_schema (default public)
SQL Serverv3-to-v2-sqlserver.sql@TargetSchema (default dbo)

These files only perform rollback, using the checkpoint Nexus created internally during the upgrade. Set the schema, then run the whole file as one script against the intended database. Do not execute selected statements. For SQL Server, run it as one batch, outside an existing transaction. The rollback script requires database compatibility level 130 or later; automatic checkpoint capture during upgrade does not impose that requirement.

The scripts target the built-in v3.0 migrations and an installation whose Nexus framework and queue tables reside in one schema. Set the schema explicitly; PostgreSQL's search path does not determine the rollback scope. Separate Nexus databases need separate checkpoints and rehearsals. Include memory-queue fallback databases in the rollback plan too; a fallback-only database without the framework migration/key-value tables needs an adapted script or backup restoration.

Do not use these files unchanged for a later release that adds migrations, an application-specific database provider, or an installation split across schemas. Review the additional changes first.

Prepare before upgrading​

  1. Deploy and run the latest v2, and let database and queue initialization finish everywhere. The scripts cannot establish which package version was actually deployed.
  2. Rehearse the upgrade and rollback against a disposable copy of that database, using the intended v2 and v3 application artifacts. Include representative persisted messages, parameters, filters, and broker integrations.
  3. At cutover, stop all Nexus producers and workers, including separately hosted producers and memory-queue hosts. Let in-flight processing finish or resolve its leases with v2 before upgrading.
  4. Take a full v2 database backup and preserve the v2 application artifact, configuration, broker resources, and offsets/backlog recovery plan. Automatic checkpoint capture does not replace these backups.
  5. Start v3. Under the database startup lock, Nexus captures nexus_v2_rollback_checkpoint or NexusV2RollbackCheckpoint before idempotent queue initialization, table renames, or category conversion. Verify the checkpoint and successful initialization before resuming normal traffic. Keep the checkpoint table.

Checkpoint capture belongs to Nexus's database initialization; there is no capture script to run or download. If capture fails, the upgrade stops before queue initialization and regular migrations proceed; fix the capture failure before retrying.

Fresh v3 installations have no v2 state and do not create a checkpoint. If an upgrade is interrupted after capture, retrying preserves the original checkpoint even if queue/schema changes have already started. Capture does not run on the normal cached startup path.

At upgrade, the checkpoint captures settings, category JSON, migration history, and queue schema/index definitions, not the queued messages. During rollback it also archives incompatible health-check results/statistics and v3-only instance events before removing them from active tables. Allow space for that archive, especially when health-check history is large. It is not a substitute for a full backup.

Job categories need special handling because v3 replaces ScheduledJobCategories with JobCategories and serializes the renamed types again. Simply changing the key or replacing type names in JSON does not restore the original type hashes or custom serializer output. The checkpoint preserves that original value exactly.

If v3 has already run without a checkpoint, the original values cannot be recovered reliably from the upgraded database. Nexus does not manufacture a v2 checkpoint from v3 state. The rollback script refuses to proceed without its checkpoint, rather than silently losing the original category JSON or other settings. Restore the v2 backup, or prepare and rehearse an installation-specific rollback using the original settings and schema from that backup. Simply installing a build with automatic capture after upgrading cannot recover that earlier state.

What rollback restores​

ChangeRollback action
Six renamed job tablesRename jobs, runs, progress, mutexes, logs, and extra runs back to their ScheduledJob names. Existing rows, identity/sequence values, indexes, and permissions remain attached to those tables.
Queue lease trackingRemove leased_version / LeasedVersion and status_after_release / StatusAfterRelease from existing main queue tables, after checking for unresolved leases.
Queue lease indexesRestore the captured v2 (status, priority, id) index definition and remove temporary indexes left by an interrupted v3 lease-index migration. Index rebuilding takes locks and needs time, disk space, and transaction-log capacity.
Activation and processing settingsDrop the queue-activation table and the six new queue metadata columns: activation delay, concurrency per instance, lease size, batch size, processing threads, and message lease time.
Saved job and queue settingsRestore the captured configuration for existing jobs and queues, including schedules cleared when adopting readiness-driven processing, disabled states, descriptions, default parameters, and queue settings. Changes to those settings made while running v3 are replaced by the checkpoint values.
Job categoriesRestore the original v2 key and serialized value, including its original version and timestamp. Remove the v3 category key.
Job-run initiatorsMap QueueReadiness to v2's automatic Schedule initiator in current/latest run details, historical runs, and extra runs. Retain the remaining execution details and history.
Health-check resultsArchive results containing the renamed JobHealthCheckData type in the checkpoint. Clear their cached result and last-called timestamp so v2 can run the check again. Archive and remove incompatible health-check statistics from active history. Compatible results/statistics and disabled states remain unchanged.
Database instance eventsArchive and remove QueueMessagesReadyInstanceEvent and JobStartRequestedInstanceEvent, which v2 cannot deserialize. Preserve other events, durable extra runs, and queued messages. These best-effort v3 notifications are not replayed on v2.
Initialization and migration recordsRemove reserved Nexus.Startup.* entries and the explicitly listed v3 migration records so a later v3 upgrade runs its migrations again. Preserve the v2 ledger and unrelated key-value entries.

The scripts preserve current queue messages, job-run history, extra runs, next-run parameters, and runtime execution details. Restoring a stale checkpoint of those values could repeat already completed work or lose work added after the upgrade. Review their payload contracts for v2 compatibility before restarting v2. Historical AwaitingRelease entries remain in history; v2 displays an unrecognized status as Unknown.

Health-check and instance-event cleanup recognizes the type metadata written by Nexus's built-in System.Text.Json and Newtonsoft.Json serializers, including custom type-hash salts. It does not rewrite type names or guess hashes. Custom serializers/binders that use another payload format need their own compatibility review. Archived rows use checkpoint kinds health-result, health-statistics, and instance-event; their value / Value contains the original row, with the serialized payload retained as a string. Keep these rows for inspection; copying them back into v2's active tables would reintroduce the incompatible types.

Execute a rollback​

  1. Stop all v3 producers and workers and keep normal traffic paused. Resolve remaining Leased and AwaitingRelease messages with v3 before reverting; do not blindly convert them to Pending, since processing may already have produced side effects or a newer payload may be waiting for release.
  2. Back up the current v3 database and relevant broker state too, preserving work written after the upgrade.
  3. Confirm the script's database and schema match the checkpoint and run the entire file. It acquires the v3 startup lock and applies its database changes in a transaction. On failure, the changes are rolled back; investigate the reported condition before retrying.
  4. Restore the v2 application artifact and configuration, including generated-queue routing, queue-job registrations and transaction behavior. Restore broker topology and direct-producer destinations as needed. SQL does not move messages between old and new Redis keys, Service Bus entities, RabbitMQ resources, or Kafka consumer groups.
  5. Start one latest-v2 instance and verify initialization, saved schedules/settings, category loading, representative persisted payloads, queue/job history, refreshed health checks and their history, and database instance-event polling. Review archived health results and control events. Check job state left by the stopped v3 instances. Then start the other instances and resume traffic deliberately.

Rollback refuses to continue when it finds an unknown migration, changed queue/filter schemas or custom indexes, added/removed queue resources, changed job/queue metadata identities, conflicting v2/v3 tables, or unresolved queue leases. The scripts do not drop new queues, discard messages, or guess how to reverse application migrations. Prepare a specific inverse for those changes, or use backup restoration.

Optional v3 features also need an application plan: distributed processors and new named queues cannot become v2 registrations through SQL. Retention cleanup, deleted messages/history, payload changes, filter backfills that replaced schema/data, and external processing side effects cannot be reconstructed from the settings checkpoint.

Keep the checkpoint and backups until the rollback is verified. A completed rollback marks the checkpoint as used and refuses to reuse it for another rollback. On a later v2-to-v3 upgrade, Nexus archives that used checkpoint with a timestamp/suffix and automatically captures a fresh v2 baseline. An unconsumed checkpoint is preserved on retries and restarts.