Deployment

Staged Rollouts for React Native: Deploy with Confidence

Learn how to implement staged rollouts for React Native OTA updates. Deploy to 1% of users first, monitor, then gradually expand to 100%.

S
SwiftPatch Team
Engineering
10 min read

Introduction: Why 100% Rollouts Are Risky

Picture this: You've tested your update, everything looks good, and you push it to all 500,000 users at once. Five minutes later, your error tracking lights up — there's a crash on Android 12 devices with Samsung's custom ROM. You just broke the app for 80,000 users.

This scenario is preventable. Staged rollouts let you deploy to a small percentage of users first, verify everything works, and then gradually expand to your entire user base.

It's the same strategy used by Google, Facebook, Netflix, and every company that deploys at scale. And with SwiftPatch, it's built right into the platform.

What Are Staged Rollouts?

A staged rollout (also called a phased release, gradual rollout, or canary deployment) is a deployment strategy where you release an update to a small percentage of users first, then gradually increase that percentage over time.

Staged Rollout Timeline:

Day 1, Hour 0:   ██░░░░░░░░░░░░░░░░░░  1% of users
Day 1, Hour 4:   ████░░░░░░░░░░░░░░░░  10% of users
Day 1, Hour 12:  ██████████░░░░░░░░░░  50% of users
Day 2, Hour 0:   ████████████████████  100% of users

At each stage, you monitor key health metrics. If something goes wrong, you halt the rollout or roll back — affecting only the small percentage of users who received the update.

The Standard Rollout Strategy

The most common staged rollout pattern follows four phases:

Phase 1: Canary (1%)

swiftpatch release --platform all --rollout 1 --description "v2.5.1: Checkout flow improvements"

Deploy to 1% of your users. This is your canary group — they're the first to receive the update.

Duration: 1-2 hours

  • Crash rate (should not increase)
  • JavaScript error rate
  • API error rates from updated endpoints
  • Console logs and Sentry/Bugsnag reports

Phase 2: Early Adopters (10%)

swiftpatch promote --rollout 10

If canary looks healthy, expand to 10%. This gives you a statistically meaningful sample to validate performance.

Duration: 4-6 hours

  • All Phase 1 metrics
  • User engagement metrics (session length, screen views)
  • Conversion rates for affected flows
  • Performance metrics (startup time, frame rate)

Phase 3: Majority (50%)

swiftpatch promote --rollout 50

Half your users now have the update. At this scale, most device/OS combinations are covered.

Duration: 12-24 hours

  • All Phase 2 metrics
  • Support ticket volume
  • App store reviews sentiment
  • Edge cases on less common devices

Phase 4: Full Release (100%)

swiftpatch promote --rollout 100

Everything looks good. Ship it to everyone.

Post-release monitoring: Continue monitoring for 48 hours after full release.

Canary Deployments Explained

A canary deployment is the first phase of a staged rollout. The term comes from the practice of coal miners bringing canaries into mines — if the canary stopped singing, it meant dangerous gas levels, and miners would evacuate.

In software, your 1% canary users are the early warning system. If the update causes problems, you detect it before it affects your entire user base.

How SwiftPatch Selects Canary Users

SwiftPatch uses a deterministic hashing algorithm to select which users are in each rollout percentage:

hash(device_id) % 100 < rollout_percentage → receives update
  • The same user always gets the update at the same rollout percentage
  • Users in the 1% group are always included in the 10% group, the 50% group, etc.
  • Selection is uniform across devices and platforms

A/B Comparison

Because canary users are deterministically selected, you can compare metrics between the canary group (updated) and the control group (not updated):

Canary group (1% - updated):
  Crash rate: 0.3%
  Avg session length: 4.2 min

Control group (99% - not updated):
  Crash rate: 0.3%
  Avg session length: 4.1 min

Status: ✅ No regression detected

Monitoring During Staged Rollouts

Key Metrics to Watch

Critical Metrics (block rollout if degraded):
- Crash rate
- ANR (App Not Responding) rate
- JavaScript fatal errors
- App startup failures

Important Metrics (investigate if degraded):
- Non-fatal error rate
- API error rates
- Performance (startup time, FPS)
- Memory usage

Business Metrics (watch for trends):
- Session length
- Conversion rates
- Feature adoption
- User retention

Setting Up Monitoring

# Configure alerts for rollout monitoring
swiftpatch alerts create \
  --metric crash_rate \
  --threshold 0.5 \
  --comparison increase_percent \
  --channel slack:#mobile-alerts

swiftpatch alerts create \
  --metric error_rate \
  --threshold 2.0 \
  --comparison increase_percent \
  --channel email:mobile-team@company.com

Real-Time Dashboard

SwiftPatch's dashboard shows real-time rollout metrics:

Deployment: dep_abc123
Status: Rolling out (10%)
Platform: all
Created: 2 hours ago

Metrics (updated vs baseline):
  Crash rate:    0.31% vs 0.30% (stable ✅)
  Error rate:    1.2% vs 1.1% (stable ✅)
  Startup time:  1.8s vs 1.7s (stable ✅)
  Adoption:      9.8% of eligible users

When to Pause, Rollback, or Expand

Decision Framework

After each rollout phase, ask:

1. Has crash rate increased?
   YES → Rollback immediately
   NO  → Continue

2. Has error rate increased significantly (>2%)?
   YES → Pause and investigate
   NO  → Continue

3. Are there user-reported issues?
   YES → Pause and investigate
   NO  → Continue

4. Are performance metrics stable?
   YES → Proceed to next phase
   NO  → Pause and investigate

All clear? → Expand to next phase

Pausing a Rollout

# Pause at current percentage (no new users get the update)
swiftpatch pause --deployment dep_abc123

Rolling Back

# Full rollback (all users revert to previous version)
swiftpatch rollback --deployment dep_abc123

# Users who already received the update will get the rollback
# on their next app launch

Resuming After Pause

# Resume rollout at the current percentage
swiftpatch resume --deployment dep_abc123

# Or promote to a higher percentage
swiftpatch promote --rollout 50

Automated vs. Manual Rollout Expansion

Manual Expansion

Best for critical updates or teams new to staged rollouts:

# Each promotion requires explicit CLI command
swiftpatch release --platform all --rollout 1
# ... human reviews metrics ...
swiftpatch promote --rollout 10
# ... human reviews metrics ...
swiftpatch promote --rollout 50
# ... human reviews metrics ...
swiftpatch promote --rollout 100

Automated Expansion

Best for mature teams with good monitoring:

swiftpatch release --platform all \
  --rollout 1 \
  --auto-expand \
  --expand-schedule "1:2h,10:6h,50:24h,100" \
  --halt-on-crash-increase 0.5 \
  --halt-on-error-increase 2.0
  1. Deploys to 1% of users
  2. After 2 hours, if metrics are healthy, expands to 10%
  3. After 6 hours at 10%, expands to 50%
  4. After 24 hours at 50%, expands to 100%
  5. Automatically halts if crash rate increases by 0.5% or error rate by 2.0%

Hybrid Approach

Many teams use automated expansion with manual gates:

swiftpatch release --platform all \
  --rollout 1 \
  --auto-expand \
  --expand-schedule "1:2h,10:6h,50" \
  --require-approval-at 50

This automates expansion from 1% to 10%, but requires manual approval before going to 50%.

SwiftPatch Staged Rollout Implementation

CLI Commands Reference

# Create a staged release
swiftpatch release --platform <ios|android|all> --rollout <percentage>

# Promote to higher percentage
swiftpatch promote --rollout <percentage>

# Pause rollout
swiftpatch pause

# Resume rollout
swiftpatch resume

# Rollback
swiftpatch rollback

# Check status
swiftpatch status

# View rollout history
swiftpatch rollout-history --deployment dep_abc123

Configuration File

# swiftpatch.yaml
rollout:
  default_strategy: staged
  phases:
    - percentage: 1
      duration: 2h
      auto_expand: true
    - percentage: 10
      duration: 6h
      auto_expand: true
    - percentage: 50
      duration: 24h
      auto_expand: false  # Require manual approval
    - percentage: 100

  halt_conditions:
    crash_rate_increase: 0.5%
    error_rate_increase: 2.0%
    startup_time_increase: 20%

  alerts:
    - channel: slack
      webhook: ${SLACK_WEBHOOK}
    - channel: email
      recipients:
        - mobile-team@company.com

CI/CD Integration for Staged Rollouts

GitHub Actions

# .github/workflows/staged-deploy.yml
name: Staged OTA Deployment

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test

  deploy-canary:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run build
      - name: Deploy Canary (1%)
        run: |
          npx swiftpatch release \
            --platform all \
            --rollout 1 \
            --sign \
            --private-key ${{ secrets.SWIFTPATCH_PRIVATE_KEY }}
        env:
          SWIFTPATCH_ACCESS_KEY: ${{ secrets.SWIFTPATCH_ACCESS_KEY }}

  expand-rollout:
    needs: deploy-canary
    runs-on: ubuntu-latest
    environment:
      name: production-expand
    steps:
      - name: Expand to 100%
        run: npx swiftpatch promote --rollout 100
        env:
          SWIFTPATCH_ACCESS_KEY: ${{ secrets.SWIFTPATCH_ACCESS_KEY }}

The production-expand environment can be configured in GitHub with required reviewers, forcing a human approval step before the rollout expands.

Real-World Examples

Example 1: E-Commerce App

An e-commerce app with 2 million users deploys a checkout flow update:

Day 1, 9:00 AM:   Deploy to 1% (20,000 users)
Day 1, 11:00 AM:  Metrics stable → expand to 10%
Day 1, 5:00 PM:   Metrics stable → expand to 50%
Day 2, 9:00 AM:   Metrics stable → expand to 100%

Result: Zero incidents, smooth rollout over 24 hours

Example 2: Banking App (Conservative)

A banking app with 500,000 users deploys a critical security patch:

Day 1, 10:00 AM:  Deploy to 0.5% (2,500 users)
Day 1, 2:00 PM:   Internal QA verifies → expand to 5%
Day 2, 10:00 AM:  All metrics green → expand to 25%
Day 3, 10:00 AM:  Compliance review → expand to 100%

Result: Extra-cautious rollout over 3 days, zero issues

Example 3: Emergency Hotfix

A social media app discovers a critical crash affecting all users:

Hour 0:   Deploy fix to 10% (skip 1% for speed)
Hour 1:   Crash rate drops from 5% to 0.3% → expand to 50%
Hour 2:   Confirmed fixed → expand to 100%

Result: Critical fix deployed to all users in 2 hours

Conclusion

Staged rollouts are the difference between deploying with confidence and deploying with fear. By releasing to a small percentage of users first, you catch issues before they become widespread problems.

  • One command to set rollout percentage
  • Automatic expansion with health monitoring
  • Instant rollback if something goes wrong
  • Real-time metrics to inform decisions

Stop deploying to 100% and hoping for the best. Deploy to 1%, know it's good, and then expand with confidence.

Get started with SwiftPatch for free →

Ready to ship updates faster?

Get started with SwiftPatch for free. No credit card required.

Join Waitlist

Related Articles