---
title: "Deploy ElectricSQL"
description: "Streams live rows from Postgres to apps over a simple HTTP API"
category: "Storage"
url: https://railway.com/deploy/electricsql
---

# Deploy ElectricSQL

Streams live rows from Postgres to apps over a simple HTTP API

**[Deploy ElectricSQL on Railway](https://railway.com/template/electricsql)**

- **Creator:** A3A
- **Category:** Storage

## Template content

### cache https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/nginx.svg

- **Source:** https://github.com/gridalpha/electricsql-railway
- **Health check:** /healthz
- **Public domain:** Yes

### electric https://raw.githubusercontent.com/electric-sql/electric/main/website/public/img/brand/favicon.svg

- **Image:** electricsql/electric:latest
- **Health check:** /v1/health

### Postgres https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/postgresql.svg

- **Source:** https://github.com/gridalpha/electricsql-railway
- **Start command:** `wrapper.sh postgres -p 5432 -c listen_addresses=* -c wal_level=logical -c max_wal_senders=10 -c max_replication_slots=10`

## Documentation

![ElectricSQL logo](https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTlTva9Jjp3krh9os15a9I9956SXBGMA2julp-fQc998F5ZaIdasZFe1cY&amp;s=10)

# Deploy and Host ElectricSQL on Railway

ElectricSQL is a Postgres sync engine. It reads your database's logical replication stream and serves any subset of it — a "shape" — over an ordinary, cacheable HTTP API, so browsers, mobile apps and edge workers hold a live local copy of exactly the rows they care about. Instead of writing polling loops, websocket fan-out and cache invalidation by hand, you point a client at a URL carrying a table name and a `where` clause, and Electric keeps it current. It is Apache-2.0 licensed, has over 10,000 GitHub stars, and is the sync layer behind TanStack DB.

Deploy ElectricSQL on Railway and you get three wired-up services: Postgres 18 started with logical replication enabled, the `electricsql/electric` sync service holding its shape logs on a volume, and an nginx caching proxy as the only public entry point. Requests hit the proxy, which caches immutable shape-log pages and collapses concurrent live subscriptions into one upstream request before forwarding to Electric over private networking. Self-hosting ElectricSQL elsewhere means configuring `wal_level` and standing up that cache yourself; here it is already done.

![Diagram of the Electric, Postgres and nginx cache services on Railway](https://res.cloudinary.com/rroe4rtk/image/upload/v1788275417/electricsql-architecture.png)

## Getting Started with ElectricSQL on Railway

Electric has no web dashboard — it is an HTTP API, and the public URL Railway gives you is its root. Open `https:///v1/health` first: a healthy deployment answers `{"status":"active"}`, while `{"status":"waiting"}` means it is still connecting to Postgres. Every other request needs the `ELECTRIC_SECRET` the template generates, passed as a `secret` query parameter; without it the service answers `401`, so the endpoint is never open. Copy that value from the `electric` service's variables.

The database ships with a small demo table called `items`, so your first request returns real data rather than an error. Fetch the whole table as a shape log:

```
curl "https:///v1/shape?table=items&amp;offset=-1&amp;secret="
```

You get a JSON array of log entries, each with a `key`, the row `value` and headers naming the operation. The response also carries `electric-handle` and `electric-offset` — pass those back with `live=true` to hold a long-poll open and receive changes as they commit. Add `where` and `columns` to sync only part of a table:

```
curl "https:///v1/shape?table=items&amp;columns=id,title,status&amp;where=status%20%3D%20%27todo%27&amp;offset=-1&amp;secret="
```

Once that works, connect a client with `npm install @electric-sql/client`, or `@electric-sql/react` for a `useShape` hook, pointing its `url` at your Railway domain. Then create your own tables in the Postgres service and drop `items`. Any table is syncable immediately — Electric adds it to its publication on the first shape request, with no registration step.

![Electric shape log holding every row of the items table](https://res.cloudinary.com/rroe4rtk/image/upload/v1788275657/electricsql-initial-sync.png)
![Shape filtered to unfinished items with three selected columns](https://res.cloudinary.com/rroe4rtk/image/upload/v1788275658/electricsql-partial-shape.png)
![Live long-poll delivering a row update with its replication LSN](https://res.cloudinary.com/rroe4rtk/image/upload/v1788275421/electricsql-live-update.png)

## About Hosting ElectricSQL

Electric solves the hardest part of real-time and local-first applications: getting a correct, resumable subset of a Postgres database into a client and keeping it there. It replaces neither your database nor your API — it sits beside them as a read path, and teams self-host it to keep that path on their own infrastructure rather than routing customer data through a third party.

- Partial replication through shapes: a table, a `where` clause and a column list
- A plain HTTP API — no custom protocol, no websocket server to operate
- Resumable, append-only logs that survive client restarts and network loss
- Built for CDN and proxy caching, so repeat syncs never touch Postgres
- Reads only: writes go through your own API, so your auth rules stay put

The deployment splits into three roles. **Postgres** owns every durable byte and runs with `wal_level=logical`. **electric** connects over a replication slot, keeps its shape logs on a 5 GB volume, and serves the API privately on port 3000. **cache** is nginx with `proxy_cache` and `proxy_cache_lock`, the only service with a public domain; its request collapsing lets subscribers share one upstream long-poll.

## Why Deploy ElectricSQL on Railway

Railway removes the setup between you and a working sync engine.

- Logical replication configured before first boot — no manual `wal_level` change
- The caching proxy Electric's docs recommend, already wired up
- Private networking keeps Postgres and the sync service off the public internet
- Persistent volumes for the database and the shape logs
- Scale CPU, memory and storage without redeploying

## Common Use Cases for Self-Hosted ElectricSQL

- Local-first apps that keep a working copy of user data in the browser
- Live dashboards and collaborative UIs, replacing polling with a change stream
- Syncing reference data — pricing, feature flags, catalogues — into edge workers
- Multi-tenant SaaS where each client syncs only the rows its `where` clause matches

## Dependencies for ElectricSQL on Railway

- `electricsql/electric:latest` — the sync service, an Elixir release serving the shape API
- `ghcr.io/railwayapp-templates/postgres-ssl:18` — Postgres 18 with logical replication
- `nginx:1-alpine` — the caching proxy in front of Electric

### Environment Variables Reference

| Variable | Service | Purpose |
|---|---|---|
| `DATABASE_URL` | electric | Postgres connection; the role needs `REPLICATION` |
| `ELECTRIC_SECRET` | electric | Required on every shape request as `?secret=` |
| `ELECTRIC_CONSUMER_PARTITIONS` | electric | Concurrency; set to the CPU quota |
| `ELECTRIC_UPSTREAM` | cache | Host and port the proxy forwards to |
| `POSTGRES_PASSWORD` | Postgres | Superuser password, generated at deploy |

### Deployment Dependencies

- GitHub: [electric-sql/electric](https://github.com/electric-sql/electric)
- Docker Hub: [electricsql/electric](https://hub.docker.com/r/electricsql/electric)
- Docs: [electric.ax/docs](https://electric.ax/docs)
- Source repository: [gridalpha/electricsql-railway](https://github.com/gridalpha/electricsql-railway)

## Hardware Requirements for Self-Hosting ElectricSQL

Electric is disk-first: shape logs are written and re-read constantly, so storage speed matters more than cores do.

| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 1 vCPU | 2–4 vCPU |
| RAM | 1 GB | 2–4 GB |
| Storage | 5 GB volume | 10 GB+, scaled to shape count |
| Runtime | Docker / OCI container | Docker / OCI container |

Postgres needs its own headroom, and each active shape keeps a log on disk — raise the Electric volume before shape count grows.

## Self-Hosting ElectricSQL with Docker

Electric needs a Postgres with `wal_level=logical` and a role carrying the `REPLICATION` attribute. Start the database with that setting on the command line:

```
docker run -d --name pg -e POSTGRES_PASSWORD=pw postgres:18 \
  postgres -c wal_level=logical -c max_wal_senders=10 -c max_replication_slots=10
```

Then run the sync service against it, giving it a directory to keep shape logs in:

```
docker run -d --name electric -p 3000:3000 \
  -e DATABASE_URL="postgresql://postgres:pw@pg:5432/postgres?sslmode=disable" \
  -e ELECTRIC_SECRET="a-long-random-string" \
  -e ELECTRIC_STORAGE_DIR=/data/electric \
  -v electric-data:/data electricsql/electric:latest
```

Electric creates the publication and replication slot itself on first connection. In production, put a caching proxy or CDN in front of port 3000.

## How Much Does ElectricSQL Cost to Self-Host?

The sync service is open source under Apache-2.0, with no paid tier, seat limit or feature gate in the self-hosted build. The company behind it sells Electric Cloud, a managed version, but nothing here depends on it. On Railway you pay only for the compute, memory and storage the three services use.

## FAQ

**What is ElectricSQL?**
A Postgres sync engine that turns logical replication into a cacheable HTTP API, so clients subscribe to a filtered subset of your database and keep it current.

**What does this Railway template deploy?**
Three services: Postgres 18 with logical replication enabled, the Electric sync service on a persistent volume, and an nginx caching proxy fronting the API publicly.

**Why does the template include Postgres instead of my existing database?**
Electric requires `wal_level=logical`, which most managed Postgres instances do not enable by default. The bundled database has it set from first boot. Point `DATABASE_URL` at your own Postgres if it already meets that requirement.

**Why is there a caching proxy in front of ElectricSQL?**
Shape-log pages below the current offset never change, so they cache indefinitely, and the proxy collapses concurrent live subscriptions into one upstream request. Electric's docs treat a cache as part of a production deployment, not an optimisation.

**How do I secure my self-hosted ElectricSQL endpoint?**
Every request must carry the generated `ELECTRIC_SECRET`. For end-user traffic, keep it server-side and proxy shape requests through your own API, applying per-user authorisation before forwarding.

**Can ElectricSQL write back to Postgres?**
No — Electric is a read path only. Writes go through your existing API or database connection, and the change comes back to clients through the shape log.


## Similar templates

- [Garage S3 Storage](https://railway.com/deploy/garage-s3-storage) — Ultra-light S3 server: fast, open-source, plug-and-play.
- [Redis](https://railway.com/deploy/redis-1) — Self Host Latest Redis with Railway
- [EasyImg](https://railway.com/deploy/easyimg) — Simple self-hostable Nuxt.js personal image hosting system.

Open this page in a browser: https://railway.com/deploy/electricsql
