Quick Verdict
For a "Notion-like" or "Figma-like" collaborative SaaS in 2026:
- Liveblocks if you want presence + comments + collaborative editing as drop-in primitives, with the smallest engineering surface.
- Convex if you want a single backend for all your data and the realtime model that comes from reactive queries — your whole app gets realtime, not just the canvas.
- Supabase Realtime if you're already on Supabase and only need lightweight broadcast / presence — not your primary collaboration layer.
If you're building a multiplayer-first product (canvas, doc, board), Liveblocks or Convex. If realtime is a side feature on a CRUD SaaS, Supabase Realtime is enough.
Key Takeaways
- Liveblocks = collaboration kit (presence, comments, threads, Yjs/Lexical/TipTap providers). You own auth and storage.
- Convex = full backend (database + functions + realtime). Reactive queries push updates to subscribed clients automatically.
- Supabase Realtime = postgres CDC + broadcast channels + presence on top of your existing Supabase Postgres.
Decision Table
| Product | Best Fit |
|---|---|
| Multi-cursor collaborative doc editor | Liveblocks (Yjs provider + Lexical/TipTap kit) |
| Live dashboard with reactive metrics | Convex (queries auto-update on writes) |
| Project tracker with real-time card moves | Liveblocks or Convex (both shine) |
| Chat or notification feed on top of an existing Supabase app | Supabase Realtime |
| Whiteboard / Figma-like canvas | Liveblocks (Storage + presence built for it) |
| AI agent inbox where users see model output stream | Convex (subscriptions) or Liveblocks Inbox |
Liveblocks
Pricing: Free up to 1,000 monthly active users; paid tiers scale by MAU and add features (Comments, Threads, Notifications, Inbox). Generous compared to its niche.
Fit: Anything where presence (cursors, avatars), shared selections, comments, threads, or collaborative editing is the product surface.
What you write:
'use client';
import { LiveblocksProvider, RoomProvider, useOthers } from '@liveblocks/react';
function CursorOverlay() {
const others = useOthers();
return others.map((u) => (
<Cursor key={u.connectionId} x={u.presence.x} y={u.presence.y} />
));
}
export default function DocPage({ docId }: { docId: string }) {
return (
<LiveblocksProvider authEndpoint="/api/liveblocks-auth">
<RoomProvider id={`doc-${docId}`} initialPresence={{ x: 0, y: 0 }}>
<CursorOverlay />
</RoomProvider>
</LiveblocksProvider>
);
}
Strengths:
- Best-in-class collaborative editing primitives — Yjs provider, TipTap and Lexical kits, Comments, Threads, Notifications, Inbox.
- Conflict resolution handled (CRDT for documents, LWW for presence).
- Drop-in React components for cursors, avatars, comment threads.
- Webhooks for storage events you can persist to your DB.
Limits:
- Not a database. You still need Postgres (or whatever) for permanent storage.
- Per-MAU pricing scales with users; large free tools sometimes outgrow it.
- Lock-in on the collaboration kit if you adopt Comments / Threads heavily.
Convex
Pricing: Free tier covers most indie products; paid scales with function calls, bandwidth, and storage. Open-source self-host runtime exists.
Fit: Greenfield SaaS that wants a unified backend (DB + functions + realtime + file storage + auth integrations) and where every read is reactive by default.
What you write:
// convex/messages.ts
import { query, mutation } from './_generated/server';
import { v } from 'convex/values';
export const list = query({
args: { roomId: v.id('rooms') },
handler: (ctx, { roomId }) =>
ctx.db.query('messages').withIndex('by_room', q => q.eq('roomId', roomId)).collect(),
});
export const send = mutation({
args: { roomId: v.id('rooms'), text: v.string() },
handler: async (ctx, { roomId, text }) => {
const userId = (await ctx.auth.getUserIdentity())!.subject;
await ctx.db.insert('messages', { roomId, text, userId, ts: Date.now() });
},
});
The React client is auto-typed and reactive:
const messages = useQuery(api.messages.list, { roomId });
When send runs, every subscribed client re-renders. No socket plumbing, no invalidation strategy.
Strengths:
- Reactive queries by default; you stop thinking about cache invalidation.
- TypeScript end-to-end without code generation steps you run manually.
- File storage, scheduled functions, vector search, and auth integration in one product.
- Strong Convex vs Supabase comparison if you're picking your primary backend.
Limits:
- It is your backend. Mixing Convex with an existing Postgres app is awkward.
- Document/key-value model, not relational SQL — query patterns are different.
- Less off-the-shelf for canvas-style multiplayer than Liveblocks (no built-in CRDT primitives).
Supabase Realtime
Pricing: Free up to 200 concurrent connections; paid plans scale connections, messages, and presence channels.
Fit: Existing Supabase apps that need lightweight live updates — chat, notifications, status indicators. Not the right primary layer for collaborative editing.
What you write:
const channel = supabase.channel(`room-${roomId}`);
channel
.on('postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'messages', filter: `room_id=eq.${roomId}` },
(payload) => addMessage(payload.new),
)
.on('presence', { event: 'sync' }, () => updateOnline(channel.presenceState()))
.on('broadcast', { event: 'cursor' }, ({ payload }) => moveCursor(payload))
.subscribe();
Strengths:
- Three modes in one API: Postgres CDC, broadcast, presence.
- Inherits Supabase RLS — same auth model as the rest of your app.
- Free with any Supabase project; no separate account.
Limits:
- No CRDT, no Yjs adapter, no comments/threads kit. You build collaborative editing yourself if you need it.
- Postgres CDC has a small latency floor (typically 200–500ms) — fine for chat, awkward for cursors.
- Channel and message limits hit before you'd expect on consumer-scale traffic.
Programming Model Comparison
| Concept | Liveblocks | Convex | Supabase Realtime |
|---|---|---|---|
| Storage primitive | LiveObject / LiveList / LiveMap | Documents in tables | Rows in Postgres |
| Conflict resolution | CRDT (Yjs option) | Last-mutation-wins (server-ordered) | Database constraints |
| Presence | First-class | Build with reactive queries | First-class |
| Comments / Threads | First-class | Build it | Build it |
| Auth | BYO (you sign tokens) | Built-in providers | Supabase Auth |
| Persisted store | Webhook → your DB | Convex DB itself | Postgres |
| Offline support | Yes (Yjs) | Reactive cache | Limited |
| Edge runtime | Yes | Yes | Yes |
Pricing Model Comparison
These are different shapes; compare carefully against your actual usage:
- Liveblocks: monthly active user count.
- Convex: function calls + database storage + bandwidth.
- Supabase Realtime: concurrent connections + messages.
For a 5,000-MAU collaborative product:
- Liveblocks: typically lands in their team plan (~$192/mo at the time of writing).
- Convex: free tier may still cover it; paid plans for power users.
- Supabase: included with your Supabase plan ($25/mo Pro covers most apps).
Starter Kit Landscape
| Starter | Realtime layer | Notes |
|---|---|---|
| Convex SaaS Starter (community) | Convex | Often pairs with Clerk or Better Auth |
| Liveblocks Next.js Starter | Liveblocks | Comments + Threads demo + auth boilerplate |
| Supastarter (any framework) | Supabase Realtime | Inherited from Supabase setup |
| Makerkit Next.js + Supabase | Supabase Realtime | Same |
| ShipFast / Indie Kit | None default | Add manually if you need realtime |
For most SaaS boilerplate buyers, the realtime layer is added to an existing kit rather than dictated by it.
What to Pick
- Building a doc / canvas / board / IDE that ships multiplayer → Liveblocks.
- Greenfield SaaS where you want every read to be live → Convex.
- Existing Supabase app that needs notifications and a chat panel → Supabase Realtime.
If you're still picking your underlying SaaS foundation, see the best Next.js SaaS boilerplates and Supabase starter kit roundup before committing to the realtime layer — the backend choice constrains it.
FAQ
Can I combine Liveblocks with Supabase? Yes — Liveblocks for the live document, Supabase as your persistent store and auth. Webhook from Liveblocks Storage to Supabase keeps the persisted copy fresh.
Does Convex replace my queue? Convex has scheduled functions and an internal queue for actions. For long-running work, pair with Trigger.dev or Inngest — see durable workflows for SaaS.
Is Liveblocks just Yjs with extra steps? No — Liveblocks provides the Yjs provider plus presence, comments, notifications, persistence, and access control that Yjs alone doesn't. If you only need a CRDT, Yjs + Hocuspocus is cheaper but more DIY.
If realtime is one piece of a larger product, see the SaaS observability stack for monitoring it under load.