apps/www/_blog/2025-12-05-realtime-broadcast-replay.mdx
Today we're releasing Broadcast Replay for Realtime - a powerful new feature that enables private channels to access messages that were sent earlier, ensuring your users never miss critical updates.
Building real-time applications comes with unique challenges. What happens when:
Previously, these scenarios meant lost context and degraded user experiences. Users would miss important messages sent while they were disconnected, and developers had to implement complex workarounds to maintain state consistency.
Broadcast Replay solves these challenges by allowing private channels to retrieve messages that were sent before a client connected or while they were disconnected. This feature integrates seamlessly with our existing Broadcast from Database functionality, storing messages in the realtime.messages table for up to 3 days.
It leverages the messages already stored when using Broadcast from Database. When you enable replay on a private channel, Realtime queries the partitioned realtime.messages table to retrieve historical messages based on your configuration.
The replay configuration accepts two parameters:
since (required): Unix timestamp in milliseconds specifying the earliest point from which messages should be retrieved;limit (optional): Number of messages to return (1-25, useful for preventing information overload).You can see Broadcast Replay in action at https://multiplayer.dev, where the chat box demonstrates how users can access historical messages when joining or reconnecting to a conversation.
Display the most recent messages when users enter a chat room, providing immediate context without complex state management:
const chatChannel = supabase.channel(`chat:${roomId}`, {
config: {
private: true,
broadcast: {
replay: {
since: Date.now() - 300000, // Last 5 minutes
limit: 25, // Show last 25 messages
},
},
},
})
Ensure fans never miss crucial moments, even after connection issues:
const gameChannel = supabase.channel(`game:${matchId}:key-events`, {
config: {
private: true,
broadcast: {
replay: {
since: matchStartTime, // Replay from match start
limit: 20, // Show key events
},
},
},
})
Highlight recent changes in documents when users return:
const docChannel = supabase.channel(`doc:${documentId}`, {
config: {
private: true,
broadcast: {
replay: {
since: lastSeenTimestamp, // Changes since last visit
limit: 15,
},
},
},
})
The triggered events are now enriched with metadata to recognise replayed messages.
{
"event": "message",
"meta": {
"id": "55f92208-37c8-4c7b-930d-756f14586e55",
"replayed": true
},
"payload": {
"content": "Hello world",
"createdAt": "2025-11-12T15:41:22Z",
"id": "3f0e4cdf-f886-4b2c-b132-1cedb5c55acc",
"username": "supabasito"
},
"type": "broadcast"
}
One can use the meta.replayed field to handle historical and live messages differently:
// Broadcast callback receives meta field
channel.on('broadcast', { event: 'chat_message' }, (payload) => {
const chatMessage = payload.payload as ChatMessage
// Render replayed messages with a different aspect
chatMessage.replayed = payload?.meta?.replayed ?? false
setMessages((current) => [...current, chatMessage])
})
Broadcast Replay is available today in Public Alpha. This feature requires:
We're actively seeking feedback to refine this feature. If you encounter any issues or have suggestions, please submit a support ticket.
Check out our documentation for detailed implementation guides and more examples.
<div className="video-container"> <iframe className="w-full" src="https://www.youtube-nocookie.com/embed/scbQlEH3pRc" title="Introducing Realtime Broadcast Replay" allow="accelerometer; autoplay; clipboard-write; encrypted-media; fullscreen; gyroscope; picture-in-picture; web-share" allowfullscreen /> </div>