Size a Deployment¶
A workflow for turning a dataset shape and workload into an index shortlist and a resource estimate. For index tuning and general performance questions, refer to the Performance FAQ. For build/search parameters and schema construction, refer to Use Indexes.
Run this interactively
The sizing skill in KDB.AI Skills for Claude Code and Codex works through this same workflow and bundles an estimator script that computes the RAM, disk, and VRAM figures from your own rows, dimensions, and index choice.
Index choice, update pattern, filters, concurrency, and search requirements all change how much RAM, disk, VRAM, and CPU the same dataset needs. Rows and dimensions alone size a raw-vector footprint, nothing more.
Work through this order:
- Establish the workload.
- Shortlist two or three viable index configurations, CPU or GPU, rather than picking one from row count alone.
- Estimate RAM, disk, and VRAM for each option.
- Decide whether to partition the table.
- Validate the shortlist with a focused proof of concept before procurement.
Establish the workload¶
The two inputs you need for a numerical estimate are row count (or total data size, if you track bytes instead) and embedding dimensions. Everything else refines the shortlist:
- Row count or data size. Use the current row count, or
table.info()for an existing table. If you only track a data volume (a total size, or a size-per-day and a retention window), convert it to rows using the vector column size (dims × bytes per value). This is an upper bound unless you know the actual per-row metadata size. - Embedding dimensions. From the index's
dims, the embedding model documentation, or the length of one vector. - Search type. Exact recall, high-recall approximate, or compression-first. Range/radius search needs
qFlat; other indexes serve top-N search. - Update pattern. One-time/batch load versus streaming inserts, updates, and deletes. This decides whether CAGRA is viable, covered below.
- Vector column type.
float32sunless you know the column isfloat64s.qFlatandqHnswrequirefloat32sand rejectfloat64s. Flat, HNSW, IVF, IVF-PQ, and CAGRA accept both. - Concurrency and deployment. Expected simultaneous searches, available CPU cores or GPU, and whether the ingestion client and KDB.AI server are co-located. Refer to Size CPU cores and workers below for the license implications of
NUM_WRK.
Index shortlist¶
Row count is a starting point, not the whole answer. Cross-check against Use Indexes for the full comparison.
| Rows | Start with (CPU) | Consider CAGRA (GPU) when | Change when |
|---|---|---|---|
| 0–100K | flat or qFlat |
Rarely worth it at this scale | Use hnsw when query latency or volume makes exhaustive search unsuitable |
| 100K–1M | hnsw; qHnsw when RAM is constrained |
Batched or high-concurrency top-N search and a GPU is already available | Use flat only when exact recall is required and measured latency is acceptable |
| 1M–10M | qHnsw or ivfpq |
Mostly static data with batched queries, and GPU throughput beyond CPU HNSW is needed | Prefer qHnsw for update-friendly graph search; prefer IVF-PQ when compression is the priority |
| 10M+ | qHnsw or ivfpq |
Same as above, once CPU HNSW throughput is the limiter | Choose by update pattern, recall, compression, and measured latency |
Row count doesn't gate CAGRA, and neither does simply owning a GPU. What matters is whether the workload has the shape CAGRA needs: mostly static data, batched or sufficiently concurrent top-N search, a supported GPU (Ampere or newer), and enough single-card VRAM for the index, search workspace, and a measured build peak. Frequent updates or deletes can make CAGRA's rebuild cost unacceptable, and that rules it out regardless of scale. Refer to Nvidia cuVS/CAGRA integration.
Estimate RAM, disk, and VRAM¶
These figures can shift across KDB.AI/cuVS versions, so validate them against a representative proof of concept before procurement.
- Raw vector footprint: four bytes per value for a stored
float32scolumn, eight forfloat64s(excludes metadata). Refer to vector column type support for how this interacts with each index's internal representation. - Fixed index RAM is a per-worker figure, and what counts toward it varies by index. For Flat, HNSW, and IVF, it's the full index vectors plus a structure on top (a graph for HNSW, centroids for IVF). qHNSW only carries index vectors at
mmapLevel=0; at the default level 1 and at level 2 it's graph-only, no vector copy. IVF-PQ never carries full vectors at all, only its compressed codes, centroids, and PQ codebook. qFlat has no fixed RAM floor. Whatever the figure comes out to, multiply it by the number of activeNUM_WRKworkers, since each can load its own copy of the resident index state. - On-disk indexes still use RAM under load. The low fixed floor quoted for
qFlat/qHnswis a minimum, and actual usage typically runs above it. Refer to the on-disk memory note in the Performance FAQ, and measure settled memory after representative queries. - Persisted disk is the raw vector column plus the index structure. Refer to vector storage per index for which indexes duplicate vectors into a separate index file versus store a compressed representation. Excludes metadata, filesystem overhead, replicas, and backups.
- CAGRA index VRAM is the resident index payload.
nvidia-smireports more than that figure, so add CUDA/cuVS runtime and search-workspace overhead (roughly 1.8× the index vectors is a documented starting point). Leave headroom for build peak too; it runs higher than steady state, and depends on insert batch size. - Client and server RAM are separate, unless co-located. Refer to the client/server memory Q&A in the Performance FAQ.
Validate any estimate with table.info() for actual rows and persisted size, and session.process_info() / session.system_info() for worker memory and system headroom.
Partitioning¶
Partitioning is a table-layout choice you make with partition_column at create_table. It's orthogonal to index choice, so a partitioned table still carries one of the shortlisted indexes. Don't partition by default or purely because the dataset is large. Raise it when the workload shows a natural filter key, the chosen index's full-volume footprint strains resources, or you need retention/archival.
- Index compatibility is a hard constraint. Partitioning supports only Flat, qFlat, HNSW, qHNSW, sparse, and TSS indexes. A partitioned table can't carry IVF, IVF-PQ, or CAGRA. If the workload needs IVF-PQ compression or CAGRA GPU search, size it as a single non-partitioned table instead.
- Pruning only pays off when the partition column is in the query filter. If queries don't filter on it, every query scans every partition, and partitioning adds cost without benefit.
- Partitioning is per table. Each table sets its own
partition_columnindependently. There's no shared database-wide partition domain to reconcile across tables. - Size RAM and disk differently for a partitioned table. Only the partitions a query selects load into memory (resident indexes per partition, mmap indexes the same way), so run the RAM estimate at the row count of the window a query actually touches. Disk still has to cover the full retained row count. For multi-year data those two numbers can differ by orders of magnitude.
Size CPU cores and workers¶
Resolve NUM_WRK and THREADS from expected active work, not from rows and dimensions. Refer to Parallel Processing for how the two interact.
Multi-worker bands below need a commercial license
The free KDB-X Community Edition license runs a single worker only (plus a 24-core, 16-qIPC-connection cap).
| Workload | KDB.AI CPU starting point | Initial configuration |
|---|---|---|
| Evaluation, development, or serial queries | 4 cores | NUM_WRK=1, THREADS=4 |
| Light production with 1–2 active searches | 8 cores | NUM_WRK=1–2, normally THREADS=4 |
| Moderate production with 3–4 active searches | 16 cores | NUM_WRK=2–4, normally THREADS=4 |
| Higher concurrency with roughly 5–8 active searches | 24 cores | NUM_WRK=4–8; start with THREADS=2–4 within core and RAM limits |
| Heavy ingestion into one table | 8–16 cores | NUM_WRK=1 (extra workers don't parallelize inserts into a single table); compare THREADS=4 and 8 |
| Parallel ingestion into different tables | ~4 cores per active stream | Add workers for independently active tables within core and RAM limits |
Validate these bands before applying them:
NUM_WRK × THREADSshould stay within your licensed or allocated core count, but treat that number as a ceiling on contention rather than something to reach for its own sake. Throughput can plateau or regress past a certain point for a given index and machine, so raise either value incrementally and measure as you go.- More workers multiply fixed index RAM, and only genuinely concurrent requests exercise more than one worker. Refer to Parallel Processing for both.
- Prefer qIPC over REST for throughput-sensitive deployments: REST serializes and deserializes every payload, and qIPC doesn't.
Size GPU VRAM for CAGRA¶
CAGRA VRAM works the same way: figures here are a starting point, and the real number comes from measuring your own workload. The VRAM planning table gives index-payload and build-peak figures for 1M, 10M, and 100M vector datasets, plus the build-algorithm trade-off (IVF_PQ versus nn_descent) behind them.
A CAGRA index must fit on a single GPU. Confirm the card's architecture (Ampere or newer) and VRAM headroom before committing to it as an option.
Validate before procurement¶
Build the shortlisted configurations on a representative sample with realistic filters, concurrency, and ingestion pattern before committing to hardware. Compare at least the nearest smaller and larger worker/thread split, and repeat performance measurements at least three times. One run can mislead you either way.
For operational configuration, refer to the Performance FAQ and Server Setup FAQ.