Vector database
Enterprise h2oGPTe uses a vector database (the VEX service) to store document chunks and their embeddings for retrieval. VEX exposes a unified API and routes requests to a pluggable storage backend selected at deploy time.
Supported backends​
VEX separates vector storage (for similarity search) from fulltext storage (for lexical search). They are configured independently:
| Backend | Vector store (vex.config.vectorDb) | Fulltext store (vex.config.fulltextDb) | Notes |
|---|---|---|---|
| PostgreSQL | postgres (uses pgvector) | postgres | Default. Shared with the application database. Scales horizontally with vex replicas. |
| Embedded HNSW | hnsw (uses hnswlib) | sqlite (uses SQLite FTS5) | Legacy in-pod storage. Single-pod only — indexes live on the pod's PVC. Performance degrades around 10M–50M entries per collection. |
| Elasticsearch | elastic_search | elastic_search | External cluster, experimental. |
| Milvus | milvus | n/a (use postgres or sqlite) | External cluster, experimental. |
| Qdrant | qdrant | qdrant | External cluster, experimental. |
| Redis | redis | redis | Single instance or cluster mode, experimental. |
A separate index is created per Collection, so per-backend limits apply at the Collection level. Connection settings for external backends (host, credentials, TLS) are documented in vex/README.md and are passed through to the vex pods via vex.extraEnv in the Helm chart.
Please contact us if your preferred vector database is not listed above — additional backends can be added based on customer interest.
Choosing a backend​
- PostgreSQL (default) — recommended for most deployments. Uses the same database as the application, simplifies operations and backups, and lets you scale vex to multiple replicas. Requires the
pgvectorextension binaries to be present in the Postgres image; mux runsCREATE EXTENSIONautomatically on startup, but it will fail if the image does not shippgvector. - Embedded HNSW + SQLite — fastest option for small, single-node deployments. Limited to one vex pod; cannot be scaled horizontally because indexes live on the pod's local volume.
- External (Elasticsearch / Milvus / Qdrant / Redis) — for organizations that already operate one of these systems or need backend-specific features. Each vex pod becomes stateless; the external database is the source of truth.
Configuring vector encryption​
VEX protects a collection's on-disk data in two independent ways, both gated by enabled:
- Vector encryption — obfuscates or encrypts embeddings with a distance-preserving scheme (so similarity search still works), using the method chosen by
provider. - Fulltext encryption — encrypts fulltext
.lexfiles with SQLCipher. This applies automatically to new files wheneverenabled: true, regardless ofprovider.
Encryption is enabled at the vex service level; once enabled, each collection can opt in or out of vector encryption at creation time — see Encrypt vectors at rest.
vex:
encryption:
enabled: true
provider: "internal"
secret: ""
approximationFactor: "7.2"
tenantId: "default"
| Option | Meaning |
|---|---|
enabled | Master switch. When false, nothing is encrypted and the per-collection encryption toggle does not appear in the UI. When true, fulltext .lex files are SQLCipher-encrypted for new collections no matter what provider is set to — but provider must also be internal or ironcore to actually encrypt vectors. Leaving provider at its default ("", equivalent to noop) stores vectors in plaintext even with enabled: true. |
provider | internal (recommended) — built-in distance-preserving vector obfuscation via orthogonal rotation. This is obfuscation, not cryptographic encryption: it makes vectors unreadable without the key, but a sophisticated attacker with known plaintext could recover the rotation matrix. It relies on SQLCipher (which derives from the same secret and is enabled alongside it) for full encryption at rest. ironcore — IronCore Alloy vector encryption; requires switching the vex deployment to the separate, AGPL-licensed vex-ironcore image. noop, "" (default), or none — vectors are stored in plaintext; fulltext files are still SQLCipher-encrypted whenever enabled: true. |
secret | Hex-encoded 32-byte (64 hex character) secret used to derive both the vector-encryption and SQLCipher keys. Provide it via --set or an external secret — do not commit it to a values file. |
approximationFactor | ironcore only. Controls the security/search-accuracy tradeoff. |
tenantId | ironcore only. Tenant identifier used for key derivation. |
The internal provider is an obfuscation technique, not cryptographic encryption of the vectors themselves — treat it accordingly when assessing risk, and rely on SQLCipher (enabled alongside it) for the actual at-rest protection.
The ironcore provider is AGPL-licensed and ships as a separate container image. Confirm this is acceptable for your deployment's license policy before enabling it.
Existing collections keep their current format when this setting changes — they are not bulk-converted. Re-ingest a collection to change its encryption status.
Migrating between backends​
The blocking migration strategy copies all collections during a maintenance window before mux starts serving traffic.
Blocking migration (planned downtime)​
If your deployment uses a vector backend other than PostgreSQL, set mux.config.skipPgvectorInitScript to 0 before starting the migration. This lets mux create the vex schema and install the pgvector extension on startup. Without this setting, the migration fails with schema "vex" does not exist.
mux:
config:
skipPgvectorInitScript: 0
vexMigration:
enabled: true
sourceDb: "internal"
destinationDb: "postgres"
blocking: true
overrideExistingCollections: false
bulkSize: 1000
collectionTimeoutSeconds: 600
concurrency: 20
continueOnError: false
Mux halts startup until every collection is copied from sourceDb to destinationDb, then resumes serving traffic with vex pointed at the new backend. Use this when you can schedule a maintenance window.
| Option | Meaning |
|---|---|
skipPgvectorInitScript | Set to 0 to let mux create the vex schema and install the pgvector extension. Required when migrating to PostgreSQL from a backend that did not use pgvector. Lives under mux.config, not inside vexMigration. |
enabled | Master switch for the migration. When false, mux ignores every other field in this block. |
sourceDb | Backend collections are read from. Valid values: internal (hnsw+sqlite), postgres, milvus, elasticsearch, qdrant, redis. |
destinationDb | Backend collections are written to. Same valid values as sourceDb. Must match vex.config.vectorDb/fulltextDb. |
blocking | true halts mux startup until every collection is copied. |
overrideExistingCollections | If true, collections already present on the destination are dropped and re-copied. Leave false to skip them and resume an interrupted migration. |
bulkSize | Rows copied per batch within a single collection. Higher values increase throughput at the cost of memory. |
collectionTimeoutSeconds | Per-collection deadline. A collection that exceeds it is marked failed (or aborts the run depending on continueOnError). |
concurrency | Number of collections migrated in parallel. Bound by destination-backend write capacity. |
continueOnError | false aborts the whole migration on the first per-collection failure (recommended for blocking runs so issues surface immediately). true skips the failure and continues. |
A zero-downtime "live" migration mode (background copy while the deployment keeps serving traffic) is planned for an upcoming release. Configuration guidance will be published here once it's ready.
Monitoring migrations​
Admins can monitor migration progress from the VEX Migration page — see VEX Migration for details.
- Submit and view feedback for this page
- Send feedback about Enterprise h2oGPTe to cloud-feedback@h2o.ai