An open-source Go server implementing the Expo Updates protocol,
with a web dashboard, multi-app support, progressive rollouts, instant rollbacks and one-command publishing.
Documentation · Quick start · Issues · Contact
The documentation is exposed as an MCP server: plug it into Cursor, VS Code, Claude Code or any MCP client.
Expo Open OTA is an independent open-source project. It is not affiliated with, endorsed or supported by Expo.
Battle-tested in production. Expo Open OTA has been serving over-the-air updates in production since early 2025, to apps totaling more than a million monthly active users.
Cut costs. EAS Update pricing scales with your monthly active users. Self-hosting serves unlimited updates to unlimited devices for the price of your infrastructure.
Own your infrastructure. Updates live in your bucket, are served by your server and travel through your CDN, behind your security policies.
No vendor lock-in. The standard Expo Updates protocol on top of standard storage. Switch clouds anytime.
Your CDN does the heavy lifting. Devices download updates from your CDN, straight out of your bucket. The server only answers lightweight update checks, so millions of devices checking in never turn into millions of downloads hitting it.
It scales horizontally. The update server is stateless: run as many replicas as your traffic needs, they stay consistent with each other out of the box.
It plugs into your monitoring. Metrics, dashboards and health checks come built in, ready for whatever observability stack you already run.
One server hosts all your Expo apps. Each app gets its own branches, channels, API tokens and update history, and your whole team manages everything from a single dashboard. No Expo account required.
Ship an update from your terminal or CI with the eoas CLI. Rollbacks and republishing are one command too.
npx eoas publish --branch production --rollout-percentage 10Your app is built once and asks for a channel. You decide which branch of updates that channel serves: remap to roll out, remap back to roll back. No rebuild, no store review.
Ship to 10% of devices, watch your metrics, then increase, finish or revert in one click from the dashboard.
A channel can serve two branches at once, with devices split deterministically between them. Test two variants in production, promote the winner.
Start with nothing but a bucket and a few environment variables, no database. When you want the multi-app dashboard, plug in PostgreSQL and the server migrates itself into control plane mode automatically.
Plus expo-updates code signing, and Hermes source maps for Sentry or PostHog.
- Deploy the server with the Railway button above, Docker or the Helm chart.
- Run
npx eoas initin your Expo project to wire it to your server. - Publish your first update with
npx eoas publish --branch production.
The full walkthrough for both modes is in the documentation: stateless mode and control plane mode. Coming from v2? Follow the migration guide.
The documentation is exposed as an MCP server, so your AI tools can answer questions about Expo Open OTA with the docs as their source:
https://mercure-technologies.gitbook.io/expo-open-ota/~gitbook/mcp
Use the install buttons at the top of this page for Cursor and VS Code. For Claude Code:
claude mcp add --transport http expo-open-ota-docs https://mercure-technologies.gitbook.io/expo-open-ota/~gitbook/mcpAny other MCP-compatible client (ChatGPT connectors included) can be pointed at the same URL.
For teams that need tighter control, the Enterprise edition adds:
- Single sign-on (OIDC): let your team sign in through Microsoft Entra ID, Okta, Google Workspace, Keycloak or any OpenID Connect issuer.
- Protected branches: once a branch is protected, only API tokens you explicitly allow can publish, roll back or republish on it. A token handed to a developer for staging can never ship to production.
- IP allowlists: restrict each API token to your CI runners' addresses, per address or CIDR range.
- Audit logs: every publish, rollback, login, role change and configuration edit is recorded with who did it, from which IP, and whether it succeeded. Browse the trail from the dashboard or export it as NDJSON for your compliance tooling.
![]() |
![]() |
The enterprise code lives in public ee/ directories you can read before you buy, and licenses are verified fully offline against an embedded key: your production servers never phone home. Everything else on this page is MIT. For a license, contact us.
Contributions are welcome! For anything beyond a small fix, please open an issue before writing code. Expo Open OTA is an open-core project and some advanced features are reserved for the commercial edition; the boundary is documented in CONTRIBUTING.md.
Expo Open OTA is not officially supported or affiliated with Expo. This is an independent open-source project.
The core is MIT and will stay MIT. Enterprise features live in ee/ directories and are covered by a commercial license (see ee/LICENSE); everything else is MIT (see LICENSE).




