1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# infino default configuration.
#
# This file is compiled into the binary via include_str! and acts as
# the floor of the config stack. Override at runtime via (in order of
# increasing precedence):
#
# 1. /etc/infino/config.yaml (system-wide)
# 2. $XDG_CONFIG_HOME/infino/config.yaml (user; falls back to
# $HOME/.config/infino/...)
# 3. ./infino.yaml (per-project / per-cwd)
#
# Each layer is a partial override — keys not set in a higher layer
# fall through to lower layers.
#
# Environment variables never override this configuration: engine
# behavior is set in YAML only, so a run's effective config is
# readable from files instead of reconstructed from process env.
# Supertable runtime knobs. Reader fan-out (skip + per-superfile
# search + top-k merge) and writer commit-time rayon-shard run on
# separate pools so a long-running commit can't spike reader p99 or
# vice versa.
#
# Thread-count values:
# - `auto` — resolves at runtime to num_cpus for reader_threads
# and max(1, num_cpus / 2) for writer_threads. Hardware-portable
# default; the same shipped config works on a 4-core dev laptop
# and a 96-core production node.
# - a positive integer — explicit override. Use when you've
# measured a workload-specific tuning.
supertable:
reader_threads: auto
writer_threads: auto
# Name of the system-managed primary-key column the supertable
# injects on every append(). The column type is fixed by the
# supertable layer; only the name is configurable. Leading
# underscore signals a system-owned field. Change this if
# `_id` collides with a business field name; otherwise leave
# as default.
id_column: _id
# Threshold above which the supertable's writer triggers an
# internal commit() to flush the in-memory buffer to disk-
# equivalent (one superfile per writer-pool thread). Specified
# in mebibytes (1 MiB = 1024 × 1024 bytes). Set 0 to disable
# auto-flush — only caller-driven commit() will produce
# superfiles.
commit_threshold_size_mb: 1024
# Verify the trailing whole-blob CRC and per-subsection CRCs
# on every SuperfileReader::open. Defaults to true. Set to
# false only when the underlying storage already validates
# checksums (content-addressed object store, ZFS, etc.) —
# skipping the scan trades that storage-layer guarantee for
# faster cold opens.
verify_crc_on_open: true
# Persistent storage wiring. Defaults to in-memory-only. Set
# `backend: s3` plus `bucket` / `prefix` to make
# SupertableOptions::apply_config attach an S3StorageProvider.
# `backend: azure` attaches an AzureStorageProvider, with `bucket`
# naming the Azure container. `backend: gcs` attaches a
# GcsStorageProvider, with `bucket` naming the GCS bucket and
# `storage_options` carrying `google_*` config keys.
storage:
backend: none
local_root:
bucket:
prefix: ""
# Object-store credentials and tuning, keyed by object_store's config
# strings. Infino reads no credentials from the environment — set them
# here (or via ConnectOptions). Empty → ambient cloud identity (IAM
# instance role / managed identity). Examples:
# backend: s3
# storage_options:
# aws_access_key_id: ...
# aws_secret_access_key: ...
# aws_region: us-east-1
# # aws_endpoint: http://localhost:9000 # MinIO / R2 / Ceph
# backend: azure # `bucket` names the container
# storage_options:
# azure_storage_account_name: ...
# azure_storage_account_key: ...
storage_options:
# When set, storage-backed reads use DiskCacheStore. For S3,
# lazy_foreground_with_background_fill is the object-store-native
# cold path: foreground opens/searches with exact range GETs (or zero
# superfile GETs at open when manifest open-batch bytes are present)
# while background fill promotes the full superfile to mmap.
disk_cache_root:
disk_budget_bytes: 10737418240
# Byte budget for the content-addressed manifest-part cache, held in a
# manifest-parts/ subdirectory of disk_cache_root. On a hit the part
# loader reads bytes from local disk instead of object storage; parts
# are content-addressed, so cached files are never stale and survive
# restarts. Independent of disk_budget_bytes. Default 2 GiB.
manifest_disk_budget_bytes: 2147483648
cold_fetch_mode: lazy_foreground_with_background_fill
cold_fetch_streams: 8
cold_fetch_chunk_bytes: 4194304
mmap_cold_threshold_secs: 300
mmap_sweep_interval_secs: 75
# Compaction merges the small superfiles produced by individual
# commits into one target-sized superfile, cutting query fan-out.
# Sizes are in mb (1 MiB = 1024 × 1024 bytes).
compaction:
# Size a compacted output aims for.
target_superfile_size_mb: 1024
# Minimum estimated live bytes to trigger a merge,
# as a percentage of `target_superfile_size_mb`.
# E.g. at 80% with a 1 GiB target, two 200 MiB superfiles (400 MiB) do not compact.
min_fill_percent: 80
# Maximum memory budget for materializing inputs during a single merge, in MiB.
max_memory_mb: 3072
# Vector-index build / search / drain tuning. Every value below
# defaults to the engine's built-in behavior — a fresh install never
# needs to touch this section. These are the levers that used to be
# one-off INFINO_* env vars; they are YAML-only now.
vector:
# Default rerank codec for cosine vector columns. Non-cosine metrics
# still use locally fitted sq8_residual (values are not bounded to
# [-1, 1]). Override per column at table-create time when needed.
# sq8_fixed_residual — fixed absolute grid (default; portable bytes)
# sq8_residual — per-cluster fitted quantizer
# fp32 — full-precision rerank
# rabitq_only — no rerank column
rerank_codec: sq8_fixed_residual
# Absolute cap on fine IVF centroids probed per vector search.
# Empty (~) derives the budget from nprobe × eligible superfiles at
# query time; set an integer to force exactly that many.
inner_budget: ~
# K-means training points per centroid for the drain's per-cell
# sub-builds.
kmeans_pts_per_centroid: 64
# Doc count above which a merged cell superfile is split into two
# sub-cells during hidden-index maintenance.
#
# Max docs in a global cell before compaction splits it into two. A cell this
# size serves fine on its own (bench: ~500K docs/cell → recall 0.994, ~17 MiB
# per query, since the per-cell fine IVF prunes within the cell), so the cap is
# set high to keep the grid coarse and split-free at ≤10M (at 64 cells, cells
# stay ~156K even at 10M). The split only engages at 100M/1B, where it bounds
# cell size so build/query cost stays flat; lower this if higher-scale recall
# needs a finer grid.
cell_split_doc_cap: 500000
# How user-superfile clusters align to the global cell grid:
# local — per-superfile k-means (default).
# global — cluster c == cell c, so the drain routes cluster → cell
# without re-scoring.
user_centroids: local
# User superfiles the hidden-index drain materializes per batch
# before publishing that batch's cell superfiles (bounds drain RAM
# to O(batch)). -1 = unbounded (one merge, O(corpus) RAM);
# 0 = skip the drain entirely.
drain_batch_superfiles: 64
# Target storage amplification for boundary-only replication (shared
# by commit and drain). <= 1.0 disables replication (the default).
# Replication was measured a net loss at 10M: its extra boundary copies
# inflated cell size (159K -> 232K rows/cell), which crowded the RaBitQ
# shortlist and displaced true neighbors before rerank — dropping
# post-drain recall 0.997 -> 0.975 while adding ~50% storage and ~35%
# more GETs/query. Grid+fine union routing carries boundary coverage
# instead. Raise above 1.0 only with evidence it helps at your scale.
drain_replica_target_factor: 1.0
# Per-cell consolidation op the drain applies:
# kmeans — re-cluster each cell's rows (default).
# splice — keep each superfile's local clusters verbatim.
drain_consolidate: kmeans
# Read fan-out for the drain's superfile opens. `auto` resolves to
# one in-flight read per hardware thread, floored at the
# background-fill default and capped at 64; or set a positive
# integer.
drain_read_concurrency: auto
# Cell count for the USER table's grid, trained at the first commit —
# controls user-superfile cell packing and pre-drain query routing. Finer
# than the hidden grid on purpose: smaller cells make the single pre-drain
# probe more precise and cheaper. Stamped at create; changing it later
# affects new tables only.
user_cell_count: 256
# Cell count for the HIDDEN vector index grid, trained at the same first
# commit. The drain reads this grid verbatim; post-drain routing runs at
# this granularity. Equal to user_cell_count: one 256-cell grid drives
# packing, pre-drain routing, the drain, and post-drain routing (user_grid
# degenerates to None when the counts match).
hidden_cell_count: 256
# Hidden vector-index compaction (distinct from the top-level
# `compaction:` section, which governs the user table). A packed cell
# shard stays a merge candidate until it reaches compaction_target_mb,
# so incremental deltas are absorbed into it instead of being sealed
# off as separate fragments. compaction_max_memory_mb caps the input
# bytes packed into one merge pass and must stay >= the target, or the
# target is never reached.
#
# 0 disables the byte floor, so a cell consolidates on fragment count alone
# (the >= 2 merge floor): drain generations collapse and post-compact cold
# GET stays at the post-drain level. This is safe now that the post-compaction
# cell split is disabled (see cell_split_doc_cap) — merging no longer triggers
# the broken split path. Contrast the user table, which keeps an 80% floor to
# amortize writes on its transient data.
compaction_target_mb: 2048
compaction_min_fill_percent: 0
compaction_max_memory_mb: 4096
# Diagnostic and hardware-capability toggles. Each gates
# instrumentation or forces a slower code path for A/B measurement;
# none of them change query results. Leave everything off unless you
# are profiling or benchmarking.
diagnostics:
# Accumulate per-phase timers during the vector drain build.
drain_build_timers: false
# Emit the FTS builder's finish-phase profile.
fts_profile: false
# Capture the object-store I/O timeline.
io_timeline: false
# Force the AVX2 vector-distance path even where AVX-512 is available.
disable_avx512: false
# Force the scalar vector-distance path even where AVX2 is available.
disable_avx2: false
# Skip the disk cache's lazy background fill so foreground-only read
# behavior can be measured.
disable_background_fill: false
# Per-connection memory budget: a ceiling on the anonymous heap the query
# and ingest paths allocate (result batches, the vector shortlist, ingest
# buffers), so one connection can't grow memory until the process is OOM-
# killed. The memory-mapped superfiles and the disk cache are bounded
# separately; this bounds heap only.
#
# Applies to connections built from this config file. Code that opens a
# connection programmatically sets the budget on ConnectOptions
# (with_connection_memory_budget_bytes) instead.
memory:
# Bytes. 0 (default) is measure-only: usage is tracked but never refused.
# A positive value enforces the ceiling (the engine reserves at 90% of it,
# leaving headroom for small untracked allocations).
connection_budget_bytes: 0