ElectricSQL: a read-path sync engine for Postgres, and what the README does not tell you
The agent platform built on sync.
At a glance
- What is it?
- Electric is an Apache-2.0 Postgres sync engine that streams table changes out over an HTTP API, with Shapes for partial replication and client libraries for TypeScript, React and Elixir. It is a read-path tool, and the documentation is explicit that the write path is your problem.
- Who is it for?
- Adopt Electric if you are shipping a read-heavy client that needs a filtered slice of Postgres kept live, and you already run Postgres with logical replication available. Do not adopt it if you need bidirectional sync or conflict resolution, because the README describes a read-path engine only.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem Electric actually solves
Most teams that want live data in a client end up writing the same three pieces of code. They poll an endpoint, they diff the response against what they already hold, and they try to keep a cursor so the next request only asks for what changed. Electric exists to remove that work. The README frames it as solving "partial replication, fan-out, and data delivery", and calls itself "a read-path sync engine for Postgres" that "syncs data out of Postgres into ... anything you like".
The audience is narrower than the tagline suggests. This is for someone who already has Postgres and wants a filtered subset of one or more tables mirrored into a browser, a mobile app, or another service, without building a change-feed protocol. The README's own examples are a React hook and a curl request, which tells you the intended consumer is a client application, not a backend-to-backend pipeline. If you need two-way sync with conflict resolution, the README does not describe that capability at all, and the word read-path is doing real work in that sentence.
Shapes, offsets and the HTTP API as the core protocol
The mechanism is deliberately plain. Electric sits in front of Postgres and exposes an HTTP endpoint, documented in an OpenAPI spec at website/electric-api.yaml. The README states that "the core sync protocol is based on a low-level HTTP API" and that this "integrates with CDNs for highly-scalable data delivery". That is the architectural bet: because delivery is ordinary HTTP with cache-friendly semantics, you can put a CDN between Electric and your users rather than building a custom socket protocol.
Partial replication is expressed as a Shape. A shape is a table plus a filter, and the README's curl example shows the shape of the shape: /v1/shape?table=foo&offset=-1. The offset=-1 is the starting point, meaning the client has nothing yet and wants the initial snapshot. Subsequent requests carry a real offset so the server can send only what changed since that point. The React example uses the same parameters through a params object, with table and a where clause such as title LIKE 'foo%'. So the filter vocabulary is SQL-shaped rather than a bespoke DSL, which is the main reason this is easy to reason about.
What the README does not spell out is how offsets are persisted, how long the server retains history for a given shape, or what happens when a client returns with an offset the server can no longer serve. Those are the questions that decide whether this works in production, and they are answered, if at all, in the linked docs rather than here.
Getting a local instance running
The prerequisites are stated plainly. You need "a Postgres database with logical replication enabled" and then you "run Electric in front of it, connected via DATABASE_URL". Logical replication is not optional, and it is the constraint most likely to bite: managed Postgres providers vary in whether they expose it, and self-hosted instances need wal_level set appropriately before Electric will see anything.
From the repository root, the README gives a Docker Compose command: docker compose -f .support/docker-compose.yml up. That brings up the stack, and the API is then reachable on port 3000. The first request is the curl shown above, against /v1/shape with table and offset parameters.
On the client side, the React integration is a single hook. You import useShape from @electric-sql/react, pass a url pointing at the shape endpoint, and a params object containing table and where. The hook returns data, which the example renders with JSON.stringify. There is also an Elixir client package and a TypeScript client package, and the repository is laid out as a monorepo with packages/sync-service, packages/elixir-client and packages/typescript-client as separate units.
For development, the README uses asdf to pin Elixir, Erlang and Node.js from .tool-versions. Tests are split: Elixir tests run under packages/sync-service and packages/elixir-client with mix test, while TypeScript tests need both the database and a running sync service, started with iex -S mix in a separate terminal, before pnpm test or pnpm -r test from the root.
The LiveDashboard is unauthenticated and the README says so
Electric bundles an optional Phoenix LiveDashboard for inspecting VM metrics, process information and ETS tables. It is off unless you set ELECTRIC_LIVE_DASHBOARD_PORT, in which case it listens on that port and serves a monitoring UI. That is a reasonable development affordance.
The README then puts a warning in bold: "The LiveDashboard endpoint is completely unauthenticated." Anyone who can reach the port can read internal system state. The guidance is to restrict the port with firewall rules or network policies and not to expose it publicly. Take that literally. There is no authentication layer to configure, no token to set, and no read-only mode described. The only control is network reachability. If your deployment model makes per-port network policy awkward, the correct answer is to leave the variable unset rather than to set it and hope.
This is worth calling out because monitoring endpoints are exactly the kind of thing that gets enabled during an incident and forgotten. The safe default is the one the README already implements: unset means not started.
Where Electric is the wrong tool
The read-path framing is the limitation, and it is a large one. If your application needs to write from the client and have those writes reconciled with concurrent writes from elsewhere, Electric does not solve that. The README describes syncing data out of Postgres, not into it. Teams that read "sync engine" and assume bidirectional CRDT-style sync are reading past the qualifier; the repository topics list crdt, but the README's own description of the product is unambiguously one-directional.
There is a second constraint in the shape model. A shape is a table plus a where clause. Queries that join across tables, aggregate, or depend on server-side computed columns do not map onto that. You would need to expose a view or a denormalized table in Postgres and shape that instead, which pushes work back into your schema design.
Finally, the offset protocol assumes clients can come back and resume. The README shows offset=-1 for a fresh snapshot but does not describe the failure mode where a client returns with an offset the server has already discarded. That is the scenario worth probing before you depend on this for an offline-capable client, because it determines whether a long-absent device gets an incremental catch-up or a full resync.
How this differs from a plain logical replication subscriber
The obvious alternative is to skip Electric and run your own logical replication consumer: connect to the replication slot directly, decode the WAL stream, and push changes to clients over whatever transport you prefer. That approach is well-trodden and uses only Postgres primitives.
The difference in approach is where the filtering and fan-out live. A hand-rolled subscriber receives the whole replication stream and must implement its own per-client filtering, its own offset bookkeeping and its own delivery layer. Electric moves that into the engine: shapes define the filter declaratively in the URL, offsets are part of the protocol rather than something you invent, and delivery is HTTP so a CDN can absorb fan-out. The README explicitly claims fan-out and data delivery as problems the project solves for you.
The trade-off is that you inherit Electric's shape model. If your filtering needs are more expressive than a table plus a where clause, a custom subscriber gives you full SQL and full control over what each client receives. You would also own the operational burden of replication slots, which is real but well understood. Electric is the better fit when the filter is simple and the number of clients is large; the custom subscriber is the better fit when the filter is complex and the client count is modest.
Licence, releases and what to check before adopting
Electric is Apache-2.0, which permits commercial use, modification and redistribution provided you retain the notices and comply with the patent grant and termination terms. The repository also links a Contributor License Agreement and a separate CONTRIBUTING.md, which matters if you intend to send patches rather than merely consume the software. Nothing here is legal advice; read the LICENSE file and the CLA before you rely on either.
On maintenance, the release cadence visible in the material is frequent and package-scoped. Recent releases include @electric-sql/react at 1.0.57, @electric-sql/y-electric at 0.1.54 and an expo starter at 1.0.29, all pushed on the same day. The version numbers are informative in one specific way: the React client is past 1.0 while the Yjs integration is still on 0.1.x, so the maturity of the integration you pick varies by package rather than being uniform across the project. The README's own status badge points at a 1.0 release announcement from March 2025.
Before adopting, the concrete things to verify in your own environment are the Postgres logical replication setting, whether your shape filters fit the table-plus-where model, and how you will handle the LiveDashboard port in production. The README gives you the commands to start the stack and the environment variable to enable the dashboard; it does not give you a retention policy for offsets, and that is the gap most likely to surface after launch rather than before.
Editorial conclusion
Adopt Electric if you are shipping a read-heavy client that needs a filtered slice of Postgres kept live, and you already run Postgres with logical replication available. Do not adopt it if you need bidirectional sync or conflict resolution, because the README describes a read-path engine only. Before committing, verify three things in your own environment: that your Postgres has logical replication enabled, that the shape query you plan to expose is expressible as a table plus a where clause, and whether you intend to set ELECTRIC_LIVE_DASHBOARD_PORT at all, since the README states that endpoint is completely unauthenticated.
Community notes