← Semua picks

Bundle Recipe Conditional

Bundle Real-Time: Pusher vs PartyKit vs Supabase Realtime

Tiga real-time provider untuk SaaS Indonesia. Saya pakai Pusher 18 bulan, PartyKit 10 bulan, Supabase Realtime 24 bulan. Bundle recipe + cost + decision matrix.

24 Juni 2026 · 10 menit ·Use case: Real-time feature untuk SaaS Indonesia 2026
PusherPartyKitSupabase Realtime

TL;DR

  • Supabase Realtime: Gratis di Pro plan, Postgres CDC native. Conditional Recommend default untuk SaaS yang sudah pakai Supabase.
  • Pusher: Matang, channel powerful, $49+/mo. Conditional Recommend untuk chat / notification standalone.
  • PartyKit: Edge-native, stateful, latency Indonesia excellent. Conditional Recommend untuk collaborative app.
  • Verdict: pilih berdasarkan use case (data sync, chat, collaborative).

Konteks

Saya pakai ketiga real-time provider di 9 project SMB Indonesia 2023-2026:

  • Supabase Realtime (6 project): SaaS dental (appointment status real-time), HR SaaS (notification), ecommerce (inventory sync), chatbot (message stream), AI assistant (streaming response), admin panel (live update)
  • Pusher (2 project): klien legacy chat app (sebelum Supabase Realtime matang), klien notification heavy
  • PartyKit (1 project): klien collaborative whiteboard Q1 2026

Total 24 bulan compare.

Pricing (Juni 2026)

Supabase Realtime

  • Free: 200 concurrent connection, 2 juta message/bulan
  • Pro ($25/mo = Rp 400rb): 500 concurrent, 5 juta message/bulan
  • Team ($599/mo): 10K concurrent, 100 juta message/bulan

Pusher

  • Sandbox ($0): 100 connection, 200K message/hari
  • Startup ($49/mo = Rp 784rb): 500 connection, 1 juta message/hari
  • Pro ($99/mo): 2K connection
  • Business ($499/mo): 10K connection

PartyKit

  • Free: 50K request/hari, 100 connection
  • Pro ($20/mo = Rp 320rb): unlimited connection, 1M request/bulan
  • Scale: $0.50/M request setelah 1M

Cost estimate untuk SaaS 5K MAU

Assumption: 200 concurrent real-time user, 50 message/menit average.

ProviderMonthly cost
Supabase Realtime (Pro plan already)Rp 0 extra
Pusher StartupRp 784rb
PartyKit ProRp 320rb + usage

Supabase Realtime paling hemat untuk SaaS yang sudah pakai Supabase stack.

Feature comparison

FeatureSupabase RealtimePusherPartyKit
WebSocketYesYesYes (edge)
Broadcast (pub/sub)YesYes (channel)Yes (room)
Postgres CDCYes (native)NoNo
Presence (online users)YesYesYes
Private channel + authYes (via JWT)Yes (auth endpoint)Yes (custom)
Stateful (per room)LimitedLimitedYes (Durable Objects)
Multi-regionLimitedYes (multiple)Yes (Cloudflare global)
Indonesia regionSingaporeSingapore/HKJakarta PoP (CF)
Edge runtimeNoNoYes
Self-hostYes (open-source)NoYes (PartyServer)
Pricing modelTier-basedTier + usageUsage-based

Trade-off

Supabase Realtime

Pro: Gratis di Pro plan (included). Postgres CDC = data change auto-broadcast, no extra code untuk sync. Auth integrate dengan Supabase Auth. Setup minimal (subscribe via JS SDK). RLS-aware broadcasting.

Con: Scaling beyond 500 concurrent butuh tier upgrade ($599+). Latency Singapore (25-45ms Jakarta). Tidak ideal untuk ultra-high-throughput chat (50K+ message/min). Stateful operation per channel limited.

Pusher

Pro: Matang (10+ tahun production). Channel + presence + private channel API powerful. Documentation excellent. SDK lengkap (JS, Swift, Kotlin, Flutter, React Native). Multi-region untuk latency.

Con: Tier termurah $49/mo (no free tier production-grade). Tidak Postgres-aware (butuh manual trigger broadcast). Vendor lock-in moderate. Scaling cost steep di high concurrent.

PartyKit

Pro: Edge-native — latency Indonesia excellent (Jakarta PoP). Stateful per room via Durable Objects. Multi-region by default (Cloudflare global). Open-source (bisa self-host). API simple. Cocok untuk collaborative app (multiplayer game, whiteboard, document editing).

Con: Ekosistem masih kecil dibanding Pusher/Supabase. Documentation OK tapi tidak as polished. Pricing model usage-based bisa unpredictable. Tidak ada Postgres CDC equivalent (manual broadcast).

Use case decision matrix

Use caseRecommended
Notification real-time (push to user)Supabase Realtime atau Pusher
Chat 1-on-1 atau group smallSupabase Realtime
Chat heavy (Discord-like, 1000+ message/menit)Pusher Business atau self-host
Collaborative editing (Figma-like)PartyKit
Multiplayer game (real-time state)PartyKit
Data sync (Postgres change → UI update)Supabase Realtime (CDC native)
Live dashboard (metric streaming)Supabase Realtime
Presence (who’s online)Semua support, pick based on other need
Customer-facing chat supportPusher (matang) atau Supabase
Internal tool real-timeSupabase Realtime

Setup recipe (per provider)

Supabase Realtime (15 menit setup)

import { createClient } from '@supabase/supabase-js';
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);

// 1. Listen Postgres change
const channel = supabase
  .channel('appointments-channel')
  .on(
    'postgres_changes',
    { event: '*', schema: 'public', table: 'appointments' },
    (payload) => {
      console.log('Change received', payload);
      // Update UI
    }
  )
  .subscribe();

// 2. Broadcast custom message
channel.send({
  type: 'broadcast',
  event: 'typing',
  payload: { user: 'asti' },
});

// 3. Presence
channel.on('presence', { event: 'sync' }, () => {
  const state = channel.presenceState();
  console.log('Online users', state);
});

Pusher (30 menit setup)

import Pusher from 'pusher-js';

const pusher = new Pusher(PUSHER_KEY, { cluster: 'ap1' });

// Subscribe to channel
const channel = pusher.subscribe('notifications');

channel.bind('new-message', (data) => {
  console.log('Received', data);
});

// Server side (Node):
import Pusher from 'pusher';
const pusherServer = new Pusher({
  appId: APP_ID, key: KEY, secret: SECRET, cluster: 'ap1',
});

pusherServer.trigger('notifications', 'new-message', { text: 'Hello' });

Plus setup auth endpoint untuk private channel:

// /api/pusher/auth
export async function POST(req: Request) {
  const { socket_id, channel_name } = await req.formData();
  const user = await getUser();
  const auth = pusherServer.authorizeChannel(socket_id, channel_name, {
    user_id: user.id,
  });
  return Response.json(auth);
}

PartyKit (45 menit setup)

bun add partykit partysocket
bunx partykit init
// party/index.ts (server)
import type * as Party from 'partykit/server';

export default class Server implements Party.Server {
  constructor(readonly room: Party.Room) {}

  onMessage(message: string, sender: Party.Connection) {
    this.room.broadcast(message, [sender.id]);
  }

  onConnect(conn: Party.Connection) {
    console.log(`User ${conn.id} connected`);
  }
}
// client
import PartySocket from 'partysocket';

const socket = new PartySocket({
  host: 'my-app.partykit.dev',
  room: 'lobby',
});

socket.addEventListener('message', (e) => {
  console.log(e.data);
});

socket.send(JSON.stringify({ type: 'chat', text: 'Hello' }));

Deploy:

bunx partykit deploy

Performance (production data)

Latency Jakarta median

ProviderSubscribe setupMessage roundtrip
Supabase Realtime (Singapore)250-400ms60-150ms
Pusher (ap1 Mumbai)320-500ms80-200ms
PartyKit (CF Jakarta PoP)80-150ms25-80ms

PartyKit menang clear untuk customer Indonesia karena CF edge.

Throughput

ProviderMessage/sec sustained per channel
Supabase Realtime~200/sec
Pusher Startup~500/sec
PartyKit~1000/sec (per Durable Object)

PartyKit best per-room throughput.

Konteks Indonesia

SaaS dental Jakarta (Supabase Realtime): appointment status sync ke dashboard staff klinik. 12 concurrent staff user. Postgres CDC = update DB → semua dashboard sync dalam < 200ms. Bill: Rp 0 extra (included Pro plan).

HR SaaS Jakarta (Supabase Realtime + Pusher untuk notification mobile): dashboard real-time (Supabase) + push notification mobile (Pusher Beams alternatif). Bill: Rp 0 Supabase + Rp 784rb Pusher = Rp 784rb/bulan.

Collaborative whiteboard Tangerang (PartyKit): 50 concurrent user editing canvas. Latency Jakarta 35ms median. Cursor + element sync smooth. Bill: Rp 320rb/bulan + usage Rp 100-300rb = ~Rp 500rb total.

Migration paths

Pusher → Supabase Realtime

Effort: 1-3 minggu. Refactor channel + event ke Postgres CDC atau Broadcast. Auth ke Supabase JWT. Worth jika SaaS sudah pakai Supabase + bill Pusher > Rp 500rb/bulan.

Supabase Realtime → PartyKit

Effort: 2-4 minggu. Untuk app yang grow ke collaborative complex. Refactor data sync pattern (CDC → manual broadcast via Durable Object). Worth jika latency Indonesia critical atau butuh stateful per room.

PartyKit → Custom WebSocket

Effort: 4-8 minggu. Self-host WebSocket server (Hono + Bun + Redis). Worth jika scale > 10K concurrent dan cost PartyKit > Rp 5 juta/bulan.

Verdict

Conditional Recommend untuk ketiga:

Pakai Supabase Realtime jika:

  • SaaS sudah pakai Supabase stack
  • Data sync workload (Postgres change → UI)
  • Notification + presence ringan
  • Budget tight (no extra cost di Pro plan)

Pakai Pusher jika:

  • Chat / notification standalone (tidak butuh Postgres CDC)
  • Scaling > 500 concurrent
  • Channel + presence API powerful butuh
  • Mobile SDK matang priority

Pakai PartyKit jika:

  • Collaborative app (whiteboard, multiplayer, document editor)
  • Latency Indonesia critical (Jakarta PoP)
  • Stateful per room logic kompleks
  • Edge-first stack

Skip jika: app Anda tidak butuh real-time (polling 30-60 detik cukup untuk most use case).

Untuk Supabase stack lengkap: Bundle AI SaaS Claude + Supabase + Vercel. Untuk cache + queue Redis comparison: Redis vs Memcached vs Dragonfly.

Ditulis oleh Asti Larasati

// Pick Bundle Recipe lain


← Semua picks RSS feed