Supabase's realtime capabilities allow your application to react instantly to changes in your database. This is crucial for building dynamic, engaging user experiences where data is constantly evolving. Whether it's live chat, collaborative editing, or real-time dashboards, Supabase makes it straightforward to subscribe to and handle these events.
The core of Supabase realtime is its subscription system. You can subscribe to specific tables and listen for different types of database events. The three primary events you'll commonly handle are INSERT, UPDATE, and DELETE.
Let's imagine we have a messages table in our Supabase database. We want our chat application to display new messages as soon as they are sent, update message statuses (like 'read'), and remove deleted messages.
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = 'YOUR_SUPABASE_URL'
const supabaseAnonKey = 'YOUR_SUPABASE_ANON_KEY'
const supabase = createClient(supabaseUrl, supabaseAnonKey)
// Subscribe to inserts in the messages table
const channel = supabase.channel('messages_channel', {
config: {
presence: {
key: 'uniqueUserId'
}
}
})
.on('postgres_changes', {
event: 'INSERT',
schema: 'public',
table: 'messages',
}, (payload) => {
console.log('New message inserted:', payload.new)
// Here, you'd update your UI to display the new message
})
.subscribe()
// To unsubscribe when the component unmounts or is no longer needed:
// supabase.removeChannel(channel);In the code above, we create a new channel named messages_channel. We then use the .on() method to listen for postgres_changes. We specify that we are interested in INSERT events from the messages table in the public schema. The callback function receives a payload object. The payload.new property contains the full new row that was inserted.
Now, let's extend this to handle UPDATE events. For instance, if a message status changes from 'sending' to 'sent' or 'read'.
const channel = supabase.channel('messages_channel', {
config: {
presence: {
key: 'uniqueUserId'
}
}
})
.on('postgres_changes', {
event: 'INSERT',
schema: 'public',
table: 'messages',
}, (payload) => {
console.log('New message inserted:', payload.new)
// Update UI for new message
})
.on('postgres_changes', {
event: 'UPDATE',
schema: 'public',
table: 'messages',
}, (payload) => {
console.log('Message updated:', payload.new)
// Here, you'd find the message in your UI and update its properties (e.g., status)
})
.subscribe()When an UPDATE event occurs, the payload.new property will contain the latest version of the row after the update. You can then compare this with existing data in your application's state to determine which parts of the UI need to be refreshed. The payload.old property contains the state of the row before the update, which can also be useful.
Finally, let's consider handling DELETE events. If a user deletes a message, we'll want to remove it from our chat view.
const channel = supabase.channel('messages_channel', {
config: {
presence: {
key: 'uniqueUserId'
}
}
})
.on('postgres_changes', {
event: 'INSERT',
schema: 'public',
table: 'messages',
}, (payload) => {
console.log('New message inserted:', payload.new)
// Update UI for new message
})
.on('postgres_changes', {
event: 'UPDATE',
schema: 'public',
table: 'messages',
}, (payload) => {
console.log('Message updated:', payload.new)
// Update UI for updated message
})
.on('postgres_changes', {
event: 'DELETE',
schema: 'public',
table: 'messages',
}, (payload) => {
console.log('Message deleted:', payload.old)
// Here, you'd remove the message with the corresponding ID from your UI
// payload.old contains the row that was deleted.
})
.subscribe()For DELETE events, the payload.old property is key. It contains the row that was removed from the database. You'll use its primary key (or another unique identifier) to find and remove the corresponding element from your application's rendered output.
It's important to note that the event parameter in .on() can also accept an array of events, like ['INSERT', 'UPDATE'], to listen for multiple event types on the same subscription. You can also subscribe to all events by omitting the event property altogether.
graph TD
A[Client Application] -- Subscribe to Table Changes --> B(Supabase Realtime Server)
B -- Publishes INSERT Event --> A
B -- Publishes UPDATE Event --> A
B -- Publishes DELETE Event --> A
A -- Receives Payload --> C{Handle Event Logic}
C -- Update UI --> D[Display Live Data]
C -- Update State --> D
The mermaid diagram illustrates the flow: your application subscribes to changes on a Supabase table. When changes occur (insert, update, delete), Supabase Realtime Server publishes these events. Your application receives the event payload and executes logic to update its state and ultimately the user interface, providing a dynamic, real-time experience.