Episode 28 brings GraphQL to mobile: Apollo Client in React Native with AsyncStorage persistence, offline-first architecture with a mutation queue and synchronization, performance optimization for mobile networks, and Flutter integration with the graphql_flutter package.

Mobile is the main reason GraphQL was created — Facebook built it for bandwidth-efficient iOS apps. Episode 28 brings GraphQL into the mobile world with React Native and Flutter.
We'll build Apollo Client in React Native, persist the cache to AsyncStorage, design an offline-first architecture with a mutation queue, optimize performance for mobile networks, and close with Flutter integration.
Apollo Client runs in React Native almost exactly like on the web. The difference: networking and storage configuration are platform-adapted. Install with npm install @apollo/client graphql @react-native-async-storage/async-storage:
import { ApolloClient, InMemoryCache, createHttpLink } from "@apollo/client";
import { AsyncStorageWrapper, persistCache } from "apollo3-cache-persist";
import AsyncStorage from "@react-native-async-storage/async-storage";
const cache = new InMemoryCache();
persistCache({
cache,
storage: new AsyncStorageWrapper(AsyncStorage),
});
export const client = new ApolloClient({
link: createHttpLink({ uri: "https://api.kalian.com/graphql" }),
cache,
});AsyncStorage persists the cache to the device's local storage. The result: previously loaded data stays available when the app is reopened, and users don't have to wait for the network to see data they've already loaded.
Use an API URL accessible from the device — localhost on an emulator doesn't point to the developer's machine. For development, pay attention to the Android emulator and iOS simulator configurations. Avoid storing tokens in AsyncStorage without encryption; use secure storage like react-native-keychain for refresh tokens.
An offline-first architecture means the app still works without a connection. The core concept: mutations that fail because of offline status go into a queue, processed when the connection returns:
import { from, Observable } from "rxjs";
function createOfflineQueueLink() {
const queue = [];
return from(new Observable((observer) => {
if (navigator.onLine) {
return forward(operation).subscribe(observer);
}
queue.push(operation);
observer.complete();
}));
}When the connection recovers, replay the entire queue in order (mutations execute serially, episode 5). Add an idempotency key to mutations so replayed operations don't create duplicate data.
Optimistic UI becomes even more important on mobile: while offline, show changes immediately based on optimisticResponse, then sync when the real response arrives. For conflict resolution when two devices change the same data, apply strategies like last-write-wins or per-field versions — the details are covered in episode 38.
Mobile networks are expensive and unstable. Required optimizations:
import { ApolloClient, InMemoryCache } from "@apollo/client";Avoid importing whole libraries; use selective imports and code splitting so the React Native bundle stays small. For images, serve them through a CDN at device-appropriate sizes.
Adapt behavior to network conditions: reduce polling when the app is in the background, increase the cache size on Wi-Fi, and show cached data first (cache-first) on slow networks. Detect connectivity with @react-native-community/netinfo and change fetchPolicy dynamically.
For Flutter, the community's official package is graphql_flutter:
dependencies:
graphql_flutter: ^5.1.0import 'package:graphql_flutter/graphql_flutter.dart';
final client = GraphQLClient(
link: HttpLink('https://api.kalian.com/graphql'),
cache: GraphQLCache(store: HiveStore()),
);Queries and mutations are done via widgets or extensions:
Query(
options: QueryOptions(
document: gql('''
query GetUser(\$id: ID!) {
user(id: \$id) { id username }
}
'''),
variables: {'id': userId},
),
builder: (result, {fetchMore, refetch}) {
if (result.isLoading) return Text('Memuat...');
return Text(result.data!['user']['username']);
},
)graphql_flutter also supports subscriptions and cache persistence with Hive — enough to build full-stack GraphQL Flutter apps using the same patterns as React Native.
Key takeaways:
In the next episode, episode 29, you'll learn about the GraphQL tooling ecosystem — schema visualization and design tools, API testing tools like Apollo Studio Explorer and Insomnia, schema management with GraphQL Inspector, IDE extensions, CLI tools, and mock servers. Your GraphQL development workflow will be far more productive!