How We Built a Real-Time Booking Platform with Supabase Realtime
Product Development

How We Built a Real-Time Booking Platform with Supabase Realtime

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

typescript
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"

typescript
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.

SupabaseRealtimeBookingNextjsPostgreSQL

Thoughts? Questions?

We would love to hear from you. Get in touch with our team.