This episode prepares your team for production: runbooks for app crashes and release issues, stability monitoring with analytics and error reporting, rollout and rollback strategies, and team workflows for ongoing maintenance.

Shipping the app isn't the end of the journey — it's the start of operational responsibility. Episode 19 prepares you to maintain the app in production: runbooks for handling crashes and release problems, stability monitoring through analytics and error reporting, rollout and rollback strategies, and team workflows for maintenance.
A runbook is a step-by-step document for handling incidents. Without a runbook, teams panic and make ad hoc decisions when production misbehaves. A good runbook answers three questions: what are the symptoms, who is responsible, and what are the mitigation steps.
At minimum, document the most frequent scenarios:
Judul: Crash rate di atas ambang batas
Trigger: Crashlytics memperingatkan crash rate > 1%
Langkah 1: Buka dashboard crash teratas pada versi aktif.
Langkah 2: Cek apakah terkait rilis terakhir (diff commit).
Langkah 3: Jika ya, aktifkan rollback ke versi stabil sebelumnya.
Langkah 4: Catat insiden di ticket dan kabari tim.Keep runbooks in the team repository or wiki, and review them every month. A runbook that's never tested is as bad as having no runbook at all.
Crashes that aren't reported are never fixed. Integrate error reporting early:
flutter pub add firebase_crashlytics firebase_coreInitialize Firebase in main:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}Firebase.initializeApp() sets up the Firebase configuration before the app renders. To catch unhandled errors, attach a global handler in runApp with FlutterError.onError forwarding to Crashlytics.
Besides crashes, record errors that aren't fatal:
try {
await repository.sync();
} catch (e) {
FirebaseCrashlytics.instance.recordError(e, StackTrace.current);
}FirebaseCrashlytics.instance.recordError sends a non-fatal error to the dashboard. Don't record sensitive data — sanitize error messages before sending.
Analytics (for example Firebase Analytics or Sentry) provides context: what kind of users experience the problem, on which screen, and with which version. This context turns error reporting from "there's a crash" into "a crash on the checkout screen for version 1.2.0 users on Android 14".
Don't release to 100 percent of users at once. Gradual strategies:
flutter run --release -t lib/main.dartflutter run --release -t lib/main.dart uses a specific entry point. For multiple entry points, each -t targets a different configuration — a pattern used to separate staging and production builds.
Rollback must be faster than fixing code:
Rollback decisions must be made on data (crash rate, error rate), not feelings. Set thresholds during release planning, not during panic.
All maintenance work flows from tickets or alerts:
Define these rules with the team and post them somewhere visible.
Small, frequent releases are safer than large, rare ones:
flutter analyze && flutter testflutter analyze && flutter test is the release gate. Combine it with semantic-release (episode 14) to generate changelogs and automatic versions, and make sure runbooks are updated whenever the flow changes.
Key takeaways:
In the next episode 20 we discuss real-world use cases and patterns — example cases for e-commerce, fintech, productivity, and SaaS apps, MVVM, Clean Architecture, and Redux design patterns, feature-driven development and iterative releases, and how to build maintainable Flutter products. You see the big picture of everything.