Skip to main content


Let's dive in and start developing with ElectricSQL. First, we'll get the stack setup, then we'll show you the basics of using the system.


If you'd prefer to understand a bit more about the system before jumping into code, start with the Introduction instead.


Get setup quickly using the create-electric-app generator. Or install, run and integrate the components yourself.

Make sure you have Docker and Node.js (>=16.11) and then:

npx create-electric-app@latest my-app

Change directory into my-app and start the backend services. This will use Docker Compose to run Postgres and the Electric sync service:

cd my-app
yarn backend:start

Open another terminal tab, navigate back to the my-app directory and create the database schema (defined in ./db/migrations):

yarn db:migrate

Generate your type-safe database client:

yarn client:generate

Start your app:

yarn start

Open localhost:3001 in your web browser. That's it, you're up and running :)


The next section goes over the basics of using ElectricSQL. It's a quick summary of the information you'll find in more detail in the Usage guide.

Define your schema

ElectricSQL works on top of a standard Postgres data model.

The generator has set you up with a simple data model defined in ./db/migrations. To evolve the schema you can add additional files and apply them using e.g.:

yarn db:migrate -file db/migrations/your_new_migration.sql

See Usage -> Data modelling -> Migrations and Integrations -> Backend for more information.

Expose data

Expose data using DDLX rules. First, electrify each table you'd like to sync:


Then assign roles and access permissions:

ON items


Authenticate the local app with the replication protocol using a JSON Web Token:

const config = {
auth: {
token: '<your JWT>'


Wrap your SQLite driver with a type-safe, schema-aware database Client:

import { electrify, ElectricDatabase } from 'electric-sql/wa-sqlite'
import { schema } from './generated/client'

const conn = await ElectricDatabase.init('my.db', '')
const { db } = await electrify(conn, schema, config)

Sync data

Sync data into the local database using Shapes:

const shape = await db.items.sync({
where: {
// ... clauses
include: {
// ... relations

Read data

Bind live data to your components using Live queries:

const { results } = useLiveQuery(
where: {
// ... filter
select: {
// ... columns
orderBy: {
// ... sort
take: 20

Either using the Prisma-inspired client or if you prefer just raw SQL:

const { results } = useLiveQuery(
sql: 'SELECT * FROM items where foo = ?',
args: ['bar']

Write data

Write data directly to the local database using Local writes:

const item = await db.items.create({
data: {
// ... item data

Writes automatically cause any relevant live queries to update. For example, if you take the following component:

import { genUUID } from 'electric-sql/util'

const MyComponent = () => {
const { db } = useElectric()!
const { results } = useLiveQuery(

const add = async () => (
await db.items.create({
data: {
value: genUUID()

return <List items={results} add={add} />

Calling add will insert a new item into the local database. ElectricSQL will automatically detect and replicate the write. The replication process emits a notification, causing the live query to re-run. This updates the value of the results state variable, which triggers the component to re-render.

This automatic reactivity works no matter where the write is made locally, on another device, by another user, or directly into Postgres.

Next steps

Take a look at the Examples, see the Usage and Integrations guides and the API docs.

You can also join the Discord community and star us on GitHub.