Skip to content

Commit cf0a972

Browse files
Improve instructions for self-hosted Postgres live-sync (#4235)
Signed-off-by: Arunprasad Rajkumar <[email protected]> Co-authored-by: Iain Cox <[email protected]>
1 parent 5e6288c commit cf0a972

File tree

3 files changed

+125
-73
lines changed

3 files changed

+125
-73
lines changed

_partials/_livesync-console.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ import TuneSourceDatabaseAWSRDS from "versionContent/_partials/_livesync-configu
1616

1717
## Limitations
1818

19-
* Indexes (including Primary Key and Unique constraints) are not migrated by $SERVICE_LONG.
19+
* The source $PG instance must be accessible from the Internet.
2020

21-
We recommend that you create only the necessary indexes on the target $SERVICE_LONG depending on your query patterns.
21+
Services hosted behind a firewall or VPC are not supported. This functionality is on the roadmap.
2222

23-
* Tables with user-defined types are not migrated by $SERVICE_LONG.
23+
* Indexes, including the primary key and unique constraints, are not migrated to the target $SERVICE_LONG.
2424

25-
You need to create the user defined types on the target $SERVICE_LONG before syncing the table.
25+
We recommend that, depending on your query patterns, you create only the necessary indexes on the target $SERVICE_LONG.
2626

2727
<LivesyncLimitations />
2828

_partials/_livesync-limitations.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1+
* This works for $PG databases only as source. $TIMESCALE_DB is not yet supported.
2+
3+
* The source must be running $PG 13 or later.
4+
15
* Schema changes must be co-ordinated.
26

37
Make compatible changes to the schema in your $SERVICE_LONG first, then make
48
the same changes to the source $PG instance.
9+
510
* Ensure that the source $PG instance and the target $SERVICE_LONG have the same extensions installed.
611

7-
$LIVESYNC_CAP does not create extensions on the target. If the table uses column types from an extension,
8-
first create the extension on the target $SERVICE_LONG before syncing the table.
12+
$LIVESYNC_CAP does not create extensions on the target. If the table uses
13+
column types from an extension, first create the extension on the
14+
target $SERVICE_LONG before syncing the table.
15+
916
* There is WAL volume growth on the source $PG instance during large table copy.
10-
* This works for $PG databases only as the source. $TIMESCALE_DB is not yet supported.

_partials/_livesync-terminal.md

Lines changed: 112 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import TuneSourceDatabaseAWSRDS from "versionContent/_partials/_migrate_live_tun
1515

1616
- [Install Docker][install-docker] on your sync machine.
1717

18-
You need a minimum of a 4 CPU/16GB EC2 instance to run $LIVESYNC.
18+
For a better experience, use a 4 CPU/16GB EC2 instance or greater to run $LIVESYNC.
1919

2020
- Install the [$PG client tools][install-psql] on your sync machine.
2121

@@ -24,9 +24,10 @@ import TuneSourceDatabaseAWSRDS from "versionContent/_partials/_migrate_live_tun
2424

2525
## Limitations
2626

27+
- The schema is not migrated by $LIVESYNC, you use `pg_dump`/`pg_restore` to migrate it.
28+
2729
<LivesyncLimitations />
2830

29-
- The schema is not migrated by $LIVESYNC, you use `pg_dump`/`pg_restore` to migrate it.
3031

3132
## Set your connection strings
3233

@@ -99,17 +100,17 @@ events data, and tables that are already partitioned using $PG declarative parti
99100
Run the following on each table in the target $SERVICE_LONG to convert it to a hypertable:
100101

101102
```shell
102-
psql -X -d $TARGET -c "SELECT create_hypertable('<table>', by_range('<partition column>', '<chunk interval>'::interval));"
103+
psql -X -d $TARGET -c "SELECT public.create_hypertable('<table>', by_range('<partition column>', '<chunk interval>'::interval));"
103104
```
104105

105106
For example, to convert the *metrics* table into a hypertable with *time* as a partition column and
106107
*1 day* as a partition interval:
107108

108109
```shell
109-
psql -X -d $TARGET -c "SELECT create_hypertable('public.metrics', by_range('time', '1 day'::interval));"
110+
psql -X -d $TARGET -c "SELECT public.create_hypertable('public.metrics', by_range('time', '1 day'::interval));"
110111
```
111112

112-
1. **Convert $PG partitions to hyperatables**
113+
1. **Convert $PG partitions to hypertables**
113114

114115
Rename the partition and create a new normal table with the same name as the partitioned table, then
115116
convert to a hypertable:
@@ -127,6 +128,44 @@ EOF
127128
</Procedure>
128129

129130

131+
## Specify the tables to synchronize
132+
133+
After the schema is migrated, you [`CREATE PUBLICATION`][create-publication] on the source database that
134+
specifies the tables to synchronize.
135+
136+
<Procedure>
137+
138+
1. **Create a publication that specifies the table to synchronize**
139+
140+
A `PUBLICATION` enables you to synchronize some or all the tables in the schema or database.
141+
142+
```sql
143+
CREATE PUBLICATION <publication_name> FOR TABLE <table_name>, <table_name>;
144+
```
145+
146+
To add tables after to an existing publication, use [ALTER PUBLICATION][alter-publication]**
147+
148+
```sql
149+
ALTER PUBLICATION <publication_name> ADD TABLE <table_name>;
150+
```
151+
152+
1. **Publish the $PG declarative partitioned table**
153+
154+
```sql
155+
ALTER PUBLICATION <publication_name> SET(publish_via_partition_root=true);
156+
```
157+
158+
To convert partitioned table to hypertable, follow [Convert partitions and tables with time-series data into hypertables](#convert-partitions-and-tables-with-time-series-data-into-hypertables).
159+
160+
1. **Stop syncing a table in the `PUBLICATION`, use `DROP TABLE`**
161+
162+
```sql
163+
ALTER PUBLICATION <publication_name> DROP TABLE <table_name>;
164+
```
165+
166+
</Procedure>
167+
168+
130169
## Synchronize data to your $SERVICE_LONG
131170

132171
You use the $LIVESYNC docker image to synchronize changes in real-time from a $PG database
@@ -136,42 +175,85 @@ instance to a $SERVICE_LONG:
136175

137176
1. **Start $LIVESYNC**
138177

139-
As you run $LIVESYNC continuously, best practice is to run it as a background process.
178+
As you run $LIVESYNC continuously, best practice is to run it as a Docker daemon.
140179

141180
```shell
142-
docker run -d --rm --name livesync timescale/live-sync:v0.1.16 run --publication analytics --subscription livesync --source $SOURCE --target $TARGET
181+
docker run -d --rm --name livesync timescale/live-sync:v0.1.17 run \
182+
--publication <publication_name> --subscription <subscription_name> \
183+
--source $SOURCE --target $TARGET
143184
```
144185

145-
1. **Trace progress**
186+
`--publication`: The name of the publication as you created in the previous step. To use multiple publication repeat the `--publication` flag.
187+
188+
`--subscription`: The name that identifies the subscription on the target $SERVICE_LONG.
189+
190+
`--source`: The connection string to the source $PG database.
191+
192+
`--target`: The connection string to the target $SERVICE_LONG.
193+
194+
1. **Capture Logs**
146195

147196
Once $LIVESYNC is running as a docker daemon, you can also capture the logs:
148197
```shell
149198
docker logs -f livesync
150199
```
151200

152-
1. **View the tables being synchronized**
201+
1. **View the progress of tables being synchronized**
202+
203+
List the tables being synchronized by $LIVESYNC using the `_ts_live_sync.subscription_rel` table in the target $SERVICE_LONG:
153204

154205
```bash
155206
psql $TARGET -c "SELECT * FROM _ts_live_sync.subscription_rel"
156-
157-
subname | schemaname | tablename | rrelid | state | lsn
158-
----------+------------+-----------+--------+-------+-----
159-
livesync | public | metrics | 17261 | d |
160207
```
208+
209+
You see something like the following:
210+
211+
| subname | pubname | schemaname | tablename | rrelid | state | lsn | updated_at | last_error | created_at | rows_copied | approximate_rows | bytes_copied | approximate_size | target_schema | target_table |
212+
|----------|---------|-------------|-----------|--------|-------|------------|-------------------------------|-------------------------------------------------------------------------------|-------------------------------|-------------|------------------|--------------|------------------|---------------|-------------|
213+
|livesync | analytics | public | metrics | 20856 | r | 6/1A8CBA48 | 2025-06-24 06:16:21.434898+00 | | 2025-06-24 06:03:58.172946+00 | 18225440 | 18225440 | 1387359359 | 1387359359 | public | metrics |
214+
215+
The `state` column indicates the current state of the table synchronization.
161216
Possible values for `state` are:
162217

163-
- d: initial table data sync
218+
| state | description |
219+
|-------|-------------|
220+
| d | initial table data sync |
221+
| f | initial table data sync completed |
222+
| s | catching up with the latest changes |
223+
| r | table is ready, synching live changes |
224+
225+
To see the replication lag, run the following against the SOURCE database:
164226

165-
- f: initial table data sync completed
227+
```bash
228+
psql $SOURCE -f - <<'EOF'
229+
SELECT
230+
slot_name,
231+
pg_size_pretty(pg_current_wal_flush_lsn() - confirmed_flush_lsn) AS lag
232+
FROM pg_replication_slots
233+
WHERE slot_name LIKE 'live_sync_%' AND slot_type = 'logical'
234+
EOF
235+
```
236+
237+
1. **Add or remove tables from the publication**
238+
239+
To add tables, use [ALTER PUBLICATION .. ADD TABLE][alter-publication]**
166240

167-
- s: catching up with the latest change
241+
```sql
242+
ALTER PUBLICATION <publication_name> ADD TABLE <table_name>;
243+
```
244+
245+
To remove tables, use [ALTER PUBLICATION .. DROP TABLE][alter-publication]**
246+
247+
```sql
248+
ALTER PUBLICATION <publication_name> DROP TABLE <table_name>;
249+
```
168250

169-
- r: table is ready, synching live changes
251+
1. **Update table statistics**
170252

171-
1. **(Optional) Update table statistics**
253+
If you have a large table, you can run `ANALYZE` on the target $SERVICE_LONG
254+
to update the table statistics after the initial sync is complete.
172255

173-
If you have a large table, you can run `ANALYZE` on the target $SERVICE_LONG to update the table statistics
174-
after the initial sync is complete. This helps the query planner make better decisions for query execution plans.
256+
This helps the query planner make better decisions for query execution plans.
175257

176258
```bash
177259
vacuumdb --analyze --verbose --dbname=$TARGET
@@ -185,7 +267,11 @@ instance to a $SERVICE_LONG:
185267

186268
1. **(Optional) Reset sequence nextval on the target $SERVICE_LONG**
187269

188-
$LIVESYNC does not automatically reset the sequence nextval on the target $SERVICE_LONG. Run the following script to reset the sequence for all tables that have a serial or identity column in the target $SERVICE_LONG:
270+
$LIVESYNC does not automatically reset the sequence nextval on the target
271+
$SERVICE_LONG.
272+
273+
Run the following script to reset the sequence for all tables that have a
274+
serial or identity column in the target $SERVICE_LONG:
189275

190276
```bash
191277
psql $TARGET -f - <<'EOF'
@@ -226,53 +312,13 @@ EOF
226312

227313
1. **Cleanup**
228314

229-
Removes replication slots created by $LIVESYNC on the source database.
315+
Use the `--drop` flag to remove the replication slots created by $LIVESYNC on the source database.
230316

231317
```shell
232-
docker run -it --rm --name livesync timescale/live-sync:v0.1.16 run --publication analytics --subscription livesync --source $SOURCE --target $TARGET --drop
233-
```
234-
235-
</Procedure>
236-
237-
238-
## Specify the tables to synchronize
239-
240-
After the $LIVESYNC docker is up and running, you [`CREATE PUBLICATION`][create-publication] on the SOURCE database to
241-
specify the list of tables which you intend to synchronize. Once you create a PUBLICATION, it is
242-
automatically picked by $LIVESYNC, which starts syncing the tables expressed as part of it.
243-
244-
For example:
245-
246-
<Procedure>
247-
248-
1. **Create a publication named `analytics` which publishes `metrics` and `tags` tables**
249-
250-
`PUBLICATION` enables you to add all the tables in the schema or even all the tables in the database. However, it
251-
requires superuser privileges on most of the managed $PG offerings.
252-
253-
```sql
254-
CREATE PUBLICATION analytics FOR TABLE metrics, tags;
255-
```
256-
257-
1. **Add tables after to an existing publication with a call to [ALTER PUBLICATION][alter-publication]**
258-
259-
```sql
260-
ALTER PUBLICATION analytics ADD TABLE events;
261-
```
262-
263-
1. **Publish $PG declarative partitioned table**
264-
265-
To publish declaratively partitioned table changes to your $SERVICE_LONG, set the `publish_via_partition_root`
266-
special `PUBLICATION` config to `true`:
267-
268-
```sql
269-
ALTER PUBLICATION analytics SET(publish_via_partition_root=true);
270-
```
271-
272-
1. **Stop syncing a table in the `PUBLICATION` with a call to `DROP TABLE`**
273-
274-
```sql
275-
ALTER PUBLICATION analytics DROP TABLE tags;
318+
docker run -it --rm --name livesync timescale/live-sync:v0.1.17 run \
319+
--publication <publication_name> --subscription <subscription_name> \
320+
--source $SOURCE --target $TARGET \
321+
--drop
276322
```
277323

278324
</Procedure>

0 commit comments

Comments
 (0)