Database Migrations

The Enterprise Stack includes a MongoDB migration system that keeps the database structure, indexes, and stored data in sync with the version of the Enterprise API you are running.

Migrations are executed automatically when the Enterprise API starts. They can also be inspected and scheduled manually through the global administration API.

Database migrations are currently supported for MongoDB deployments. The in-memory database does not support migration execution.

How Migrations Work

Each migration has a numeric version, a description, a list of affected collections, and a set of allowed actions. Migrations are registered in version order and are designed to be safe to run in clustered deployments.

When an Enterprise API node starts:

  1. The node connects to MongoDB.
  2. The migration framework checks the current cluster database version.
  3. Required startup migrations are executed before the application continues.
  4. Background migrations are started asynchronously after startup.
  5. The node records progress and results in the migrations collection.

Only one node executes migrations at a time. The migration system uses a MongoDB-backed lock named migration_lock in the cluster_locks collection. Other nodes wait until the lock is released or expires.

Migration Types

Migrations are grouped by impact:

  • SCHEMA - creates or updates collections and document structure.
  • INDEX - creates, updates, or drops database indexes.
  • DATA - transforms existing records. These migrations can take longer on large collections.

Automatic Startup Behavior

Most migrations are applied automatically. The Enterprise API distinguishes between two execution modes:

  • Startup migrations run before the application completes database initialization.
  • Background migrations run after startup, so the API can become available while lower-risk migrations continue.

Background migrations are used when the application can safely handle both the old and new data shape during the migration.

Before upgrading production environments, create a database backup and review the release notes for migrations introduced by the target version.

Cluster Safety and Recovery

The migration framework is cluster-aware:

  • Only one node can hold the migration lock and execute migrations.
  • Lock ownership is refreshed while a migration is running.
  • If a node stops while holding the lock, the lock expires and another node can continue.
  • Migration runs without a completedAt timestamp are treated as aborted and can be recovered.
  • If a node with an older database version leaves the cluster, the missing migrations are scheduled for execution.

This allows rolling deployments while preventing two nodes from applying the same migration at the same time.

Get Migration Status

Use the migration status endpoint to list registered migrations and their run history.

CURL

Endpoint: /v1/admin/admin/migrations

Example Request

curl -X 'GET' \
  'https://{host}/v1/admin/admin/migrations' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {superAdminToken}'

Example Response

[
  {
    "version": 4,
    "allowedActions": [
      "APPLY",
      "RUN",
      "DRY_RUN",
      "VALIDATE_PRECONDITIONS"
    ],
    "description": "Migrate 'timestamp' (millis from epoch) field to 'created_at' and 'updated_at' (string ISO date)",
    "affectsCollections": [
      "organization_trees"
    ],
    "runs": [
      {
        "runId": "1a5a4a42-2a3f-48df-a571-8a4b68c9a941",
        "action": "APPLY",
        "remark": "Startup of Application",
        "startedAt": "2026-06-25T09:15:00.000Z",
        "completedAt": "2026-06-25T09:15:03.000Z",
        "totalItems": 1200,
        "processedItems": 1200,
        "success": true,
        "messages": [],
        "errorMessage": null
      }
    ]
  }
]

Response Fields

  • version: Numeric migration version.
  • allowedActions: Actions that can be scheduled for this migration.
  • description: Human-readable summary of what the migration does.
  • affectsCollections: MongoDB collections touched by the migration.
  • runs: Previous or currently running migration attempts.
  • runId: Unique identifier for one migration run.
  • startedAt: Time when execution started. If this is empty, the action is scheduled but not yet started.
  • completedAt: Time when execution finished. If this is empty after startedAt is set, the run is still active or was interrupted.
  • totalItems and processedItems: Progress counters for migrations that report item-level progress.
  • success: true for successful runs, false for failed runs, and empty while the run is still pending or active.
  • messages: Informational messages written by the migration.
  • errorMessage: Error details for failed runs.

Schedule a Migration Action

Migration actions are scheduled through the administration API. The endpoint returns 202 Accepted after the action has been recorded. Execution starts once a node acquires the database migration lock.

CURL

Endpoint: /v1/admin/admin/migrations/{dbVersion}

Example Request

curl -X 'POST' \
  'https://{host}/v1/admin/admin/migrations/{dbVersion}' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {superAdminToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "action": "DRY_RUN",
  "remark": "Check migration impact before production upgrade"
}'

Path Parameters

  • dbVersion: Version of the migration to schedule, for example 4.

Body Parameters

  • action: Migration action to schedule.
  • remark: Optional note stored with the migration run history.

Response

  • 202 Accepted - The migration action was scheduled.

Migration Actions

The following actions can appear in allowedActions:

  • APPLY: Applies the migration and updates the cluster database version after success. This is the normal automatic startup/background action.
  • RUN: Executes the migration logic without updating the cluster database version.
  • DRY_RUN: Executes the migration's dry-run logic where supported. Use it to inspect impact before applying a migration.
  • VALIDATE_PRECONDITIONS: Runs precondition checks and records messages or errors without applying the migration.
  • ROLLBACK: Runs the rollback logic where supported. Not every migration supports rollback.

Only schedule actions listed in allowedActions for the migration. Unsupported actions are rejected by the API.

Dry Run and Rollback Support

Dry run and rollback support is defined per migration. Always check the allowedActions field returned by GET /v1/admin/admin/migrations before scheduling either action.

Dry Run

DRY_RUN is used to preview the impact of a migration without applying persistent changes. A dry run still creates a migration run history entry, so you can inspect messages, totalItems, processedItems, success, and errorMessage after it finishes.

Use dry runs when you want to:

  • Check that migration preconditions pass.
  • Estimate how many records are affected.
  • Review informational messages before applying a data migration.
CURL

Endpoint: /v1/admin/admin/migrations/{dbVersion}

Example Request

curl -X 'POST' \
  'https://{host}/v1/admin/admin/migrations/{dbVersion}' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {superAdminToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "action": "DRY_RUN",
  "remark": "Preview migration impact before applying it"
}'

Rollback

ROLLBACK executes a migration's rollback logic where that migration supports it. Rollbacks do not update the cluster database version. They are intended for targeted operational recovery, not as a replacement for a database backup.

Not every migration can be rolled back. Data transformations may not have enough information to reconstruct the previous state. For production upgrades, always keep a MongoDB backup even if a migration lists ROLLBACK in allowedActions.

CURL

Endpoint: /v1/admin/admin/migrations/{dbVersion}

Example Request

curl -X 'POST' \
  'https://{host}/v1/admin/admin/migrations/{dbVersion}' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {superAdminToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "action": "ROLLBACK",
  "remark": "Rollback migration after operational validation"
}'

Common Operational Flow

For a production upgrade:

  1. Back up the MongoDB database.
  2. Deploy the new Enterprise API version.
  3. Watch the application logs for migration progress.
  4. Call GET /v1/admin/admin/migrations to verify each required migration has success: true.
  5. Investigate any run with success: false or an errorMessage.

For a manual check before applying a specific migration:

  1. Call GET /v1/admin/admin/migrations and find the migration version.
  2. Schedule VALIDATE_PRECONDITIONS if it is listed in allowedActions.
  3. Schedule DRY_RUN if it is listed in allowedActions.
  4. Review the runs entry for messages, progress, and errors.
  5. Schedule APPLY only when you are ready to execute the migration.

Current Migration Coverage

The Enterprise API currently registers migrations for:

  • Initial MongoDB collection creation. This migration supports DRY_RUN.
  • Base indexes for organization_trees, host_aliases, and accounts.
  • Extended indexes for organization_trees.
  • Event collection indexes.
  • Migration of legacy timestamp fields to createdAt and updatedAt on organization_trees. This migration supports DRY_RUN.
  • An updatedAt index for sorting and querying organization_trees. This migration supports ROLLBACK.

New Enterprise API releases may add more migrations. Always use the status endpoint as the source of truth for the migrations available in your running version.

Troubleshooting

Migration Is Waiting

If a migration is scheduled but has no startedAt, another node may currently hold the migration lock. The scheduled run will start when a node acquires the lock.

Migration Was Interrupted

If a migration has startedAt but no completedAt, the node may have stopped before finishing. The framework treats this as an aborted run and will attempt recovery on startup or when a migration recovery job is triggered.

Migration Failed

If success is false, check errorMessage and the application logs for the root cause. After resolving the issue, you can schedule the same supported action again.

No Migrations Are Listed

If the status endpoint returns an empty list, verify that the deployment is using MongoDB as its database. Migration execution is not supported for the in-memory database.

Last updated on June 25, 2026