Skip to Content
Real-timeSynchronization

Flutter InstantDB provides real-time synchronization across all connected clients using WebSocket connections. Changes are propagated instantly with conflict resolution and offline support.

Enabling Sync

Enable real-time synchronization during database initialization:

final db = await InstantDB.init( appId: 'your-app-id', config: const InstantConfig( syncEnabled: true, // Enable real-time sync verboseLogging: false, // Set to true for detailed sync logs ), );

Connection Status

Monitor the connection status to provide user feedback:

// Using a reactive widget Watch((context) { final syncEngine = db.syncEngine; final isConnected = syncEngine?.connectionStatus.value ?? false; return Row( children: [ Icon( isConnected ? Icons.cloud_done : Icons.cloud_off, color: isConnected ? Colors.green : Colors.grey, ), Text(isConnected ? 'Connected' : 'Offline'), ], ); }); // Or create a custom connection status widget class ConnectionStatusIndicator extends StatelessWidget { @override Widget build(BuildContext context) { final db = InstantProvider.of(context); return Watch((context) { final isOnline = db.syncEngine?.connectionStatus.value ?? false; return AnimatedContainer( duration: const Duration(milliseconds: 300), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: isOnline ? Colors.green : Colors.orange, borderRadius: BorderRadius.circular(12), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( isOnline ? Icons.wifi : Icons.wifi_off, size: 16, color: Colors.white, ), const SizedBox(width: 4), Text( isOnline ? 'Online' : 'Offline', style: const TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.w500, ), ), ], ), ); }); } }

How Sync Works

Differential Sync

InstantDB uses differential synchronization to efficiently sync only the changes:

  1. Local Changes: When you make local changes, they’re applied immediately (optimistic updates)
  2. Sync Queue: Changes are queued for synchronization with the server
  3. WebSocket Transmission: Changes are sent via WebSocket in real-time
  4. Server Processing: Server processes and broadcasts changes to other clients
  5. Conflict Resolution: Automatic handling of concurrent modifications

Transaction Integrity

All operations maintain transaction integrity during sync:

// This transaction will be synced atomically await db.transact([ ...db.create('posts', { 'id': db.id(), 'title': 'New Post', 'authorId': userId, }), db.update(userId, { 'postCount': {'$increment': 1}, }), ]);

Sync Events

Monitor sync events for debugging or user feedback:

// Listen to sync engine events (if available) db.syncEngine?.onConnectionChange.listen((isConnected) { print('Connection status changed: $isConnected'); if (isConnected) { // Connection restored - sync pending changes showSnackBar('Connection restored'); } else { // Connection lost - work offline showSnackBar('Working offline'); } });

Handling Offline/Online Transitions

InstantDB handles offline scenarios gracefully:

Offline Behavior

When offline, InstantDB:

  • Stores all changes locally in SQLite
  • Continues to serve queries from local data
  • Queues mutations for later synchronization
  • Provides immediate UI updates (optimistic)

Coming Back Online

When connection is restored:

  • Pending transactions are automatically synced
  • Server changes are downloaded and applied
  • Conflicts are resolved automatically
  • UI updates reflect the synchronized state
// Example of handling online/offline states class OfflineAwareWidget extends StatelessWidget { @override Widget build(BuildContext context) { final db = InstantProvider.of(context); return Watch((context) { final isOnline = db.syncEngine?.connectionStatus.value ?? false; return Column( children: [ if (!isOnline) Container( width: double.infinity, padding: const EdgeInsets.all(8), color: Colors.orange, child: const Text( 'Working offline - changes will sync when connected', textAlign: TextAlign.center, style: TextStyle(color: Colors.white), ), ), // Your main content InstantBuilder( query: {'todos': {}}, builder: (context, result) { // Data is always available, even offline return TodoList(todos: result.data!['todos']); }, ), ], ); }); } }

Sync Performance

Batching Operations

For better performance, batch multiple operations:

// Instead of multiple separate transactions await db.transact([...db.create('item1', data1)]); await db.transact([...db.create('item2', data2)]); await db.transact([...db.create('item3', data3)]); // Use a single batched transaction await db.transact([ ...db.create('item1', data1), ...db.create('item2', data2), ...db.create('item3', data3), ]);

Optimistic Updates

InstantDB provides optimistic updates by default:

// UI updates immediately, then syncs in background await db.transact([ db.update(todoId, {'completed': true}), ]); // The UI shows the change instantly, sync happens asynchronously

Advanced Sync Configuration

Custom Sync Settings

Configure sync behavior during initialization:

final db = await InstantDB.init( appId: 'your-app-id', config: const InstantConfig( syncEnabled: true, // Custom WebSocket URL (optional) websocketUrl: 'wss://custom.instantdb.com/ws', // Enable detailed logging for debugging verboseLogging: true, // Custom API endpoint baseUrl: 'https://custom.instantdb.com', ), );

Sync Debugging

Enable verbose logging to debug sync issues:

final db = await InstantDB.init( appId: 'your-app-id', config: const InstantConfig( syncEnabled: true, verboseLogging: true, // Detailed sync logs ), );

This will log:

  • WebSocket connection events
  • Transaction synchronization
  • Conflict resolution
  • Network errors and retries

Best Practices

1. Handle Connection States

Always provide feedback for offline states:

// Good: Show connection status if (!isOnline) { return OfflineBanner(); } // Bad: No indication of offline state

2. Optimistic UI Updates

Trust InstantDB’s optimistic updates:

// Good: Update immediately, let InstantDB handle sync await db.transact([db.update(id, newData)]); // Bad: Wait for server confirmation

3. Batch Operations

Group related operations into single transactions:

// Good: Atomic operation await db.transact([ ...db.create('post', postData), db.update(userId, {'postCount': {'$increment': 1}}), ]); // Bad: Separate operations that could fail independently

4. Monitor Connection

Provide connection status in your UI:

// Always show connection status in critical apps AppBar( actions: [ ConnectionStatusIndicator(), ], )

Troubleshooting Sync Issues

Common Issues

  1. Not Syncing: Check if syncEnabled: true in config
  2. Slow Sync: Check network connection and server status
  3. Conflicts: Review conflict resolution logs
  4. Memory Issues: Ensure proper disposal of database instances

Debug Logging

Enable verbose logging to diagnose issues:

// Add this to see detailed sync logs config: const InstantConfig( syncEnabled: true, verboseLogging: true, ),

Network Debugging

Test sync with network conditions:

// Simulate offline mode for testing db.syncEngine?.disconnect(); // Reconnect db.syncEngine?.connect();

Next Steps

Learn more about InstantDB’s real-time features: