Riverpod: Reactive State Management for Flutter with Code Generation
A reactive caching and data-binding framework. Riverpod makes working with asynchronous code a breeze.
At a glance
- What is it?
- Riverpod is a reactive caching and data-binding framework for Dart and Flutter that handles loading and error states by default, separates business logic from the UI, and uses the @riverpod annotation for code generation. It ships as three packages covering plain Dart, Flutter, and flutter_hooks integration.
- Who is it for?
- Riverpod is a strong choice for Flutter teams who want to manage asynchronous data fetching, caching, and state transitions with compile-time safety and without InheritedWidget boilerplate. It is the wrong choice for teams who need a minimal solution with no code generation step: the @riverpod annotation approach adds a build_runner dependency and a code generation workflow that must be integrated into CI.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Dart, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What Problem Riverpod Solves for Flutter Developers
Flutter's built-in state management relies on InheritedWidget and its descendants such as InheritedNotifier. Accessing a provider from a widget requires the widget to be in the right subtree, which makes testing harder and leads to code that couples UI structure to data access. The most common workaround before dedicated state management packages was to pass state down through constructor parameters, which becomes unwieldy at scale.
Riverpod's README describes four goals: handling loading and error states by default so the developer does not need to write manual try/catch blocks, supporting advanced scenarios such as pull-to-refresh natively, separating business logic from the UI layer, and keeping code testable, scalable, and reusable.
The package is a Flutter Favorite on pub.dev, which is an editorial designation from the Flutter team for packages that meet quality and documentation standards. The author, Remi Rousselet, also wrote Provider, which Riverpod was designed to improve upon; the name itself is an anagram of Provider.
The @riverpod Annotation and Code Generation Model
Riverpod's modern usage style relies on the @riverpod annotation, processed by riverpod_generator to produce a typed provider. A developer writes a plain Dart function annotated with @riverpod, and the generator creates the corresponding provider class. This means the provider variable (boredSuggestionProvider in the example below) is generated code with type safety enforced at compile time rather than being looked up by runtime string key.
The README shows this pattern for a network request:
@riverpod
Future<String> boredSuggestion(Ref ref) async {
final response = await http.get(
Uri.https('boredapi.com', '/api/activity'),
);
final json = jsonDecode(response.body);
return json['activity']! as String;
}The generated boredSuggestionProvider is then watched inside a ConsumerWidget. The generated code handles caching and invalidation; calling ref.watch() on the same provider in multiple widgets shares the underlying Future rather than launching multiple requests.
This approach requires build_runner and riverpod_generator as dev dependencies, and the code generation step must run before the project compiles.
Reading Providers in the UI: ConsumerWidget and ref.watch
On the widget side, Riverpod replaces StatelessWidget with ConsumerWidget. The difference is a second parameter, WidgetRef, passed to the build method. This ref object is the entry point to all provider reads: ref.watch() subscribes the widget to a provider and rebuilds it when the value changes; ref.read() performs a one-time read without subscribing.
The README shows how the same boredSuggestion provider is consumed in a widget:
class Home extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final boredSuggestion = ref.watch(boredSuggestionProvider);
return switch (boredSuggestion) {
AsyncData(:final value) => Text('data: $value'),
AsyncError(:final error) => Text('error: $error'),
_ => const Text('loading'),
};
}
}The switch statement on boredSuggestion covers all three states: AsyncData for a resolved value, AsyncError for a failed future, and the default case for loading. The README describes this as handling loading and error states by default, because the type system forces the developer to address all three cases rather than leaving them as runtime surprises.
The Three Packages and Their Intended Uses
The repository publishes three packages to pub.dev. riverpod is the core package for plain Dart applications without Flutter. flutter_riverpod adds Flutter-specific components including ProviderScope (the widget that initialises the provider container) and ConsumerWidget. hooks_riverpod combines flutter_riverpod with the flutter_hooks package from the same author, exposing a HookConsumerWidget base class for developers who prefer the hooks pattern.
The README presents this as a table with version badges for each package. The packages are in the packages/ directory of the monorepo. Most Flutter applications use flutter_riverpod as the direct dependency and add riverpod as a transitive dependency. The hooks_riverpod package is optional; it is only needed when the project already uses flutter_hooks.
The packages/ directory also contains supporting tools such as riverpod_generator for the code generation model and riverpod_lint for static analysis rules.
Where Riverpod Adds Overhead
The code generation workflow adds a build step to the development cycle. A developer who modifies a @riverpod annotated function must run dart run build_runner build or dart run build_runner watch before the changes are reflected. Teams that do not configure a watch process will encounter compile errors caused by stale generated files.
Riverpod's separation of providers from the widget tree, while good for testability, means that simple one-screen applications gain little from the framework. A counter or a form with local state does not need the caching, invalidation, or async state machinery that Riverpod provides. Using Riverpod for purely local, ephemeral widget state adds indirection without benefit.
The documentation lives at riverpod.dev and is extensive. The README points there for learning the framework. Engineers who want to understand when to use AsyncNotifier versus Notifier versus a plain provider function face a learning curve that simpler state management solutions do not impose.
Riverpod vs Provider: Same Author, Different Design Decisions
Provider is also written by Remi Rousselet and remains widely used in the Flutter ecosystem. It wraps Flutter's InheritedWidget directly and does not require code generation. A Provider value is accessed with context.read() or context.watch() inside the widget tree.
Riverpod's difference is architectural: providers are declared as global Dart objects rather than being tied to the widget tree. This makes them accessible without a BuildContext, which simplifies writing Dart-only business logic and unit tests that do not need a Flutter test environment. It also enables providers to depend on each other without the nesting structure that Provider requires.
The trade-off is the build_runner dependency and generated code. Provider has no code generation step. For projects already on Provider that want to avoid migrating build tooling, Provider remains a maintained option. For new projects starting fresh, the README positions Riverpod as the intended successor.
License, Maintenance, and BLoC as a Third Alternative
The repository carries an MIT license and the last push was on 2026-09-26, indicating active development. There are no GitHub releases; versioning is tracked per package on pub.dev. The CONTRIBUTING.md documents the pull request process and the benchmarks/ directory suggests that performance is tracked over time.
BLoC (Business Logic Component) is another Flutter state management approach, maintained separately by the Very Good Ventures team. BLoC structures state changes as events processed by a stream-based component. The conceptual model is different: in BLoC, state transitions are explicit events dispatched to a bloc object, while in Riverpod, state is derived by watching providers that re-evaluate when their dependencies change. Teams who prefer an event-driven mental model and explicit state machine semantics may find BLoC a better fit.
Editorial conclusion
Riverpod is a strong choice for Flutter teams who want to manage asynchronous data fetching, caching, and state transitions with compile-time safety and without InheritedWidget boilerplate. It is the wrong choice for teams who need a minimal solution with no code generation step: the @riverpod annotation approach adds a build_runner dependency and a code generation workflow that must be integrated into CI. Teams already using flutter_hooks will find hooks_riverpod a natural fit. The repository carries an MIT license and the last push was on 2026-09-26.
Frequently asked questions
What is Riverpod in Flutter?
Riverpod is a reactive state management framework for Flutter that handles loading and error states by default and uses the @riverpod annotation for code generation. It provides ConsumerWidget as a replacement for StatelessWidget, with a WidgetRef parameter for accessing providers.
What is Riverpod used for?
Riverpod is used to manage asynchronous data fetching, caching, and state transitions in Dart and Flutter applications. It separates business logic from the UI layer and keeps state testable by declaring providers as global Dart objects rather than tying them to the widget tree.
What is the difference between Provider and Riverpod?
Both are written by the same author. Provider wraps Flutter's InheritedWidget and requires a BuildContext to access values. Riverpod declares providers as global Dart objects, supports code generation via @riverpod, and allows providers to be read outside the widget tree. Riverpod adds a code generation step that Provider does not require.
Which is better, BLoC or Riverpod?
BLoC uses an event-driven model where state changes are dispatched as explicit events to a stream-based component. Riverpod derives state by watching providers that re-evaluate when dependencies change. The README does not compare them directly; the choice depends on whether a team prefers event-driven state machines or reactive dependency tracking.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rrousselgit-riverpod)
Community notes