Comparison & positioning

Where GrowlerDB fits, and where it doesn’t, next to the tools you’re probably already running. For the numbers behind the claims here, see Performance; for the mechanics of moving over, see Migrating from Elasticsearch/OpenSearch.

  1. The one-line frame
  2. vs. Elasticsearch / OpenSearch
  3. vs. Trino / Spark full-text on Iceberg
  4. When GrowlerDB is a good fit
  5. When to reach for something else (today)

The one-line frame

GrowlerDB is a derived retrieval index (full-text, vector, and hybrid) over your data, Apache Iceberg today. Your source stays the system of record; a search returns document keys that hydrate back to the authoritative rows. That single design choice, to not own a second copy of the data, is what separates it from both search engines and query engines.

vs. Elasticsearch / OpenSearch

  Elasticsearch / OpenSearch GrowlerDB
System of record the engine’s own _source (a second copy) Apache Iceberg (your lake)
A search returns full documents document keys + score, hydrate on demand
Ingestion _bulk / index API you operate a changelog connector tracks the source table
Staying in sync your job (dual-writes, reindex) derived from the Iceberg changelog
Governance search-time copy, separately secured hydration returns the catalog-governed live row
Rebuild / re-shard reindex the world drop and rebuild the derived index from source

Choose GrowlerDB when your data already lives in (or can land in) Iceberg and you don’t want a parallel datastore to provision, secure, and keep from drifting. That fits logs, telemetry, and event/time-series data especially well, where the lake is already the archive of record.

Elasticsearch/OpenSearch is the better fit when you need capabilities GrowlerDB doesn’t ship yet: sub-10 ms authoritative single-document retrieval (ES serves _source from its own store, while GrowlerDB pays an Iceberg hydration round-trip; cache display fields to close the gap for the display case), a write API (GrowlerDB ingests from the changelog, not _bulk), or the full breadth of the aggregation, scripting, and ingest-pipeline surface. GrowlerDB’s OpenSearch _search adapter covers a documented read-path subset and returns 501 on anything unsupported, so you never get a silent wrong answer.

Ingesting from Iceberg. Both engines can index an Iceberg table, but by different paths. GrowlerDB’s ingestion is a streaming changelog connector purpose-built for Iceberg: it follows the table’s commit stream to keep the derived index in sync, with no second write path to operate. OpenSearch has no native Iceberg ingest: you either dual-write via _bulk (a separate pipeline to build and keep from drifting) or bridge the table through Data Prepper’s Iceberg CDC source, which is experimental and copy-on-write-only and polls snapshots on an interval. So for data that already lives in Iceberg, GrowlerDB stays in sync natively where OpenSearch needs an extra, less-mature moving part.

vs. Trino / Spark full-text on Iceberg

You can already run LIKE/regexp or a full-text UDF over an Iceberg table with Trino or Spark. The difference is scan versus index:

  Trino / Spark on Iceberg GrowlerDB
How a text query runs scans the table (grows with rows) inverted-index lookup (flat in dataset size)
Typical filtered-search latency grows with the table size milliseconds, flat in dataset size
Ranking none / bolt-on BM25 relevance, per-hit explain
Returning rows reads columns during the scan hydrates only the K matching rows by key
Same source of truth Yes, the Iceberg table Yes, the same Iceberg table

Both read the same Iceberg table, but GrowlerDB adds a search index, so filtered search resolves through an index lookup instead of a column scan. The lookup stays flat as the table grows while a scan grows with it. GrowlerDB doesn’t replace your query engine; it adds the search access path the query engine lacks. For authoritative full-row retrieval, GrowlerDB fetches only the matching rows by key rather than scanning the table. See Performance for the current numbers.

When GrowlerDB is a good fit

  • Your data is in (or can land in) Apache Iceberg, and you’d rather not run a separate search cluster that owns a second copy.
  • Logs, telemetry, events, and catalogs: text with filters, ranges, and time windows, where fast filtered search and cheap cold storage matter.
  • You want search results that resolve to the live, governed lakehouse row rather than a search-time snapshot.
  • You value operational honesty: rebuild-from-source recovery, an explicit compatibility subset, and no silent wrong answers.

When to reach for something else (today)

  • You need sub-10 ms authoritative single-document retrieval and can’t cache display fields; ES _source wins on raw latency there.
  • You need a write/ingest API into the search engine itself. GrowlerDB ingests from the Iceberg changelog, not a _bulk endpoint.
  • Your data isn’t in Apache Iceberg. Iceberg is the supported source; GrowlerDB’s whole model is a derived index over an authoritative source.

See Migrating from Elasticsearch/OpenSearch for the two integration paths (native API or the _search adapter) and a cutover checklist.


GrowlerDB — AGPL-3.0. Search returns coordinates; rows hydrate from Iceberg.

This site uses Just the Docs, a documentation theme for Jekyll.