Your users are waiting for the page to catch up. Not a full reload — just the number in the corner to change, or a collaborator's cursor to appear. That gap between database write and client render is where real-time architecture decisions either age well or turn into expensive rewrites.
I've built real-time features on three different stacks across several B2B SaaS products. The honest summary: each of the three main options in 2026 — Supabase Realtime, Liveblocks, and PartyKit — solves a different problem, and picking the wrong one costs you either money or engineering time you didn't budget for.
Here's the specific decision each one is built for, with actual numbers.
When Does Supabase Realtime Make Sense?
Supabase Realtime fits when your requirement is: reflect database writes to connected clients, not coordinate simultaneous edits between multiple users.

If your feature is "when row X changes, client Y should see it" — a dashboard that updates when a new order lands, a status indicator that flips when a job completes — Supabase Realtime is the right call. Zero new infrastructure. Works in the same stack you're already running.
The platform ships in three modes. Postgres Changes listens to actual DB mutations and pushes them over WebSocket. Broadcast is pub/sub between clients without touching the database at all. Presence tracks who is online in a channel. Each mode has distinct limits, and the limits matter more than most documentation leads you to believe.
According to Supabase's limits documentation, the Free tier gives you 200 concurrent connections and 100 messages per second. Pro ($25/month) raises that to 500 connections and 500 messages/second, with overage priced at $10 per 1,000 peak connections above 500 and $2.50 per million messages. For most early-stage products this is plenty. At 1,000 concurrent users you're adding $5/month in connection overage on top of Pro — not a budget problem.
Presence is where the hidden limits appear. Max 5 track calls per client per 30 seconds. Max 10 presence keys per object. Pro allows 50 presence messages per second across the entire project. These numbers are fine at 20 users. They are not fine at 500.
What trips teams up most is the delivery model. Supabase's Postgres Changes docs say explicitly: the server does not guarantee every message is delivered. If a client disconnects for 30 seconds and reconnects, every change that happened in between is gone. No queue. No replay. The client picks up with current state and has no way to know what it missed.
This is the correct behavior for a live analytics dashboard. It is the wrong behavior for a booking calendar where a missed delivery means a double-booking silently sits in the database.
There is also an authorization N+1 problem specific to Postgres Changes. If 100 users subscribe to a table and one row is inserted, Supabase runs 100 separate row-level security checks — one per subscriber — to validate read access. On a busy table this creates a database-side throughput bottleneck. If you are already using the React + Supabase RLS stack, this is the constraint that connects your RLS policy complexity to your real-time throughput ceiling.
One production ghost that's worth knowing about: Presence state can go stale after a tab loses and regains focus, leaving phantom "online" entries that never actually left. The fix is re-tracking on the browser's visibilitychange event with a fresh timestamp. It's not documented prominently. Teams find it by noticing their active user count creeping upward over a session.
Supabase added Broadcast and Presence Authorization in a 2024 update, allowing custom JWT claims to gate channel access. Previously, Broadcast channels were effectively unauthenticated. That gap is closed. For a multi-tenant SaaS, you want to verify your channel join logic actually enforces tenant boundaries — the authorization model is there, but it is opt-in, not automatic.
Is Liveblocks Worth the Cost for Collaborative UI?
Liveblocks earns its price when multiple users need to edit shared state simultaneously and you'd rather not build CRDT conflict resolution yourself.

The core differentiator is the data model. Liveblocks uses Conflict-Free Replicated Data Types — LiveObject, LiveList, LiveMap — that resolve concurrent edits automatically without server-side merge logic. Two users click the same field at the same millisecond, and both changes survive without either overwriting the other. For text editing specifically, Liveblocks exposes a Yjs integration, plugging into the full Yjs ecosystem (CodeMirror, TipTap, Blocknote) while Liveblocks handles the WebSocket transport and persistence layer.
What you get out of the box: rooms, presence, storage, comments with threading, notification feeds, and an AI copilot layer. For a project management tool or a design app, the managed platform compresses what would be a month of infrastructure decisions into a few days of SDK integration. That is its actual value proposition.
Then there is the pricing, which needs concrete numbers to evaluate honestly.
The Pro plan is $30/month ($25/month billed annually) and includes $30 in monthly credits. Metered rates apply after credits are consumed: $0.002 per collaboration minute, $0.01 per comment created, $0.01 per custom notification event. The free plan caps simultaneous connections at 10 per room.
Let me make the math tangible. 500 monthly active users, each averaging 20 minutes of collaborative session time per month: 10,000 collaboration minutes at $0.002/minute = $20. Add 200 comments at $0.01 each: $2. Total with Pro base: $52/month.
Scale to 5,000 monthly active users at the same usage pattern: 100,000 collaboration minutes = $200 for that line item alone, pushing toward the Team plan at $600–$3,750/month depending on tier. The jump from Pro to Team is steep. Know where your product's active session profile sits before the bill surprises you.
The 20 simultaneous connections per room limit on Pro (50 on Team) is the other ceiling that shows up unexpectedly. A "room" in Liveblocks is a shared collaborative space, not a user account. A product with a large shared workspace where 25 team members are online simultaneously hits the Pro limit. For most B2B SaaS this is fine. For a large-team document or whiteboard with high concurrent density, it is not.
Liveblocks is the correct choice for products where real-time collaboration is the feature, not a supporting behavior. The SaaS MVP stack doesn't need it unless the collaborative editing experience is what users are paying for. A dashboard that auto-updates every 10 seconds doesn't need CRDTs. A co-editing product does.
When Should You Choose PartyKit Instead?
Choose PartyKit when your real-time logic requires custom server code that doesn't fit the DB-sync or managed-CRDT model.

State machines that live server-side, game loops, chat rooms with custom routing, collaborative tools where you need to own the conflict resolution because it's domain-specific. These fall outside what Supabase Realtime and Liveblocks do cleanly.
PartyKit runs on Cloudflare's edge computing network using Durable Objects. You write a class with onConnect, onMessage, and onClose methods. Each named "party" (a room instance) is a Durable Object with its own memory and WebSocket connections. No connection pooling. No horizontal scaling config. The party lives as long as clients are connected and hibernates when the last one leaves.
That hibernation behavior is the key to the cost model. PartyKit supports WebSocket Hibernation via Cloudflare's Hibernatable WebSockets API, which unloads the party from memory when no messages are being exchanged. Duration billing — the main cost driver for Durable Objects — drops to near-zero for idle parties. For a SaaS where users connect for a session, go idle, then reconnect, this is a significant cost lever.
The cost differential is real. A workload running approximately 10,000 monthly rooms at peak loads around 80 concurrent users per room costs approximately $4/month in Durable Objects billing under PartyKit. The equivalent Liveblocks workload costs approximately $80/month — a roughly 20x delta for the same user load. That gap widens as usage grows because Liveblocks scales by MAU, and PartyKit scales by actual compute consumption.
The tradeoff is full ownership. No built-in CRDT. No presence abstraction. No comment threading. You write the WebSocket message handlers, the state reconciliation, the reconnection backoff. If you've shipped a stateful WebSocket server before, this is familiar ground. If you haven't, Liveblocks' DX is meaningfully faster for the first version.
PartyKit has a 128MB memory limit per party. Generous for most use cases, but a real constraint if you're holding large in-memory documents or revision history inside a party. The hibernation API helps by clearing memory for idle parties, but active parties under heavy load are still bounded. Design your state model with the limit in mind.
One billing change worth noting: Cloudflare's SQLite-backed Durable Objects storage billing went live in January 2026. If your PartyKit parties persist state using the SQLite storage layer, you're now paying for that storage on top of compute. Check Cloudflare's Durable Objects pricing page before building persistence-heavy parties — it was free in beta and is now metered.
Supabase vs Liveblocks vs PartyKit: Side-by-Side
| | Supabase Realtime | Liveblocks | PartyKit | |---|---|---|---| | Primary model | DB-driven push | CRDT collaborative rooms | Custom edge WebSocket server | | Best for | Dashboard sync, DB state broadcast | Presence, cursors, co-editing | Custom protocols, game loops, chat | | Delivery guarantee | Best-effort, no message queue | Managed sync with CRDT | You implement it | | CRDT built-in | No | Yes (LiveObject/Yjs) | No | | Free tier | 200 concurrent, 2M msg/mo | 10 sim. connections/room | Cloudflare free tier (100k requests/day) | | ~Cost at 1k MAU | ~$25/mo (Pro) | ~$30–60/mo | ~$1–5/mo | | ~Cost at 10k MAU | ~$25–45/mo + overage | $600+/mo (Team) | ~$5–20/mo | | SOC 2 | Yes (Team plan+) | Yes (Team plan+) | Cloudflare infrastructure-level | | Custom server logic | Limited (Broadcast only) | None server-side | Full control |
The Decision That Actually Matters
The technology choice follows the use case. Get the use case wrong first and the stack choice is irrelevant.
On BookBed, the booking SaaS built on Flutter + Firebase + Stripe, the real-time requirement was narrow: push booking confirmation status to the host dashboard when a guest confirmed. That's Supabase Realtime's problem. Or Firebase Realtime Database, as it happened. Pure DB-to-client state sync with no conflict resolution needed.
If I were rebuilding that product with live seat selection — where two buyers could click the same seat within milliseconds of each other — Liveblocks' conflict-free data types would be the right layer. The alternative is writing optimistic concurrency control and conflict resolution from scratch. Possible. Not a two-day job.
If I were building a multiplayer coding environment with custom annotation tools, PartyKit. The session state is domain-specific, the protocol is custom, and the 20x cost advantage at scale is hard to ignore once you've seen the Liveblocks Team plan invoice.
The "start with Supabase Realtime because we're already on Supabase" instinct is usually correct at the MVP stage. Two hundred connection free tier covers most closed-beta scenarios. If you hit the Postgres Changes authorization bottleneck — a single table write triggering RLS checks for hundreds of subscribers — switch that specific feature to Broadcast. Same infra, different channel mode, no authorization fan-out.
If Supabase's presence layer starts failing you at scale, or you're getting channel join errors under load, evaluate Liveblocks before rolling your own. The $30/month Pro plan is cheap compared to the engineering time for equivalent infrastructure.
If your Liveblocks bill is trending toward Team plan and your real-time logic isn't CRDT-dependent, that's the PartyKit migration signal.
Whichever stack you're on: test the failure mode before you ship. Disconnect a client while writes are happening, wait 30 seconds, reconnect. What does your UI show? If the answer is stale data with no indication that anything was missed — that's your first integration requirement. None of the three platforms solve this for you automatically.
