Question #53EasyFlutter BasicsImportant

Flutter difference between (debug , release , profile )build

#flutter

Answer

Overview

Flutter supports three build modes: Debug, Release, and Profile. Each mode is optimized for different stages of development and has different performance characteristics.


Debug Mode

Purpose: Development and debugging

Characteristics

  • Assertions enabled - Runtime checks active
  • Hot reload enabled - Fast development cycle
  • DevTools enabled - Debugging tools available
  • Observatory enabled - Performance profiling
  • Slow performance - Not optimized
  • Large app size - Includes debug symbols
  • JIT compilation - Code compiled on-the-fly

When to Use

  • Daily development
  • Testing features
  • Debugging issues
  • Using DevTools inspector

How to Run

bash
# Default mode
flutter run

# Explicitly debug
flutter run --debug

# On specific device
flutter run -d <device_id>

Example

dart
void main() {
  // Assertions only run in debug mode
  assert(someCondition, 'This only checks in debug');

  // Debug-only code
  if (kDebugMode) {
    print('Running in debug mode');
  }

  runApp(MyApp());
}

Debug Banner

dart
// Remove debug banner
MaterialApp(
  debugShowCheckedModeBanner: false, // Hide "DEBUG" banner
  home: HomePage(),
)

Release Mode

Purpose: Production deployment (App Store, Play Store)

Characteristics

  • Assertions disabled - No runtime checks
  • Hot reload disabled - No development tools
  • DevTools disabled
  • Maximum performance - Fully optimized
  • Small app size - No debug symbols
  • AOT compilation - Pre-compiled native code
  • Tree shaking - Unused code removed
  • Obfuscation - Code is minified

When to Use

  • Building for production
  • App Store/Play Store upload
  • Performance testing
  • Final user testing

How to Run

bash
# Build APK (Android)
flutter build apk --release

# Build App Bundle (Android - recommended)
flutter build appbundle --release

# Build iOS
flutter build ios --release

# Run on device (rare)
flutter run --release

Performance

dart
// Example: Release mode optimizations
void main() {
  // ❌ This assert is REMOVED in release mode
  assert(false, 'Never executes in release');

  // ✅ This check works in all modes
  if (someCondition) {
    throw Exception('Always executes');
  }

  runApp(MyApp());
}

Profile Mode

Purpose: Performance profiling and optimization

Characteristics

  • Assertions disabled - Like release
  • Performance tracking enabled - Unlike release
  • DevTools enabled - For profiling
  • Some debugging info - Stack traces available
  • Near-release performance - Optimized but with profiling overhead
  • No hot reload - Like release

When to Use

  • Performance testing
  • Finding performance bottlenecks
  • Measuring frame rates
  • Profiling animations
  • Before release build

How to Run

bash
# Run in profile mode
flutter run --profile

# On specific device
flutter run --profile -d <device_id>

# Build for profile
flutter build apk --profile  # Android
flutter build ios --profile  # iOS

Performance Profiling

dart
import 'package:flutter/foundation.dart';

void main() {
  // Profile mode check
  if (kProfileMode) {
    print('Running in profile mode');
  }

  runApp(MyApp());
}

// Timeline for profiling
import 'dart:developer';

void expensiveOperation() {
  Timeline.startSync('ExpensiveOperation');
  // ... your code ...
  Timeline.finishSync();
}

Detailed Comparison Table

FeatureDebugProfileRelease
CompilationJIT (Just-In-Time)AOT (Ahead-Of-Time)AOT
Assertions✅ Enabled❌ Disabled❌ Disabled
Hot Reload✅ Yes❌ No❌ No
DevTools✅ Full access✅ Limited (profiling)❌ No
PerformanceSlow (10x slower)Fast (near-release)Fastest
App SizeLarge (~20MB+)MediumSmall (~5-10MB)
Observatory✅ Yes✅ Yes❌ No
Debug Banner✅ Shows❌ Hidden❌ Hidden
Tree Shaking❌ No✅ Yes✅ Yes
Code Obfuscation❌ No❌ No✅ Yes (optional)
Use CaseDevelopmentTesting performanceProduction

Build Mode Detection

dart
import 'package:flutter/foundation.dart';

void main() {
  // Check current mode
  if (kDebugMode) {
    print('Debug mode');
  } else if (kReleaseMode) {
    print('Release mode');
  } else if (kProfileMode) {
    print('Profile mode');
  }

  runApp(MyApp());
}

// Conditional features
class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      // Show debug tools only in debug
      debugShowCheckedModeBanner: kDebugMode,

      // Different API endpoints per mode
      home: HomePage(
        apiUrl: kReleaseMode
            ? 'https://api.production.com
            : 'https://api.staging.com
      ),
    );
  }
}

Performance Comparison

Frame Rate (60 FPS target)

ModeTypical FPSPerformance
Debug20-40 FPSVery slow (10x slower than release)
Profile55-60 FPSNear-release performance
Release60 FPSMaximum performance

App Size (Example)

ModeAPK SizeNotes
Debug~25 MBIncludes debug symbols
Profile~12 MBIncludes profiling info
Release~8 MBOptimized, tree-shaken

Real-World Examples

Example 1: API Configuration

dart
class ApiConfig {
  static String get baseUrl {
    if (kDebugMode) {
      return 'http://localhost:3000 // Local dev server
    } else if (kProfileMode) {
      return 'https://staging-api.example.com
    } else {
      return 'https://api.example.com // Production
    }
  }
}

Example 2: Logging

dart
void log(String message) {
  // Only log in debug mode
  if (kDebugMode) {
    print('[DEBUG] $message');
  }
}

void main() {
  log('App started'); // Only prints in debug
  runApp(MyApp());
}

Example 3: Feature Flags

dart
class FeatureFlags {
  static bool get showDebugInfo => kDebugMode;

  static bool get enableAnalytics => kReleaseMode;

  static bool get useProductionDB => kReleaseMode || kProfileMode;
}

// Usage
if (FeatureFlags.showDebugInfo) {
  return DebugPanel();
}

Common Pitfalls

❌ Don't Test Performance in Debug Mode

dart
// ❌ Bad - testing in debug mode
flutter run
// Check performance → Will be 10x slower than release!

// ✅ Good - test in profile mode
flutter run --profile
// Check performance → Accurate results

❌ Don't Use Assertions for Production Logic

dart
// ❌ Bad - assertion removed in release
assert(user != null);
user.name; // Crashes in release if user is null!

// ✅ Good - proper null check
if (user == null) throw Exception('User required');

❌ Don't Submit Debug Builds

bash
# ❌ Bad - never submit debug build
flutter build apk  # Defaults to release, but be explicit

# ✅ Good - always explicit
flutter build apk --release
flutter build appbundle --release

Build Commands Summary

Android

bash
# Debug
flutter run
flutter build apk --debug

# Profile
flutter run --profile
flutter build apk --profile

# Release
flutter build apk --release         # APK (for testing)
flutter build appbundle --release   # App Bundle (for Play Store)

iOS

bash
# Debug
flutter run
flutter build ios --debug

# Profile
flutter run --profile
flutter build ios --profile

# Release
flutter build ios --release
flutter build ipa --release  # For App Store

Web

bash
# Debug
flutter run -d chrome

# Release
flutter build web --release

Best Practices

PracticeRecommendation
DevelopmentAlways use Debug mode
Performance testingAlways use Profile mode
ProductionAlways use Release mode
Store submissionRelease mode with
text
--release
flag
API endpointsDifferent per mode (dev/staging/prod)
LoggingOnly in Debug mode
NeverTest performance in Debug mode

Key Takeaways

Debug: Development with hot reload (slow, large size)

Profile: Performance testing (fast, profiling enabled)

Release: Production deployment (fastest, smallest size)

Always test performance in Profile mode, not Debug!


Resources