Skip to content

Commit 980218e

Browse files
KyleAMathewsclaude
andauthored
docs: Add comprehensive PostgreSQL permissions guide (#3278)
## Summary https://deploy-preview-3278--electric-next.netlify.app/docs/guides/postgres-permissions Adds a comprehensive guide for setting up PostgreSQL users with the necessary permissions for Electric. This documentation addresses a common setup question by providing clear, actionable guidance for different deployment scenarios. ## What's included - **Quick start** example for common use cases - **Three setup scenarios**: - Global setup (full database access) - Table-scoped setup (restricted to specific tables) - Minimum privilege setup (manual publication management) - **Core permission requirements** explained: - REPLICATION role - CREATE, SELECT, ALTER TABLE privileges - Publication ownership - **Automatic vs manual publication management** modes - **AWS RDS/Aurora** specific configuration - **Manual configuration steps** for publications and replica identity - **Troubleshooting section** with common errors and solutions - **Security best practices** ## Why this is needed Based on investigation of the sync-service codebase (particularly `Electric.Postgres.Configuration` and `Electric.Postgres.ReplicationClient.ConnectionSetup`), Electric requires specific PostgreSQL permissions that aren't fully documented in one place. This guide consolidates that information with practical examples. ## Test plan - [ ] Verify documentation renders correctly on the docs site - [ ] Check all SQL examples for syntax correctness - [ ] Validate links to other documentation pages 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <[email protected]>
1 parent bf44bbc commit 980218e

File tree

6 files changed

+309
-2
lines changed

6 files changed

+309
-2
lines changed

website/.vitepress/config.mts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ export default defineConfig({
231231
{ text: 'Shapes', link: '/docs/guides/shapes' },
232232
{ text: 'Writes', link: '/docs/guides/writes' },
233233
{ text: 'Installation', link: '/docs/guides/installation' },
234+
{
235+
text: 'PostgreSQL Permissions',
236+
link: '/docs/guides/postgres-permissions',
237+
},
234238
{ text: 'Deployment', link: '/docs/guides/deployment' },
235239
{ text: 'Security', link: '/docs/guides/security' },
236240
{ text: 'Troubleshooting', link: '/docs/guides/troubleshooting' },

website/docs/guides/installation.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ docker run \
4848

4949
You can use any Postgres (new or existing) that has [logical replication](https://www.postgresql.org/docs/current/logical-replication-config.html) enabled. You also need to connect as a database user that has the [`REPLICATION`](https://www.postgresql.org/docs/current/logical-replication-security.html) role.
5050

51+
See the [PostgreSQL Permissions guide](/docs/guides/postgres-permissions) for detailed instructions on configuring database users with the necessary permissions for Electric.
52+
5153
## Advanced
5254

5355
You can also choose to build and run Electric [from source](https://github.com/electric-sql/electric) as an [Elixir](https://elixir-lang.org) application.
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
---
2+
title: PostgreSQL Permissions - Guide
3+
description: >-
4+
How to create and configure PostgreSQL users with the necessary permissions for Electric.
5+
outline: [2, 3]
6+
---
7+
8+
# PostgreSQL Permissions
9+
10+
This guide explains how to create PostgreSQL users with the necessary permissions for Electric to work correctly. Electric requires specific database privileges to enable [logical replication](https://www.postgresql.org/docs/current/logical-replication.html) and manage publications.
11+
12+
## Quick Start
13+
14+
Choose the approach that fits your needs:
15+
16+
**For Development:**
17+
Use the default `postgres` superuser. Electric will automatically configure everything.
18+
19+
```shell
20+
DATABASE_URL=postgresql://postgres:your_password@localhost:5432/your_database
21+
```
22+
23+
This is often fine for production too. See [For Development](#for-development) below for details.
24+
25+
**For Production (Automatic Mode):**
26+
Create a dedicated Electric user with automatic table configuration.
27+
→ See [Automatic Mode Setup](#automatic-mode-setup)
28+
29+
**For Production (Manual Mode / Least-Privilege):**
30+
Pre-configure tables manually and use minimal Electric privileges.
31+
→ See [Manual Mode Setup](#manual-mode-setup)
32+
33+
## Core Permission Requirements
34+
35+
Electric needs the following PostgreSQL permissions:
36+
37+
| Permission | Purpose | Required For |
38+
|------------|---------|--------------|
39+
| [`REPLICATION`](https://www.postgresql.org/docs/current/sql-createrole.html) | Enable logical replication streaming | Creating [replication slots](https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION-SLOTS) and consuming the [WAL](https://www.postgresql.org/docs/current/wal-intro.html) |
40+
| [`CREATE`](https://www.postgresql.org/docs/current/ddl-priv.html) on database | Create publications | Automatic publication management |
41+
| [`SELECT`](https://www.postgresql.org/docs/current/sql-grant.html) on tables | Read table data | Initial shape snapshots |
42+
| [Table ownership](https://www.postgresql.org/docs/current/ddl-priv.html) | Set replica identity | Configuring [`REPLICA IDENTITY FULL`](https://www.postgresql.org/docs/current/sql-altertable.html) |
43+
| [Publication ownership](https://www.postgresql.org/docs/current/sql-createpublication.html) | Modify publications | Adding/removing tables from publication; you must also own each table you add to the publication |
44+
45+
## Automatic vs Manual Publication Management
46+
47+
Electric can operate in two modes:
48+
49+
### 1. Automatic Mode (Recommended)
50+
51+
Electric automatically creates the publication and adds tables to it as shapes are requested. Requires `CREATE` privilege on the database and either table ownership or pre-configured `REPLICA IDENTITY FULL` on tables.
52+
53+
### 2. Manual Mode
54+
55+
You manually manage the publication and Electric only validates the configuration. Enable this with [`ELECTRIC_MANUAL_TABLE_PUBLISHING=true`](/docs/api/config#electric-manual-table-publishing). Requires only `REPLICATION` and `SELECT` privileges, but you must pre-configure the publication and `REPLICA IDENTITY FULL`.
56+
57+
**When to use manual mode:**
58+
- When Electric's database user doesn't have `CREATE` privileges
59+
- When you want explicit control over which tables are replicated
60+
- In security-sensitive environments with strict privilege separation
61+
62+
## Setup Examples
63+
64+
### For Development
65+
66+
Use the default `postgres` superuser or another superuser role:
67+
68+
```shell
69+
DATABASE_URL=postgresql://postgres:your_password@localhost:5432/your_database
70+
```
71+
72+
Electric will automatically create publications, configure `REPLICA IDENTITY FULL`, and manage everything for you. This is often fine for production too, especially for smaller deployments.
73+
74+
### Automatic Mode Setup
75+
76+
Create a dedicated Electric user with automatic table configuration. Electric will create publications and add tables as shapes are requested.
77+
78+
```sql
79+
-- Create the Electric user with REPLICATION
80+
CREATE ROLE electric_user WITH LOGIN PASSWORD 'secure_password' REPLICATION;
81+
82+
-- Grant database-level privileges
83+
GRANT CONNECT ON DATABASE mydb TO electric_user;
84+
GRANT USAGE, CREATE ON SCHEMA public TO electric_user;
85+
GRANT CREATE ON DATABASE mydb TO electric_user;
86+
87+
-- Grant SELECT on tables (Electric is read-only, only needs to read data)
88+
-- For all tables:
89+
GRANT SELECT ON ALL TABLES IN SCHEMA public TO electric_user;
90+
91+
-- Grant SELECT on future tables automatically (https://www.postgresql.org/docs/current/sql-alterdefaultprivileges.html)
92+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
93+
GRANT SELECT ON TABLES TO electric_user;
94+
95+
-- For specific tables only:
96+
-- GRANT SELECT ON public.users, public.posts TO electric_user;
97+
```
98+
99+
**Handling REPLICA IDENTITY FULL - Choose one option:**
100+
101+
**Option A: Pre-configure as DBA (Recommended)**
102+
103+
Have your DBA or a superuser set `REPLICA IDENTITY FULL` before Electric runs, keeping table ownership with your application:
104+
105+
```sql
106+
-- As superuser/DBA, set REPLICA IDENTITY on tables that will be synced
107+
ALTER TABLE public.users REPLICA IDENTITY FULL;
108+
ALTER TABLE public.posts REPLICA IDENTITY FULL;
109+
ALTER TABLE public.comments REPLICA IDENTITY FULL;
110+
```
111+
112+
**Option B: Transfer Ownership to Electric**
113+
114+
Transfer table ownership so Electric can manage `REPLICA IDENTITY` automatically:
115+
116+
```sql
117+
DO $$
118+
DECLARE
119+
r RECORD;
120+
BEGIN
121+
FOR r IN SELECT tablename FROM pg_tables WHERE schemaname = 'public'
122+
LOOP
123+
EXECUTE 'ALTER TABLE public.' || quote_ident(r.tablename) || ' OWNER TO electric_user';
124+
END LOOP;
125+
END$$;
126+
```
127+
128+
> [!Warning] Ownership Transfer
129+
> Transferring table ownership removes ownership from the previous owner. If you prefer to keep table ownership with your application or DBA role, use Option A instead.
130+
131+
Then connect Electric:
132+
133+
```shell
134+
DATABASE_URL=postgresql://electric_user:secure_password@localhost:5432/mydb
135+
```
136+
137+
### Manual Mode Setup
138+
139+
For environments with strict security requirements, you can use manual publication management to minimize Electric's privileges.
140+
141+
```sql
142+
-- Create the Electric user with REPLICATION (but minimal other privileges)
143+
CREATE ROLE electric_user WITH LOGIN PASSWORD 'secure_password' REPLICATION;
144+
145+
-- Grant only connection and usage privileges
146+
GRANT CONNECT ON DATABASE mydb TO electric_user;
147+
GRANT USAGE ON SCHEMA public TO electric_user;
148+
149+
-- Grant SELECT only on specific tables
150+
GRANT SELECT ON public.users TO electric_user;
151+
GRANT SELECT ON public.posts TO electric_user;
152+
```
153+
154+
Then, as a superuser or database owner, follow the [Manual Configuration Steps](#manual-configuration-steps) below to create the publication, add tables, and configure replica identity.
155+
156+
Configure Electric with:
157+
158+
```shell
159+
DATABASE_URL=postgresql://electric_user:secure_password@localhost:5432/mydb
160+
ELECTRIC_MANUAL_TABLE_PUBLISHING=true
161+
```
162+
163+
## AWS RDS and Aurora
164+
165+
AWS RDS and Aurora require special handling for replication permissions. See the [AWS integration guide](/docs/integrations/aws) for details on enabling logical replication and granting the `rds_replication` role.
166+
167+
## Manual Configuration Steps
168+
169+
If you need to manually configure the publication and replica identity (for use with `ELECTRIC_MANUAL_TABLE_PUBLISHING=true`):
170+
171+
### 1. [Create the Publication](https://www.postgresql.org/docs/current/sql-createpublication.html)
172+
173+
```sql
174+
-- Create an empty publication
175+
CREATE PUBLICATION electric_publication_default;
176+
177+
-- Or with a custom name (configure with ELECTRIC_REPLICATION_STREAM_ID)
178+
CREATE PUBLICATION my_custom_publication;
179+
```
180+
181+
### 2. [Add Tables to the Publication](https://www.postgresql.org/docs/current/sql-alterpublication.html)
182+
183+
```sql
184+
-- Add specific tables
185+
ALTER PUBLICATION electric_publication_default ADD TABLE public.users;
186+
ALTER PUBLICATION electric_publication_default ADD TABLE public.posts;
187+
ALTER PUBLICATION electric_publication_default ADD TABLE public.comments;
188+
```
189+
190+
### 3. [Configure Replica Identity](https://www.postgresql.org/docs/current/sql-altertable.html)
191+
192+
For each table you want to sync, you must set the replica identity to `FULL`:
193+
194+
```sql
195+
ALTER TABLE public.users REPLICA IDENTITY FULL;
196+
ALTER TABLE public.posts REPLICA IDENTITY FULL;
197+
ALTER TABLE public.comments REPLICA IDENTITY FULL;
198+
```
199+
200+
This tells Postgres to include all column values in the replication stream, which Electric requires for accurate change tracking.
201+
202+
### 4. Set Publication Ownership
203+
204+
Make the Electric user the owner of the publication (or ensure the publication was created by the same user Electric connects as):
205+
206+
```sql
207+
ALTER PUBLICATION electric_publication_default OWNER TO electric_user;
208+
```
209+
210+
### 5. Verify the Configuration
211+
212+
Check that your publication is correctly configured:
213+
214+
```sql
215+
-- List all publications
216+
SELECT * FROM pg_publication;
217+
218+
-- Check publication settings
219+
SELECT pubname, pubinsert, pubupdate, pubdelete, pubtruncate
220+
FROM pg_publication
221+
WHERE pubname = 'electric_publication_default';
222+
223+
-- List tables in the publication
224+
SELECT schemaname, tablename
225+
FROM pg_publication_tables
226+
WHERE pubname = 'electric_publication_default';
227+
228+
-- Check replica identity for tables
229+
SELECT schemaname, tablename, relreplident
230+
FROM pg_class
231+
JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
232+
WHERE relreplident = 'f'; -- 'f' means FULL
233+
```
234+
235+
## Troubleshooting
236+
237+
For common permission errors and their solutions, see the [Database permissions section](/docs/guides/troubleshooting#database-permissions-how-do-i-configure-postgresql-users-for-electric) in the main Troubleshooting guide.
238+
239+
## Next Steps
240+
241+
- Review the [Deployment guide](/docs/guides/deployment) for production setup
242+
- Learn about [Security](/docs/guides/security) best practices
243+
- See [Troubleshooting](/docs/guides/troubleshooting) for common issues
244+
- Check the [Configuration reference](/docs/api/config) for all available options

website/docs/guides/security.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ This API is [public by default](#public-by-default). It should be secured in pro
3939

4040
### Public by default
4141

42-
Electric connects to Postgres as a normal [database user](https://www.postgresql.org/docs/current/user-manag.html). It then exposes access to **any&nbsp;data** that its database user can access in Postgres to **any&nbsp;client** that can connect to the Electric HTTP API.
42+
Electric connects to Postgres as a normal [database user](https://www.postgresql.org/docs/current/user-manag.html). See the [PostgreSQL Permissions guide](/docs/guides/postgres-permissions) for details on configuring database users with the necessary permissions. Electric then exposes access to **any&nbsp;data** that its database user can access in Postgres to **any&nbsp;client** that can connect to the Electric HTTP API.
4343

4444
You generally do _not_ want to expose public access to the contents of your database, so you **must** secure access to the Electric HTTP API.
4545

website/docs/guides/troubleshooting.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,63 @@ If you're stopping Electric for the weekend, we recommend removing the `electric
113113

114114
You can also control the size of the WAL with [`wal_keep_size`](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-WAL-KEEP-SIZE). On restart, Electric will detect if the WAL is past the resume point too.
115115

116+
### Database permissions &mdash; how do I configure PostgreSQL users for Electric?
117+
118+
Electric requires specific PostgreSQL permissions to function correctly, including the `REPLICATION` role and appropriate table permissions.
119+
120+
##### Solution &mdash; see the PostgreSQL Permissions guide
121+
122+
See the [PostgreSQL Permissions guide](/docs/guides/postgres-permissions) for detailed instructions on:
123+
- Quick start setup for development and production
124+
- Different permission levels (superuser, dedicated user, least-privilege)
125+
- How to handle `REPLICA IDENTITY FULL` requirements
126+
127+
##### Common permission errors
128+
129+
**Error: "insufficient privilege to create publication"**
130+
131+
**Cause:** The user doesn't have `CREATE` privilege on the database.
132+
133+
**Solution:** Either:
134+
- Grant `CREATE` privilege: `GRANT CREATE ON DATABASE mydb TO electric_user;`
135+
- Or use manual publication management (create the publication as a superuser and set `ELECTRIC_MANUAL_TABLE_PUBLISHING=true`)
136+
137+
**Error: "publication not owned by the provided user"**
138+
139+
**Cause:** The publication exists but is owned by a different user.
140+
141+
**Solution:** Change the publication owner:
142+
```sql
143+
ALTER PUBLICATION electric_publication_default OWNER TO electric_user;
144+
```
145+
146+
**Error: "table does not have its replica identity set to FULL"**
147+
148+
**Cause:** The table hasn't been configured with `REPLICA IDENTITY FULL`.
149+
150+
**Solution:** Set replica identity manually:
151+
```sql
152+
ALTER TABLE schema.tablename REPLICA IDENTITY FULL;
153+
```
154+
155+
**Error: "permission denied for table"**
156+
157+
**Cause:** The Electric user doesn't have `SELECT` permission on the table.
158+
159+
**Solution:** Grant appropriate permissions:
160+
```sql
161+
GRANT SELECT ON schema.tablename TO electric_user;
162+
```
163+
164+
**Error: "must be owner of table"**
165+
166+
**Cause:** You attempted an operation that requires ownership (e.g., `ALTER TABLE ... REPLICA IDENTITY FULL` or adding the table to a publication).
167+
168+
**Solution:** Run as the table owner (or superuser), or transfer ownership:
169+
```sql
170+
ALTER TABLE schema.tablename OWNER TO electric_user;
171+
```
172+
116173
## IPv6 support
117174

118175
If Electric or Postgres are running behind an IPv6 network, you might have to perform additional configurations on your network.

website/docs/integrations/aws.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ If you already run Postgres in AWS, potentially using RDS or Aurora, then it's a
2929

3030
AWS provides Postgres hosting via RDS and Aurora. Electric works with either. You need to configure them to enable logical replication and connect with the right user.
3131

32-
The default `wal_level` is `minimal` for RDS and `replica` for Aurora. It can be changed to `logical` by creating a [custom parameter group](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.html) for the RDS instance (or the Aurora DB cluster) and setting the value of the `rds.logical_replication` parameter to `1` and rebooting the instance.
32+
Enable logical replication by setting `rds.logical_replication=1` in your [custom parameter group](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.html) for the RDS instance (or the Aurora DB cluster) and rebooting the instance. This sets `wal_level` to `logical`. The PostgreSQL default `wal_level` is `replica`.
3333

3434
The default `postgres` user has the `REPLICATION` role. If you need to add it to another user you can do so by granting the `rds_replication` role, e.g.:
3535

0 commit comments

Comments
 (0)