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.
- The one-line frame
- vs. Elasticsearch / OpenSearch
- vs. Trino / Spark full-text on Iceberg
- When GrowlerDB is a good fit
- 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
_sourcewins on raw latency there. - You need a write/ingest API into the search engine itself. GrowlerDB ingests from the Iceberg
changelog, not a
_bulkendpoint. - 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.