CodePush was retired in March 2025. Your hotfixes don't have to be.

Ship React Native fixes
in minutes, not review cycles.

Over-the-air updates for React Native that run on your Cloudflare account. Crash rollback, code signing and staged rollouts built in. Open source.

$ npm install react-native-airdrop
~/my-app
$ airdrop release -p ios -m "Fix checkout" --rollout 20
Releasing My App • ios • runtime 2.4.0 • channel production
$ react-native bundle --platform ios --dev false ...
$ hermesc -emit-binary -O ...
38 files (2.41 MB), 1 new to upload, 37 already on server
  ↑ main.jsbundle (2.1 MB → 612 KB gz)
✔ Published update 7c070454-84bd-4dc2 (20% rollout, signed)

$ airdrop updates list
id        platform  status  installs  rollbacks  message
7c070454  ios       20%     1,284     0          Fix checkout
a83d4042  ios       100%    48,920    3          Price formatting
0.71 → 0.87+React Native, old & new arch
Only changed filescontent-addressed diff downloads
$0 egressR2 storage, edge-cached assets
~1 query / coloper 10s, regardless of fleet size

Features

Everything CodePush did. Then the parts it didn't.

⚡

Minutes, not review cycles

Fix a bug in JavaScript and every user has it on their next launch. No App Store or Play Store review for JS and asset changes.

🛟

Automatic crash rollback

If a new update crashes before your app renders, the next launch boots the previous bundle and that update is never installed again.

🔏

End-to-end code signing

ECDSA P-256 signatures verified on device with a key baked into your binary. Even a compromised server can't ship code.

📦

Diff downloads

Files are content-addressed. Devices only download what changed and reuse the rest, gzip-compressed and cached at the edge.

🎯

Rollouts & channels

Staged rollouts from 1% to 100%, staging/production channels, mandatory updates, promote between channels, instant rollback.

🧬

Native-safe by design

Updates are bound to a runtime version, so JS never runs against native code it wasn't built for. New store builds reset OTA state.

How it works

Three steps. One afternoon.

1

Deploy the server

One Worker, one D1 database, one R2 bucket, on your own Cloudflare account.

cd apps/server
pnpm run deploy
2

Wire up your app

Point the bundle URL at Airdrop and wrap your root component.

import { withAirdrop } from "react-native-airdrop";

export default withAirdrop(App);
3

Release

Bundle, sign and publish from your laptop or CI. Roll back with one command.

airdrop release -p android
airdrop rollback <updateId>

Safety net

Bad update? Your users never notice.

Every update must call home with notifyAppReady() after it renders. If it crashes first, the next launch silently restores the previous bundle, blacklists the update on that device and reports a rollback, so you see it in airdrop updates list before your users do.

Read the launch protocol →
  1. v41 runningconfirmed healthy
  2. v42 downloadedhashes + signature verified, staged
  3. v42 crashes on launchnever reached notifyAppReady()
  4. Back on v41v42 blacklisted · rollback reported

Compare

Own your update pipeline

AirdropEAS UpdateCodePush
Ships JS + assets without store review✓✓—
Self-hosted on your Cloudflare account✓—archived
Works with bare React Native (no Expo)✓via expo-updates✓
New Architecture✓✓partial
Automatic crash rollback✓✓✓
End-to-end code signing✓✓✓
Per-file diff downloads✓✓—
Pricingyour Cloudflare billper MAUretired Mar 2025

Native code can't be updated over the air on any platform: Apple and Google forbid downloading executable code. Airdrop keeps JS and native in sync with runtime versions instead. Why?

Your next hotfix can ship today.

Open source, MIT licensed, runs on infrastructure you already pay for.