Self-hosted

Self-Hosted OTA Updates for React Native

Most over-the-air update services are somebody else's servers holding your release history and shipping your code to your users. That is fine until it is not — until procurement asks where the bundles live, until a data-residency requirement lands, or until you would simply rather not have a third party in the path between your CI and your users' phones. This runs on your infrastructure, in full, with one command.

What you actually run

Four pieces, all of them ordinary: a Fastify API, PostgreSQL for release metadata, an S3-compatible bucket for the bundles themselves, and the dashboard. There is no hidden control plane calling home, and no component that only works when someone else's service is up.
  • docker compose up -d brings the whole stack up
  • Bundle storage is any S3-compatible object store — AWS S3, Cloudflare R2, or MinIO on your own hardware
  • Devices download bundles directly from your storage via presigned URLs, so the API is not in the data path
  • The same SDK and CLI work against your server; only the endpoint changes

Why teams choose to self-host

  • Data residency — bundles and release history stay in a region and an account you control
  • Security review — the code your users run is served from infrastructure your own team audits
  • No vendor lock-in — if this project disappeared tomorrow, your server keeps serving updates
  • Cost predictability at scale — bandwidth is billed by your cloud provider at your rates, not marked up per active user

Security you can verify rather than trust

Self-hosting only helps if the thing you are hosting is careful with what it ships. The integrity work happens on the device, where it counts.
  • The SHA-256 published with a release is checked before the archive is unpacked, so a corrupted or tampered payload never becomes a runnable bundle
  • Extraction is zip-slip protected
  • A release that never confirms it booted is reverted automatically
  • Passwords are bcrypt-hashed; API keys are stored as SHA-256 and shown exactly once

Self-hosted or managed — the same product

The managed service exists so you do not have to run this if you do not want to, and the self-hosted path exists so you are never stuck with that choice. Same SDK, same CLI, same dashboard. See pricing for the managed plans, or the quickstart to get moving either way.

Frequently asked questions

What do I need to run this?
Somewhere to run containers, a PostgreSQL database, and an S3-compatible bucket. A single modest VM with docker compose is enough to start; the storage is where bandwidth and size actually accrue.
Do devices talk to my server for every download?
No. The API answers the update check and hands back a presigned URL, and the device downloads the bundle straight from your object storage. Your API stays out of the bandwidth path.
Can I move from the managed service to self-hosted later?
Yes — that is the point of keeping both paths on the same SDK and CLI. Your app configuration changes to point at your own endpoint.
Is the rollout logic the same when self-hosted?
Yes. Staged percentage rollouts, deterministic per-device bucketing, binary version targeting and rollback all behave identically; they are properties of the server you are running, not of the hosting.

Keep reading

Ship a fix without waiting for review.

Free to start. Publish a bundle, stage it to a percentage of devices, and roll it back for everyone if it goes wrong.