Crash Courses · Masters
Real-time Subscriptions
Build live features with Supabase Realtime — presence, broadcast, and Postgres changes.
10 min read+175 XP on completionCert: Supabase Crash Course
Tap any word in the text below to start reading from there.
Real-time Subscriptions
Supabase Realtime lets you subscribe to database changes over WebSockets. UIs update live without polling.
Subscribe to Table Changes
'use client'
import { useEffect, useState } from 'react'
import { createClient } from '@/lib/supabase/client'
function LiveCourseList() {
const [courses, setCourses] = useState<Course[]>([])
const supabase = createClient()
useEffect(() => {
// Initial load
supabase
.from('courses')
.select('*')
.then(({ data }) => setCourses(data ?? []))
// Subscribe to changes
const channel = supabase
.channel('courses-changes')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'courses' },
(payload) => {
if (payload.eventType === 'INSERT') {
setCourses(prev => [...prev, payload.new as Course])
}
if (payload.eventType === 'DELETE') {
setCourses(prev => prev.filter(c => c.id !== payload.old.id))
}
if (payload.eventType === 'UPDATE') {
setCourses(prev => prev.map(c => c.id === payload.new.id ? payload.new as Course : c))
}
}
)
.subscribe()
return () => { supabase.removeChannel(channel) }
}, [])
return <CourseList courses={courses} />
}Presence (Online Users)
useEffect(() => {
const channel = supabase.channel('course-room')
channel
.on('presence', { event: 'sync' }, () => {
const state = channel.presenceState()
const onlineCount = Object.keys(state).length
setOnlineUsers(onlineCount)
})
.subscribe(async (status) => {
if (status === 'SUBSCRIBED') {
await channel.track({ user_id: userId, online_at: new Date().toISOString() })
}
})
return () => { supabase.removeChannel(channel) }
}, [])Reading progress
0% read
In this module
Realtime
postgres_changes
channel
Presence
0%