androidengineers.Book a session

CI/CD Pipeline

Staged Rollouts & Hotfix Flows

article20 minMedium

Staged rollouts reduce risk by releasing to a small percentage of users first, monitoring for crashes, and expanding only when metrics are healthy. Hotfix flows let you ship critical fixes fast without going through the normal release cycle.

Staged Rollout on Google Play

1%  → monitor 2h (crash rate, ANR rate, 1-star reviews)
10% → monitor 12h
25% → monitor 24h
50% → monitor 24h
100% → full release

Automating with Fastlane

# Fastfile
lane :deploy_staged do
  upload_to_play_store(
    track: "production",
    rollout: "0.01",   # 1%
    aab: "app/build/outputs/bundle/productionRelease/app-production-release.aab",
    skip_upload_apk: true,
    release_status: "inProgress"
  )
end

lane :expand_rollout do |options|
  percentage = options[:percentage] || "0.1"
  upload_to_play_store(
    track: "production",
    rollout: percentage,
    release_status: "inProgress",
    version_code: options[:version_code]
  )
end

Pause and Halt

If crash rate spikes during staged rollout:

  1. Pause rollout in Play Console (stops expansion; existing installs keep the version)
  2. Halt rollout (marks version as halted; users still on old version won't update)
  3. Fix the bug
  4. Submit a new version; restart rollout

Release Branch Strategy

main (production)
├── release/3.2.0      → tags v3.2.0, v3.2.1 (hotfix)
├── release/3.3.0      → next release cycle
└── feature/*          → day-to-day development

Hotfix Flow

A hotfix is a critical fix that bypasses the normal feature branch → develop → release flow:

# 1. Branch from the production tag
git checkout v3.2.0
git checkout -b hotfix/3.2.1-crash-on-checkout

# 2. Apply the minimal fix
git commit -m "fix: NPE in CheckoutViewModel when cart is empty"

# 3. Tag and push
git tag v3.2.1
git push origin hotfix/3.2.1-crash-on-checkout --tags

# 4. Merge back to both release and main
git checkout release/3.2.0
git merge hotfix/3.2.1-crash-on-checkout

git checkout main
git merge hotfix/3.2.1-crash-on-checkout

Hotfix CI Pipeline

# .github/workflows/hotfix.yml
name: Hotfix Release

on:
  push:
    tags: ['v*.*.*']

jobs:
  release-hotfix:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Get tag version
        run: |
          echo "VERSION_NAME=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV

      - name: Set version code
        run: echo "VERSION_CODE=$(date +%Y%m%d)02" >> $GITHUB_ENV

      - name: Build release bundle
        env:
          # ... signing env vars
        run: ./gradlew bundleProductionRelease

      - name: Upload to Play internal track
        run: fastlane deploy_hotfix
        # Then manually promote to staged rollout once validated

Remote Config for Feature Flags (Kill Switch)

A kill switch lets you disable a broken feature without a code push:

class FeatureFlagManager(private val remoteConfig: FirebaseRemoteConfig) {
    init {
        // Set sensible defaults (features ON by default)
        remoteConfig.setDefaultsAsync(
            mapOf(
                "checkout_v2_enabled" to true,
                "new_search_enabled" to true
            )
        )
    }

    val isCheckoutV2Enabled: Boolean
        get() = remoteConfig.getBoolean("checkout_v2_enabled")
}

// In CheckoutScreen
if (featureFlags.isCheckoutV2Enabled) {
    CheckoutV2Screen()
} else {
    CheckoutV1Screen()  // safe fallback
}

When checkout_v2_enabled is set to false in the Firebase console, the next Remote Config fetch (typically every hour) disables the feature for all users — no Play Store submission required.

Key Takeaways

PracticeRule
Staged rolloutStart at 1%; expand only if crash rate < threshold (e.g., 0.1%)
Halt earlyIf crash rate spikes, halt immediately — don't wait for user complaints
Hotfix branchingBranch from production tag, not main
Hotfix versionCodeIncrement last digit (3.2.0 → 3.2.1); CI tags trigger the pipeline
Kill switchRemote Config bool per feature; set false to disable without release
Merge hotfix backAlways merge hotfix into main and develop to avoid regression

YOUR LEARNING JOURNEY

0 of 177 available lessons completed

Progress saved in this browser. No account needed.
Staged Rollouts & Hotfix Flows | Android System Design | Android Engineers