DEV Community

Jason Lee
Jason Lee

Posted on

PowerSync Makes You Write the Conflict Resolver. Zero Won't Let You. Electric Doesn't Have One.

ElectricSQL

If you've shipped a web or mobile app in the last year, you've probably felt the itch: users expect Linear-fast interactions, Figma-style multiplayer cursors, and apps that keep working when the wifi drops on a train. Rolling that yourself on top of REST endpoints and useEffect polling is miserable. So a category of infrastructure — "local-first sync engines" — has spent the last two years trying to make it a solved problem: replicate a slice of your database onto the client, let reads and often writes happen locally and instantly, and reconcile with the server in the background.

Three names keep coming up in that conversation right now: ElectricSQL, PowerSync, and Zero from Rocicorp. All three market themselves under the same "local-first" banner, all three sit on top of Postgres, and all three shipped major architectural changes in the last two years — which means whatever comparison post you read in 2024 is already describing products that no longer exist in that form. Electric rebuilt itself from scratch. Zero just hit its first stable release. PowerSync kept iterating on mobile.

The pitch sounds identical across all three vendors' landing pages: "instant," "offline-first," "no more loading spinners." It isn't the same product. Once you look past the marketing copy, each one made a different bet about the single hardest problem in this space — what happens when two writes conflict — and each bet has real consequences for how much code you'll be writing six months from now.

The term "local-first" itself comes from a specific place: a 2019 research essay by Martin Kleppmann and collaborators at Ink & Switch, which defined it as software that's offline-capable, real-time collaborative, and conflict-free by construction, usually via CRDTs (conflict-free replicated data types). That's a high bar, and it's worth keeping in mind while reading vendor marketing, because — as this piece will get into — none of the three products here actually clears it in full. They're closer to a newer, more commercially pragmatic category: Postgres-native sync engines that borrow the "local-first" label because it's the phrase developers now search for.

Why this comparison is a live decision right now

Two things converged to make this an active decision point for a lot of teams in 2026, not a hypothetical.

First, Postgres quietly became the default backend for a huge share of new apps — helped along by Supabase, Neon, and PlanetScale competing on how fast you can get a Postgres instance provisioned. That gives sync engines a stable, well-understood source of truth to replicate from, which is a big part of why all three products in this piece are Postgres-native rather than trying to be database-agnostic.

Second, all three vendors materially changed their architecture recently, which resets the decision for anyone who evaluated this space even a year ago:

  • Electric published "A new approach to building Electric" in July 2024, discontinuing its original bidirectional-sync engine and rebuilding from a blank sheet.
  • Zero reached its 1.0 release in mid-2026, after roughly two years of development, more than 50 releases, and thousands of commits — meaning the product most people evaluated in 2024–2025 was pre-1.0.
  • PowerSync kept its architecture stable but expanded aggressively into mobile-native platforms and added a source-available self-hosted edition alongside its managed cloud.

If you're picking a data-sync layer today, you're picking between three products that are all meaningfully younger, in their current form, than they look.

What each one actually does

ElectricSQL used to be a full bidirectional sync engine: writes made offline on the client would sync back to Postgres, with conflict-free replicated data types (CRDTs) handling merges automatically. That product is gone. The current Electric — sometimes still referred to by its rebuild codename "electric-next" — is a read-path-only sync engine. It streams subsets of your Postgres data to clients and services over plain HTTP using what it calls "Shapes": essentially a partial, filtered, continuously-updated replica of a table or query, delivered as a resumable HTTP stream that can sit behind a CDN. Writes are explicitly not Electric's problem anymore — you send mutations to your own API, the same way you would without Electric in the picture.

PowerSync takes the opposite shape. It gives the client a real, full SQLite database (via native SQLite on mobile or WASM SQLite in the browser), and that database works completely offline — both reads and writes. "Sync rules" you define server-side determine which rows land on which client (this doubles as your authorization boundary). When the client reconnects, queued local writes are uploaded through your own backend API, and you write the code that decides what happens when two writes touch the same row.

Zero pairs a zero-client library in the app with a zero-cache service that maintains a read-only replica of your Postgres database, similar in spirit to Electric's Shapes but wrapped in Zero's own reactive query language, ZQL. Queries run against a local IndexedDB cache first and return in the next frame — which is where the "zero latency" branding comes from — while the authoritative result syncs from the server in the background. Writes are optimistic and queued locally, then reconciled by the server, which has final say.

All three, notably, are open-source at the core (Electric under Apache 2.0, Zero self-hostable with its core kept open, PowerSync shipping a source-available "Open Edition"), with the vendor's actual business model living in the managed cloud service layered on top.

How each is actually built

The architectural choices explain the marketing differences better than the marketing does.

Electric's Shapes are deliberately boring: a shape is just a filtered, ordered log of a table or query, delivered over standard HTTP with ETags and range requests, so it composes with existing CDN and caching infrastructure instead of requiring a bespoke sync protocol or persistent WebSocket. That's a legitimate operational win — it's the reason Electric can plausibly promise unlimited free reads (more on pricing below). The tradeoff is that "sync" here means one direction: server to client. Anything that looks like local-first writing has to be built by you, on top of a separate mutation path, often using something like TanStack DB for optimistic local updates layered over Electric's read replication.

PowerSync's SQLite-on-the-client model is the most conventional of the three, in the sense that it looks like what "offline sync" meant a decade ago (think CouchDB/PouchDB), just executed with a much more mature engine underneath. The upload path — client to server — runs through code you write against your own backend, and PowerSync's docs are explicit that conflict handling is your responsibility, with "last write wins" offered only as an unopinionated default you can override with real business logic (deciding, say, that an inventory decrement should never be silently overwritten). This is more implementation work, but it also means PowerSync isn't hiding a hard problem — it's making you solve it in your own codebase, where you can test it, version it, and change it without waiting on a vendor.

Zero is the successor to Rocicorp's earlier product, Replicache, and it shows: instead of a generic replicated table, Zero wants you to define your data access through its mutator pattern and ZQL, giving it more information to make reads instant and writes optimistic without you writing bespoke caching code. Custom mutators run once optimistically on the client for the instant UI update, then run again authoritatively on the server against the real Postgres state — the server's result always wins. The cost is that conflict resolution is fixed: writes are reconciled by the server using last-write-wins, and as of 1.0 that policy isn't customizable. For a huge share of CRUD apps that's a non-issue. For anything that looks like two people editing the same document field at the same time, it's a real gap — one write silently disappears with no merge, no warning, and no hook to intervene.

It's also worth distinguishing all three of these from raw CRDT libraries like Yjs or Automerge, which solve conflict resolution generically at the data-structure level (any two changes are provably mergeable) but leave you to build the transport, persistence, and server-authority layer yourself. Electric, PowerSync, and Zero are the opposite trade: they hand you transport and persistence out of the box, in exchange for a narrower, less generic conflict model. Neither approach is strictly better — CRDT libraries are the right call for genuinely collaborative document editing (think a text editor), while sync engines are the right call for CRUD-shaped app data (records, rows, lists) where "one writer wins per field" is an acceptable default most of the time.

What changed versus a year or two ago

The most consequential shift is Electric's. The original ElectricSQL was pitched squarely at the "local-first" definition from Ink & Switch's research — offline-capable, real-time collaborative, conflict-free by construction. The rebuilt Electric abandoned that scope. Its GitHub repository now describes the project as "the agent platform built on sync," and its new commercial pricing (launched as "Electric Cloud" in April 2026) is split across two products: Postgres Sync (the local-first-adjacent use case) and Durable Streams, explicitly aimed at AI and multi-agent workloads. Reading between the lines, Electric's own roadmap suggests the company sees more near-term commercial upside in being real-time infrastructure for AI agent messaging than in being the offline-sync layer for consumer apps — which is a reasonable business bet, but it means evaluating Electric today as "a local-first sync engine" is arguably answering a question the vendor itself has partly moved past.

Zero's shift is more straightforward: it went from an ambitious pre-1.0 project a lot of teams were wary of putting in production, to a stable release with a real version number and a changelog you can point a risk-averse engineering lead at. PowerSync's shift has been quieter — mostly deepening mobile support and formalizing the free self-hosted edition — which is consistent with its position as the most conservative, production-proven option of the three.

Why developers should actually care

Cost. Electric's usage-based pricing waives bills under $5/month (roughly 5 million writes) and prices data delivery — reads, fan-out to any number of concurrent clients — as free and unlimited. Writes are metered at $1 per million to any stream, with an additional $2 per million specifically for Postgres Sync, landing at an effective $3 per million for live database changes; a Pro plan adds features at $249/month. That model rewards read-heavy, write-light workloads (dashboards, notification feeds) and can get unpredictable if your app does a lot of small, frequent writes. PowerSync's managed cloud starts free (soft limits, and inactive free projects get deactivated after a week) with paid usage-based plans starting at $49/month. Zero's managed service starts around $30/month. All three let you self-host to sidestep vendor billing entirely, at the cost of running the infrastructure yourself.

Latency. Zero's local-cache-first reads are the fastest perceived experience of the three by design — the whole product is built around returning cached results before the network round-trip completes. PowerSync's local SQLite gives near-native query performance offline, which matters when connectivity is genuinely absent, not just slow. Electric's write latency is just your own API's latency, since Electric isn't in the write path at all — which is either irrelevant or a real limitation depending on whether write speed was ever your bottleneck.

Developer experience and lock-in. PowerSync asks for the most code (sync rules, upload logic, conflict resolution) but the payoff is that your business logic lives in your codebase, not the vendor's protocol. Zero asks for the least code but wants you to adopt its schema, mutators, and query language end to end — genuine lock-in if you later want to leave. Electric's mental model (HTTP-shaped subscriptions) is the easiest to reason about and the easiest to rip out, precisely because it deliberately does less.

Security. This is the one developers most often underweight. A sync engine's entire job is to widen your database's read surface out to the client, which means authorization logic that used to live in one API layer now has to be correctly expressed in Electric's Shape definitions, PowerSync's sync rules, or Zero's permission model — and a misconfigured rule leaks rows the same way a broken Postgres row-level-security policy does, just with a less familiar debugging surface. Concretely: Electric's Shapes are typically scoped with a WHERE clause you write per-subscription, so a shape defined as "all rows" instead of "rows where user_id = current_user" ships every user's data to every client. PowerSync's sync rules are a separate YAML-like configuration layer that has to be kept in sync with your actual Postgres permissions by hand, which is exactly the kind of two-systems-that-must-agree setup that drifts over time. Zero's permission system is newer and less battle-tested in the wild simply because 1.0 shipped recently — fewer teams have found its edge cases yet.

Maintainability. PowerSync concentrates complexity in code you own and can unit-test. Zero and Electric concentrate complexity in vendor-controlled protocols and pricing you don't set the roadmap for — a reasonable tradeoff if you trust the vendor's trajectory, a real risk if (as with Electric) that trajectory is visibly shifting toward a different market.

Switching cost. Because all three ask you to model your data access differently — Shapes for Electric, sync rules plus an upload endpoint for PowerSync, mutators and ZQL for Zero — migrating between them later isn't a config change, it's closer to a rewrite of your entire client data layer. That argues for picking conservatively: a short internal prototype against your actual schema and a realistic offline scenario (kill the network mid-write, see what your users would actually experience) will tell you more in a week than any comparison post, including this one.

Practical use cases

ElectricSQL fits teams that already have a backend and an API they trust, and just want cheap, fast, read-only real-time fan-out on top of it — live dashboards, activity feeds, notification streams, or piping database changes into background jobs. Trigger.dev is a concrete example: it uses Electric to power Trigger.dev Realtime, scaling to millions of updates a day, precisely the read-heavy, server-authoritative-write pattern Electric is built for. Another good fit given Electric's newer positioning: streaming intermediate output from a long-running AI agent to a UI in real time, where "read replication of an append-only log" is basically the whole requirement. It's a poor fit if what you actually need is an app that keeps accepting new data while genuinely offline — a field inspector filling out a form on a plane isn't Electric's problem to solve.

PowerSync fits mobile and field-service style apps — logistics, healthcare, inspections, retail point-of-sale, anything where a device might be offline for hours and needs to keep working, with domain-specific merge logic (an inventory count shouldn't just take whichever write arrived last; a nurse's medication log shouldn't silently drop an entry because two tablets synced out of order). It's also the safer choice if your team wants a vendor-neutral fallback: the Open Edition self-hosted core exists specifically so you're not fully dependent on PowerSync's cloud, which matters more in regulated industries where "we can't verify what a third-party service does with patient data in transit" is a real procurement blocker.

Zero fits collaborative web apps that want an instant, low-friction feel and are comfortable adopting Zero's full stack from day one — think project-management or note-taking tools where most writes touch distinct records rather than the same field simultaneously. A Linear-style issue tracker, where different users are usually editing different tickets, tolerates last-write-wins fine; a Google-Docs-style shared paragraph does not. It's a weaker fit for real co-editing (two people typing in the same text field at once) unless you're prepared to build extra conflict-avoidance — optimistic locking, field-level ownership, or a separate CRDT layer for just the collaborative parts — on top of a policy you can't currently customize.

If none of the three quite fit — say you want reactive client-side caching without adopting anyone's server protocol — TanStack DB is worth a look as a lighter-weight, more portable alternative that composes with TanStack Query rather than requiring a dedicated sync backend.

What the marketing leaves out

Electric's copy still leans on "local-first" and "instant sync" language inherited from its original, discontinued product. The current Electric doesn't sync writes at all — it's a real-time read-replication and streaming layer with a good pricing story, not a bidirectional offline framework. That's a legitimate product to be; it's just not the same claim as "your app works offline," and teams evaluating it for that reason will hit the gap the first time they try to write data while disconnected.

PowerSync's "full offline support" is accurate for reads and for capturing writes locally, but it undersells that conflict resolution is homework you're assigned, not a feature you're buying. Budget real engineering time for it, and expect to revisit it as your data model grows.

Zero's "zero latency" framing is about reads. Its writes are constrained to last-write-wins with no override as of 1.0, and the product doesn't surface that limitation loudly — a team building anything collaborative should treat "not customizable (yet)" as a hard constraint today, not a roadmap promise.

Comparison table

Dimension ElectricSQL PowerSync Zero (Rocicorp)
Sync direction Server → client only (reads); writes go through your own API Bidirectional; offline writes queued in local SQLite, uploaded on reconnect Bidirectional; optimistic local writes, reconciled by server
Client storage HTTP-delivered "Shapes"; optional local Postgres via PGlite Full local SQLite (native or WASM) IndexedDB cache
Conflict resolution Not applicable — Electric doesn't sync writes back You implement it in your backend API; no default enforced Server-authoritative last-write-wins; not customizable at 1.0
Data source Postgres only Postgres only Postgres primary; broader backend support claimed
Offline write support No (by design) Yes, mature, mobile-proven Yes, queued and optimistic
Self-hosting Yes, Apache 2.0 Yes, "Open Edition," source-available Yes, core kept open source
Managed pricing (entry) Free under ~5M writes/mo; then $1–3/M writes; Pro at $249/mo Free tier (soft limits, deactivates after 1 week idle); paid from $49/mo Managed service from roughly $30/mo
Maturity Rebuilt from scratch in 2024; reached 1.0 status March 2025 Most production-proven, especially mobile Reached 1.0 in June 2026
Platform strength Web, real-time streaming, AI/agent event pipes Mobile-native (iOS/Android/Flutter/React Native) and web Web-first, reactive UI
Best-known production user Trigger.dev (Realtime feature) Widely used in mobile field-ops apps Rocicorp's own internal tools
Vendor's current strategic focus Pivoting toward "Durable Streams" for AI agents Staying focused on offline-first sync Growing the general-purpose web sync category

An independent read

None of these three is "local-first" in the strict, original sense of the term — offline-capable, real-time collaborative, and conflict-free by construction. All three are pragmatic, Postgres-centric engineering compromises, each optimized for a different point on the tradeoff curve, and the honest 2026 question isn't "which local-first sync engine should I use," it's "which specific problem do I actually have."

If you need genuine offline resilience and are willing to own the hard part, PowerSync is the safer default precisely because it doesn't pretend conflict resolution is solved — it hands you the pen. If you want the snappiest possible web UI and can commit to a full-stack pattern on day one, Zero delivers the best raw feel, with the explicit caveat that its conflict policy is currently a hard constraint, not a dial. And Electric, post-rewrite, has arguably exited the category it's still marketed under — it's closer to real-time data-streaming infrastructure than to an offline-sync framework, and its own roadmap (chasing AI agent workloads with Durable Streams) agrees with that read. None of that makes Electric a bad product; it makes it a different product than the one being compared here by name.

Which reader should pick which option

  • Mobile or field-ops team that needs the app to survive hours of no connectivity, and is willing to own business-specific merge logic → PowerSync.
  • Web app team building something collaborative and Linear/Figma-fast, comfortable adopting a full server-side pattern, and fine with last-write-wins for now → Zero.
  • Team with an existing backend that just wants cheap, fast, read-only real-time fan-out — dashboards, notifications, AI agent event streams — without touching the write path → ElectricSQL.
  • Team that wants reactive client-side caching without committing to anyone's sync protocol → look at TanStack DB before any of the three.

If your app's core value proposition depends on true offline writes, that single requirement eliminates one of these three outright — check that before you get pulled in by the shared "instant, local-first" pitch.

Where's the line for your own team: at what point does "last write wins" stop being an acceptable default and become a bug you have to build a whole CRDT layer to fix — and have you actually measured how often your users' writes collide, or are you just assuming it's rare?

Sources:

Top comments (1)

Collapse
 
kobie profile image
Kobie Botha

Trying using a newer model to generate your posts for you. A lot of content here is stale.