Ref 06

Riverpod Production Best Practices Handbook

Calculating reading time... Module 1.5: Master Reference

🏆 The Ultimate Best Practices Catalog

A production-grade compilation of 10 engineering rules for building scalable, testable, and maintainable Flutter Riverpod 3 applications.

1. The 10 Commandments of Production Riverpod

Never write manual StateNotifierProvider or ChangeNotifierProvider in modern Riverpod 3 apps. Always use @riverpod annotations paired with build_runner.

Group screens, widgets, providers, and repositories by feature (lib/features//...) rather than by global layer types.

Allow providers to dispose of state when screens unmount. Reserve @Riverpod(keepAlive: true) exclusively for global session context.

Before updating state after an await boundary, always check if (!ref.mounted) return; to prevent unmounted provider mutation crashes.

Every screen depending on async data MUST explicitly handle data, loading, and error branches. Never swallow exceptions silently.

Custom parameter classes passed to Family providers must implement value equality to prevent infinite fetch loops and cache miss overhead.

Use ref.watch() inside build() for reactive updates. Use ref.read() exclusively inside event callbacks (e.g. onPressed).

Cancel active HTTP requests, WebSocket connections, and background timers inside ref.onDispose() callbacks to eliminate memory leaks.

When a widget only depends on a specific field of a complex state object, use select() to avoid re-rendering on unrelated field changes.

Widgets should only invoke methods on Riverpod Notifiers. Inject Repositories into Notifiers via ref.watch() for complete isolation.