DEV Community

kanta13jp1
kanta13jp1

Posted on

Supabase Realtime — Postgres Changes, Presence, and Broadcast

Supabase Realtime — Postgres Changes, Presence, and Broadcast

Supabase Realtime delivers WebSocket-based real-time features in three distinct modes.

Postgres Changes (DB Change Subscription)

// Receive INSERT/UPDATE/DELETE from a table in real time
final channel = supabase.channel('public:messages');

channel
  .onPostgresChanges(
    event: PostgresChangeEvent.all,
    schema: 'public',
    table: 'messages',
    callback: (payload) {
      final newRow = payload.newRecord;
      setState(() => _messages.add(Message.fromJson(newRow)));
    },
  )
  .subscribe();

// Cleanup
@override
void dispose() {
  supabase.removeChannel(channel);
  super.dispose();
}
Enter fullscreen mode Exit fullscreen mode

Presence (Online Status)

// Share user presence state in real time
final presenceChannel = supabase.channel('room:${roomId}');

presenceChannel
  .onPresenceSync((_) {
    final state = presenceChannel.presenceState();
    final onlineUsers = state.keys.toList();
    setState(() => _onlineUsers = onlineUsers);
  })
  .subscribe(
    (status, _) async {
      if (status == RealtimeSubscribeStatus.subscribed) {
        await presenceChannel.track({'user_id': userId, 'online_at': DateTime.now().toIso8601String()});
      }
    },
  );
Enter fullscreen mode Exit fullscreen mode

Broadcast (P2P Messaging)

// Lightweight real-time communication without hitting the DB (typing indicators, cursors)
final typingChannel = supabase.channel('typing:${roomId}');

typingChannel
  .onBroadcast(
    event: 'typing',
    callback: (payload) {
      final typingUserId = payload['user_id'] as String;
      setState(() => _typingUsers.add(typingUserId));
    },
  )
  .subscribe();

// Notify others that the current user is typing
await typingChannel.sendBroadcastMessage(
  event: 'typing',
  payload: {'user_id': currentUserId},
);
Enter fullscreen mode Exit fullscreen mode

Summary

Postgres Changes → instant DB change propagation (chat, notifications, dashboards)
Presence         → user online state (online badges, collaborative editing)
Broadcast        → DB-bypass lightweight messaging (typing indicators, cursors)
Cleanup          → always call removeChannel() in dispose()
Enter fullscreen mode Exit fullscreen mode

Realtime delivers faster than push notifications, cheaper than polling — it's the fastest path to a live-updating UX.

Top comments (0)