# How Telegram-iOS Configures Build Variants for Internal versus App Store Releases

> Discover how Telegram iOS configures build variants for internal and App Store releases using Xcode and Bazel for seamless feature gating.

- Repository: [TelegramMessenger/Telegram-iOS](https://github.com/TelegramMessenger/Telegram-iOS)
- Tags: how-to-guide
- Published: 2026-04-07

---

**Telegram-iOS distinguishes between internal beta and public App Store releases using compile-time macros defined in Xcode configuration files and injected by Bazel, which the `BuildConfig` module exposes as Boolean properties for runtime feature gating.**

The TelegramMessenger/Telegram-iOS repository handles multiple distribution channels by statically defining **build variants configured for internal versus App Store releases** through a centralized compilation pipeline. By resolving environment flags at build time rather than runtime, the codebase prevents experimental features from leaking into production binaries while eliminating performance overhead from dynamic environment checks.

## The BuildConfig Registry

The variant detection centers on the `BuildConfig` component located in `submodules/BuildConfig/Sources/BuildConfig.m`. This Objective-C implementation exposes two critical Boolean properties:

- **`isInternalBuild`** – Returns `true` for beta or test flight builds, controlled by the `APP_CONFIG_IS_INTERNAL_BUILD` macro defined at lines 177–179.
- **`isAppStoreBuild`** – Returns `true` only for binaries submitted to the App Store, controlled by the `APP_CONFIG_IS_APPSTORE_BUILD` macro defined at lines 181–183.

These values resolve to hardcoded constants at compile time, ensuring zero runtime overhead for environment detection.

## Compile-Time Macro Injection

The build variants are determined before compilation through a pipeline involving Bazel rules and Xcode configuration files.

### Bazel BUILD Configuration

In `submodules/BuildConfig/BUILD`, the Bazel rule passes variant flags to the compiler using `-D` preprocessor definitions (lines 26–30):

```python
"-DAPP_CONFIG_IS_INTERNAL_BUILD={}".format(telegram_is_internal_build),
"-DAPP_CONFIG_IS_APPSTORE_BUILD={}".format(telegram_is_appstore_build),

```

These flags translate the build system variables into C macros that `BuildConfig.m` evaluates at compilation.

### Xcode Configuration Files (.xcconfig)

Concrete values for each variant live in `.xcconfig` files within `Telegram/Telegram-iOS/`:

**Internal (Fork) Variant** – `Config-Fork.xcconfig` typically sets `APP_CONFIG_IS_INTERNAL_BUILD=true` for beta testing scenarios.

**App Store Variant** – `Config-AppStoreLLC.xcconfig` explicitly disables internal flags and enables store mode, including the real App Store ID:

```bash
APP_CONFIG_IS_INTERNAL_BUILD=NO
APP_CONFIG_IS_APPSTORE_BUILD=YES
APP_CONFIG_APPSTORE_ID=686449807

```

This configuration ensures the binary identifies correctly with Apple's commerce systems while excluding debug capabilities.

## Runtime Feature Gating

Once instantiated, `BuildConfig` drives conditional logic throughout the Swift codebase, primarily within [`submodules/TelegramUI/Sources/AppDelegate.swift`](https://github.com/TelegramMessenger/Telegram-iOS/blob/main/submodules/TelegramUI/Sources/AppDelegate.swift).

### Initializing the Configuration

The `AppDelegate` creates the configuration object early in the lifecycle:

```swift
let buildConfig = BuildConfig(baseAppBundleId: baseAppBundleId)

```

### Conditional Feature Enabling

In [`AppDelegate.swift`](https://github.com/TelegramMessenger/Telegram-iOS/blob/main/AppDelegate.swift) (lines 639–642), the code uses `isAppStoreBuild` to determine experimental feature availability:

```swift
let useBetaFeatures = !buildConfig.isAppStoreBuild
let sharedContext = SharedAccountContextImpl(
    // ...
    useBetaFeatures: useBetaFeatures,
    // ...
)

```

### In-App Purchase Restrictions

The [`MakeTempAccountContext.swift`](https://github.com/TelegramMessenger/Telegram-iOS/blob/main/MakeTempAccountContext.swift) file (lines 34–35) gates commerce functionality strictly to App Store builds:

```swift
if buildConfig.isAppStoreBuild {
    // Enable StoreKit transactions
}

```

### Resource Selection

App icon selection (lines 951–952 in [`AppDelegate.swift`](https://github.com/TelegramMessenger/Telegram-iOS/blob/main/AppDelegate.swift)) also respects the variant:

```swift
let appIcon = PresentationAppIcon(
    name: "BlueIcon",
    imageName: "BlueIcon",
    isDefault: buildConfig.isAppStoreBuild
)

```

## Summary

- **Compile-time constants** defined in `.xcconfig` files determine the build variant before code compilation.
- **Bazel BUILD rules** inject these values as preprocessor macros (`-DAPP_CONFIG_IS_INTERNAL_BUILD` and `-DAPP_CONFIG_IS_APPSTORE_BUILD`) into `submodules/BuildConfig/Sources/BuildConfig.m`.
- **Zero runtime cost** for environment checks because `isInternalBuild` and `isAppStoreBuild` evaluate to static Booleans.
- **Feature isolation** ensures internal beta features never ship in `Config-AppStoreLLC.xcconfig` releases, while [`MakeTempAccountContext.swift`](https://github.com/TelegramMessenger/Telegram-iOS/blob/main/MakeTempAccountContext.swift) and [`AppDelegate.swift`](https://github.com/TelegramMessenger/Telegram-iOS/blob/main/AppDelegate.swift) consume these flags to toggle StoreKit, UI experiments, and app icons.

## Frequently Asked Questions

### How does Telegram-iOS detect if it's running an internal build?

The app checks the `isInternalBuild` property on the `BuildConfig` class, which returns the value of the `APP_CONFIG_IS_INTERNAL_BUILD` macro defined at compile time in `submodules/BuildConfig/Sources/BuildConfig.m`. This macro is set via Xcode configuration files like `Config-Fork.xcconfig` and injected by Bazel build rules.

### What build system injects the variant macros in Telegram-iOS?

Bazel injects the macros through the `BUILD` file in `submodules/BuildConfig/`, specifically using compiler flags `-DAPP_CONFIG_IS_INTERNAL_BUILD` and `-DAPP_CONFIG_IS_APPSTORE_BUILD` that read values from Xcode `.xcconfig` files such as `Config-AppStoreLLC.xcconfig`.

### Why use compile-time macros instead of runtime checks for build variants?

Compile-time macros eliminate the risk of debug code executing in production and remove runtime performance overhead for environment detection. As implemented in `BuildConfig.m`, these Booleans resolve to constants during compilation, allowing the compiler to optimize away unreachable code paths for each variant.

### Which configuration file controls the official App Store release settings?

`Telegram/Telegram-iOS/Config-AppStoreLLC.xcconfig` defines the official App Store variant, setting `APP_CONFIG_IS_APPSTORE_BUILD=YES` and `APP_CONFIG_IS_INTERNAL_BUILD=NO` while specifying the production App Store ID (e.g., `APP_CONFIG_APPSTORE_ID=686449807`).