랭킹으로 돌아가기

toluaina/pgsync

Pythonpgsync.com

Postgres to Elasticsearch/OpenSearch sync

elasticsearchelasticsearch-syncpostgresqlchange-data-capturesqlopensearchpythonetlkibanamariadbmysqlmysql-database
스타 성장
스타
1.4k
포크
211
주간 성장
이슈
197
5001k
2019년 9월2021년 12월2024년 4월2026년 7월
아티팩트PyPIpip install pgsync
README

PGSync

Real-time PostgreSQL to Elasticsearch/OpenSearch sync

Keep your relational database as the source of truth while powering lightning-fast search

PyPI version Python versions Build status codecov Downloads License

Docker Code style: black

Website · Documentation · Examples · Report Bug


What is PGSync?

PGSync is a change data capture tool that syncs data from PostgreSQL, MySQL, or MariaDB to Elasticsearch or OpenSearch in real-time. Define your document structure in JSON, and PGSync handles the rest — no custom code required.

Django integration: Use django-pgsync to integrate PGSync with Django projects.

%%{init: {'look': 'handDrawn', 'theme': 'neutral'}}%%
flowchart LR
    subgraph Source["🗄️ Source Database"]
        DB[(PostgreSQL<br/>MySQL<br/>MariaDB)]
    end

    subgraph CDC["⚡ Change Data Capture"]
        P[PGSync]
    end

    subgraph Search["🔍 Search Engine"]
        ES[(Elasticsearch<br/>OpenSearch)]
    end

    DB -->|WAL / Binlog| P
    P -->|Bulk Index| ES

Key Features

Feature Description
Real-time sync Changes propagate instantly via logical replication
Zero code Define mappings in JSON — no ETL pipelines to build
Nested documents Automatically denormalize complex relationships
Fault tolerant Resumes from checkpoints after crashes
Transactionally consistent Documents appear in commit order
Minimal overhead Lightweight CDC with negligible database impact

Quick Start

Using Docker (Fastest)

docker run --rm -it \
  -e PG_URL=postgres://user:pass@host/db \
  -e ELASTICSEARCH_URL=http://localhost:9200 \
  -e REDIS_HOST=localhost \
  -v "$(pwd)/schema.json:/app/schema.json" \
  toluaina1/pgsync:latest -c schema.json -d -b

Using pip

pip install pgsync
# Bootstrap (one-time setup)
bootstrap --config schema.json

# Run sync
pgsync --config schema.json -d

Using Docker Compose

Default (Elasticsearch + Kibana):

git clone https://github.com/toluaina/pgsync
cd pgsync
docker-compose up

This starts PostgreSQL, Redis, Elasticsearch, Kibana, and PGSync configured for Elasticsearch.

For OpenSearch:

docker-compose --profile opensearch up

This starts PostgreSQL, Redis, OpenSearch, and PGSync configured for OpenSearch.

Ports:

  • PostgreSQL: 15432
  • Elasticsearch: 9201 (default)
  • Kibana: 5601 (default)
  • OpenSearch: 9400 (OpenSearch profile)

How It Works

1. Define your schema — Map tables to document structure:

{
  "table": "book",
  "columns": ["isbn", "title", "description"],
  "children": [{
    "table": "author",
    "columns": ["name"]
  }]
}

2. PGSync generates optimized queries — Complex JOINs handled automatically:

SELECT JSON_BUILD_OBJECT(
  'isbn', book.isbn,
  'title', book.title,
  'authors', (SELECT JSON_AGG(author.name) FROM author ...)
) FROM book

3. Get denormalized documents — Ready for search:

{
  "isbn": "9785811243570",
  "title": "Charlie and the Chocolate Factory",
  "authors": ["Roald Dahl"]
}

Changes to any related table automatically update the document in Elasticsearch/OpenSearch.


Requirements

Component Version
Python 3.10+
PostgreSQL 9.6+ (or MySQL 5.7.22+ / MariaDB 10.5+)
Elasticsearch 6.3.1+ (or OpenSearch 1.3.7+)
Redis 3.1+ (or Valkey 7.2+) — optional in WAL mode

Database Setup

PostgreSQL

Enable logical decoding in postgresql.conf:

wal_level = logical
max_replication_slots = 1

Optionally limit WAL size:

max_slot_wal_keep_size = 100GB
MySQL / MariaDB

Enable binary logging in my.cnf:

server-id = 1
log_bin = mysql-bin
binlog_row_image = FULL
binlog_expire_logs_seconds = 604800

Create replication user:

CREATE USER 'replicator'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'replicator'@'%';
FLUSH PRIVILEGES;

Example

Consider a book library with related authors:

Book
isbn (PK) title description
9785811243570 Charlie and the Chocolate Factory Willy Wonka's famous...
9781471331435 1984 George Orwell's chilling...
Author
id (PK) name
1 Roald Dahl
4 George Orwell

PGSync transforms this into search-ready documents:

[
  {
    "isbn": "9785811243570",
    "title": "Charlie and the Chocolate Factory",
    "authors": ["Roald Dahl"]
  },
  {
    "isbn": "9781471331435",
    "title": "1984",
    "authors": ["George Orwell"]
  }
]

Any change — updating an author's name, adding a new book, deleting a relationship — is automatically synced.


Transforms

PGSync supports built-in transforms to modify field values before indexing. Transforms are applied in order: replacerenameconcat.

Replace

Find and replace substrings within field values:

{
  "table": "product",
  "columns": ["code", "name"],
  "transform": {
    "replace": {
      "code": {
        "-": "/",
        "_": " "
      }
    }
  }
}
Before After
ABC-DEF_GHI ABC/DEF GHI

Rename

Rename fields in the output document:

{
  "table": "book",
  "columns": ["id", "title"],
  "transform": {
    "rename": {
      "id": "book_id",
      "title": "book_title"
    }
  }
}

Concat

Combine multiple fields into a new field:

{
  "table": "user",
  "columns": ["first_name", "last_name"],
  "transform": {
    "concat": {
      "columns": ["first_name", "last_name"],
      "destination": "full_name",
      "delimiter": " "
    }
  }
}

Combined Example

Transforms can be combined and applied to nested children:

{
  "table": "book",
  "columns": ["isbn", "title"],
  "children": [{
    "table": "publisher",
    "columns": ["code", "name"],
    "transform": {
      "replace": { "code": { "-": "." } },
      "rename": { "name": "publisher_name" }
    }
  }],
  "transform": {
    "concat": {
      "columns": ["isbn", "title"],
      "destination": "search_text",
      "delimiter": " - "
    }
  }
}

Why PGSync?

Challenge PGSync Solution
Dual writes are error-prone Captures changes from WAL — single source of truth
Complex JOIN queries Auto-generates optimized SQL from your schema
Nested document updates Detects changes in any related table
Data consistency Transactionally consistent, ordered delivery
Crash recovery Checkpoint-based resumption

Environment Variables

Full list at pgsync.com/env-vars

Variable Description
PG_URL PostgreSQL connection string
ELASTICSEARCH_URL Elasticsearch/OpenSearch URL
REDIS_HOST Redis/Valkey host
REDIS_CHECKPOINT Use Redis for checkpoints (recommended for production)

One-Click Deploy

Deploy to DigitalOcean


Sponsors

DigitalOcean

Contributing

Contributions welcome! See CONTRIBUTING.rst for guidelines.

License

MIT — use it freely in your projects.

관련 저장소
macrozheng/mall

mall项目是一套电商系统,包括前台商城系统及后台管理系统,基于Spring Boot+MyBatis实现,采用Docker容器化部署。 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。 后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。

JavaMavenApache License 2.0spring-bootspring-security
macrozheng.com/admin/
84.3k29.8k
doocs/advanced-java

😮 Core Interview Questions & Answers For Experienced Java(Backend) Developers | 互联网 Java 工程师进阶知识完全扫盲:涵盖高并发、分布式、高可用、微服务、海量数据处理等领域知识

JavaMavenCreative Commons Attribution Share Alike 4.0 Internationaljavadistributed-systems
java.doocs.org
79k19.2k
elastic/elasticsearch

Free and Open Source, Distributed, RESTful Search Engine

JavaMavenOtherelasticsearchjava
elastic.co/products/elasticsearch
77.6k26.1k
grafana/grafana

The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.

TypeScriptnpmGNU Affero General Public License v3.0grafanamonitoring
grafana.com
75.7k14.3k
typesense/typesense

Open Source alternative to Algolia + Pinecone and an Easier-to-Use alternative to ElasticSearch ⚡ 🔍 ✨ Fast, typo tolerant, in-memory fuzzy Search Engine for building delightful search experiences

C++GNU General Public License v3.0search-enginesearch
typesense.org
26.3k955
elastic/kibana

Your window into all of your data

TypeScriptnpmOtherkibanaelasticsearch
elastic.co/products/kibana
21.2k8.6k
openobserve/openobserve

Open source observability platform for logs, metrics, traces, frontend monitoring, pipelines and LLM observability. A sophisticated, simple and highly performant alternative to Datadog, Splunk, and Elasticsearch with 140x lower storage costs and single binary deployment.

TypeScriptnpmGNU Affero General Public License v3.0logsmetrics
openobserve.ai
20.3k952
YunaiV/yudao-cloud

ruoyi-vue-pro 全新 Cloud 版本,优化重构所有功能。基于 Spring Cloud Alibaba + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城、CRM、ERP、MES、IM、AI 大模型、IoT 物联网等功能。你的 ⭐️ Star ⭐️,是作者生发的动力!

JavaMavenMIT Licensedubbospringcloud
cloud.iocoder.cn
19.3k4.8k
Tencent/APIJSON

🏆 Real-Time no-code, powerful and secure ORM 🚀 providing APIs and Docs without coding by Backend, and Frontend(Client) can customize response JSONs 🏆 实时 零代码、全功能、强安全 ORM 库 🚀 后端接口和文档零代码,前端(客户端) 定制返回 JSON 的数据和结构

JavaMavenOtherpostgresql-databasetidb
apijson.cn
18.4k2.3k
deviantony/docker-elk

The Elastic stack (ELK) powered by Docker and Compose.

ShellMIT Licensedockerelasticsearch
18.4k6.9k
zincsearch/zincsearch

ZincSearch . A lightweight alternative to elasticsearch that requires minimal resources, written in Go.

GoGo ModulesOthergogolang
zincsearch-docs.zinc.dev
17.9k777
infinilabs/analysis-ik

🚌 The IK Analysis plugin integrates Lucene IK analyzer into Elasticsearch and OpenSearch, support customized dictionary.

JavaMavenApache License 2.0elasticsearchik-analysis
17.5k3.3k