Happy Dussehra! May good always win. Merry Christmas! Warm wishes from Vizag. Happy New Year! Here’s to a great year ahead.

DevOps · CNCF daily

openGemini: A Distributed Time-Series Database That Speaks InfluxDB and Prometheus

A CNCF Sandbox time-series database written in Go. It splits into stateless SQL nodes, a Raft metadata group and LSM-based storage nodes, accepts InfluxDB line protocol and Prometheus remote write, and answers InfluxQL and PromQL.

18 min read

CNCF Sandbox

  • openGemini
  • InfluxDB line protocol
  • InfluxQL
  • PromQL
  • Prometheus remote write
  • Go
  • AWS EC2
  • Vector
CNCF project page

openGemini is an open-source time-series database for telemetry: metrics, device readings and logs that arrive continuously, carry a timestamp and are queried mostly by time range. It was created by Huawei Cloud’s database team, open-sourced in 2022 and accepted into the CNCF at the Sandbox level on July 9, 2024. It is written in Go under the Apache-2.0 licence. You write to it with the InfluxDB v1 line protocol, query it with InfluxQL (or PromQL), and it is built to scale out as a cluster of three kinds of process. This brief explains the project from the problem it solves to installing, configuring, securing and operating it, and is honest about where its documentation and community are thin.

CNCF daily · Sprint 5, post 5 of 14 · Database

At a glance

Category App Definition and Development, subcategory Database (CNCF Landscape)
CNCF status Sandbox, accepted July 9, 2024
Written in Go (go.mod on main targets Go 1.26)
License Apache-2.0
Origin and maintainers Created by Huawei Cloud; the six maintainers in MAINTAINERS.md are all Huawei-affiliated
Architecture Three components: ts-sql (stateless access and query), ts-meta (metadata, Raft) and ts-store (LSM storage). ts-server bundles all three for one node
Write interfaces InfluxDB line protocol over HTTP /write, Prometheus remote write, a record (column) write protocol, an Arrow Flight column protocol (off by default)
Query interfaces InfluxQL-style language (“GeminiQL”) over HTTP /query and a CLI; PromQL since v1.3.0
Default ports ts-sql HTTP 8086, Flight 8087; ts-meta 8088, 8091 (HTTP), 8092 (RPC)
Releases Stable tags v1.5.0, v1.5.1 and v1.5.2; v1.5.3 was at release candidate 5 when I checked. Check the releases page for the current one
Install Release tarball and ts-server, gemix (cluster), an operator for Kubernetes, or build from source

The problem openGemini solves

A time-series workload has an awkward shape. Writes are constant, append-only and bursty. Each point is tiny, but there are very many of them. Queries ask for a time window, usually filtered by a few labels such as a device or a site, and often downsampled. Data ages: yesterday’s readings matter in full detail, last year’s only as hourly averages, and some data must simply expire.

A general-purpose relational database can store this, but you end up hand-building partitioning by time, expiry jobs and rollups. A single-node time-series database handles the shape well until the write rate, the number of distinct series or the retention outgrow one machine. openGemini targets that second step: it keeps the InfluxDB v1 ecosystem (line protocol, InfluxQL, existing client libraries and agents such as Telegraf) but spreads storage and query across nodes, and adds features for large series counts, downsampling and retention.

Key concepts

Term Meaning
Measurement The “table”: a named set of points, for example readings.
Tag An indexed label (device_id, site). Each unique tag combination in a measurement is one series.
Field The measured values (temp_c, door_open). Fields are not indexed.
Point One row: measurement, tags, fields and a timestamp. One line of line protocol is one point.
Series cardinality The number of unique series. Very high cardinality is the classic way to overload a time-series index.
Database and retention policy A database holds measurements. A retention policy (RP) sets how long data is kept, the shard duration and the replication factor; every database has a default RP named autogen.
Shard and shard group Data is partitioned first by time into shard groups, then spread over ts-store nodes. Dropping an expired time range means dropping whole shards.
Shard key An optional key that spreads a measurement’s data across stores. Without it, series are hashed by name.
Continuous query (CQ) A stored query that runs on a schedule and writes aggregates into another measurement or RP, for downsampling.
Subscription A rule that forwards writes arriving at the cluster to other HTTP endpoints.

Architecture

openGemini architecture: writers such as Vector, Prometheus and Telegraf and readers such as Grafana and the InfluxQL CLI connect through a load balancer to stateless ts-sql nodes; ts-sql nodes talk to a three-node ts-meta Raft group for metadata and to several ts-store nodes that keep write-ahead logs and LSM files on local disks.

Clients talk only to ts-sql. ts-meta holds the cluster map and ts-store holds the data. Green is a destination, purple is an openGemini component, blue is a client and dark grey is the load balancer. Open the zoomable diagram, or download it as SVG or PNG.

Component Responsibility
ts-sql The single front door for reads and writes. On a write it validates the format, hashes the data by series and forwards it to the right ts-store. On a query it builds a distributed plan, sends sub-plans to the stores and merges the results. It is stateless, so you scale it out behind a load balancer.
ts-meta Holds metadata: databases, measurements, retention policies, shard layout and cluster membership. The documented cluster layout uses three ts-meta nodes.
ts-store Stores and queries the data. It appends writes to a write-ahead log and an in-memory buffer, flushes to an LSM-tree layout on disk with compaction, and uses an inverted index to find the series involved in a query. It scales out.
ts-server A single binary that runs a ts-sql, a ts-meta and a ts-store together, for one node.
ts-monitor An optional agent that reports process and disk metrics and error logs from each node.

Design principle. Separate the stateless front door from the stateful storage. Because ts-sql holds no data, you can add or lose query nodes freely, and because ts-store owns time-partitioned shards, expiry and rollups work on whole shards instead of row by row.

From a raw reading to a stored point

Write and query flow in openGemini: a client posts line protocol to ts-sql, ts-sql asks ts-meta for the shard and store, forwards the point to the right ts-store, which appends to the write-ahead log and memory and acknowledges; a later InfluxQL query arrives at ts-sql, is split into sub-plans for the stores and the merged result returns to the client.

One write and one query. Open the zoomable diagram, or download it as SVG or PNG.

  1. A client sends POST /write?db=telemetry with line protocol to any ts-sql node.
  2. ts-sql parses and validates the lines, then looks up which retention policy and shard group the timestamps fall into.
  3. It hashes each point by its series (or shard key) and picks the owning ts-store.
  4. The store appends the point to its write-ahead log and in-memory buffer and answers success.
  5. Later the buffer is flushed to immutable files and compacted in the background.
  6. A query (SELECT mean(temp_c) FROM readings ... GROUP BY time(5m)) reaches ts-sql, which sends sub-queries to the stores holding the relevant shards and merges what comes back.

The flow is my reading of the documented architecture; exact internals (such as batching and acknowledgement timing) vary with configuration and version.

Cluster architecture in the docs

Install openGemini

The official documentation offers several routes. Pick by purpose:

Route Use it for
Release tarball and ts-server A single node for learning and tests
gemix Installing and managing a multi-node cluster on VMs or servers; the docs call it the recommended cluster route
Manual ts-meta, ts-store, ts-sql Understanding how the pieces start; the docs themselves say it is not recommended
openGemini operator Kubernetes; a separate project from the main repository
Build from source Contributors; requires a recent Go toolchain and Python for the build script

Single node

The quick start downloads the release tarball for your platform, unpacks it and starts the standalone binary. Replace <version> with a release you chose from the releases page:

wget https://github.com/openGemini/openGemini/releases/download/v<version>/openGemini-<version>-linux-amd64.tar.gz
tar -xzf openGemini-<version>-linux-amd64.tar.gz
# ts-server reads openGemini.singlenode.conf
./usr/bin/ts-server -config etc/openGemini.singlenode.conf

The paths inside the tarball and the exact flags change between versions, so follow the quick start for the version you downloaded. Two defaults matter: it listens on 127.0.0.1:8086, and data and logs go to /tmp/openGemini. Change both before you keep anything you care about. The repository also has scripts/install.sh and scripts/install_cluster.sh for local single-node and “pseudo-cluster” runs.

The CLI

The bundled ts-cli was removed from the main repository in November 2026; it now lives in its own repository, openGemini-cli, and installs with Go:

go install github.com/openGemini/openGemini-cli/cmd/ts-cli@latest
ts-cli --host 127.0.0.1 --port 8086

Older tarballs still contain a ts-cli. Any InfluxDB v1 client and plain curl also work against the HTTP API.

A cluster

A minimal documented topology is three ts-meta, two ts-sql and two ts-store, each component on its own node so the ports do not clash. Nodes find the metadata group through meta-join:

[common]
  meta-join = ["10.0.1.11:8092", "10.0.1.12:8092", "10.0.1.13:8092"]

Start ts-meta first, then ts-store, then ts-sql. Use gemix for anything beyond a lab, and use host names rather than raw IPs if node addresses can change.

Using openGemini

Examples below use neutral sensor data. I have not run these against a live cluster; they follow the official documentation, so check them against your version.

Create a database with retention

CREATE DATABASE telemetry WITH DURATION 90d REPLICATION 1 SHARD DURATION 1d NAME rp90d

Omit the WITH clause and you get the default autogen policy with unlimited duration. Shard duration defaults depend on the retention duration (one hour under two days, one day up to about six months, seven days beyond that).

Write line protocol over HTTP

curl -i -XPOST "http://localhost:8086/write?db=telemetry&precision=s" --data-binary '
readings,device_id=d001,site=depot-a temp_c=4.1,door_open=false 1799884800
readings,device_id=d002,site=depot-a temp_c=3.8,door_open=false 1799884800
'

A successful write returns 204. The docs show exactly this endpoint shape (/write?db=... with --data-binary). Write in batches, not one point per request.

Query with InfluxQL

curl -G "http://localhost:8086/query" \
  --data-urlencode "db=telemetry" \
  --data-urlencode "q=SELECT mean(temp_c) FROM readings WHERE time > now() - 1h GROUP BY time(5m), device_id"

Explicit tables and shard keys

The README also describes creating a measurement explicitly and naming a shard key, so data is partitioned by time first and by your key second:

CREATE MEASUREMENT readings WITH SHARDKEY site

Choose a shard key with enough distinct values to spread load, and avoid one with a handful of values.

Downsample with a continuous query

CREATE CONTINUOUS QUERY cq_hourly ON telemetry
BEGIN
  SELECT mean(temp_c) INTO telemetry.rp90d.temp_hourly FROM readings GROUP BY time(1h), device_id
END

Create the target retention policy before the CQ. A reported 2024 issue (on v1.2.0) showed a CQ pointing at a missing retention policy stopping ts-sql; I did not check whether it is fixed in the current release, so create targets first and test on your version.

Prometheus remote write and PromQL

remote_write:
  - url: "http://127.0.0.1:8086/api/v1/prom/write?db=prometheus"
remote_read:
  - url: "http://127.0.0.1:8086/api/v1/prom/read?db=prometheus"

Create the database first. PromQL queries (instant and range, label and series metadata) have been supported since v1.3.0. The docs ask you to read and write through the same API family: data written with /api/v1/prom/write is read with /api/v1/prom/read or /api/v1/query.

Send data from Vector

Vector’s influxdb_logs sink emits line protocol, so pointing its endpoint at ts-sql on 8086 with database: telemetry is the intended path. This was not tested in the Vector brief or here, and the sprint’s final project (Part 2) must verify it, including how the sink maps event fields to tags and fields.

Features

Feature What it gives you
InfluxDB v1 compatibility Line protocol, InfluxQL and existing client libraries and agents work with little or no change
Prometheus remote read/write and PromQL Use it as long-term storage for Prometheus, or query with PromQL
Distributed MPP layout Scale query nodes and storage nodes independently
LSM storage with columnar compression Append-heavy writes and compressed storage; the project claims large compression ratios
High-cardinality engine A separate storage engine for very large series counts, with its own feature limits (for example, it does not support Prometheus remote read/write)
Retention policies and table-level TTL Whole-shard expiry
Multi-level downsampling and continuous queries Keep detail short term and aggregates long term
Subscriptions Forward writes to other HTTP endpoints
Data replication Added in the v1.3 line; read the replication section of the docs for the exact guarantees and limits
Monitoring Built-in metrics and ts-monitor; metrics can be written into an _internal database
Stream computing and anomaly detection Optional analysis features described in the docs; check maturity before relying on them

The documentation claims large performance gains over InfluxDB for some queries. Treat vendor benchmarks as a starting point and measure your own workload.

Production reference design

This is a design suggestion for AWS, not an official reference architecture, and I have not deployed it.

Layer Suggestion
ts-meta Three small EC2 instances in three Availability Zones, each with its own gp3 volume for the metadata directory
ts-store Two or more instances sized for memory and IOPS, local NVMe or gp3 EBS for store-data-dir, and a separate volume for the write-ahead log directory
ts-sql Two or more stateless instances behind a Network Load Balancer on port 8086, scaled on CPU
Network Private subnets, security groups that allow 8086 only from known clients and the meta and store ports only between cluster nodes
Placement Use stable host names (a private Route 53 zone) for meta-join, so instance replacement does not break discovery
Backups EBS snapshots of the data volumes, and a tested restore; copy snapshots to another Region if required
Sizing Start from your points per second and series count, then load test; do not size from the headline claims

Security

Treat the defaults as a lab setup.

Control Detail
Authentication auth-enabled = false by default. Create an administrator account first, then enable it in the [http] section and restart. Passwords must be 8 to 256 characters with mixed character classes, and a weak-password list is checked
TLS https-enabled = false by default. Set https-enabled, https-certificate and https-private-key in [http]; a [tls] section can set the minimum version (the docs suggest TLS 1.2) and ciphers
Authorisation Per-database READ, WRITE or ALL privileges for ordinary users; admin users for the rest
Credentials in URLs Prometheus examples put u= and p= in the URL. Prefer Basic auth over TLS and keep secrets out of logs
Column and record write paths Separate flags (flight-auth-enabled, [record-write] with its own TLS and mutual TLS) that are also off by default
Network Keep 8086 off the internet; put a load balancer or private link in front, and restrict the internal ports
Subscriptions Basic auth in the destination URL is supported; avoid sending data to unauthenticated endpoints

I did not find a published security audit for openGemini in the sources I read.

Monitoring and day-2 operations

Task How
Health and metrics Enable the [monitor] section to write node metrics into _internal, and run ts-monitor for disk, process and error-log reports; the docs list more than 260 metrics
Capacity Watch disk, memory and compaction; set max-concurrent-write-limit and max-concurrent-query-limit to protect nodes
Scale out Add ts-sql nodes freely; add ts-store nodes and check how shards rebalance on your version
Upgrades Read release notes first; upgrade ts-meta, then stores, then SQL nodes, and test on a copy
Retention and downsampling Review SHOW RETENTION POLICIES and CQs; the retention and downsample services check on a timer (30 minutes by default)
Debug /debug/ctrl endpoints control compaction, snapshots and flushing; use them carefully
Symptom First checks
Writes slow or rejected Batch size, concurrent write limit, store disk latency and compaction backlog
Queries slow Time range, tag filters, series cardinality, shard duration, result cache settings
Node does not rejoin meta-join addresses, host name resolution, firewall between nodes
Disk growing Retention duration, a DURATION 0s policy, failed or missing downsampling
ts-sql exits on a CQ Missing target retention policy; check logs

Usage cases

  • Device and sensor telemetry. Store high-frequency readings tagged by device and site, query by time window, and keep raw data short and aggregates long.
  • Infrastructure monitoring. Use it as remote storage for Prometheus, or as the backend for InfluxDB-style agents.
  • Long-term metrics. Offload Prometheus history so a local Prometheus can stay small.
  • Industrial and vehicle data. The project’s adopters list names IIoT and smart-energy scenarios.
  • Cold-chain sprint project. The Sprint 5 final project keeps a time-series history of every reading in openGemini, queried alongside alerts.

Operational considerations

  • Docs age. Several documentation pages I read show page ages of about 1,000 days; defaults and syntax may have moved. Read the docs that match your release and the config/openGemini.conf in that tag.
  • Dependencies. No external coordination service is needed; metadata uses its own ts-meta group.
  • Replication. Some older doc pages say replication supports only a factor of 1. Replication was added in v1.3; verify current behaviour before promising durability.
  • Series design. Keep tags low-cardinality unless you adopt the high-cardinality engine, and know its feature differences.
  • Query surface. InfluxQL compatibility is for the v1 language; do not expect Flux or InfluxDB 2.x and 3.x APIs.
  • Time source. Points carry client timestamps; keep devices on reliable time and decide how to handle late data.
  • Single-node paths. Move data and logs off /tmp.

Adoption

The project’s own ADOPTERS.md lists seven entries: Huawei Cloud Eye Service, Huawei Cloud IIoT, Huawei Cloud CloudScope, Yinhehangtian, Databuff, Yunnan Yuntianhua and Kehua, across cloud-service monitoring, IT operations monitoring and industrial use. Most are Huawei or China-based. A Huawei Cloud Developer Alliance article on a community live session reports about 25 production clusters inside Huawei Cloud, the largest at 70 nodes handling 20 TB a day; it is vendor-reported and I could not verify it independently. I found no public adopter list outside that region.

Alternatives

Solution Model Best suited to
InfluxDB (v1, 2.x, 3) Time-series database The reference for line protocol and InfluxQL; check licensing of the edition you need
TimescaleDB PostgreSQL extension SQL and joins with relational data
Prometheus with Thanos or Mimir Pull-based metrics with long-term storage Pure metrics, PromQL-first teams
VictoriaMetrics Time-series database Prometheus-compatible, simple operation
Apache Druid or ClickHouse Analytical column stores Large-scale analytics over events
Amazon Timestream Managed service Teams that want no database operations on AWS (check current availability and pricing)

Strengths and limitations

Strengths Limitations
InfluxDB v1 and Prometheus compatibility eases migration Sandbox project with all listed maintainers from one company
Stateless SQL layer and separate storage layer Documentation pages are old and partly Chinese-only
Retention, downsampling and subscriptions built in Small public adopter list, mostly in one region
Single binary for small installs, gemix for clusters Authentication and TLS off by default
Active development on main Release candidates and no recent stable since January; track the next release
High-cardinality engine for very large series counts That engine has feature limits (no Prometheus remote read/write)

Project status and roadmap

openGemini is a CNCF Sandbox project (accepted July 9, 2024). On November 5, 2026 the main branch still received commits (CI, dependency and test changes, a Go 1.26 upgrade and the move of the CLI to its own repository). Stable tags are v1.5.0, v1.5.1 and v1.5.2, with v1.5.3 at release candidate 5. Third-party mirrors report roughly 1,200 GitHub stars; I could not confirm the current count from GitHub itself. The repository’s ROADMAP.md lists shipped features through v1.4.1 (IP index, PromQL, record write protocol). I did not rely on any unlisted future plans.

Recommendation

Assess for a first project, Trial if you want an InfluxDB-compatible store that scales out and you can live with Sandbox maturity. openGemini fits a pipeline that writes sensor or metric data through line protocol and queries it with InfluxQL or PromQL. Start with a single ts-server, load representative data through the HTTP API, then build a three-meta cluster, turn on authentication and TLS, and test failure and restore before trusting it. Read the documentation for your exact version.

References: openGemini documentation · openGemini repository · Cluster architecture · Install and deployment · Line protocol insert · Prometheus remote read/write · Use PromQL · Retention policy · Continuous queries · User management · Use HTTPS · CNCF project page

Spotted something wrong or out of date?Suggest a correction. I review every suggestion before changing the page.