> ## Documentation Index
> Fetch the complete documentation index at: https://patch.codemagic.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Preparing for production

> Checklist before shipping OTA to Production: Staging validation, signing, and sync behavior.

Use this checklist after [Staging looks good](/docs/using-patch/verify-test-release#after-staging-looks-good) and before you ship OTA to real users. Each item links to the full guide; the goal is to catch gaps before the first Production release.

## 1. Confirm Staging end to end

QA should have validated on a build that matches how you test: correct deployment key, reachable server URLs, and a visible change after update. If not, finish [Verify a test release](/docs/using-patch/verify-test-release) first.

## 2. Ship a Production native binary

Production devices need a store (or production-track) build with the **Production** deployment key embedded, not Staging.

  <TabItem value="react-native" label="React Native">

- Copy the Production key from `cmpatch deployment list` or the [dashboard](/docs/using-patch/dashboard)
- Wire `CodemagicPatchDeploymentKey`, `CodemagicPatchApiUrl`, and `CodemagicPatchDownloadBaseUrl` for Production in [Native setup](/docs/setup/native-setup)
- Staging OTAs never reach users on the Production key, and vice versa

  </TabItem>
  <TabItem value="capacitor" label="Capacitor">

- Copy the Production key from `cmpatch-capacitor deployment list` or the [dashboard](/docs/using-patch/dashboard)
- Wire Production `deploymentKey`, `apiUrl`, and `downloadBaseUrl` in [Native setup](/docs/setup/native-setup-capacitor)
- Staging OTAs never reach users on the Production key, and vice versa

  </TabItem>
</SdkTabs>

See [Core concepts. Deployment model](/docs/introduction/core-concepts#deployment-model).

## 3. Tune client sync by build

Install timing (`installMode`, `mandatoryInstallMode`, when you call `sync()`) is **client-side only**. The server does not push different sync rules per deployment.

Typical pattern:

| Build | Deployment key | Sync behavior |
| --- | --- | --- |
| Internal / QA / debug | Staging | `IMMEDIATE` or frequent foreground checks for fast iteration |
| App Store / Play Production | Production | `ON_NEXT_RESTART` or `ON_NEXT_RESUME` for gentler UX |

  <TabItem value="react-native" label="React Native">

Branch in app code using your existing build flavors (`__DEV__`, Xcode schemes, Gradle product flavors, Expo `extra`, etc.). With `Patch.wrap(App, options)`, pass the selected options to the wrapper. For a direct integration, use your existing `sync()` call:

```tsx

void sync(
  __DEV__
    ? {
        installMode: InstallMode.IMMEDIATE,
        mandatoryInstallMode: InstallMode.IMMEDIATE,
      }
    : {
        installMode: InstallMode.ON_NEXT_RESTART,
        mandatoryInstallMode: InstallMode.ON_NEXT_RESUME,
      },
);
```

  </TabItem>
  <TabItem value="capacitor" label="Capacitor">

Choose options based on a build-time flag (such as Vite's `import.meta.env.DEV` or Angular's `environment.production`) and pass them to `start()`:

```ts

start(
  import.meta.env.DEV
    ? {
        installMode: InstallMode.IMMEDIATE,
        mandatoryInstallMode: InstallMode.IMMEDIATE,
      }
    : {
        checkFrequency: CheckFrequency.ON_APP_RESUME,
        installMode: InstallMode.ON_NEXT_RESTART,
        mandatoryInstallMode: InstallMode.ON_NEXT_RESUME,
      },
);
```

  </TabItem>
</SdkTabs>

Also wire foreground re-checks if updates should download while the app is open. See [Checking for updates](/docs/setup/checking-for-updates).

Reserve server-side `--mandatory` for fixes that truly cannot wait. Immediate mandatory reloads can flash a white screen mid-session, see [Troubleshooting. White flash](/docs/troubleshooting#white-flash-when-applying-an-update).

## 4. Check delivery and URLs

Production phones must reach your Patch API and storage domains over **public HTTPS**, not `localhost` or a dev machine LAN IP.

  <TabItem value="react-native" label="React Native">

- Confirm `CodemagicPatchDownloadBaseUrl` exactly matches the server's
  `PUBLIC_BASE_URL`; only the bundled-storage default necessarily ends with
  `/codemagic-patch`
- Remove `android:usesCleartextTraffic="true"` if you added it for local evaluation

  </TabItem>
  <TabItem value="capacitor" label="Capacitor">

- Confirm `downloadBaseUrl` (or a `CodemagicPatchDownloadBaseUrl` override) exactly matches the server's `PUBLIC_BASE_URL`; only the bundled-storage default necessarily ends with `/codemagic-patch`
- Remove `android:usesCleartextTraffic="true"` if you added it for local evaluation

  </TabItem>
</SdkTabs>
- Put a CDN in front of the storage domain if you expect large install bases; see [Delivery](/docs/using-patch/delivery), [Cloudflare setup](/docs/setup/cloudflare), and [CloudFront setup](/docs/setup/cloudfront)

## 5. Optional: bundle signing

If your app requires signed releases, configure keys before the first Production publish. See [Code signing](/docs/using-patch/security#code-signing-update-integrity).

## 6. Plan the first Production release

Do not jump straight to 100% of users:

1. Publish or [promote](/docs/using-patch/releasing-updates#step-3-promote-to-production) to Production
2. Start with a [gradual rollout](/docs/using-patch/production-control#gradual-rollout) (e.g. 10% → 50% → 100%)
3. Watch [Analytics](/docs/using-patch/analytics) for download and failure spikes
4. Know how to [roll back](/docs/using-patch/production-control#roll-back-to-the-previous-release) before you need it

Day-to-day release controls: [Production control](/docs/using-patch/production-control).

## 7. Harden the server

Before opening the dashboard to a wider team, review [Security](/docs/using-patch/security) and [Ongoing maintenance](/docs/setup/ongoing-maintenance) (backups, upgrades, health).

## Related

- [Releasing updates](/docs/using-patch/releasing-updates): Staging → Production workflow
- [Troubleshooting](/docs/troubleshooting): version targeting, pending restart
- [Pricing](/docs/introduction/pricing): free MAU threshold and commercial rates
- [FAQ](/docs/faq): compatibility, self-hosting
