Remote Cache Sync for Flutter
Remote Cache Sync lets you manage remote data via a single cache-first query API. You don't call remote SDKs directly; the orchestrator keeps your local cache synchronized and evaluates your queries consistently offline and online.
Overview
- Single entrypoint: orchestrator handles reads/writes, sync, conflicts
- Cache-consistent queries using
QuerySpec
- Policies:
remoteFirst
,localFirst
,offlineOnly
,onlineOnly
- Adapters included: Appwrite, PocketBase, Supabase; Local store: Drift
Quick Setup (Supabase)
dependencies:
remote_cache_sync:
supabase_flutter:
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:remote_cache_sync/remote_cache_sync.dart';
await Supabase.initialize(url: 'https://YOUR_PROJECT.supabase.co', anonKey: 'YOUR_ANON_OR_SERVICE_ROLE_KEY');
final client = Supabase.instance.client;
final remote = SupabaseRemoteStore<Todo, String>(
config: SupabaseRemoteConfig<Todo, String>(
client: client,
table: 'todos',
idColumn: 'id',
updatedAtColumn: 'updated_at',
deletedAtColumn: 'deleted_at',
scopeNameColumn: 'scope_name',
scopeKeysColumn: 'scope_keys',
idOf: (t) => t.id,
idToString: (s) => s,
idFromString: (s) => s,
toJson: (t) => {/* map Todo -> row */},
fromJson: (m) => /* map row -> Todo */,
serverTimeRpcName: 'server_time_utc',
),
);
Orchestrator-first Quickstart
final orchestrator = SimpleSyncOrchestrator<Todo, String>(
local: DriftLocalStore<Todo, String>(/* ... */),
remote: SupabaseRemoteStore<Todo, String>(/* ... */),
resolver: const LastWriteWinsResolver<Todo>(),
idOf: (t) => t.id,
);
final scope = const SyncScope('todos', {'userId': 'u1'});
final items = await orchestrator.readWith(
scope,
QuerySpec(
filters: [
FilterOp(field: 'updatedAt', op: FilterOperator.gte, value: DateTime.utc(2025, 1, 1)),
],
orderBy: [OrderSpec('updatedAt', descending: true)],
limit: 20,
),
policy: CachePolicy.remoteFirst, // sync then evaluate on local cache
preferRemoteEval: false, // set true to try remote-side filtering first
fallbackToLocal: true, // fall back when remote can't support a filter
);
Key benefits:
- Orchestrator-driven single entrypoint for reads/writes
- Cache-consistent query evaluation with
QuerySpec
- Seamless offline/online via
CachePolicy
- Pluggable remotes (Appwrite, PocketBase, Supabase) and local stores (Drift)
Documentation
Issues and feedback
- File issues/feature requests: Issues
Contributing
- See repository guidelines: Contributing
Libraries
- remote_cache_sync
- remote_cache_sync_adapters
- remote_cache_sync_method_channel
- remote_cache_sync_platform_interface
- sync/cache_policy
- sync/conflict_resolver
- sync/drift/connection/connection
- sync/drift/connection/connection_native
- sync/drift/connection/connection_web
- sync/drift/database
- sync/drift/drift_local_store
- sync/in_memory_local_store
- sync/in_memory_remote_store
- sync/remote/appwrite_remote_store
- sync/remote/appwrite_search_plan
- sync/remote/pocketbase_remote_store
- sync/remote/pocketbase_search_plan
- sync/remote/supabase_remote_store
- sync/remote/supabase_search_plan
- sync/simple_sync_orchestrator
- sync/store_interfaces
- sync/sync_orchestrator
- sync/sync_types
- Common sync-related types shared across features.