One of our recent projects was a multi-tenant booking platform for a healthcare provider network. The core requirement: appointments must be visible to all relevant parties in real-time — no refresh, no polling.
The Architecture Decision
We evaluated several approaches:
- Client-side polling: Simple, but creates excessive load and poor UX.
- WebSockets with a custom server: Full control, but adds infrastructure complexity.
- Supabase Realtime: Built on top of Phoenix Channels, leverages PostgreSQL's built-in logical replication. Zero infrastructure to manage.
We chose Supabase Realtime.
Setting Up Realtime Subscriptions
const channel = supabase
.channel('appointments-room')
.on(
'postgres_changes',
{
event: '*', // INSERT, UPDATE, DELETE
schema: 'public',
table: 'appointments',
filter: `provider_id=eq.${providerId}`
},
(payload) => {
if (payload.eventType === 'INSERT') {
setAppointments(prev => [...prev, payload.new]);
} else if (payload.eventType === 'UPDATE') {
setAppointments(prev =>
prev.map(a => a.id === payload.new.id ? payload.new : a)
);
}
}
)
.subscribe();
// Cleanup on unmount
return () => supabase.removeChannel(channel);Implementing Presence: "Who's Online"
const presenceChannel = supabase.channel('online-users', {
config: { presence: { key: userId } }
});
presenceChannel
.on('presence', { event: 'sync' }, () => {
const state = presenceChannel.presenceState();
setOnlineUsers(Object.keys(state));
})
.subscribe(async (status) => {
if (status === 'SUBSCRIBED') {
await presenceChannel.track({ user_id: userId, online_at: new Date().toISOString() });
}
});Scaling Realtime for Production
When we load-tested the platform with 5,000 concurrent users:
- Batched subscriptions by provider page (one channel per provider, not per user).
- Used Presence features to track connected users.
- Implemented a heartbeat mechanism that cleaned up stale connections every 30 seconds.
Conclusion
Supabase Realtime allowed us to ship production-grade real-time features without managing WebSocket infrastructure. The booking platform handles over 15,000 appointments per month with sub-200ms broadcast latency.

