Compare vs Supabase

Cuitty vs Supabase.

Supabase is a managed Postgres + auth + storage stack with a polished dashboard. Cuitty Persist is local-first: records, events, blobs, and key-value sync to a device or peer before they touch a server.

Supabase is the right answer when the work is a CRUD app with auth, a dashboard, and a managed Postgres behind it. The DX is good, the open-source story is real, and the migrate-off path exists in principle.

Cuitty Persist starts at a different layer. The default is local-first: a Persist store lives on the device, syncs to peers over P2P, and replicates to the region of your choice only when it has to. Conflict resolution is built in. The same SDK handles records, events, blobs, and key-value — and every sync, conflict, and handshake emits to Cuitty Observe so you can watch your durability layer in traces and errors.

This page is for teams who already know they want local-first data, want to avoid a Postgres-as-a-service lock-in, and want to evaluate a vendor that ships the storage SDK and the observability surface in one place.

Feature parity

✓ supported · ~ partial · ✗ not supported. Notes link out to the relevant docs where useful.

Capability Cuitty Persist Supabase
Local-first data model
Data lives on the device first, replicates second.
Yes
Stores live on the device; sync is a separate concern.
No
Hosted Postgres; reads/writes hit the server.
P2P sync
Yes
Peer-to-peer over WebRTC + relay fallback.
No
Realtime is server-broadcast.
Conflict resolution
Yes
CRDT-backed records, configurable resolvers per store.
Partial Partial
Last-write-wins via Postgres; app-level logic on top.
Self-hostable
Yes
SDK is OSS; relay + hosting stack runs anywhere.
Yes
Self-hosted Supabase exists; non-trivial operationally.
Managed SaaS
Yes
Cuitty Cloud, US/EU/AP regions.
Yes
Supabase Cloud, mature.
Records / documents
Yes
Schema-validated structured records.
Yes
Postgres tables + Row Level Security.
Event streams
Yes
Append-only ordered streams native to the SDK.
Partial Partial
DIY with Postgres + Realtime.
Blobs / file storage
Yes
Chunked upload + streaming reads via SDK.
Yes
Supabase Storage.
Key-value with TTL + CAS
Yes
Native primitive in the SDK.
Partial Partial
Build on Postgres; no first-class KV.
Offline-first apps
Yes
Reads + writes work fully offline, queued for sync.
No
Cache layer only; server is the source of truth.
Vendor lock-in surface
What's the cost of leaving the platform?
Yes
Stores export to plain files; SDK is OSS.
Partial Partial
Postgres is portable; Realtime + Edge Functions are not.
Built-in observability
Yes
Every sync + conflict emits to Cuitty Observe.
Partial Partial
Dashboard logs; external APM for the rest.

When to choose Supabase

  • A standard CRUD app that wants hosted Postgres with RLS and a polished dashboard.
  • The team is happy with cloud-only reads and writes — offline is not a requirement.
  • You want batteries-included auth, storage, and edge functions in one product.
  • You don't need P2P sync, CRDT conflict resolution, or local-first guarantees.

When to choose Cuitty Persist

  • Mobile, desktop, or edge apps that need to work offline and sync when reconnected.
  • Collaboration features where peers should share data without round-tripping a server.
  • You want one SDK for records, events, blobs, and key-value — not four products glued together.
  • Durability and sync are observable in the same place you watch the rest of your stack.

Migration path

Mirror a Supabase table to a Persist store

Start by replicating one Supabase table into a Persist records store. Reads stay on Supabase until you flip the SDK to read-from-local.

sync.ts typescript
import { createClient } from "@cuitty/persist";
import { createClient as supa } from "@supabase/supabase-js";

const persist = createClient({ workspace: "acme", region: "us-east" });
const supabase = supa(process.env.SUPABASE_URL!, process.env.SUPABASE_KEY!);

// One-shot import; subsequent writes go through Persist's sync engine.
const { data } = await supabase.from("tasks").select("*");
const store = persist.records("tasks");
for (const row of data ?? []) {
  await store.put(row.id, row);
}

Verdict

Pick Supabase if a hosted Postgres + REST + Realtime is the product, and the team is content with cloud-only reads. Pick Cuitty Persist if the data needs to live on the device, sync over P2P, and never lock into one vendor's runtime.