Elasticsearch
Elasticsearch is a source only in Data Sync — there is no Elasticsearch sink. It is also the one source in these docs that is not log-based, and that difference changes what you can build on it. Read the limitation below before you design around this connector.
Overview
Supported versions are 7.10 and later, 8.x and 9.x. The floor is 7.10 because the snapshot phase uses point-in-time search, which does not exist before that release.
Every other source in these docs reads a change log — the PostgreSQL write-ahead log, SQL Server's CDC tables, a Spanner change stream. Elasticsearch has no such log to tail. Data Sync therefore reads it by polling: it asks repeatedly for documents whose watermark field has moved past the last value it saw. That works well for append-and-update workloads, and it has one consequence that is not recoverable by tuning.
How it reads
A sync in the default snapshot_then_cdc mode runs two phases, and they read the index in genuinely different ways.
Snapshot. Data Sync opens a point-in-time reader, which pins a consistent view of the index for the duration of the backfill, and paginates it with sliced search_after. By default it uses one slice per primary shard, which is the natural parallelism boundary — each slice reads shard-local data, so slices do not contend. Set snapshot_slices if you want to override that.
CDC. Once the backfill is done, Data Sync switches to polling on the watermark field. Each round asks for documents whose watermark is:
- greater than the last watermark value it processed, and
- older than
now − cdc_safety_lag.
Results are sorted by the watermark and paginated with search_after, and the highest watermark seen becomes the lower bound for the next round. Between rounds the connector waits cdc_poll_interval.
The upper bound is the part people delete first and regret later. It has its own section.
Choosing a watermark field
This is the most important configuration decision on this connector. The watermark is the only thing telling Data Sync which documents are new, so a field that does not move forward on every write means changes are silently never read.
The field must be two things:
- Monotonically increasing — it must be updated to a larger value every time the document changes. A
created_atthat is written once and never touched again will replicate the initial write and nothing after it. - Sortable — the CDC query sorts on it and pages with
search_after, both of which need a field type that supports sorting.
A date field is the natural choice, and the default cdc_watermark_field is @timestamp for exactly that reason. If your indexing pipeline stamps an update time on every write, use that.
A bare text field is not sortable — it is analysed into terms, and there is no single value to order by. Where a text field has a keyword sub-field, Data Sync uses the .keyword form automatically, so you can name the parent field and it will resolve. Where it does not, the field cannot be used.
<field>.keyword form where one exists. That is deliberate — a watermark problem discovered at start time is a configuration fix, whereas the same problem discovered at runtime looks like a sync that is quietly replicating nothing.The cdc_safety_lag window
cdc_safety_lag (default 30s) is the window of recent time that Data Sync refuses to read into. Each poll's upper bound is now − cdc_safety_lag, so the most recent half-minute of documents is deliberately left alone until the next round.
The window exists because a watermark is not a log position. Two writes stamped a millisecond apart can become visible to search in the opposite order, a document can be indexed with a slightly older timestamp than one already read, and a page boundary can fall between two documents that share a watermark value. Reading right up to now would step over all three cases and lose the documents involved — permanently, because the lower bound has already moved past them.
Lowering cdc_safety_lag reduces end-to-end latency by exactly the amount you remove. It also shrinks the margin absorbing out-of-order and late-arriving writes, so set it low only if you know your indexing path is tight, and treat missing near-boundary documents as the failure mode to watch for.
Connection fields
Set once, on the Connection, in step 2 of the add-a-connection wizard.
| Field | Default | Description | |
|---|---|---|---|
hosts | One of | — | Comma-separated cluster URLs. Either this or cloud_id is required. |
cloud_id | One of | — | Elastic Cloud deployment identifier, as an alternative to listing hosts. |
username | Optional | — | Basic-auth user. |
password | Optional | — | Basic-auth password, held as a secret. |
api_key | Optional | — | API key, held as a secret. An API key takes precedence over basic auth — if you set both, the username and password are not used. |
ca_cert | Advanced | — | Path to a CA certificate for validating the cluster's TLS certificate. |
tls_skip_verify | Advanced | false | Disables certificate validation. Leave it off outside a lab. |
Fill in hosts or a cloud ID, not both. Credentials are collected in step 3 and stored as a reference, so the key itself never lives in the connection record.
Sync fields
Set per sync. These control which indices are read and how the two phases are paced.
| Field | Default | Description |
|---|---|---|
index_pattern | * | Which indices the sync matches. |
snapshot_slices | 0 | Slices used for the point-in-time backfill. 0 means one slice per primary shard. |
page_size | 1000 | Documents per search_after page, in both phases. |
cdc_watermark_field | @timestamp | The field CDC polls on. See Choosing a watermark field. |
cdc_poll_interval | 2s | How long to wait between polling rounds. |
cdc_safety_lag | 30s | How far behind now each poll stops reading. See above. |
How indices appear
Data Sync's mapping layer is built around schemas and tables, and Elasticsearch has neither. The connector bridges that with a synthetic schema named indices, so an index called orders is addressed as the table indices.orders everywhere in the wizard and in the mappings.
Each document's _id is the primary key. That is what makes replays converge at a keyed sink: the same document re-read after a restart upserts onto itself rather than duplicating.
The Arrow schema prepends two synthetic string columns before the document's own fields:
| Column | What it holds |
|---|---|
_id | The document identifier. Also the primary key. |
_index | The concrete index the document came from — useful when index_pattern matches an alias or a rollover set. |
Metadata fields other than those two are skipped. Document fields follow, flattened to dotted-path columns.
Type mapping
Elasticsearch mapping type on the left, the Arrow type Data Sync produces on the right. Each sink then maps Arrow to its own types — see the sink connector's page for that half.
| Elasticsearch type | Arrow type |
|---|---|
keyword, constant_keyword, wildcard, text, match_only_text, search_as_you_type, ip, version, geo_point, geo_shape, shape, point | String |
integer, short, byte, token_count | Int32 |
long, unsigned_long | Int64 |
float, half_float | Float32 |
double, scaled_float | Float64 |
boolean | Boolean |
date, date_nanos | Timestamp (µs, UTC) |
binary | Binary |
nested, flattened | String, JSON-encoded |
| Anything else | String |
Limitations
Collected in one place, because several of them follow from the polling model rather than from anything you configured.
| Limitation | What it means in practice |
|---|---|
| Deletes are not captured | A poll cannot see a document that no longer exists. Deleted documents remain at the sink. This is structural — no setting changes it. |
| Unmapped fields arrive as String | A field present in _source but absent from the index mapping is added as a String column. Its precise type is picked up on the next mapping refresh, so an early row may carry a number as text. |
_source disabled | Documents in an index with _source disabled cannot be replicated. There is no document body to read. |
| Nested and array values | Values that cannot be flattened into dotted-path scalar columns are carried as JSON text. They arrive intact, but the sink sees a string, not structure. |
| Cross-shard page order | Page order across shards is not deterministic. Correctness does not depend on it — it comes from the watermark ordering plus cdc_safety_lag — which is also why cutting the safety lag too far risks missing writes near a page boundary. |