Snapshot then stream, no gap
The source position is captured before the copy and checkpointed only after Meilisearch confirms. Writes are idempotent, so replays are safe.
Open source · change data capture for Meilisearch
meilisearch-cdc copies your tables once, then streams every insert, update and delete into one or many Meilisearch instances in near real time. Sources, destinations, sync tasks, users, alerts and AI access are all managed from the dashboard, with zero configuration to start.
How it works
A task joins a connector and a table to a destination and an index. The source position is captured before the snapshot, so streaming picks up exactly where the copy ended, with no gap. Checkpoints advance only after Meilisearch confirms the write.
Keyset-paginated copy of the table, chunked and back-pressured, with the replication position pinned first.
Inserts, updates and deletes are coalesced per batch and sent as pipelined, gzipped NDJSON tasks.
At-least-once with idempotent writes. Even after kill -9, the task replays from its last checkpoint.
Features
Built for production sync: safe by default, observable, and operable without touching a config file.
The source position is captured before the copy and checkpointed only after Meilisearch confirms. Writes are idempotent, so replays are safe.
PostgreSQL, MySQL/MariaDB, MongoDB, DynamoDB, CouchDB, SQL Server, CockroachDB, Kafka (Debezium), Redis Streams, webhook push and SQL polling.
Rebuild an index into a shadow index and swap it in. Search never drops while the data is reloaded.
Rejected documents are isolated by bisection into a DLQ to replay or discard. Mass-delete and truncate guards hold the task; a primary key lock protects indexes.
Granular filterable attributes, embedders, synonyms, typo tolerance, ranking rules, faceting and more, with drift detection and one-click apply.
Compare source columns with index fields and coverage. Diff source and index document by document, field by field, and repair missing, stale and extra documents.
Destinations with health checks, per-instance indexes, search playground, document browser, swap, compact, task monitor, dumps, snapshots and experimental features.
Saved source connections with encrypted credentials. Test them and browse tables, collections or topics before creating a task.
Email, Telegram and webhook delivery for failed, held or retrying tasks, lag, DLQ growth, error bursts, stalled snapshots and Meilisearch outages.
Product tour
From the first connection to day-two operations. Scroll through the steps, or click any screenshot to enlarge it.
01 · Overview
Every task with its state and throughput, plus the health of each Meilisearch instance, updated live over server-sent events.
02 · Wizard · connector
The task wizard begins with a saved connector or a new one. Credentials are encrypted at rest and the connection is tested before you continue.
03 · Wizard · source
Browse the source's tables, collections or topics, then choose the primary key and the sync mode: snapshot and stream, snapshot only or stream only.
04 · Wizard · mapping
Include, exclude or rename columns, add static fields, format timestamps, build geo points or composite keys, and preview real transformed sample documents.
05 · Wizard · index
Set filterable attributes with granular features, sortable fields, ranking rules, synonyms, typo tolerance or embedders. Changes are previewed before they apply.
06 · Task detail
Throughput and lag charts, logs, dead letters, schema check, diff and index settings in one place. Pause, resume, restart or resync with zero downtime.
07 · Dead letters
Documents Meilisearch rejects are isolated by bisection into a dead letter queue, so the rest of the batch goes through. Replay or discard them later. Mass-delete and truncate guards hold the task instead of emptying your index.
08 · Schema & diff
The schema checker compares source columns, index fields and coverage. The diff checker compares documents field by field and repairs missing, stale and extra ones.
09 · Destinations
Each destination is health-checked in the background: latency, failures, version, documents, synced tasks and the last sync time.
10 · Search
A search playground with filters, sort and facets, and a document browser, per index and per instance.
11 · Alerts
Rules for failed, held or retrying tasks, lag, DLQ growth, error bursts, stalled snapshots and Meilisearch outages, delivered by email, Telegram or webhook.
More screens
Light and dark themes, responsive down to a phone, live updates over server-sent events.
Performance
End to end: a row changes in Postgres and the document is confirmed by Meilisearch and searchable. Every number waits for Meilisearch to finish indexing. Measured by the open-source load test in test/bench; run it yourself with make load.
92k
docs/s Postgres snapshot
83k–92k across runs, 200,000 rows
46k
docs/s Postgres streaming
39k–46k, 500-row transactions
~47 MiB
idle memory
process RSS, dashboard included
~⅓
of one CPU core
used by the service at peak rate; Meilisearch indexing is the bottleneck
Security & operations
Email and password (argon2id), server-side sessions, CSRF protection and brute-force rate limiting. Viewer, moderator and admin roles; nobody changes their own role.
The first admin owns the installation. Its role and account cannot be changed or deleted from the dashboard or the API, only by the operator CLI.
Invitations are emailed when SMTP is configured. Logins, user changes and settings changes are recorded in the audit log.
AES-256-GCM with a key ring and rotation. Each ciphertext is bound to its record and field; secrets are never returned by the API. Every secret has a *_FILE variant for Docker and Kubernetes.
Prometheus metrics at /metrics, a live dashboard over SSE, structured logs and optional /debug/pprof for admins.
Import and export tasks, or declare them in a YAML file applied at startup with ${VAR} expansion.
Reset passwords, transfer ownership, sign everyone out, turn MCP off, revoke tokens and purge stored data by scope. It talks to the running service over its admin socket, or works on the data directory while the service is stopped.
meilisearch-cdc admin users reset-password --email you@example.com --generate
meilisearch-cdc admin purge sessions alert-events --yes
AI agents · Model Context Protocol
A built-in MCP server (Streamable HTTP at /mcp) lets agents inspect tasks, check health and act on your pipelines.
{
"mcpServers": {
"meilisearch-cdc": {
"type": "http",
"url": "http://localhost:8080/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}
Get started
Open http://localhost:8080. The first visit creates the admin account, then an onboarding flow guides you through connecting Meilisearch, connecting a source and creating your first sync.
Download the archive for your platform (see Download), extract it and run the binary. It needs no runtime and no configuration.
tar -xzf meilisearch-cdc_<version>_<os>_<arch>.tar.gz
cd meilisearch-cdc_<version>_<os>_<arch>
./meilisearch-cdc
Multi-arch image (linux/amd64, linux/arm64) on GitHub Container Registry. State lives in the /data volume.
docker run -d --name cdc -p 8080:8080 -v cdc-data:/data \
ghcr.io/ja7ad/meilisearch-cdc:latest
Operator CLI inside the container: docker exec -it cdc meilisearch-cdc admin users list
Meilisearch and meilisearch-cdc together. With MEILI_URL set the service is pinned to that instance; leave it out to manage several destinations in the dashboard.
services:
meilisearch:
image: getmeili/meilisearch:latest
environment:
MEILI_MASTER_KEY: masterKey
volumes: [meili:/meili_data]
cdc:
image: ghcr.io/ja7ad/meilisearch-cdc:latest
depends_on: [meilisearch]
environment:
MEILI_URL: http://meilisearch:7700
MEILI_API_KEY: masterKey
ports: ["8080:8080"]
volumes: [cdc:/data]
volumes: {meili: {}, cdc: {}}
Want a full demo with Postgres, 10,000 products and a running sync? Clone the repository and run docker compose -f deploy/docker-compose.yml up --build.
Configuration, sources, index settings, alerts, MCP and the operator CLI are covered step by step in the documentation.
Download
Pure Go, statically linked, no cgo: one archive per platform with the binary, the README and the API and CLI docs. Or run the multi-arch Docker image.
See releases on GitHubYou are on a phone or tablet. meilisearch-cdc runs on servers and desktops: download a build below on that machine, or run it there with Docker.
Recommended for Windows
Recommended for Linux
Recommended for macOS
docker pull ghcr.io/ja7ad/meilisearch-cdc:latest
Every release ships a SHA-256 checksums.txt. Put it next to the archive and run:
sha256sum -c checksums.txt --ignore-missing # Linux
shasum -a 256 -c checksums.txt --ignore-missing # macOS
FAQ
PostgreSQL uses logical replication (pgoutput) and needs wal_level=logical. MySQL 8 and MariaDB read the binlog with binlog_format=ROW and binlog_row_image=FULL. MongoDB uses change streams on a replica set; DynamoDB uses DynamoDB Streams; CouchDB and Cloudant the _changes feed; SQL Server its native CDC change tables; CockroachDB changefeeds; Redis Streams XREAD. Kafka carries Debezium JSON envelopes, which also covers Oracle, Db2, Cassandra and others. Anything with a database/sql driver can be polled with an incremental cursor column, and the webhook source accepts HTTP pushes.
At-least-once with idempotent writes. The source position is captured before the snapshot, and checkpoints advance only after Meilisearch confirms a write. After a crash, even kill -9, the task replays from its last checkpoint. Failed tasks are re-applied without overwriting newer data, and if a source position is lost the task resyncs automatically.
Yes. Destinations are named Meilisearch instances with their own URL, key, gzip, timeout and health check interval. Each task maps one connector and table to one destination and index, so several tasks can send one table to several instances.
They are isolated by bisection into a dead letter queue, so the rest of the batch goes through. From the dashboard you can replay or discard them.
Use zero-downtime resync: the task rebuilds into a shadow index and swaps it in when it is complete. Search keeps serving the old index until the swap.
No. Everything is optional and managed in the dashboard. Environment variables and flags exist for the listen address, the data directory, pinning to one Meilisearch instance (MEILI_URL), the secret key, a bootstrap admin, and a YAML tasks file for GitOps. See the documentation.
Encrypted at rest with AES-256-GCM, bound to their record and field, decrypted only when a connection opens and never returned by the API. The key is generated automatically if you do not provide one, and can be rotated with CDC_SECRET_KEY_PREVIOUS.
On the server, run meilisearch-cdc admin users reset-password --email you@example.com --generate. The operator CLI also transfers the primary administrator, signs everyone out and turns MCP off. See docs/cli.md.
Go 1.27 with the official meilisearch-go SDK, an embedded state store, and a dashboard in plain ES modules with Preact, embedded in the binary. For the license, see the repository.
One command to start, then a dashboard that walks you through the rest.