Quickstart guide

In this guide we’re going to get you up and running with ElectricSQL.

You can choose two paths. The default path (that we recommend) is to start with a local-only app and walk through the steps to electrify it, so it becomes local-first. Alternatively, you can take the shortcut path to fire up an existing ElectricSQL example app.

In both cases, we demonstrate realtime cloud sync and active-active replication between Postgres in the cloud and SQLite in the browser.

You don't need to run any backend services but you do need to use the command line, clone a git repo and have Node.js installed. You also need to sign up and create an account.

Clone the examples repo, and navigate to the quickstart project, a minimalist, local-only React + SQL.js web application:

git clone https://github.com/electric-sql/examples
cd examples/quickstart

Install the dependencies:

yarn

Build and run:

yarn start

This should open localhost:3001 in your web browser. You should be able to add and clear items. Note that if you refresh the page, your items are lost (because this example is configured initially to store items in an in-memory SQLite database; there’s no local or cloud persistence – yet).

Electrification

We’re now going to walk through the steps of electrifying your app so it becomes local-first with durability, realtime cloud sync and active-active replication between Postgres in the cloud and SQLite in the browser.

Install dependencies

Install the electric-sql client library:

yarn add electric-sql

Because we’re electrifying a web application you also need to install absurd-sql for local persistence [note that we support both absurd-sql and wa-sqlite – see the Web drivers docs for more info]:

yarn add @aphro/absurd-sql@0.0.53

absurd-sql needs to run in a Web Worker, so whilst you’re at it, also uncomment the source of src/worker.js to start up the messaging interface between your code and the worker:

import { ElectricWorker } from 'electric-sql/browser'

ElectricWorker.start(self);

Great! That’s the dependencies sorted. Now let’s get your cloud sync service setup.

Setup cloud sync

If you haven’t done so already, now’s the time to sign up to ElectricSQL. Follow the instructions to create a new app. After the system provisions the infrastructure, you’ll be able to view the connection details for your sync service and Postgres database:

Screenshot of the connection details available in the console.

Copy these somewhere safe (like a password manager). You’re now in position to define your database schema.

Define your database schema

With ElectricSQL, you define your database schema by writing migrations and then apply the same migrations to your local app and cloud Postgres. This ensures that they both use the same database schema. You do this using our command line interface (CLI) tool, which provides commands to generate migrations, bundle them into your app and upload them to your cloud service.

Install the CLI. For example using Homebrew, or see the install guide for more options:

brew install electric-sql/tap/electric

Login on the command line (using the email and password you signed up with, replacing EMAIL with your email address):

electric auth login EMAIL

Make sure you’re in the examples/quickstart folder and run (replacing APP with the app identifier from your sync service connection details you copied earlier):

electric init APP

This creates an ./electric.json config file and initialises a ./migrations folder.

Create a migration:

electric migrations new "create items"

This generates a subfolder at ./migrations/*_create_items/ containing a migration.sql file. Open this file in your text editor and paste in:

CREATE TABLE IF NOT EXISTS items (
  value TEXT PRIMARY KEY NOT NULL
) WITHOUT ROWID;

This is a very simple migration creating the items table used by your app. For more complex schemas, you can write multiple DDL statements in the same migration.sql file and you can generate multiple migrations. See the migrations guide for more details and for the current limitations on schema design.

Build your migrations:

electric build

Upload to your cloud service:

electric sync

Check if the migrations were applied successfully:

electric migrations list

------ Electric SQL Migrations ------
20221228_192139_608_init  default: applied
20221228_192910_066_create_items  default: applied

You can also check the schema of your cloud Postgres directly using the PSQL connection string you copied from the console earlier, e.g.:

psql "postgresql://..."
...

electric=> \d
         List of relations
 Schema | Name  | Type  |  Owner
--------+-------+-------+----------
 public | items | table | postgres
(1 row)

Congratulations! You’ve setup your sync service and database migrations. You’re now ready to electrify your app!

Electrify your app

Open src/Example.tsx. Start by uncommenting the electric-sql imports:

import { ElectrifiedDatabase, initElectricSqlJs } from 'electric-sql/browser'
import { ElectricProvider, useElectric, useElectricQuery } from 'electric-sql/react'

Import your application config and your bundled migrations:

import config from '../.electric/@config'

Enable the absurd-sql web worker:

const worker = new Worker('./worker.js', { type: 'module' });

In the Example component, edit the init function inside useEffect to instantiate and assign an electrified database connection:

useEffect(() => {
  const init = async () => {
    const SQL = await initElectricSqlJs(worker, locateOpts)
    const electrified = await SQL.openDatabase('example.db', config)

    setDb(electrified)
  }

  init()
}, [])

Wrap the component hierarchy in an ElectricProvider context provider:

return (
  <ElectricProvider db={db}>
    <ExampleComponent />
  </ElectricProvider>
)

Your components can now:

  1. use the useElectric hook to get the electrified database connection and use it to make arbitrary reads and writes; and
  2. use the useElectricQuery hook to bind the results of a live, reactive query to state variables

Update ExampleComponent to use these hooks. The result should look like this:

const ExampleComponent = () => {
  const db = useElectric() as ElectrifiedDatabase
  const { results } = useElectricQuery('SELECT value FROM items', [])

  const addItem = () => {
    db.run('INSERT INTO items VALUES(?)', [crypto.randomUUID()])
  }

  const clearItems = () => {
    db.run('DELETE FROM items where true')
  }

  return (
    // ... markup here is unchanged
  )
}

That’s it! Your local-only app is now local-first, with built-in reactive, realtime cloud sync and both local and durable cloud persistence.

Clone the examples repo, and navigate to the web project, an existing ElectricSQL example web application using React and SQL.js:

git clone https://github.com/electric-sql/examples
cd examples/web

Install the dependencies:

yarn

Testing the sync

The simplest way to test the sync is to open two different browsers side by side (different browsers so they use a different local SQLite database). Make sure the app is running:

yarn start

Open localhost:3001 in both browser windows. Data changes in one window will be automatically detected in the other. If you refresh the page, your items will still be there.

You can also monitor the changes in your cloud Postgres, using the PSQL connection string you copied from your ElectricSQL console into your password manager earlier e.g.:

psql "postgresql://..."
...
electric=> select * from items; \watch 1.0

Open another terminal window and insert items directly in Postgres and watch them appear in both of your browser windows and the watched query, e.g.:

psql "postgresql://..."
...
electric=> insert into items values (gen_random_uuid()) returning value;

You should see something like this. The apps are running locally. Changes made using the buttons are written to the local, embedded SQLite first. They’re then replicated in the background via the cloud to other devices and the cloud Postgres. Changes to the Postgres are replicated to all devices:

For bonus points, use a tool like Ngrok to expose your local service on a public URL and then open the Forwarding address (that starts with https://) in your mobile/cell phone browser:

ngrok http 3001 --bind-tls true

Note that Ngrok can be quite laggy, depending mainly on your Internet connection. Test your app more realistically by publishing it to a free hosting service like Render.

For even more bonus points, fire up one of the Expo or React Native examples, using the same app ID. Watch changes sync in realtime with transactional causal+ consistency across multiple web browsers, a native mobile app and cloud Postgres.

Next steps

Continue with more detailed guides on:

See the example applications on GitHub.