
- Postgres logical replication 16+ cho phép replicate selective table giữa VPS US và VPS VN, low overhead.
- Latency US-VN ~220ms nhưng async replication chịu được, lag thường <1 giây cho 100 write/s.
- Use case: read-only mirror cho user VN (giảm latency app), backup near-realtime, edge cache.
- Setup 30-40 phút: bật wal_level=logical, tạo PUBLICATION + SUBSCRIPTION, mở port 5432 firewall.
- Khác physical replication (streaming): logical cho phép replicate sub-set table, đổi schema linh hoạt hơn.
Bài toán phổ biến 2026: app SaaS host trên VPS US (gần Stripe, Auth0, Cloudflare workers) nhưng user chủ yếu ở VN. Mỗi query SELECT mất 220ms round-trip = trải nghiệm chậm. Giải pháp: mirror DB read-only sang VPS VN bằng logical replication, app VN đọc local 5ms, write vẫn về US.
Bài này hướng dẫn full setup Postgres logical replication 2 VPS Ubuntu cross-region (US gigabit + VN VPS TND 200Mbps). Test thực tế với DB 50GB, 200 write/s, lag <2 giây ổn định. Phù hợp dev VN có app trên VPS US muốn tăng tốc cho user VN.
Mục tiêu cuối bài: bạn có 2 Postgres cluster, mọi INSERT/UPDATE/DELETE trên US tự sync sang VN trong <2 giây, app VN read-only từ VPS local, monitor lag qua dashboard.
1. Logical vs Physical replication
| Đặc điểm | Logical replication | Physical (streaming) |
|---|---|---|
| Đơn vị | Logical change (INSERT/UPDATE/DELETE) | WAL byte-level |
| Selective table | Có (PUBLICATION chọn table) | Không, replicate full cluster |
| Khác Postgres version | Có (10 -> 16 OK) | Không, phải cùng version |
| Replica writable | Có (chỉ tránh write vào table replicated) | Không (read-only) |
| Overhead | Cao hơn 10-20% | Thấp |
| Use case | Cross-region, sharding, migration | HA, read-replica full |
Logical replication phù hợp cross-region vì: replicate sub-set table (chỉ users, orders, products thay vì pg_largeobject 100GB), tolerant với lag cao, replica vẫn writable cho local-only table (analytics local, cache).
2. Yêu cầu 2 VPS
- Publisher (US): Postgres 14+ (khuyến nghị 16), 4GB+ RAM, port 5432 mở cho IP subscriber.
- Subscriber (VN): Postgres cùng version hoặc mới hơn, 4GB+ RAM, connectivity ra US TCP 5432.
- Network: VPS US tới VPS VN qua public internet, latency ~220ms, bandwidth dùng 0.5-2 Mbps tuỳ write rate.
- VPN tùy chọn: WireGuard giữa 2 VPS để encrypt + giảm latency 10-30ms (tùy ISP).
3. Cài Postgres 16 trên cả 2 VPS
# Cài qua repo official Postgres
sudo sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
sudo apt update
sudo apt install -y postgresql-16
# Kiểm tra
sudo systemctl status postgresql
psql --version4. Config publisher (US VPS)
# Sửa /etc/postgresql/16/main/postgresql.conf
listen_addresses = '*'
wal_level = logical
max_replication_slots = 10
max_wal_senders = 10
wal_sender_timeout = 60s# /etc/postgresql/16/main/pg_hba.conf
# Allow subscriber connect
host all replicator 5.6.7.8/32 scram-sha-256
host all replicator 0.0.0.0/0 scram-sha-256 # nếu IP VN động# Restart Postgres
sudo systemctl restart postgresql
# Tạo user replication
sudo -u postgres psql
CREATE ROLE replicator WITH LOGIN REPLICATION PASSWORD 'strong_password';
GRANT pg_read_all_data TO replicator;
# Tạo PUBLICATION (chọn table cần replicate)
c myapp
CREATE PUBLICATION app_pub FOR TABLE users, orders, products;
-- hoặc FOR ALL TABLES nếu replicate hếtLưu ý quan trọng: PUBLICATION không tự replicate sequence (SERIAL). Khi failover, phải sync sequence thủ công. Dùng UUID PK thay vì SERIAL nếu muốn tránh.
5. Config subscriber (VN VPS)
# /etc/postgresql/16/main/postgresql.conf
listen_addresses = '127.0.0.1' # local app only
max_replication_slots = 10
max_logical_replication_workers = 4
max_sync_workers_per_subscription = 2
sudo systemctl restart postgresql# Tạo DB target và schema giống publisher
sudo -u postgres psql -c "CREATE DATABASE myapp_replica;"
sudo -u postgres psql -d myapp_replica -f /tmp/schema.sql
# (schema.sql dump từ publisher qua pg_dump --schema-only)
# Tạo SUBSCRIPTION
sudo -u postgres psql -d myapp_replica
CREATE SUBSCRIPTION app_sub
CONNECTION 'host=us-publisher.your-domain.com port=5432 dbname=myapp user=replicator password=strong_password'
PUBLICATION app_pub
WITH (copy_data = true, create_slot = true);copy_data=true sẽ initial sync toàn bộ data hiện có. Với 50GB DB trên link 100Mbps, sync mất ~2-4 giờ. Sau đó switch sang streaming mode, only delta thay đổi đi qua.
6. Verify replication hoạt động
# Trên publisher: kiểm tra replication slot
SELECT slot_name, plugin, active, restart_lsn
FROM pg_replication_slots;
# Trên subscriber: kiểm tra status
SELECT subname, received_lsn, latest_end_lsn, latest_end_time
FROM pg_stat_subscription;
# Test: insert trên US
INSERT INTO users (name, email) VALUES ('test', '[email protected]');
# Đợi 1-2 giây, query trên VN
SELECT * FROM users WHERE email = '[email protected]';
-- thấy = replication OK7. Monitor lag và alert
# Query lag (bytes) trên publisher
SELECT
application_name,
pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn) AS sent_lag_bytes,
pg_wal_lsn_diff(pg_current_wal_lsn(), flush_lsn) AS flush_lag_bytes
FROM pg_stat_replication;
# Query lag (time) trên subscriber
SELECT
subname,
now() - latest_end_time AS replication_lag_time
FROM pg_stat_subscription;Setup script cron 1 phút check lag, alert Telegram khi >10 giây. Lag thường spike khi: vacuum lớn trên publisher, bandwidth bị throttle, conflict (unique violation, missing FK).
8. App layer: route read VN, write US
// Node.js + Prisma example
import { PrismaClient } from "@prisma/client";
const writeDb = new PrismaClient({
datasources: { db: { url: process.env.US_DB_URL } }
});
const readDb = new PrismaClient({
datasources: { db: { url: process.env.VN_DB_URL } }
});
// Trong route handler
export async function GET(req) {
// SELECT từ VN (latency 5ms)
const users = await readDb.user.findMany();
return Response.json(users);
}
export async function POST(req) {
// INSERT vào US (latency 220ms, nhưng acceptable cho write)
const data = await req.json();
const user = await writeDb.user.create({ data });
return Response.json(user);
}App layer phân biệt read/write client. Cho user VN: 95% query là SELECT (read VN nhanh), 5% INSERT/UPDATE (write US chậm chấp nhận). Trải nghiệm tổng thể nhanh hơn 10-30x.
9. Xử lý "read after write" inconsistency
Vấn đề: user POST tạo order trên US, redirect sang trang view (GET từ VN). Có thể replication chưa kịp -> 404. Giải pháp:
- Sticky session: sau POST, hold session client read US trong 5 giây.
- Read-your-writes: sau write, read trực tiếp US thay vì VN cho user đó.
- Optimistic UI: return data từ POST response không cần re-fetch.
- Notification: socket.io subscribe channel replication-ready khi VN nhận update.
10. Conflict resolution
Nếu subscriber có write vào table replicated, conflict xảy ra. Postgres 16+ hỗ trợ skip option:
# Khi conflict, subscription tạm dừng
ALTER SUBSCRIPTION app_sub SKIP (lsn = '0/16A7BB1');
ALTER SUBSCRIPTION app_sub ENABLE;Best practice: replica VN read-only về table được replicate. Schema separate (table local_cache, local_analytics) cho write VN, tránh đụng conflict.
11. Bảo mật connection
- Bắt buộc SSL: sửa pg_hba.conf
hostsslthay vìhost, generate cert Let's Encrypt cho FQDN US. - Whitelist IP: chỉ accept IP VN VPS, không 0.0.0.0/0.
- Password mạnh: scram-sha-256 (Postgres 14+ default).
- WireGuard VPN: 2 VPS qua mesh, Postgres listen 10.0.0.0/8, không expose port 5432 public.
- Audit log: pgaudit extension log mọi SUBSCRIPTION action.
12. Failover khi US VPS down
Khi US VPS chết, subscriber VN có thể promote thành master:
- App switch DB connection sang VN (DNS update hoặc load balancer reroute).
- Sync sequence nếu dùng SERIAL:
SELECT setval('users_id_seq', (SELECT MAX(id) FROM users) + 1); - DISABLE SUBSCRIPTION trên VN.
- Khi US online lại, reverse direction (VN publisher, US subscriber).
Failover thủ công an toàn hơn auto (tránh split-brain). Test failover quý 1 lần.
VPS VN làm Postgres replica subscriber giảm latency app
Cloud VPS TND datacenter HCM/HN, SSD CEPH, snapshot 1-click, backup hằng ngày, network 200Mbps trong nước. Latency tới app server VN xuống dưới 5ms. Subscriber Postgres replicate cross-region từ US, giảm latency SELECT 40x cho user VN.
Xem 8 cấu hình Cloud VPS →Trước khi dựng: bạn có thật sự cần nhân bản xuyên vùng không
| Tình huống | Có cần không | Phương án đơn giản hơn |
|---|---|---|
| Khách chủ yếu ở Việt Nam, máy chủ đang ở nước ngoài | Không | Chuyển hẳn máy chủ về trong nước |
| Khách ở cả hai nơi, phần đọc chiếm đa số | Có thể | Cân nhắc bộ nhớ đệm ở phía gần khách trước |
| Cần bản dự phòng ở vùng khác để chống thảm họa | Có | Nhưng có thể chỉ cần sao lưu định kỳ chuyển vùng |
| Muốn giảm độ trễ cho vài truy vấn nặng | Không | Tối ưu truy vấn và thêm chỉ mục trước |
Nói thẳng: nhân bản xuyên vùng thêm rất nhiều việc vận hành, thêm một lớp có thể hỏng, và sinh ra vấn đề dữ liệu không nhất quán mà ứng dụng phải xử lý. Với phần lớn hệ thống vừa và nhỏ ở Việt Nam, chuyển máy chủ về trong nước giải quyết vấn đề độ trễ rẻ hơn và ít rủi ro hơn nhiều.
Ba việc phải làm nếu vẫn dựng
# 1. Theo doi do tre nhan ban, day la chi so quan trong nhat psql -c "SELECT slot_name, active, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS tre FROM pg_replication_slots;" # 2. Canh bao khi do tre vuot nguong # Do tre tang dan khong giam la dau hieu ben nhan khong theo kip # 3. Kenh truyen phai duoc ma hoa # Du lieu di qua internet cong cong giua hai vung # 4. Doc lai sau khi ghi: ung dung phai xu ly # Nguoi dung ghi o vung A roi doc o vung B co the khong thay du lieu vua ghi
Bẫy lớn nhất: khe nhân bản không hoạt động làm đầy ổ
Đây là sự cố nghiêm trọng nhất của mô hình này và ít người lường trước: nếu bên nhận ngừng hoạt động, bên gửi sẽ giữ lại toàn bộ nhật ký ghi để chờ, và ổ đĩa bên gửi đầy dần cho tới khi cơ sở dữ liệu dừng ghi. Nghĩa là bên nhận chết có thể kéo bên chính chết theo.
Ba biện pháp: đặt giới hạn kích thước tối đa cho khe nhân bản; đặt cảnh báo khi độ trễ vượt ngưỡng; và có quy trình xóa khe nhân bản khi bên nhận ngừng hoạt động lâu.
Nếu chỉ cần giảm độ trễ cho khách Việt Nam
Phương án đơn giản hơn nhiều và thường đủ: đặt máy chủ chính trong nước, dùng mạng phân phối cho tệp tĩnh và ảnh, và sao lưu định kỳ ra vùng khác để chống thảm họa. Xem VPS Việt Nam và VPS NVMe.
FAQ
Logical replication tốn bao nhiêu bandwidth?
Tỷ lệ thuận với write rate. App 100 write/s với mỗi write ~1KB = ~10 Mbps. App 1000 write/s heavy = 100 Mbps. Cross-region US-VN trên VPS 200Mbps thoải mái cho 90% workload SaaS. Khi peak, dùng synchronous_commit=off để giảm latency commit.
Có thể replicate giữa 2 phiên bản Postgres khác nhau không?
Có. Logical replication hỗ trợ publisher version cũ hơn subscriber. Ví dụ pub Postgres 14, sub Postgres 16. Cùng version vẫn phù hợp để tránh edge case. Đây cũng là cách "zero downtime migration" upgrade Postgres major version.
Replication có tự handle DDL (ALTER TABLE) không?
Không. Logical replication chỉ replicate DML (INSERT/UPDATE/DELETE/TRUNCATE). DDL phải apply thủ công cả 2 phía. Best practice: schema migration tool (Prisma migrate, Flyway, Sqitch) chạy trên cả publisher và subscriber theo thứ tự (subscriber trước nếu thêm cột để khỏi miss data).
Khi subscriber down lâu, slot có overflow WAL không?
Có. Replication slot giữ WAL chưa được consume, có thể chiếm hết disk publisher. Set max_slot_wal_keep_size = 10GB trong postgresql.conf để giới hạn. Khi vượt, slot bị invalidate, subscriber phải re-init. Trade-off safety vs disk.
Subscriber có index riêng không?
Có. Subscriber tự maintain index của nó, không cần khớp publisher. Bạn có thể tạo index optimize cho read query VN khác với index US. Lưu ý: phải có PK hoặc REPLICA IDENTITY FULL trên table publisher để UPDATE/DELETE replicate được.
Có thể replicate ngược lại sau khi failover không?
Có, nhưng cần re-init thường. Sau khi VN làm master, dữ liệu mới ghi vào VN. Khi US online lại, không thể tự catch up vì WAL US đã out-of-sync. Quy trình: DROP SUBSCRIPTION cũ, pg_dump VN -> restore US, tạo PUBLICATION VN + SUBSCRIPTION US (reverse direction). Tốn thời gian, nên failover ngược cần planning.
- Top 7 VPS Việt Nam giá rẻ 2026: so sánh thực tế từ user dev
- NVMe có phải SSD không? Phân biệt giao thức và ổ đĩa
- Cài PostgreSQL trên VPS Ubuntu: chuẩn production 15 phút
- Self-host n8n + AI workflow trên VPS Việt Nam (Docker, webhook, LLM)
- Cài Coolify trên VPS: self-host PaaS thay Heroku và Vercel
- VPS GPU thuê tháng vs theo giờ: chi phí thật cho AI workload (2026)



