> electric-postgres-security

Pre-deploy security checklist for Postgres with Electric. Checks REPLICATION role, SELECT grants, CREATE on database, table ownership, REPLICA IDENTITY FULL on all synced tables, publication management (auto vs manual with ELECTRIC_MANUAL_TABLE_PUBLISHING), connection pooler exclusion for DATABASE_URL (use direct connection), and ELECTRIC_POOLED_DATABASE_URL for pooled queries. Load before deploying Electric to production or when diagnosing Postgres permission errors.

fetch
$curl "https://skillshub.wtf/electric-sql/electric/electric-postgres-security?format=md"
SKILL.mdelectric-postgres-security

This skill builds on electric-proxy-auth. Read it first for proxy security patterns.

Electric — Postgres Security Checklist

Run through each section before deploying Electric to production.

User Permission Checks

Check: Electric user has REPLICATION role

Expected:

SELECT rolreplication FROM pg_roles WHERE rolname = 'electric_user';
-- Should return: true

Fail condition: rolreplication = false or user does not exist. Fix: ALTER ROLE electric_user WITH REPLICATION;

Check: Electric user has SELECT on synced tables

Expected:

SELECT has_table_privilege('electric_user', 'todos', 'SELECT');
-- Should return: true

Fail condition: Returns false. Fix: GRANT SELECT ON todos TO electric_user; or GRANT SELECT ON ALL TABLES IN SCHEMA public TO electric_user;

Check: Electric user has CREATE on database

Expected:

SELECT has_database_privilege('electric_user', current_database(), 'CREATE');
-- Should return: true (unless using manual publishing mode)

Fail condition: Returns false and not using ELECTRIC_MANUAL_TABLE_PUBLISHING=true. Fix: GRANT CREATE ON DATABASE mydb TO electric_user;

Table Configuration Checks

Check: REPLICA IDENTITY FULL on all synced tables

Expected:

SELECT relname, relreplident
FROM pg_class
WHERE relname IN ('todos', 'users')
  AND relreplident = 'f';  -- 'f' = FULL

Fail condition: relreplident is 'd' (default) or 'n' (nothing). Fix: ALTER TABLE todos REPLICA IDENTITY FULL;

Check: Tables are in the Electric publication

Expected:

SELECT tablename FROM pg_publication_tables
WHERE pubname = 'electric_publication_default';

Fail condition: Synced tables missing from the list. Fix (manual mode): ALTER PUBLICATION electric_publication_default ADD TABLE todos;

Connection Checks

Check: DATABASE_URL uses direct connection (not pooler)

Expected:

DATABASE_URL=postgres://user:pass@db-host:5432/mydb

Fail condition: URL points to a connection pooler (e.g., PgBouncer on port 6432, Supabase pooler). Fix: Use direct Postgres connection for DATABASE_URL. Set ELECTRIC_POOLED_DATABASE_URL separately for pooled queries.

Check: wal_level is set to logical

Expected:

SHOW wal_level;
-- Should return: logical

Fail condition: Returns replica or minimal. Fix: Set wal_level = logical in postgresql.conf and restart Postgres.

Common Security Mistakes

CRITICAL Using connection pooler for DATABASE_URL

Wrong:

DATABASE_URL=postgres://user:pass@pooler.example.com:6432/mydb

Correct:

DATABASE_URL=postgres://user:pass@db.example.com:5432/mydb
ELECTRIC_POOLED_DATABASE_URL=postgres://user:pass@pooler.example.com:6432/mydb

Connection poolers (except PgBouncer 1.23+) do not support logical replication. Electric must connect directly to Postgres for its replication slot.

Source: website/docs/guides/deployment.md:91

HIGH Missing REPLICA IDENTITY FULL on tables

Wrong:

CREATE TABLE todos (id UUID PRIMARY KEY, text TEXT);
-- Replica identity defaults to 'default' (PK only)

Correct:

CREATE TABLE todos (id UUID PRIMARY KEY, text TEXT);
ALTER TABLE todos REPLICA IDENTITY FULL;

Without REPLICA IDENTITY FULL, Electric cannot stream the full row on updates and deletes. Updates may be missing non-PK columns.

Source: website/docs/guides/troubleshooting.md:373

HIGH Electric user without REPLICATION role

Wrong:

CREATE USER electric_user WITH PASSWORD 'secret';

Correct:

CREATE USER electric_user WITH PASSWORD 'secret' REPLICATION;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO electric_user;

Electric uses logical replication and requires the REPLICATION role on the database user.

Source: website/docs/guides/postgres-permissions.md

Pre-Deploy Summary

  • Electric user has REPLICATION role
  • Electric user has SELECT on all synced tables
  • Electric user has CREATE on database (or manual publishing configured)
  • All synced tables have REPLICA IDENTITY FULL
  • All synced tables are in the Electric publication
  • DATABASE_URL uses direct Postgres connection (not pooler)
  • wal_level = logical in Postgres config
  • ELECTRIC_SECRET is set (not using ELECTRIC_INSECURE=true)
  • Secrets are injected server-side only (never in client bundle)

See also: electric-proxy-auth/SKILL.md — Proxy injects secrets that Postgres security enforces. See also: electric-deployment/SKILL.md — Deployment requires correct Postgres configuration.

Version

Targets Electric sync service v1.x.

> related_skills --same-repo

> blog-planner

Interactive blog post authoring. Produces a draft blog post file with structured outline, inline guidance comments, and meta briefs that the author proses up in place. Supports pyramid principle, best sales deck, and release post formats.

> electric-yjs

Set up ElectricProvider for real-time collaborative editing with Yjs via Electric shapes. Covers ElectricProvider configuration, document updates shape with BYTEA parser (parseToDecoder), awareness shape at offset='now', LocalStorageResumeStateProvider for reconnection with stableStateVector diff, debounceMs for batching writes, sendUrl PUT endpoint, required Postgres schema (ydoc_update and ydoc_awareness tables), CORS header exposure, and sendErrorRetryHandler. Load when implementing collabora

> electric-shapes

Configure ShapeStream and Shape to sync a Postgres table to the client. Covers ShapeStreamOptions (url, table, where, columns, replica, offset, handle), custom type parsers (timestamptz, jsonb, int8), column mappers (snakeCamelMapper, createColumnMapper), onError retry semantics, backoff options, log modes (full, changes_only), requestSnapshot, fetchSnapshot, subscribe/unsubscribe, and Shape materialized view. Load when setting up sync, configuring shapes, parsing types, or handling sync errors.

> electric-schema-shapes

Design Postgres schema and Electric shape definitions together for a new feature. Covers single-table shape constraint, cross-table joins using multiple shapes, WHERE clause design for tenant isolation, column selection for bandwidth optimization, replica mode choice (default vs full for old_value), enum casting in WHERE clauses, and txid handshake setup with pg_current_xact_id() for optimistic writes. Load when designing database tables for use with Electric shapes.

┌ stats

installs/wk0
░░░░░░░░░░
github stars10.0K
██████████
first seenMar 17, 2026
└────────────

┌ repo

electric-sql/electric
by electric-sql
└────────────

┌ tags

└────────────