Upgrades

Upgrade a self-hosted installation without losing data or plugin compatibility.

Back up first; see Database Migrations. For runtime settings, see Configuration. For the deployment this upgrades, see Self-Hosting.

How releases and images are tagged

erxes versions are cut with release-it (pnpm release): .release-it.json tags the release commit as <version> (tagMatch: 3.*) and updates CHANGELOG.md from conventional commits. Tag pushes then trigger release.yml, which re-tags a fixed matrix of Docker images (erxes/erxes-next-core-api, erxes/erxes-next-gateway, erxes/erxes-next-ui, erxes/erxes-next-logs, erxes/erxes-next-automations, all eleven erxes/erxes-next-<plugin>_api images, plus erxes/frontline-widgets, erxes/posclient-front, and erxes/help-center) from :latest to :<version> using docker buildx imagetools create. erxes/erxes-next-migrations is published by its own CI workflow but is not in the release matrix, so it has no :3.1.x tag; pin it by latest or digest.

So a released version does produce matching :3.1.9-style tags across all core and plugin images, but each tag aliases whatever :latest was at release time. Between releases, CI also publishes floating latest plus per-service tags (YYYYMMDD-<short-sha> for APIs and services, full commit SHA for the gateway, branch/SHA/semver metadata tags for UI and apps). Prefer an explicit version tag or digest over latest so rollback is a config change, not a guess.

Plugin frontends are not images: the ci-ui-* workflows sync each *_ui build to the plugins.erxes.io CDN under latest/ or the release tag. Enabling a plugin version whose UI assets were not published breaks its navigation; see Frontend & Plugin Loading.

Reading the changelog: 3.1.6 to 3.1.9

CHANGELOG.md is the source of truth for what each release changed. For the 3.1.6 to 3.1.9 jump:

  • 3.1.7 added OAuth scope-per-plugin-module fixes, a compact user header with a 64 KB header budget, document locking, milestone/GitHub-issue sync, and a call-widget cache control.
  • 3.1.8 fixed call transfer, content Postiz delivery (tenant routing, JWT signing, QEMU-safe builds), MS Dynamics customer checks, and frontline surveys; it added conversation→ticket/deal/task conversion and CALLPRO_SUBDOMAINS gating.
  • 3.1.9 added "Basic information" system fields in Settings → Properties, member email activity logs, and frontline convert-property visibility.

None of these releases document a required manual migration. The changelog only tells you what each release includes; confirm by diffing backend/saas-migrations/ and plugin src/migrations/ directories between your tags, as described in Database Migrations.

Upgrade procedure

  1. Choose a compatible image set

    List every image you run (Core UI, gateway, Core API, logs-service, each *_api, any apps), pick one version tag or digest for the whole set, and record current references for rollback:

    docker compose images
    docker images --digests | grep erxes
    
  2. Back up and stage

    Take a restorable mongodump of the application database and <db>_logs (Database Migrations). Restore it to staging, deploy the candidate image set with the production .env shape, run any new migration scripts, and verify login, enabled plugins, automations, file URLs, and customer-facing apps.

  3. Upgrade production

    Announce the window; a single-server Compose update causes a short outage. Update the image references in .env, then:

    docker compose pull
    docker compose up -d
    docker compose ps
    

    Wait for Core API to register and the gateway to recompose its supergraph (the gateway-update-apollo-router job handles plugins that join after startup). Run migration scripts for the release if it includes them.

  4. Check it works

    Check /health on gateway and Core API, the __typename GraphQL probe, owner login, and one representative flow per enabled plugin, including the plugin's remote UI (/get-frontend-plugins must return reachable remoteEntry.js URLs). Keep the previous image digests and the pre-upgrade backup until the new version is stable.

Rollback

  1. Restore the previous image references in .env and run docker compose up -d.
  2. Restore the pre-upgrade database backup only if a migration changed stored data and a forward fix is riskier; restoring loses writes made after the backup.
  3. Re-verify health, GraphQL, login, and plugin UI loading.

Rollback does not undo migrations

Recreating containers with older images reverts code, not data. If the release ran a data migration, the only safe rollback is the backup taken before it ran.

Was this helpful?