Skip to content
App Store Deployment: From Code to Production

App Store Deployment: From Code to Production

DodaTech Updated Jun 20, 2026 8 min read

App store deployment is the process of preparing, signing, and distributing mobile applications through Apple’s App Store and Google Play Store — involving code signing, provisioning profiles, versioning, release tracks, and compliance with store review guidelines.

What You’ll Learn

You’ll set up App Store Connect and Google Play Console, configure code signing and provisioning profiles, build app bundles and APKs, manage versioning, use release tracks (internal/alpha/beta/production), navigate app review guidelines, and implement in-app purchases.

Why App Store Deployment Matters

Building the app is only half the work. Getting it into users’ hands requires navigating complex deployment pipelines. Doda Browser and Durga Antivirus Pro go through this process for every update. Understanding deployment ensures your users always have the latest, most secure version of your app.

App Store Deployment Learning Path

    flowchart LR
  A[Mobile App Testing] --> B[Push Notifications]
  B --> C[App Store Deployment]
  C:::current
  classDef current fill:#f90,color:#fff,stroke:#333,stroke-width:2px
  
Prerequisites: A completed iOS or Android app ready for release. Apple Developer account ($99/year) and/or Google Play Developer account ($25 one-time).

App Store Connect Setup (iOS)

Step 1: Create an App Record

  1. Go to App Store Connect
  2. Navigate to Apps > + > New App
  3. Fill in:
    • Platform: iOS (or visionOS/tvOS)
    • Name: DodaBrowser
    • Primary language: English
    • Bundle ID: com.dodatech.browser (must match Xcode)
    • SKU: DODABROWSER001

Step 2: Configure App Information

  • Description: What your app does (up to 4000 characters)
  • Keywords: browser, privacy, secure
  • Support URL: https://dodatech.com/support
  • Marketing URL: https://dodatech.com
  • Privacy Policy URL: https://dodatech.com/privacy (required)

Step 3: Upload Screenshots

  • 6.5-inch iPhone: 4 screenshots (1242×2688 or 1290×2796)
  • 5.5-inch iPhone: 4 screenshots (1242×2208)
  • iPad Pro: 4 screenshots (2048×2732 or 2732×2048)

Code Signing (iOS)

Code signing proves your app comes from a legitimate developer and hasn’t been tampered with.

Xcode Automatic Signing

# In Xcode:
# 1. Select your target
# 2. Signing & Capabilities → "Automatically manage signing"
# 3. Select your team
# 4. Xcode creates provisioning profiles automatically

Manual Signing (CI/CD)

# Generate certificates and profiles manually:
# 1. Create Certificate Signing Request (CSR) via Keychain Access
# 2. Upload CSR to developer.apple.com
# 3. Download certificate (.cer) and install in Keychain
# 4. Create App ID and provisioning profile
# 5. Download profile (.mobileprovision)

# Fastlane match handles this elegantly:
match development --app_identifier "com.dodatech.browser"
match appstore --app_identifier "com.dodatech.browser"

Provisioning Profiles

Profile TypeUseDevices
DevelopmentTesting on dev devicesSpecific devices
Ad HocTesting on up to 100 devicesSpecific devices
App StoreApp Store distributionAll devices
EnterpriseInternal distributionAll devices

Google Play Console Setup (Android)

Step 1: Create an App

  1. Go to Google Play Console
  2. Click Create app
  3. Fill in:
    • App name: DodaBrowser
    • Default language: English
    • App or game: App
    • Free or paid: Free

Step 2: Store Listing

  • Short description: 80 characters
  • Full description: Up to 4000 characters
  • Screenshots: 2-8 screenshots (minimum 320px, maximum 3840px)
  • Feature graphic: 1024×500px
  • App icon: 512×512px (32-bit PNG)
  • Content rating: Complete questionnaire

Building for Release

Android: App Bundle vs APK

# Build an Android App Bundle (recommended)
./gradlew bundleRelease
# Output: app/build/outputs/bundle/release/app-release.aab

# Build an APK
./gradlew assembleRelease
# Output: app/build/outputs/apk/release/app-release.apk

# Sign the app bundle (via build.gradle)
android {
    signingConfigs {
        release {
            storeFile file("dodatech-keystore.jks")
            storePassword System.getenv("KEYSTORE_PASSWORD")
            keyAlias "dodatech"
            keyPassword System.getenv("KEY_PASSWORD")
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
            isMinifyEnabled = true
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
    }
}

iOS: Archive and Export

# In Xcode:
# 1. Product → Archive
# 2. Organizer window opens
# 3. Select archive → Distribute App
# 4. Choose: App Store Connect / Ad Hoc / Development
# 5. Upload or export .ipa

# Or using fastlane:
fastlane gym --scheme DodaBrowser --export_method app-store

Versioning

Semantic Versioning

1.2.3
↑ ↑ ↑
| | └── Patch (bug fixes)
| └──── Minor (new features, backward compatible)
└────── Major (breaking changes)

Android versioning

// build.gradle.kts
android {
    defaultConfig {
        versionCode = 12          // Monotonic integer — always increase
        versionName = "1.2.3"     // User-visible version
    }
}

iOS versioning

// In Xcode project settings:
// Marketing Version: 1.2.3 (user-visible)
// Build Number: 12 (monotonic integer)

// Or in Info.plist
// CFBundleShortVersionString: 1.2.3
// CFBundleVersion: 12

Release Tracks

    flowchart TD
    Dev[Development] --> Internal[Internal Testing]
    Internal --> Alpha[Alpha / Closed Track]
    Alpha --> Beta[Beta / Open Track]
    Beta --> Production[Production]
    Production -->|Hotfix| Beta
    Beta --> Production
  

Google Play Tracks

TrackAudienceReview RequiredAvailability
InternalUp to 100 email addressesNoMinutes
ClosedCustom list (email/Google Groups)NoHours
OpenAnyone with linkNoHours-days
ProductionAll usersYes1-3 days

App Store Connect

DistributionAudienceNotes
TestFlight InternalUp to 100 team membersNo review
TestFlight ExternalUp to 10,000 testersBeta App Review (usually quick)
App StoreAll usersFull review (1-3 days)

App Review Guidelines

Common iOS Rejection Reasons

  • 2.1 — Crashes/Bugs: App crashes during review. Test thoroughly.
  • 2.3 — Metadata: Screenshots show features the app doesn’t have.
  • 3.1 — In-App Purchases: Using external payment for digital goods.
  • 4.2 — Minimum Functionality: App is too simple (single webview).
  • 5.1 — Privacy: No privacy policy or collecting data without consent.

Common Android Rejection Reasons

  • Policy: Deceptive Behavior: Misleading app description or screenshots.
  • Policy: Permissions: Requesting permissions that don’t relate to app function.
  • Policy: Spam: Duplicate apps or keyword stuffing.
  • Policy: Gambling: Real-money gambling without proper licensing.

Best Practices for Smooth Review

  • Test your app on real devices (not just simulators)
  • Provide demo accounts for review team
  • Make sure “Sign in with Apple” is included if using social login
  • Submit with all metadata complete
  • Respond to review feedback within 24 hours

In-App Purchases

iOS (StoreKit)

import StoreKit

class PurchaseManager: NSObject, SKProductsRequestDelegate {
    func fetchProducts() {
        let request = SKProductsRequest(productIdentifiers: ["premium_monthly"])
        request.delegate = self
        request.start()
    }

    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        for product in response.products {
            print("Product: \(product.localizedTitle)\(product.price)")
        }
    }
}

Android (Billing Library)

val billingClient = BillingClient.newBuilder(context)
    .setListener { purchases, _ ->
        for (purchase in purchases) {
            if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
                // Grant entitlement
                unlockPremium()
            }
        }
    }
    .enablePendingPurchases()
    .build()

Common App Store Deployment Errors

1. Expired Certificates or Provisioning Profiles

Developer certificates expire after 1 year, distribution certs after 3 years. Renew before expiry or use Fastlane Match to automate management.

2. Mismatched Bundle ID

The bundle ID in Xcode must match App Store Connect. A mismatch causes “No matching provisioning profiles” errors.

3. Missing Privacy Policy

Apple requires a privacy policy URL for all apps since 2018. Google requires it for apps that collect personal data. Link to a proper policy page.

4. Version Code Not Incremented

Android requires a strictly increasing versionCode. Forgetting to increment causes upload rejection. Automate this in CI/CD.

5. 64-Bit Architecture Requirement

Since 2019, both stores require 64-bit support. iOS dropped 32-bit with iOS 11. Android requires 64-bit binaries for new apps.

6. Not Testing on Real Devices

Simulators/emulators don’t show real-world behavior (network, sensors, battery). Test on actual devices before submission.

7. Incomplete Metadata

Missing screenshots, descriptions, or privacy URLs blocks submission. Use Fastlane Deliver or Gradle Play Publisher to automate metadata upload.

Practice Questions

1. What’s the difference between an APK and an Android App Bundle?

APK is the legacy format containing all code for all device configurations. App Bundle (AAB) defers APK generation to Google Play, which delivers only the code/resources needed for the user’s specific device (smaller downloads).

2. Why does iOS require code signing?

Code signing proves the app’s authenticity (it came from a registered developer) and integrity (it hasn’t been modified since signing). Without it, anyone could distribute malware through the App Store.

3. What are the four release tracks in Google Play Console?

Internal (up to 100 testers), Closed (custom list), Open (anyone with link), and Production (all users). Each has different review requirements.

4. How do you handle in-app purchases for subscriptions?

In iOS, use StoreKit 2 with Product.SubscriptionInfo. On Android, use Billing Library 6+ with BillingClient.queryProductDetailsAsync(). Both require server-side receipt validation.

5. Challenge: Build a CI/CD deployment pipeline.

Create a Fastlane setup that: builds the app, increments version code, runs tests, uploads to TestFlight (iOS) / Internal Track (Android), and notifies the team on Slack. Handle certificate management with match.

FAQ

How long does app review take?
App Store review typically takes 1-3 days. Google Play review takes 1-3 days for new apps, hours for updates. Expedited reviews are available for critical bug fixes (Apple) or can be requested (Google).
Can I distribute apps outside the App Store?
iOS requires App Store distribution (unless using Enterprise certificates for internal apps). Android allows sideloading APKs and has alternative stores (Amazon, Samsung, F-Droid).
What happens if my app is rejected?
Read the rejection reason, fix the issue, and resubmit. Most rejections are resolved within 1-2 resubmissions. Apple and Google provide detailed feedback.
Do I need to submit updates for every OS version?
Not for every OS version, but you should test and update within 6 months of major OS releases. Apple and Google may delist apps that haven’t been updated in over 2 years.

Try It Yourself

Deploy a test app:

  1. Create a simple “Hello World” app in both platforms
  2. Set up App Store Connect / Google Play Console
  3. Configure code signing
  4. Build a release version
  5. Distribute via TestFlight / Internal Testing track
  6. Install on a device and verify it works

What’s Next

You now know the complete deployment pipeline: code signing, build configuration, release tracks, and app review navigation. Automate the process with Fastlane or Gradle Play Publisher so deployment becomes a single command instead of a manual checklist.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro