← Back to blog
Xinchuang 4 min read 炬鲸团队

Migrating from Elasticsearch to a Domestic Observability Stack: A Checklist

Replacing ELK in a Xinchuang environment is more than reinstalling software. This post covers inventory before migration, query compatibility, three data migration paths, and benchmark numbers on Kylin OS + Kunpeng.

Know your inventory before you move

Before touching anything, answer three questions: how much log data you hold, how it is sharded, and which DSL syntax the query side actually relies on. These three determine your migration window and compatibility effort, and getting them wrong is the most common way a migration slips.

Spend a week exporting a query audit first: pull every slow query run in Kibana and every query referenced by an alert, then group them by syntax feature. You will find that only aggregation, range filters, and field-existence checks are truly load-bearing—the fancy syntax barely gets used once a year. That list is the boundary of your rewrite work, and it is usually far smaller than anyone expects.

Query compatibility and rewriting

Domestic stacks generally do not support Lucene query syntax, but most ship a SQL-like or LogQL-like search language. Rewriting falls into three buckets:

  1. Exact match: term maps directly to field = "value".
  2. Range and aggregation: range and date_histogram map to field BETWEEN ... and time-bucket aggregation.
  3. Full-text: narrow match down to structured field queries, keeping fuzzy matching only where it is truly necessary.

Build a comparison table of twenty or so high-frequency queries, translate each one, and run them in a test environment until result counts and latency match. The query side is where silent behavior changes hide, so this step alone cuts migration risk in half. A useful trick is to keep the original query next to the rewritten one in a shared doc for the first month, so anyone triaging an incident can see the mapping without opening a ticket.

Three ways to move the data

Option one, dual-write cutover. New logs go straight to the new stack; you migrate only the last 30 days of history and leave cold data in the old cluster for on-demand queries. Best for steady volume and low dependence on history.

Option two, offline import. Dump ES indices by day into Parquet, then bulk-load into the new stack. Suits a one-shot move where a short read-only window is acceptable—import is controllable and re-runnable, which matters when a batch fails at hour forty.

Option three, on-demand backfill. Migrate only the last 7 days day-to-day; when an old incident surfaces, trigger a backfill task for that specific window. Cheapest on storage, but historical queries wait on backfill first, so it trades latency for cost.

Dual-run validation and benchmark numbers

Do not retire the old cluster right after cutover—keep it for a week of dual-run. Execute the same set of queries on both ends and compare result counts and Top-N distributions; only tear the old stack down once they agree.

On the performance side, on Kylin V10 SP3 with a Kunpeng 920 (64 cores / 256 GB), we benchmarked the same 1-billion-record, ~3.2 TB log set: sustained single-node ingest peaked at 80,000 events/s, and common aggregation queries finished with P99 under 1.8 s. Using a native ARM image instead of an x86 translation runtime added another ~25% ingest throughput.

Two tuning points make the difference. Shard indices by day and split hot/cold tiers so hot data sits on SSD; on the OS side, enable THP and raise the file-descriptor limit to avoid jitter during large index merges. After migration, disk usage ran about 60% of the original ES footprint, thanks largely to tighter field encoding. End to end, a two-week window is realistic, with data movement taking the lion's share—plan around it.

On the team side, split the work into three parallel tracks: one owns the query rewrite table, one owns data movement, and one owns dashboards and alerts on the new stack. They converge at the dual-run checkpoint, the only place where a discrepancy shows up as either a platform issue or a rewrite mistake. Resist the temptation to redesign dashboards during migration—port them as-is first, then improve. Otherwise you will never know whether a difference comes from the new stack or from your own redesign. And keep the old cluster's read path alive for a full retention cycle, because the cold data you decided not to migrate is exactly what someone will need the week after you retire it.