Skip to main content
Technical Preview

Overview

A client-mode connector for the Elasticsearch REST API that writes MQTT data into Elasticsearch and reads it back: Topics use data/elasticsearch/<object>/<verb>, and replies go to <topic>/response. BASE_ADDRESS has no trailing slash; one connector instance talks to one cluster or project: Copy the Elasticsearch endpoint from the Elastic Cloud console (Manage / Connection details), not the Kibana URL.

Auth

Every event sends Authorization: ApiKey …. The template reads the key from the MQTT payload field api_key. Keep it in a Hub secret such as GET SECRET "ELASTICSEARCH_API_KEY" and never commit it.
  • API key (recommended, required on Serverless): create one in Kibana (Stack Management → API keys) or with POST /_security/api_key, and use the encoded value, which is base64 of id:api_key. See Elasticsearch API keys.
  • Scope the key to what the connector writes. A key like the one used in testing:
Drop manage_index_templates once the template exists, and drop index if the connector only appends (create_doc).
  • Basic auth (alternative, self-managed and Hosted): remove the Authorization header lines and add WITH USERNAME "coreflux_writer" and WITH PASSWORD GET SECRET "ELASTICSEARCH_PASSWORD" to REST_API_CONFIG. Don’t use the elastic superuser.
A 401 security_exception means the key is missing, wrong or expired. A 403 naming an action such as indices:admin/auto_create means the key is valid but lacks that privilege on that index.

Basic Syntax

JSON bodies come from the payload field body, so control fields (api_key, index, id, name) are not sent to Elasticsearch. BulkIndex sends the payload field content as the raw NDJSON body.

Example MQTT payloads

Index one reading into a data stream (data/elasticsearch/document/index):
Bulk-load a batch (data/elasticsearch/bulk). Every line ends in \n, including the last one. Data streams only accept create:
Upsert the latest state of an asset (data/elasticsearch/document/put, then data/elasticsearch/document/update):
Search the latest readings for a site (data/elasticsearch/search):
Average temperature by site with ES|QL (data/elasticsearch/esql/query):
Create the time-series index template once (data/elasticsearch/index-template/put):
Smoke (data/elasticsearch/cluster/info): { "api_key": "<…>" }.
Batch high-rate telemetry with _bulk (a few hundred to a few thousand docs, or about 5 to 15 MB per request) instead of one _doc call per sample. Elastic recommends this for indexing throughput.

Gotchas

  • _bulk returns 200 even when items fail. Check "errors": true and each items[].<action>.status in the response. A body that doesn’t end in a newline is rejected with 400 The bulk request must be terminated by a newline [\n].
  • Data streams are append-only. Each document needs @timestamp. In _bulk, use create, not index. PUT /{ds}/_doc/{id} and _update are rejected on data streams; use a regular index (such as factory-assets) for latest-state documents.
  • Index names must be lowercase and can’t start with _, - or +. Several indices can be comma-separated in Search, CountDocuments and RefreshIndex (for example factory-telemetry,metrics-coreflux-*).
  • Near real-time: new documents become searchable after the next refresh (about 1 s by default; on Serverless refreshes are managed). Call RefreshIndex only in tests or after a batch, never per document.
  • Self-managed TLS: Elasticsearch 8.x and 9.x turn on TLS with a self-signed CA at first start. The broker host must trust that CA (or use a publicly trusted certificate) for USE_SSL "true" to work.
  • Serverless doesn’t expose every API. Per Elastic’s Serverless OpenAPI, GET /_cluster/health is not available there (use GET / as the smoke instead), and some index settings such as number_of_replicas are managed for you. Indexing, _bulk, search, count, _update, _refresh, ES|QL, index templates and data streams are all available.
  • Deletes (documents, indices, data streams, templates), _delete_by_query, _update_by_query, security and API key management, cluster settings, snapshots, ILM and Kibana APIs are left out on purpose.

Rate limits

Elasticsearch has no fixed request quota. When the write thread pool queue is full, it returns 429 es_rejected_execution_exception, either for the whole request or for individual _bulk items. Back off and retry only the rejected items. Elastic Cloud Serverless also applies per-project ingest limits. See Tune for indexing speed.

Testing

Status: ready (beta). On 2026-10-04 every event was sent over HTTP, built exactly as the connector builds it (method, endpoint, headers and body substituted from sample MQTT payloads), against a local Elasticsearch 9.5.4 with security on and a scoped API key: Not tested yet: Elastic Cloud Hosted or Serverless, TLS to a self-managed node, and a broker MQTT round-trip (including how the broker substitutes newlines in content for _bulk).
Last modified on October 21, 2026