← All releases
v3.0.0Breaking changes

Multi-app, control plane and progressive rollouts

  • Server
  • Dashboard
  • eoas CLI
  • Enterprise
  • Helm & Docker

v3 is the largest release since the project started, still under the Expo Open OTA name at the time. It served production traffic through the whole beta, to apps totaling more than a million monthly active users. Coming from v2, read the migration guide first: this release has breaking changes.

One server, all your apps

A single deployment hosts every Expo app. Each app gets its own branches, channels, API tokens and update history. No Expo account is needed anymore.

Control plane mode and the dashboard

Plug in PostgreSQL and the server migrates itself into control plane mode: a web dashboard where each team member signs in with their own account to manage apps, channels, tokens and rollouts. Stateless mode still works with a bucket and a few environment variables, and stays the simplest way to start.

Progressive rollouts

Ship an update to a percentage of devices, then increase, finish or revert from the dashboard. From the CLI:

npx eoas publish --branch production --rollout-percentage 10

A/B testing

A channel can serve two branches at once. Devices are split deterministically between them, so a given device always lands on the same side. Promote the winner when you are done.

Enterprise edition

Built on the same MIT core, the Enterprise edition adds single sign-on through any OIDC provider (Microsoft Entra ID, Okta, Google Workspace, Keycloak), protected branches that only explicitly allowed tokens can publish to, and per-token IP allowlists.

Breaking changes

  • Apps identify themselves with the expo-app-id request header instead of the server-side EXPO_APP_ID variable. Add it to updates.requestHeaders in your app config and rebuild.
  • The bucket layout now includes the app id. The re-path runs on first v3 boot and needs delete permission on the bucket (s3:DeleteObject on S3, roles/storage.objectAdmin on GCS). The server answers 503 until it completes.
  • Publishing requires eoas v3: publish routes moved under /{appId}/.
  • Dashboard sign-in takes ADMIN_EMAIL together with ADMIN_PASSWORD.
  • S3_KEY_PREFIX is renamed BUCKET_KEY_PREFIX. The old name still works with a deprecation warning.
  • Prometheus metrics carry an appId label, and update_error_users_total counts unique clients.

Also

  • Readiness and liveness probes for orchestrators.
  • PostgreSQL-backed stores, Go 1.25.
  • The repository moved to mercuretechnologies/expo-open-ota. Images and charts are published under both ghcr.io/mercuretechnologies and ghcr.io/axelmarciano.

Deploy

docker pull ghcr.io/mercuretechnologies/expo-open-ota:v3.0.0
helm install expo-open-ota oci://ghcr.io/mercuretechnologies/charts/expo-open-ota --version 3.0.0
npx eoas@3

Release on GitHub