Configuring Build Configurations: Debug, Release, Staging

We regularly encounter projects where, a month before release, it turns out that a debug API key is going into production. This is not a hypothetical risk — in our practice, there have been about 30 such projects over the past few years. Proper build configuration for Debug, Release, and Staging env

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Configuring Build Configurations: Debug, Release, Staging
Medium
from 1 day to 3 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

We regularly encounter projects where, a month before release, it turns out that a debug API key is going into production. This is not a hypothetical risk — in our practice, there have been about 30 such projects over the past few years. Proper build configuration for Debug, Release, and Staging environments means each environment has its own constants, behavior, and settings, not a set of #if DEBUG scattered throughout the code. For example, one of our clients lost 500,000 rubles because test push notifications were sent to real users. This leak could have been prevented by simple configuration separation. We have been configuring builds for over 5 years and have implemented more than 40 projects — this allows us to guarantee a fast and safe release.

Why Separate Build Configurations?

Classic situation: an application goes to production with a hardcoded https://api-dev.myapp.com base URL. Or testers receive a build that logs everything to the console and crashes due to enabled StrictMode. A Staging configuration reduces the risk of such crashes by 3 times compared to Debug, and Release eliminates them entirely. After configuring builds, these problems disappear forever. Separation of build configurations reduces debugging time by 2 times compared to a monolithic project.

How It Works on iOS

In Xcode, there are two default build configurations: Debug and Release. Staging is added manually: Product → Scheme → Edit Scheme → Duplicate Release → rename to Staging.

For storing configuration values, we use .xcconfig files:

// Config/Debug.xcconfig API_BASE_URL = https://api-dev.myapp.com LOG_LEVEL = verbose BUNDLE_ID_SUFFIX = .debug // Config/Staging.xcconfig API_BASE_URL = https://api-staging.myapp.com LOG_LEVEL = info BUNDLE_ID_SUFFIX = .staging // Config/Release.xcconfig API_BASE_URL = https://api.myapp.com LOG_LEVEL = error BUNDLE_ID_SUFFIX = 

In Info.plist, values are pulled via $(API_BASE_URL). In code, they are read through Bundle.main.infoDictionary:

enum AppConfig { static var apiBaseURL: URL { guard let urlString = Bundle.main.object(forInfoDictionaryKey: "API_BASE_URL") as? String, let url = URL(string: urlString) else { fatalError("API_BASE_URL not configured") } return url } } 

No #if DEBUG for URLs — only Bundle.

Using the same scheme, we configure separate app icons and names: add different AppIcon assets and a condition in xcconfig (ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-Staging).

What About Android?

On Android, configurations are managed via build.gradle.kts. Build Types (debug, release, staging) + Product Flavors give a matrix of variants.

android { buildTypes { debug { applicationIdSuffix = ".debug" versionNameSuffix = "-debug" isDebuggable = true buildConfigField("String", "API_BASE_URL", "\"https://api-dev.myapp.com\"") buildConfigField("Boolean", "ENABLE_LOGGING", "true") } create("staging") { initWith(getByName("release")) applicationIdSuffix = ".staging" versionNameSuffix = "-staging" buildConfigField("String", "API_BASE_URL", "\"https://api-staging.myapp.com\"") buildConfigField("Boolean", "ENABLE_LOGGING", "true") signingConfig = signingConfigs.getByName("debug") } release { isMinifyEnabled = true buildConfigField("String", "API_BASE_URL", "\"https://api.myapp.com\"") buildConfigField("Boolean", "ENABLE_LOGGING", "false") proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } } 

BuildConfig.API_BASE_URL is available in code after building — it's a generated class. Note: in Release we enable ProGuard/R8, which reduces APK size by 30-40%. Separate icons and names for Staging and Debug are set via src/debug/res/ and src/staging/res/.

What About Cross-Platform?

In React Native, environment configurations are managed via react-native-config or native build types. The package compiles variables into native code — values are not available via process.env during JS runtime.

In Flutter — --dart-define or --dart-define-from-file:

flutter build apk --dart-define=API_URL=https://api-staging.myapp.com --flavor staging 

Comparison of Approaches

Platform Storage Method Advantages Notes
iOS (Swift) .xcconfig + Info.plist Clean integration with Xcode Requires re-scheme build for new environment
Android (Kotlin) buildConfigField / BuildConfig Auto-generation BuildConfig persists through ProGuard
Flutter --dart-define / .env Simplicity Must explicitly pass during build
React Native react-native-config Isolation Additional dependency, ignore .env files

What the Work Includes and How We Do It

We don't just write configuration files — we analyze the project, find all places with hardcoded and unsafe practices, create a configuration matrix, choose the optimal approach (Xcconfig, buildConfigField, --dart-define), implement, test each configuration, and set up automatic publishing. In the end, you get:

  • Audit of current configuration state.
  • Creation of xcconfig/buildTypes/productFlavors for all environments.
  • Migration of hardcoded values into configuration files.
  • Configuration of app icons and names for Staging/Debug.
  • Update of CI scripts.
  • Documentation for the team.
  • Support for 2 weeks after delivery.

How Long Does Configuration Take?

Project Type Time Dependencies
Single platform (iOS or Android) 1–2 days Access to source code and CI system
Both platforms 2–3 days Access to App Store and Google Play accounts
+Flutter or React Native +1 day Flutter define or .env files

The cost is calculated individually. Contact us to get a consultation and accurate estimate for your project.

What Mistakes Does Proper Configuration Prevent?

Proper configuration prevents leakage of confidential data (production keys do not end up in debug builds), confusion with environments (testers always see which version is installed), and failures due to different behavior (on Staging you can enable logging without risk of crashes). After implementing these practices, you will forget about problems related to build configurations. Order configuration setup today — and reduce the risk of financial losses. Get a consultation right now.

ProGuard documentation: https://www.guardsquare.com/manual