Reference
CLI reference
Every ysearch command, flag, and setting, generated from the binary's own manual at the pinned revision.
The manual describes the binary on ysearch main, which is still the search
engine inherited from yolosearch plus the ysearch groundwork landed so far.
The ysearch roles and verbs of the design are not in it yet; see
Status.
ysearch serves an index, reads and changes a running server's settings, shows its statistics, and builds and publishes the immutable segments it reads. The client verbs talk to --server; the server verbs read their settings from the configuration catalog (discovered files, the environment, flags); the offline verbs work on an object store directly.
The hand-written guide with walkthroughs is guide.md.
Every command accepts these. The catalog-backed ones have a key and an environment variable; a file may set the key too.
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--json |
bool | false |
client.json |
YSEARCH_CLIENT_JSON |
Emit JSON instead of tables. [client.json; env YSEARCH_CLIENT_JSON] |
--quiet |
bool | false |
client.quiet |
YSEARCH_CLIENT_QUIET |
Suppress progress output. [client.quiet; env YSEARCH_CLIENT_QUIET] |
--server |
string | 127.0.0.1:9500 |
client.server |
YSEARCH_CLIENT_SERVER |
Server address the client verbs dial. [client.server; env YSEARCH_CLIENT_SERVER] |
--timeout |
duration | 30s |
client.timeout |
YSEARCH_CLIENT_TIMEOUT |
Client request timeout. [client.timeout; env YSEARCH_CLIENT_TIMEOUT] (positive) |
--config-dir |
string | config.dir |
YSEARCH_CONFIG_DIR |
Directory whose *.yml and *.yaml files are layered in name order after the default locations and before config.file. [config.dir; env YSEARCH_CONFIG_DIR] | |
--config |
string | config.file |
YSEARCH_CONFIG_FILE |
YAML configuration file layered last among files. [config.file; env YSEARCH_CONFIG_FILE] | |
--config-search |
bool | true |
config.search |
YSEARCH_CONFIG_SEARCH |
Probe /etc/ysearch, $XDG_CONFIG_HOME/ysearch (default ~/.config/ysearch), and ./ysearch.yml at startup. [config.search; env YSEARCH_CONFIG_SEARCH] |
ysearch catalog— Resolve, publish, reconcile, or dry-run garbage collection of the catalog (offline)ysearch catalog compact— Physically merge active immutable segments and atomically replace themysearch catalog gc-dry-run— Propose unreferenced objects against explicit retention horizons; removes nothingysearch catalog publish— Announce a published segment (also converges the catalog on everything committed)ysearch catalog reconcile— Repair the catalog's lineage from the committed segments without announcing anything newysearch catalog resolve— Print the latest generation, or --generation, as the catalog records itysearch catalog startup-bundle— Build optional bounded startup metadata pages for an existing generationysearch config— Read and change a running server's settingsysearch config export— Resolve this process's own configuration offline and print it, or write it as a YAML fileysearch config get— Show one setting and where its value came fromysearch config list— List every setting with its value, scope, and sourceysearch config set— Override a node-runtime setting until unset or restartysearch config unset— Drop a runtime override; the file, environment, or flag value returnsysearch config watch— Print every matching setting, then one line per change, until interruptedysearch delete— Tombstone documents by keyysearch explain— Show the AST, digest, and lowered query for a Lucene or CQP queryysearch index— List and describe the indexes a server holdsysearch index describe— Describe one index and its current schemaysearch index list— List every index with its schema version and generationysearch manual— Print the complete reference (every command, flag, and setting) as Markdownysearch node— Run fleet roles: coordinator, worker, merger, aggregator, compactor, router, builderysearch push— Validate, convert, and stream JSON documents into an indexysearch routing— Build optional query routing artifacts from existing segments (offline)ysearch routing build— Build and publish exact presence routing for a catalog generationysearch schema— Apply and inspect an index's versioned schemaysearch schema apply— Apply a schema to an index (additive, auto-versioned)ysearch schema diff— Preview a schema change without applying itysearch schema history— List every version of an index's schemaysearch schema options— Print the annotation .proto a document schema importsysearch schema propose— Infer an editable schema and normalized JSONL from local documentsysearch schema show— Print one version of an index's schemaysearch search— Search an index with a Lucene or CQP queryysearch segment— Build and publish immutable segments (offline)ysearch segment build— Build one immutable segment from JSONL and write its checkpoint to the object directoryysearch segment publish— Publish a built segment commit-last and announce it to the catalogysearch serve— Run a single-process server: every index under an object root, or oneysearch sources— Read and change which datasets a server attaches read-onlyysearch sources add— Declare a new source, refusing to replace an existing oneysearch sources get— Show one declared source in fullysearch sources list— List every declared source with its stateysearch sources remove— Withdraw a source and drain its in-flight readsysearch sources replace— Replace an existing source's declarationysearch sources watch— Stream the registry: a snapshot, then every changeysearch stats— Show index, node, or fleet statisticsysearch version— Print the build identity (the same line as --version)
ysearch catalog [flags]Resolve, publish, reconcile, or dry-run garbage collection of the catalog (offline)
Subcommands:
ysearch catalog compact— Physically merge active immutable segments and atomically replace themysearch catalog gc-dry-run— Propose unreferenced objects against explicit retention horizons; removes nothingysearch catalog publish— Announce a published segment (also converges the catalog on everything committed)ysearch catalog reconcile— Repair the catalog's lineage from the committed segments without announcing anything newysearch catalog resolve— Print the latest generation, or --generation, as the catalog records itysearch catalog startup-bundle— Build optional bounded startup metadata pages for an existing generation
ysearch catalog compact [flags]Physically merge active immutable segments and atomically replace them
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--input-segments |
stringSlice | [] |
active segment IDs to merge (comma-separated or repeated; at least two) | ||
--job-id |
string | optional 32-hex idempotency key; generated when omitted | |||
--output-segment-id |
string | optional 32-hex output identity; generated when omitted | |||
--builder-version |
string | ysearch-compactor |
publisher identity recorded on the output | ||
--analysis-batch-documents |
int | 0 |
builder.analysis_batch_documents |
YSEARCH_BUILDER_ANALYSIS_BATCH_DOCUMENTS |
Documents handed to the analysis workers at once; zero derives sixteen per worker. A batch is the unit that must fit in builder.analysis_memory_bytes, so a larger batch amortises the hand-off over more documents but raises the peak the analysis share has to cover. The derived shape is what the resource gates measure, so a corpus of unusually large documents is the case for lowering it rather than raising the share. [builder.analysis_batch_documents; env YSEARCH_BUILDER_ANALYSIS_BATCH_DOCUMENTS] (in [0, 1048576]) |
--analysis-memory-bytes |
bytes | 0 |
builder.analysis_memory_bytes |
YSEARCH_BUILDER_ANALYSIS_MEMORY_BYTES |
The share of builder.sort_memory_bytes reserved for documents in flight through analysis; zero derives a thirty-second of it, clamped to between 64KiB and 32MiB and never more than a quarter of what the public-id and docvalue spools leave. It only has to hold one bounded batch, and a document larger than the whole share still runs alone under builder.max_document_working_bytes, so the derived value is deliberately small: a three-million-document run peaked at 9.5MiB against a 128MiB share. Every byte reserved here is a byte the term partitions cannot use, which raises mini-run count and write amplification directly, so raise it only against a measured analysis stall. [builder.analysis_memory_bytes; env YSEARCH_BUILDER_ANALYSIS_MEMORY_BYTES] |
--analysis-workers |
int | 0 |
builder.analysis_workers |
YSEARCH_BUILDER_ANALYSIS_WORKERS |
Goroutines tokenising documents inside one build; zero derives GOMAXPROCS, bounded at eight. Analysis is the one parallel stage of an otherwise serial build, so this is per build and multiplies with builder.build_concurrency: the bound exists because a dozen builds each spawning a worker per core oversubscribes the machine and the scheduler churn costs more than the parallelism returns. Output order is preserved regardless of this value. [builder.analysis_workers; env YSEARCH_BUILDER_ANALYSIS_WORKERS] (in [0, 1024]) |
--blob-dictionary |
bool | true |
builder.blob_dictionary |
YSEARCH_BUILDER_BLOB_DICTIONARY |
Compress stored values against a dictionary trained per blob file. Denser on homogeneous documents, but the dictionary is coded on the build's hottest path, so turning it off trades index size for ingest throughput. [builder.blob_dictionary; env YSEARCH_BUILDER_BLOB_DICTIONARY] |
--blob-zstd-level |
int | 0 |
builder.blob_zstd_level |
YSEARCH_BUILDER_BLOB_ZSTD_LEVEL |
Zstd effort for stored values; zero keeps the storage default (7). Levels select different zstd encoders, and a build re-seeds the chosen encoder from the blob dictionary for every value it writes, so a lower level cuts build cost by more than the usual level trade-off suggests. [builder.blob_zstd_level; env YSEARCH_BUILDER_BLOB_ZSTD_LEVEL] (in [0, 11]) |
--build-concurrency |
int | 0 |
builder.build_concurrency |
YSEARCH_BUILDER_BUILD_CONCURRENCY |
Sealed builds that may run through the seal pipeline at once; zero derives one per CPU, bounded at twelve. One build is a mostly single-threaded chain of analysis, sort, merge and publish that spends about half its time blocked in file system calls, so a single pipeline leaves a multi-core host idle under bulk ingest. The builder's memory is this number times builder.sort_memory_bytes. [builder.build_concurrency; env YSEARCH_BUILDER_BUILD_CONCURRENCY] (in [0, 256]) |
--builder-catalog-publication |
enum | direct |
builder.catalog_publication |
YSEARCH_BUILDER_CATALOG_PUBLICATION |
Catalog writer mode: direct is the single-node compatibility path; external stops after commit markers for a lease-fenced publisher role. [builder.catalog_publication; env YSEARCH_BUILDER_CATALOG_PUBLICATION] (one of direct, external) |
--dedupe-index-identities |
int | 0 |
builder.dedupe_index_identities |
YSEARCH_BUILDER_DEDUPE_INDEX_IDENTITIES |
Distinct document keys one open spool's dedupe index may hold before it gives up; zero derives 1048576. A key spooled twice in one build must resolve to a single winner before analysis, or the segment's dense ordinal assignment refuses the build outright. The index resolves that as records are spooled, from identities ingest already holds, and the sealed build inherits the answer; past this bound it gives up and the build reconstructs the answer by reading its spool twice instead — slower, and exactly as correct. One entry is a 16-byte key hash, a sequence and a mutation version, so the default bounds it at tens of megabytes per open spool and is reached only by a spool of a million very small documents. Lower it to cap that memory on a host running many indexes; set it to one to force the scanning path. [builder.dedupe_index_identities; env YSEARCH_BUILDER_DEDUPE_INDEX_IDENTITIES] (in [0, 268435456]) |
--builder-fuse-memory-bytes |
bytes | 0 |
builder.fuse_memory_bytes |
YSEARCH_BUILDER_FUSE_MEMORY_BYTES |
Optional binary fuse construction workspace during publication; zero retains Bloom, failed admission retains Bloom. [builder.fuse_memory_bytes; env YSEARCH_BUILDER_FUSE_MEMORY_BYTES] (in [0, 64MiB]) |
--lexical-blob-threshold |
bytes | 0 |
builder.lexical_blob_threshold |
YSEARCH_BUILDER_LEXICAL_BLOB_THRESHOLD |
Size at which a posting, position or term value is stored in a blob file rather than inline in the key log; zero keeps the default of 64KiB. Separation exists to spare compaction from rewriting large values, and a segment is never compacted — while a blob value is compressed on its own, which with a trained dictionary costs an encoder reset each time, where key-log blocks are compressed in bulk. [builder.lexical_blob_threshold; env YSEARCH_BUILDER_LEXICAL_BLOB_THRESHOLD] |
--lexical-block-compression |
string | builder.lexical_block_compression |
YSEARCH_BUILDER_LEXICAL_BLOCK_COMPRESSION |
Codec the term, posting and position families compress key-log blocks with: none, snappy, lz4, lz4fast or zstd. Empty keeps the default of lz4. The storage engine's own default leaves the newest level raw because it expects compaction to rewrite it, and a segment stays where it lands. On 300k articles lz4 measured 24.8s and 1.0GB against zstd's 37.7s and 0.8GB, so zstd is the choice for an index written once and read for a long time. [builder.lexical_block_compression; env YSEARCH_BUILDER_LEXICAL_BLOCK_COMPRESSION] | |
--max-document-working-bytes |
bytes | 0 |
builder.max_document_working_bytes |
YSEARCH_BUILDER_MAX_DOCUMENT_WORKING_BYTES |
What one document may use beyond the partition budget while it is being analyzed; zero derives 64MiB, or a quarter of builder.sort_memory_bytes when that is smaller. It is an allowance rather than a reservation: it exists so a single document larger than the whole partition budget still builds, alone, instead of failing the build. Only a corpus with documents in the hundreds of megabytes needs it raised. [builder.max_document_working_bytes; env YSEARCH_BUILDER_MAX_DOCUMENT_WORKING_BYTES] |
--max-queued-builds |
int | 0 |
builder.max_queued_builds |
YSEARCH_BUILDER_MAX_QUEUED_BUILDS |
Sealed builds that may wait for or run in the pipeline before ingest is throttled; zero derives it as four times builder.build_concurrency. A waiting build is a spool on disk, not memory, so this buys ingest room across a build at the cost of ingest.seal_bytes of disk per queued build. Set too low, a bulk load throttles the moment the pipeline is full and ingest runs at the speed of the builds rather than ahead of them. [builder.max_queued_builds; env YSEARCH_BUILDER_MAX_QUEUED_BUILDS] (in [0, 1024]) |
--max-token-bytes |
bytes | 64KiB |
builder.max_token_bytes |
YSEARCH_BUILDER_MAX_TOKEN_BYTES |
Maximum analyzed token size. A build must be able to admit one token this large, so raising it raises the floor under builder.sort_memory_bytes: a budget that leaves the partitions less than one maximum term refuses to start rather than fail partway. Tokens are words after analysis, so the default is already far past any natural language; raise it only for a corpus with genuinely enormous unbroken tokens. [builder.max_token_bytes; env YSEARCH_BUILDER_MAX_TOKEN_BYTES] (positive) |
--merge-fan-in |
int | 0 |
builder.merge_fan_in |
YSEARCH_BUILDER_MERGE_FAN_IN |
Spilled mini-runs merged in one pass; zero derives as many as an eighth of the partition budget affords at builder.run_page_bytes plus 512 bytes of reader overhead each, capped at sixty-four and floored at two. Runs beyond the fan-in need further passes, and each pass rewrites the data, so a low fan-in on a build that spilled heavily shows up as write amplification rather than as a slow merge. The cap is a file-descriptor and seek-pattern bound, not a memory one. [builder.merge_fan_in; env YSEARCH_BUILDER_MERGE_FAN_IN] (in [0, 64]) |
--builder-output-format-version |
int | 0 |
builder.output_format_version |
YSEARCH_BUILDER_OUTPUT_FORMAT_VERSION |
Segment format emitted by builders and compactors; zero selects this binary's current format. The Kubernetes operator pins this to compatibility.writeFormat on writer roles during staged rollouts. Format 7 adds the stats, forward and hashterms families (spec/40 §3); a compaction that includes an older input writes format 6 instead, unless 7 or 8 is set explicitly, which refuses such a merge. Format 8 adds the exact vector lanes (canonical fp16 vectors, IVF radii, int8 codes; spec/40 §3.2). [builder.output_format_version; env YSEARCH_BUILDER_OUTPUT_FORMAT_VERSION] (in [0, 8]) |
--builder-paged-posting-directory |
bool | false |
builder.paged_posting_directory |
YSEARCH_BUILDER_PAGED_POSTING_DIRECTORY |
Experimental commit-anchored posting-directory pages under query admission and the existing persistent block quota; old commits retain canonical traversal. [builder.paged_posting_directory; env YSEARCH_BUILDER_PAGED_POSTING_DIRECTORY] |
--builder-posting-partition-penalty |
float | 4 |
builder.posting_partition_penalty |
YSEARCH_BUILDER_POSTING_PARTITION_PENALTY |
Metadata cost penalty for experimental variable posting blocks. [builder.posting_partition_penalty; env YSEARCH_BUILDER_POSTING_PARTITION_PENALTY] (in [0, 1e+06]) |
--publish-verification |
string | checksum |
builder.publish_verification |
YSEARCH_BUILDER_PUBLISH_VERIFICATION |
How a published segment is confirmed: checksum, sample, or readback. checksum compares every object against the checksum the object store reported when it accepted the write — S3 computes that server-side and refuses a mismatched write, and the filesystem backend computes it over the bytes it synced — so nothing is transferred back. sample additionally opens the published copy through the store and queries it; readback additionally fetches every object and rehashes it, which costs the whole index again on every build. An object whose store reports no comparable checksum is read back in any mode. [builder.publish_verification; env YSEARCH_BUILDER_PUBLISH_VERIFICATION] |
--builder-routing-fragment-bytes |
bytes | 8MiB |
builder.routing_fragment_bytes |
YSEARCH_BUILDER_ROUTING_FRAGMENT_BYTES |
Optional routing fragment disk cap per built segment; zero disables, overflow keeps canonical scan fallback. Matches compaction.routing_fragment_bytes so a freshly ingested segment and a freshly compacted one carry a fragment the same way; the two stay separate keys because a background merge must be able to carry its own share independent of foreground ingestion. Only a segment built or compacted after this defaulted on carries a fragment: nothing rewrites an existing one, so a settled corpus stays without a routing table until it is backfilled or compacted. [builder.routing_fragment_bytes; env YSEARCH_BUILDER_ROUTING_FRAGMENT_BYTES] (in [0, 64MiB]) |
--run-page-bytes |
bytes | 0 |
builder.run_page_bytes |
YSEARCH_BUILDER_RUN_PAGE_BYTES |
Read-ahead page one spilled mini-run is buffered in during the final merge; zero derives 64KiB, shrinking it when an eighth of the partition budget cannot hold sixty-four such pages. The merge reserves one page per open run for the whole build, so page size and builder.merge_fan_in trade against each other out of the same share: the derivation prefers smaller pages to a fan-in that would force extra compaction passes on a hot partition. [builder.run_page_bytes; env YSEARCH_BUILDER_RUN_PAGE_BYTES] |
--sort-memory-bytes |
bytes | 256MiB |
builder.sort_memory_bytes |
YSEARCH_BUILDER_SORT_MEMORY_BYTES |
Total accounted builder budget: one ledger every part of a build charges against, and the setting the other builder budgets derive from. It divides into the public-id sorter (an eighth, capped at 64MiB), the docvalue and lane spools (their own worst case), the analysis share (builder.analysis_memory_bytes), and the term partitions, which take what is left. A build that cannot hold its partitions in that remainder spills to disk instead, which is the difference between one file per build and hundreds. This is per build, so the builder's memory is builder.build_concurrency times this. [builder.sort_memory_bytes; env YSEARCH_BUILDER_SORT_MEMORY_BYTES] (positive) |
--builder-spill-merge-strategy |
enum | heap |
builder.spill_merge_strategy |
YSEARCH_BUILDER_SPILL_MERGE_STRATEGY |
Experimental spill merge selector; heap preserves the baseline until full ingestion benchmarks qualify an alternative. [builder.spill_merge_strategy; env YSEARCH_BUILDER_SPILL_MERGE_STRATEGY] (one of heap, replace-root, loser-tree) |
--builder-startup-bundles |
bool | false |
builder.startup_bundles |
YSEARCH_BUILDER_STARTUP_BUNDLES |
Asynchronously produce optional startup bundles after catalog publication. One bounded coalescing worker per publishing host; oversized sources retain canonical startup fallback. [builder.startup_bundles; env YSEARCH_BUILDER_STARTUP_BUNDLES] |
--term-dictionary-block-size |
bytes | 64KiB |
builder.term_dictionary_block_size |
YSEARCH_BUILDER_TERM_DICTIONARY_BLOCK_SIZE |
Key-log data-block size of the term family. A table carries one block-index entry per data block and reads the whole index before it can look up anything, so this is what a cold term probe pays to find out where to look. At the storage engine's 4KiB an 8MiB dictionary needs about two thousand entries — around 65KiB read on every open of the table and held in memory until it closes — where 64KiB needs about a sixteenth of that. A probe then reads a bigger block, which over an object store is the cheap side of the trade: measured on a 6MiB dictionary the block cost 17KiB compressed against the 48KiB of index it replaced. [builder.term_dictionary_block_size; env YSEARCH_BUILDER_TERM_DICTIONARY_BLOCK_SIZE] (positive) |
--term-dictionary-bloom |
bool | false |
builder.term_dictionary_bloom |
YSEARCH_BUILDER_TERM_DICTIONARY_BLOOM |
Write a Bloom filter over the term family. The storage engine writes one by default; a segment does not, because the filter is read whole — uncompressed, about 1.2 bytes per distinct term — when the table is opened, and kept in memory until it closes, to save at most one block read per probe against the single table a published segment's term family is. Measured, it was nine tenths of what a cold term probe read: 431KiB of 481KiB on a 360k-term dictionary. A table says in its own footer whether it has a filter, so segments published with one keep working unchanged. [builder.term_dictionary_bloom; env YSEARCH_BUILDER_TERM_DICTIONARY_BLOOM] |
--builder-variable-posting-blocks |
bool | false |
builder.variable_posting_blocks |
YSEARCH_BUILDER_VARIABLE_POSTING_BLOCKS |
Experimental bounded-window BM25F-aware posting partitioning for format5 or newer output. [builder.variable_posting_blocks; env YSEARCH_BUILDER_VARIABLE_POSTING_BLOCKS] |
--cache-dir |
string | cache.dir |
YSEARCH_CACHE_DIR |
Disposable local cache directory; symlinks in its path are resolved once at startup and the cache then anchors there without following any. It holds the two disk budgets, cache.full_bytes and cache.block_bytes, and nothing else: every other cache.* budget is process memory. A relative value in a configuration file resolves against that file's directory. [cache.dir; env YSEARCH_CACHE_DIR] | |
--index |
string | index.name |
YSEARCH_INDEX_NAME |
Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles. [index.name; env YSEARCH_INDEX_NAME] | |
--object-backend |
enum | fs |
object.backend |
YSEARCH_OBJECT_BACKEND |
Object store backend. [object.backend; env YSEARCH_OBJECT_BACKEND] (one of fs, s3) |
--object-dir |
string | object.dir |
YSEARCH_OBJECT_DIR |
Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory. [object.dir; env YSEARCH_OBJECT_DIR] | |
--object-root |
string | indexes |
object.root |
YSEARCH_OBJECT_ROOT |
Object key root. [object.root; env YSEARCH_OBJECT_ROOT] |
--s3-anonymous |
bool | false |
object.s3.anonymous |
YSEARCH_OBJECT_S3_ANONYMOUS |
Sign no requests at all, for a bucket that grants public reads. This is a deliberate choice, never a fallback: an unresolved credential chain already signs anonymously, and a reader that quietly degraded to unsigned requests would report a permissions problem as an empty index. [object.s3.anonymous; env YSEARCH_OBJECT_S3_ANONYMOUS] |
--s3-bucket |
string | object.s3.bucket |
YSEARCH_OBJECT_S3_BUCKET |
S3 bucket; required for the s3 backend. [object.s3.bucket; env YSEARCH_OBJECT_S3_BUCKET] | |
--s3-endpoint |
string | object.s3.endpoint |
YSEARCH_OBJECT_S3_ENDPOINT |
S3 endpoint host:port; required for the s3 backend. [object.s3.endpoint; env YSEARCH_OBJECT_S3_ENDPOINT] | |
--s3-path-style |
bool | false |
object.s3.path_style |
YSEARCH_OBJECT_S3_PATH_STYLE |
Use path-style S3 addressing. [object.s3.path_style; env YSEARCH_OBJECT_S3_PATH_STYLE] |
--s3-prefix |
string | object.s3.prefix |
YSEARCH_OBJECT_S3_PREFIX |
S3 key prefix. [object.s3.prefix; env YSEARCH_OBJECT_S3_PREFIX] | |
--s3-region |
string | object.s3.region |
YSEARCH_OBJECT_S3_REGION |
S3 region. [object.s3.region; env YSEARCH_OBJECT_S3_REGION] | |
--s3-use-ssl |
bool | true |
object.s3.use_ssl |
YSEARCH_OBJECT_S3_USE_SSL |
Use TLS to the S3 endpoint. [object.s3.use_ssl; env YSEARCH_OBJECT_S3_USE_SSL] |
--source |
string | object.source |
YSEARCH_OBJECT_SOURCE |
Dataset URL to attach read-only, such as s3://bucket/root/ for a whole root or s3://bucket/root/indexes/name/ for one index. It derives object.backend, the bucket, prefix and root, the index when the URL names one, and server.read_only, each only where nothing more specific was set. Reading someone else's published index is the whole purpose, so attaching one implies read-only and cannot be talked out of it. [object.source; env YSEARCH_OBJECT_SOURCE] | |
--tail-impact-maximum-bands |
int | 64 |
tail.impact_maximum_bands |
YSEARCH_TAIL_IMPACT_MAXIMUM_BANDS |
Maximum score-impact bands persisted for one term. [tail.impact_maximum_bands; env YSEARCH_TAIL_IMPACT_MAXIMUM_BANDS] (in [1, 4096]) |
--tail-impact-target-documents |
int | 4096 |
tail.impact_target_documents |
YSEARCH_TAIL_IMPACT_TARGET_DOCUMENTS |
Target postings per persisted impact run. [tail.impact_target_documents; env YSEARCH_TAIL_IMPACT_TARGET_DOCUMENTS] (in [1, 4294967295]) |
ysearch catalog gc-dry-run [flags]Propose unreferenced objects against explicit retention horizons; removes nothing
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--retained-generations |
int | -1 |
generations before the latest to keep reachable | ||
--stream-lifetime |
duration | -1ns |
longest a query stream may still read a generation | ||
--grace |
duration | -1ns |
margin beyond every other horizon | ||
--minimum-upload-age |
duration | -1ns |
age below which an object may still be an upload in flight | ||
--index |
string | index.name |
YSEARCH_INDEX_NAME |
Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles. [index.name; env YSEARCH_INDEX_NAME] | |
--object-backend |
enum | fs |
object.backend |
YSEARCH_OBJECT_BACKEND |
Object store backend. [object.backend; env YSEARCH_OBJECT_BACKEND] (one of fs, s3) |
--object-dir |
string | object.dir |
YSEARCH_OBJECT_DIR |
Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory. [object.dir; env YSEARCH_OBJECT_DIR] | |
--object-root |
string | indexes |
object.root |
YSEARCH_OBJECT_ROOT |
Object key root. [object.root; env YSEARCH_OBJECT_ROOT] |
--s3-anonymous |
bool | false |
object.s3.anonymous |
YSEARCH_OBJECT_S3_ANONYMOUS |
Sign no requests at all, for a bucket that grants public reads. This is a deliberate choice, never a fallback: an unresolved credential chain already signs anonymously, and a reader that quietly degraded to unsigned requests would report a permissions problem as an empty index. [object.s3.anonymous; env YSEARCH_OBJECT_S3_ANONYMOUS] |
--s3-bucket |
string | object.s3.bucket |
YSEARCH_OBJECT_S3_BUCKET |
S3 bucket; required for the s3 backend. [object.s3.bucket; env YSEARCH_OBJECT_S3_BUCKET] | |
--s3-endpoint |
string | object.s3.endpoint |
YSEARCH_OBJECT_S3_ENDPOINT |
S3 endpoint host:port; required for the s3 backend. [object.s3.endpoint; env YSEARCH_OBJECT_S3_ENDPOINT] | |
--s3-path-style |
bool | false |
object.s3.path_style |
YSEARCH_OBJECT_S3_PATH_STYLE |
Use path-style S3 addressing. [object.s3.path_style; env YSEARCH_OBJECT_S3_PATH_STYLE] |
--s3-prefix |
string | object.s3.prefix |
YSEARCH_OBJECT_S3_PREFIX |
S3 key prefix. [object.s3.prefix; env YSEARCH_OBJECT_S3_PREFIX] | |
--s3-region |
string | object.s3.region |
YSEARCH_OBJECT_S3_REGION |
S3 region. [object.s3.region; env YSEARCH_OBJECT_S3_REGION] | |
--s3-use-ssl |
bool | true |
object.s3.use_ssl |
YSEARCH_OBJECT_S3_USE_SSL |
Use TLS to the S3 endpoint. [object.s3.use_ssl; env YSEARCH_OBJECT_S3_USE_SSL] |
--source |
string | object.source |
YSEARCH_OBJECT_SOURCE |
Dataset URL to attach read-only, such as s3://bucket/root/ for a whole root or s3://bucket/root/indexes/name/ for one index. It derives object.backend, the bucket, prefix and root, the index when the URL names one, and server.read_only, each only where nothing more specific was set. Reading someone else's published index is the whole purpose, so attaching one implies read-only and cannot be talked out of it. [object.source; env YSEARCH_OBJECT_SOURCE] |
ysearch catalog publish [flags]Announce a published segment (also converges the catalog on everything committed)
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--segment-id |
string | 32 lowercase hex characters | |||
--expected-parent |
string | generation this announcement expects to extend | |||
--generation |
string | index.generation |
YSEARCH_INDEX_GENERATION |
Exact generation to pin, or empty for the latest. [index.generation; env YSEARCH_INDEX_GENERATION] | |
--index |
string | index.name |
YSEARCH_INDEX_NAME |
Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles. [index.name; env YSEARCH_INDEX_NAME] | |
--object-backend |
enum | fs |
object.backend |
YSEARCH_OBJECT_BACKEND |
Object store backend. [object.backend; env YSEARCH_OBJECT_BACKEND] (one of fs, s3) |
--object-dir |
string | object.dir |
YSEARCH_OBJECT_DIR |
Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory. [object.dir; env YSEARCH_OBJECT_DIR] | |
--object-root |
string | indexes |
object.root |
YSEARCH_OBJECT_ROOT |
Object key root. [object.root; env YSEARCH_OBJECT_ROOT] |
--s3-anonymous |
bool | false |
object.s3.anonymous |
YSEARCH_OBJECT_S3_ANONYMOUS |
Sign no requests at all, for a bucket that grants public reads. This is a deliberate choice, never a fallback: an unresolved credential chain already signs anonymously, and a reader that quietly degraded to unsigned requests would report a permissions problem as an empty index. [object.s3.anonymous; env YSEARCH_OBJECT_S3_ANONYMOUS] |
--s3-bucket |
string | object.s3.bucket |
YSEARCH_OBJECT_S3_BUCKET |
S3 bucket; required for the s3 backend. [object.s3.bucket; env YSEARCH_OBJECT_S3_BUCKET] | |
--s3-endpoint |
string | object.s3.endpoint |
YSEARCH_OBJECT_S3_ENDPOINT |
S3 endpoint host:port; required for the s3 backend. [object.s3.endpoint; env YSEARCH_OBJECT_S3_ENDPOINT] | |
--s3-path-style |
bool | false |
object.s3.path_style |
YSEARCH_OBJECT_S3_PATH_STYLE |
Use path-style S3 addressing. [object.s3.path_style; env YSEARCH_OBJECT_S3_PATH_STYLE] |
--s3-prefix |
string | object.s3.prefix |
YSEARCH_OBJECT_S3_PREFIX |
S3 key prefix. [object.s3.prefix; env YSEARCH_OBJECT_S3_PREFIX] | |
--s3-region |
string | object.s3.region |
YSEARCH_OBJECT_S3_REGION |
S3 region. [object.s3.region; env YSEARCH_OBJECT_S3_REGION] | |
--s3-use-ssl |
bool | true |
object.s3.use_ssl |
YSEARCH_OBJECT_S3_USE_SSL |
Use TLS to the S3 endpoint. [object.s3.use_ssl; env YSEARCH_OBJECT_S3_USE_SSL] |
--source |
string | object.source |
YSEARCH_OBJECT_SOURCE |
Dataset URL to attach read-only, such as s3://bucket/root/ for a whole root or s3://bucket/root/indexes/name/ for one index. It derives object.backend, the bucket, prefix and root, the index when the URL names one, and server.read_only, each only where nothing more specific was set. Reading someone else's published index is the whole purpose, so attaching one implies read-only and cannot be talked out of it. [object.source; env YSEARCH_OBJECT_SOURCE] |
ysearch catalog reconcile [flags]Repair the catalog's lineage from the committed segments without announcing anything new
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--generation |
string | index.generation |
YSEARCH_INDEX_GENERATION |
Exact generation to pin, or empty for the latest. [index.generation; env YSEARCH_INDEX_GENERATION] | |
--index |
string | index.name |
YSEARCH_INDEX_NAME |
Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles. [index.name; env YSEARCH_INDEX_NAME] | |
--object-backend |
enum | fs |
object.backend |
YSEARCH_OBJECT_BACKEND |
Object store backend. [object.backend; env YSEARCH_OBJECT_BACKEND] (one of fs, s3) |
--object-dir |
string | object.dir |
YSEARCH_OBJECT_DIR |
Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory. [object.dir; env YSEARCH_OBJECT_DIR] | |
--object-root |
string | indexes |
object.root |
YSEARCH_OBJECT_ROOT |
Object key root. [object.root; env YSEARCH_OBJECT_ROOT] |
--s3-anonymous |
bool | false |
object.s3.anonymous |
YSEARCH_OBJECT_S3_ANONYMOUS |
Sign no requests at all, for a bucket that grants public reads. This is a deliberate choice, never a fallback: an unresolved credential chain already signs anonymously, and a reader that quietly degraded to unsigned requests would report a permissions problem as an empty index. [object.s3.anonymous; env YSEARCH_OBJECT_S3_ANONYMOUS] |
--s3-bucket |
string | object.s3.bucket |
YSEARCH_OBJECT_S3_BUCKET |
S3 bucket; required for the s3 backend. [object.s3.bucket; env YSEARCH_OBJECT_S3_BUCKET] | |
--s3-endpoint |
string | object.s3.endpoint |
YSEARCH_OBJECT_S3_ENDPOINT |
S3 endpoint host:port; required for the s3 backend. [object.s3.endpoint; env YSEARCH_OBJECT_S3_ENDPOINT] | |
--s3-path-style |
bool | false |
object.s3.path_style |
YSEARCH_OBJECT_S3_PATH_STYLE |
Use path-style S3 addressing. [object.s3.path_style; env YSEARCH_OBJECT_S3_PATH_STYLE] |
--s3-prefix |
string | object.s3.prefix |
YSEARCH_OBJECT_S3_PREFIX |
S3 key prefix. [object.s3.prefix; env YSEARCH_OBJECT_S3_PREFIX] | |
--s3-region |
string | object.s3.region |
YSEARCH_OBJECT_S3_REGION |
S3 region. [object.s3.region; env YSEARCH_OBJECT_S3_REGION] | |
--s3-use-ssl |
bool | true |
object.s3.use_ssl |
YSEARCH_OBJECT_S3_USE_SSL |
Use TLS to the S3 endpoint. [object.s3.use_ssl; env YSEARCH_OBJECT_S3_USE_SSL] |
--source |
string | object.source |
YSEARCH_OBJECT_SOURCE |
Dataset URL to attach read-only, such as s3://bucket/root/ for a whole root or s3://bucket/root/indexes/name/ for one index. It derives object.backend, the bucket, prefix and root, the index when the URL names one, and server.read_only, each only where nothing more specific was set. Reading someone else's published index is the whole purpose, so attaching one implies read-only and cannot be talked out of it. [object.source; env YSEARCH_OBJECT_SOURCE] |
ysearch catalog resolve [flags]Print the latest generation, or --generation, as the catalog records it
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--generation |
string | index.generation |
YSEARCH_INDEX_GENERATION |
Exact generation to pin, or empty for the latest. [index.generation; env YSEARCH_INDEX_GENERATION] | |
--index |
string | index.name |
YSEARCH_INDEX_NAME |
Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles. [index.name; env YSEARCH_INDEX_NAME] | |
--object-backend |
enum | fs |
object.backend |
YSEARCH_OBJECT_BACKEND |
Object store backend. [object.backend; env YSEARCH_OBJECT_BACKEND] (one of fs, s3) |
--object-dir |
string | object.dir |
YSEARCH_OBJECT_DIR |
Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory. [object.dir; env YSEARCH_OBJECT_DIR] | |
--object-root |
string | indexes |
object.root |
YSEARCH_OBJECT_ROOT |
Object key root. [object.root; env YSEARCH_OBJECT_ROOT] |
--s3-anonymous |
bool | false |
object.s3.anonymous |
YSEARCH_OBJECT_S3_ANONYMOUS |
Sign no requests at all, for a bucket that grants public reads. This is a deliberate choice, never a fallback: an unresolved credential chain already signs anonymously, and a reader that quietly degraded to unsigned requests would report a permissions problem as an empty index. [object.s3.anonymous; env YSEARCH_OBJECT_S3_ANONYMOUS] |
--s3-bucket |
string | object.s3.bucket |
YSEARCH_OBJECT_S3_BUCKET |
S3 bucket; required for the s3 backend. [object.s3.bucket; env YSEARCH_OBJECT_S3_BUCKET] | |
--s3-endpoint |
string | object.s3.endpoint |
YSEARCH_OBJECT_S3_ENDPOINT |
S3 endpoint host:port; required for the s3 backend. [object.s3.endpoint; env YSEARCH_OBJECT_S3_ENDPOINT] | |
--s3-path-style |
bool | false |
object.s3.path_style |
YSEARCH_OBJECT_S3_PATH_STYLE |
Use path-style S3 addressing. [object.s3.path_style; env YSEARCH_OBJECT_S3_PATH_STYLE] |
--s3-prefix |
string | object.s3.prefix |
YSEARCH_OBJECT_S3_PREFIX |
S3 key prefix. [object.s3.prefix; env YSEARCH_OBJECT_S3_PREFIX] | |
--s3-region |
string | object.s3.region |
YSEARCH_OBJECT_S3_REGION |
S3 region. [object.s3.region; env YSEARCH_OBJECT_S3_REGION] | |
--s3-use-ssl |
bool | true |
object.s3.use_ssl |
YSEARCH_OBJECT_S3_USE_SSL |
Use TLS to the S3 endpoint. [object.s3.use_ssl; env YSEARCH_OBJECT_S3_USE_SSL] |
--source |
string | object.source |
YSEARCH_OBJECT_SOURCE |
Dataset URL to attach read-only, such as s3://bucket/root/ for a whole root or s3://bucket/root/indexes/name/ for one index. It derives object.backend, the bucket, prefix and root, the index when the URL names one, and server.read_only, each only where nothing more specific was set. Reading someone else's published index is the whole purpose, so attaching one implies read-only and cannot be talked out of it. [object.source; env YSEARCH_OBJECT_SOURCE] |
ysearch catalog startup-bundle [flags]Build optional bounded startup metadata pages for an existing generation
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--generation |
string | index.generation |
YSEARCH_INDEX_GENERATION |
Exact generation to pin, or empty for the latest. [index.generation; env YSEARCH_INDEX_GENERATION] | |
--index |
string | index.name |
YSEARCH_INDEX_NAME |
Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles. [index.name; env YSEARCH_INDEX_NAME] | |
--object-backend |
enum | fs |
object.backend |
YSEARCH_OBJECT_BACKEND |
Object store backend. [object.backend; env YSEARCH_OBJECT_BACKEND] (one of fs, s3) |
--object-dir |
string | object.dir |
YSEARCH_OBJECT_DIR |
Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory. [object.dir; env YSEARCH_OBJECT_DIR] | |
--object-root |
string | indexes |
object.root |
YSEARCH_OBJECT_ROOT |
Object key root. [object.root; env YSEARCH_OBJECT_ROOT] |
--s3-anonymous |
bool | false |
object.s3.anonymous |
YSEARCH_OBJECT_S3_ANONYMOUS |
Sign no requests at all, for a bucket that grants public reads. This is a deliberate choice, never a fallback: an unresolved credential chain already signs anonymously, and a reader that quietly degraded to unsigned requests would report a permissions problem as an empty index. [object.s3.anonymous; env YSEARCH_OBJECT_S3_ANONYMOUS] |
--s3-bucket |
string | object.s3.bucket |
YSEARCH_OBJECT_S3_BUCKET |
S3 bucket; required for the s3 backend. [object.s3.bucket; env YSEARCH_OBJECT_S3_BUCKET] | |
--s3-endpoint |
string | object.s3.endpoint |
YSEARCH_OBJECT_S3_ENDPOINT |
S3 endpoint host:port; required for the s3 backend. [object.s3.endpoint; env YSEARCH_OBJECT_S3_ENDPOINT] | |
--s3-path-style |
bool | false |
object.s3.path_style |
YSEARCH_OBJECT_S3_PATH_STYLE |
Use path-style S3 addressing. [object.s3.path_style; env YSEARCH_OBJECT_S3_PATH_STYLE] |
--s3-prefix |
string | object.s3.prefix |
YSEARCH_OBJECT_S3_PREFIX |
S3 key prefix. [object.s3.prefix; env YSEARCH_OBJECT_S3_PREFIX] | |
--s3-region |
string | object.s3.region |
YSEARCH_OBJECT_S3_REGION |
S3 region. [object.s3.region; env YSEARCH_OBJECT_S3_REGION] | |
--s3-use-ssl |
bool | true |
object.s3.use_ssl |
YSEARCH_OBJECT_S3_USE_SSL |
Use TLS to the S3 endpoint. [object.s3.use_ssl; env YSEARCH_OBJECT_S3_USE_SSL] |
--source |
string | object.source |
YSEARCH_OBJECT_SOURCE |
Dataset URL to attach read-only, such as s3://bucket/root/ for a whole root or s3://bucket/root/indexes/name/ for one index. It derives object.backend, the bucket, prefix and root, the index when the URL names one, and server.read_only, each only where nothing more specific was set. Reading someone else's published index is the whole purpose, so attaching one implies read-only and cannot be talked out of it. [object.source; env YSEARCH_OBJECT_SOURCE] |
ysearch config [flags]config talks to the ConfigService of the server --server names. list, get, set, unset, and watch act on that node; set writes an ephemeral overlay that a restart drops and unset removes. Only node-runtime settings accept set; a startup setting answers FAILED_PRECONDITION naming its scope. export is the offline verb: it resolves this process's own layering and prints it.
Subcommands:
ysearch config export— Resolve this process's own configuration offline and print it, or write it as a YAML fileysearch config get— Show one setting and where its value came fromysearch config list— List every setting with its value, scope, and sourceysearch config set— Override a node-runtime setting until unset or restartysearch config unset— Drop a runtime override; the file, environment, or flag value returnsysearch config watch— Print every matching setting, then one line per change, until interrupted
ysearch config export [flags]export needs no server. It layers the defaults, the discovered files (or --config / --config-dir), the environment, and the flags exactly as serve would, and prints every setting with its source. --yaml prints the values as one configuration file: secrets, the discovery keys, and compile-time settings are left out because a file may not set them.
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--yaml |
bool | false |
print the resolved values as a configuration file |
ysearch config get <key> [flags]Show one setting and where its value came from
ysearch config list [flags]List every setting with its value, scope, and source
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--prefix |
string | only keys with this prefix (a trailing dot selects one section) |
ysearch config set <key> <value> [flags]Override a node-runtime setting until unset or restart
Example:
ysearch config set log.level debug
ysearch config set ingest.seal_age 5sysearch config unset <key> [flags]Drop a runtime override; the file, environment, or flag value returns
ysearch config watch [flags]Print every matching setting, then one line per change, until interrupted
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--prefix |
string | only keys with this prefix (a trailing dot selects one section) |
ysearch delete <index> <keys...|-> [flags]delete tombstones each given key: that key's current version is superseded by nothing, and it stops appearing in results without invalidating the rest of the index. It suppresses the document — the bytes are not reclaimed until a later compaction physically merges the segment holding it away. Deleting a key that does not exist is not an error: delete is idempotent.
Keys are given directly as arguments, or read one per line from stdin (blank lines skipped) when the sole argument is -. Unless --no-flush it flushes and waits for the segment to publish, printing the sealed segment and generation, exactly as push does.
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--batch |
int | 500 |
keys per batch | ||
--batch-bytes |
int64 | 2097152 |
byte cap per batch | ||
--no-flush |
bool | false |
accept ephemerally; do not flush or wait for publication | ||
--require-ack |
bool | false |
wait for PUBLISHED on every batch |
ysearch explain <query> [flags]explain parses a query and prints its AST, its stable digest, the schema it
lowered against, the lowered structured query, and its filters — without
touching an index. Without --index the assumed schema is used (every named
field is indexed, word is every indexed field); with --index the real
schema is fetched and its field names are resolved. --json prints the same as
a nested object.
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--dialect |
string | lucene |
query dialect: lucene or cqp | ||
--index |
string | resolve field names against this index's schema (default: the assumed schema) |
ysearch index [flags]index talks to the IndexService of the server --server names. list names every index in the server's object root with its schema version and active generation; describe prints one index's header and its current schema.
Subcommands:
ysearch index describe— Describe one index and its current schemaysearch index list— List every index with its schema version and generation
ysearch index describe <index> [flags]Describe one index and its current schema
ysearch index list [flags]List every index with its schema version and generation
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--prefix |
string | only list indexes whose name starts with this prefix |
ysearch manual [flags]manual renders the reference from the command tree and the configuration
catalog, so it cannot drift from the binary. docs/cli.md is this output;
go run ./tools/dev manual-check fails when it differs.
ysearch node [flags]node serves any combination of the query-fleet roles plus the maintenance-only compactor role from one process. Catalog-bound roles resolve their generation before the listener opens, so a node that cannot read its catalog fails at startup rather than accepting work it cannot perform. A dedicated compactor opens no query engine or full-segment cache; it follows latest and performs single-flight copy-on-write physical merges under the compaction budgets.
Example:
ysearch node --roles aggregator --listen 127.0.0.1:9601
ysearch node --roles worker --listen 127.0.0.1:9602 --index demo --object-dir ./objects --cache-dir ./cache --aggregators 127.0.0.1:9601
ysearch node --roles compactor --listen 127.0.0.1:9701 --index demo --object-dir ./objects --ingest-dir ./scratchFlags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--analysis-batch-documents |
int | 0 |
builder.analysis_batch_documents |
YSEARCH_BUILDER_ANALYSIS_BATCH_DOCUMENTS |
Documents handed to the analysis workers at once; zero derives sixteen per worker. A batch is the unit that must fit in builder.analysis_memory_bytes, so a larger batch amortises the hand-off over more documents but raises the peak the analysis share has to cover. The derived shape is what the resource gates measure, so a corpus of unusually large documents is the case for lowering it rather than raising the share. [builder.analysis_batch_documents; env YSEARCH_BUILDER_ANALYSIS_BATCH_DOCUMENTS] (in [0, 1048576]) |
--analysis-memory-bytes |
bytes | 0 |
builder.analysis_memory_bytes |
YSEARCH_BUILDER_ANALYSIS_MEMORY_BYTES |
The share of builder.sort_memory_bytes reserved for documents in flight through analysis; zero derives a thirty-second of it, clamped to between 64KiB and 32MiB and never more than a quarter of what the public-id and docvalue spools leave. It only has to hold one bounded batch, and a document larger than the whole share still runs alone under builder.max_document_working_bytes, so the derived value is deliberately small: a three-million-document run peaked at 9.5MiB against a 128MiB share. Every byte reserved here is a byte the term partitions cannot use, which raises mini-run count and write amplification directly, so raise it only against a measured analysis stall. [builder.analysis_memory_bytes; env YSEARCH_BUILDER_ANALYSIS_MEMORY_BYTES] |
--analysis-workers |
int | 0 |
builder.analysis_workers |
YSEARCH_BUILDER_ANALYSIS_WORKERS |
Goroutines tokenising documents inside one build; zero derives GOMAXPROCS, bounded at eight. Analysis is the one parallel stage of an otherwise serial build, so this is per build and multiplies with builder.build_concurrency: the bound exists because a dozen builds each spawning a worker per core oversubscribes the machine and the scheduler churn costs more than the parallelism returns. Output order is preserved regardless of this value. [builder.analysis_workers; env YSEARCH_BUILDER_ANALYSIS_WORKERS] (in [0, 1024]) |
--blob-dictionary |
bool | true |
builder.blob_dictionary |
YSEARCH_BUILDER_BLOB_DICTIONARY |
Compress stored values against a dictionary trained per blob file. Denser on homogeneous documents, but the dictionary is coded on the build's hottest path, so turning it off trades index size for ingest throughput. [builder.blob_dictionary; env YSEARCH_BUILDER_BLOB_DICTIONARY] |
--blob-zstd-level |
int | 0 |
builder.blob_zstd_level |
YSEARCH_BUILDER_BLOB_ZSTD_LEVEL |
Zstd effort for stored values; zero keeps the storage default (7). Levels select different zstd encoders, and a build re-seeds the chosen encoder from the blob dictionary for every value it writes, so a lower level cuts build cost by more than the usual level trade-off suggests. [builder.blob_zstd_level; env YSEARCH_BUILDER_BLOB_ZSTD_LEVEL] (in [0, 11]) |
--build-concurrency |
int | 0 |
builder.build_concurrency |
YSEARCH_BUILDER_BUILD_CONCURRENCY |
Sealed builds that may run through the seal pipeline at once; zero derives one per CPU, bounded at twelve. One build is a mostly single-threaded chain of analysis, sort, merge and publish that spends about half its time blocked in file system calls, so a single pipeline leaves a multi-core host idle under bulk ingest. The builder's memory is this number times builder.sort_memory_bytes. [builder.build_concurrency; env YSEARCH_BUILDER_BUILD_CONCURRENCY] (in [0, 256]) |
--builder-catalog-publication |
enum | direct |
builder.catalog_publication |
YSEARCH_BUILDER_CATALOG_PUBLICATION |
Catalog writer mode: direct is the single-node compatibility path; external stops after commit markers for a lease-fenced publisher role. [builder.catalog_publication; env YSEARCH_BUILDER_CATALOG_PUBLICATION] (one of direct, external) |
--dedupe-index-identities |
int | 0 |
builder.dedupe_index_identities |
YSEARCH_BUILDER_DEDUPE_INDEX_IDENTITIES |
Distinct document keys one open spool's dedupe index may hold before it gives up; zero derives 1048576. A key spooled twice in one build must resolve to a single winner before analysis, or the segment's dense ordinal assignment refuses the build outright. The index resolves that as records are spooled, from identities ingest already holds, and the sealed build inherits the answer; past this bound it gives up and the build reconstructs the answer by reading its spool twice instead — slower, and exactly as correct. One entry is a 16-byte key hash, a sequence and a mutation version, so the default bounds it at tens of megabytes per open spool and is reached only by a spool of a million very small documents. Lower it to cap that memory on a host running many indexes; set it to one to force the scanning path. [builder.dedupe_index_identities; env YSEARCH_BUILDER_DEDUPE_INDEX_IDENTITIES] (in [0, 268435456]) |
--builder-fuse-memory-bytes |
bytes | 0 |
builder.fuse_memory_bytes |
YSEARCH_BUILDER_FUSE_MEMORY_BYTES |
Optional binary fuse construction workspace during publication; zero retains Bloom, failed admission retains Bloom. [builder.fuse_memory_bytes; env YSEARCH_BUILDER_FUSE_MEMORY_BYTES] (in [0, 64MiB]) |
--lexical-blob-threshold |
bytes | 0 |
builder.lexical_blob_threshold |
YSEARCH_BUILDER_LEXICAL_BLOB_THRESHOLD |
Size at which a posting, position or term value is stored in a blob file rather than inline in the key log; zero keeps the default of 64KiB. Separation exists to spare compaction from rewriting large values, and a segment is never compacted — while a blob value is compressed on its own, which with a trained dictionary costs an encoder reset each time, where key-log blocks are compressed in bulk. [builder.lexical_blob_threshold; env YSEARCH_BUILDER_LEXICAL_BLOB_THRESHOLD] |
--lexical-block-compression |
string | builder.lexical_block_compression |
YSEARCH_BUILDER_LEXICAL_BLOCK_COMPRESSION |
Codec the term, posting and position families compress key-log blocks with: none, snappy, lz4, lz4fast or zstd. Empty keeps the default of lz4. The storage engine's own default leaves the newest level raw because it expects compaction to rewrite it, and a segment stays where it lands. On 300k articles lz4 measured 24.8s and 1.0GB against zstd's 37.7s and 0.8GB, so zstd is the choice for an index written once and read for a long time. [builder.lexical_block_compression; env YSEARCH_BUILDER_LEXICAL_BLOCK_COMPRESSION] | |
--max-document-working-bytes |
bytes | 0 |
builder.max_document_working_bytes |
YSEARCH_BUILDER_MAX_DOCUMENT_WORKING_BYTES |
What one document may use beyond the partition budget while it is being analyzed; zero derives 64MiB, or a quarter of builder.sort_memory_bytes when that is smaller. It is an allowance rather than a reservation: it exists so a single document larger than the whole partition budget still builds, alone, instead of failing the build. Only a corpus with documents in the hundreds of megabytes needs it raised. [builder.max_document_working_bytes; env YSEARCH_BUILDER_MAX_DOCUMENT_WORKING_BYTES] |
--max-queued-builds |
int | 0 |
builder.max_queued_builds |
YSEARCH_BUILDER_MAX_QUEUED_BUILDS |
Sealed builds that may wait for or run in the pipeline before ingest is throttled; zero derives it as four times builder.build_concurrency. A waiting build is a spool on disk, not memory, so this buys ingest room across a build at the cost of ingest.seal_bytes of disk per queued build. Set too low, a bulk load throttles the moment the pipeline is full and ingest runs at the speed of the builds rather than ahead of them. [builder.max_queued_builds; env YSEARCH_BUILDER_MAX_QUEUED_BUILDS] (in [0, 1024]) |
--max-token-bytes |
bytes | 64KiB |
builder.max_token_bytes |
YSEARCH_BUILDER_MAX_TOKEN_BYTES |
Maximum analyzed token size. A build must be able to admit one token this large, so raising it raises the floor under builder.sort_memory_bytes: a budget that leaves the partitions less than one maximum term refuses to start rather than fail partway. Tokens are words after analysis, so the default is already far past any natural language; raise it only for a corpus with genuinely enormous unbroken tokens. [builder.max_token_bytes; env YSEARCH_BUILDER_MAX_TOKEN_BYTES] (positive) |
--merge-fan-in |
int | 0 |
builder.merge_fan_in |
YSEARCH_BUILDER_MERGE_FAN_IN |
Spilled mini-runs merged in one pass; zero derives as many as an eighth of the partition budget affords at builder.run_page_bytes plus 512 bytes of reader overhead each, capped at sixty-four and floored at two. Runs beyond the fan-in need further passes, and each pass rewrites the data, so a low fan-in on a build that spilled heavily shows up as write amplification rather than as a slow merge. The cap is a file-descriptor and seek-pattern bound, not a memory one. [builder.merge_fan_in; env YSEARCH_BUILDER_MERGE_FAN_IN] (in [0, 64]) |
--builder-output-format-version |
int | 0 |
builder.output_format_version |
YSEARCH_BUILDER_OUTPUT_FORMAT_VERSION |
Segment format emitted by builders and compactors; zero selects this binary's current format. The Kubernetes operator pins this to compatibility.writeFormat on writer roles during staged rollouts. Format 7 adds the stats, forward and hashterms families (spec/40 §3); a compaction that includes an older input writes format 6 instead, unless 7 or 8 is set explicitly, which refuses such a merge. Format 8 adds the exact vector lanes (canonical fp16 vectors, IVF radii, int8 codes; spec/40 §3.2). [builder.output_format_version; env YSEARCH_BUILDER_OUTPUT_FORMAT_VERSION] (in [0, 8]) |
--builder-paged-posting-directory |
bool | false |
builder.paged_posting_directory |
YSEARCH_BUILDER_PAGED_POSTING_DIRECTORY |
Experimental commit-anchored posting-directory pages under query admission and the existing persistent block quota; old commits retain canonical traversal. [builder.paged_posting_directory; env YSEARCH_BUILDER_PAGED_POSTING_DIRECTORY] |
--builder-posting-partition-penalty |
float | 4 |
builder.posting_partition_penalty |
YSEARCH_BUILDER_POSTING_PARTITION_PENALTY |
Metadata cost penalty for experimental variable posting blocks. [builder.posting_partition_penalty; env YSEARCH_BUILDER_POSTING_PARTITION_PENALTY] (in [0, 1e+06]) |
--publish-verification |
string | checksum |
builder.publish_verification |
YSEARCH_BUILDER_PUBLISH_VERIFICATION |
How a published segment is confirmed: checksum, sample, or readback. checksum compares every object against the checksum the object store reported when it accepted the write — S3 computes that server-side and refuses a mismatched write, and the filesystem backend computes it over the bytes it synced — so nothing is transferred back. sample additionally opens the published copy through the store and queries it; readback additionally fetches every object and rehashes it, which costs the whole index again on every build. An object whose store reports no comparable checksum is read back in any mode. [builder.publish_verification; env YSEARCH_BUILDER_PUBLISH_VERIFICATION] |
--builder-routing-fragment-bytes |
bytes | 8MiB |
builder.routing_fragment_bytes |
YSEARCH_BUILDER_ROUTING_FRAGMENT_BYTES |
Optional routing fragment disk cap per built segment; zero disables, overflow keeps canonical scan fallback. Matches compaction.routing_fragment_bytes so a freshly ingested segment and a freshly compacted one carry a fragment the same way; the two stay separate keys because a background merge must be able to carry its own share independent of foreground ingestion. Only a segment built or compacted after this defaulted on carries a fragment: nothing rewrites an existing one, so a settled corpus stays without a routing table until it is backfilled or compacted. [builder.routing_fragment_bytes; env YSEARCH_BUILDER_ROUTING_FRAGMENT_BYTES] (in [0, 64MiB]) |
--run-page-bytes |
bytes | 0 |
builder.run_page_bytes |
YSEARCH_BUILDER_RUN_PAGE_BYTES |
Read-ahead page one spilled mini-run is buffered in during the final merge; zero derives 64KiB, shrinking it when an eighth of the partition budget cannot hold sixty-four such pages. The merge reserves one page per open run for the whole build, so page size and builder.merge_fan_in trade against each other out of the same share: the derivation prefers smaller pages to a fan-in that would force extra compaction passes on a hot partition. [builder.run_page_bytes; env YSEARCH_BUILDER_RUN_PAGE_BYTES] |
--sort-memory-bytes |
bytes | 256MiB |
builder.sort_memory_bytes |
YSEARCH_BUILDER_SORT_MEMORY_BYTES |
Total accounted builder budget: one ledger every part of a build charges against, and the setting the other builder budgets derive from. It divides into the public-id sorter (an eighth, capped at 64MiB), the docvalue and lane spools (their own worst case), the analysis share (builder.analysis_memory_bytes), and the term partitions, which take what is left. A build that cannot hold its partitions in that remainder spills to disk instead, which is the difference between one file per build and hundreds. This is per build, so the builder's memory is builder.build_concurrency times this. [builder.sort_memory_bytes; env YSEARCH_BUILDER_SORT_MEMORY_BYTES] (positive) |
--builder-spill-merge-strategy |
enum | heap |
builder.spill_merge_strategy |
YSEARCH_BUILDER_SPILL_MERGE_STRATEGY |
Experimental spill merge selector; heap preserves the baseline until full ingestion benchmarks qualify an alternative. [builder.spill_merge_strategy; env YSEARCH_BUILDER_SPILL_MERGE_STRATEGY] (one of heap, replace-root, loser-tree) |
--builder-startup-bundles |
bool | false |
builder.startup_bundles |
YSEARCH_BUILDER_STARTUP_BUNDLES |
Asynchronously produce optional startup bundles after catalog publication. One bounded coalescing worker per publishing host; oversized sources retain canonical startup fallback. [builder.startup_bundles; env YSEARCH_BUILDER_STARTUP_BUNDLES] |
--term-dictionary-block-size |
bytes | 64KiB |
builder.term_dictionary_block_size |
YSEARCH_BUILDER_TERM_DICTIONARY_BLOCK_SIZE |
Key-log data-block size of the term family. A table carries one block-index entry per data block and reads the whole index before it can look up anything, so this is what a cold term probe pays to find out where to look. At the storage engine's 4KiB an 8MiB dictionary needs about two thousand entries — around 65KiB read on every open of the table and held in memory until it closes — where 64KiB needs about a sixteenth of that. A probe then reads a bigger block, which over an object store is the cheap side of the trade: measured on a 6MiB dictionary the block cost 17KiB compressed against the 48KiB of index it replaced. [builder.term_dictionary_block_size; env YSEARCH_BUILDER_TERM_DICTIONARY_BLOCK_SIZE] (positive) |
--term-dictionary-bloom |
bool | false |
builder.term_dictionary_bloom |
YSEARCH_BUILDER_TERM_DICTIONARY_BLOOM |
Write a Bloom filter over the term family. The storage engine writes one by default; a segment does not, because the filter is read whole — uncompressed, about 1.2 bytes per distinct term — when the table is opened, and kept in memory until it closes, to save at most one block read per probe against the single table a published segment's term family is. Measured, it was nine tenths of what a cold term probe read: 431KiB of 481KiB on a 360k-term dictionary. A table says in its own footer whether it has a filter, so segments published with one keep working unchanged. [builder.term_dictionary_bloom; env YSEARCH_BUILDER_TERM_DICTIONARY_BLOOM] |
--builder-variable-posting-blocks |
bool | false |
builder.variable_posting_blocks |
YSEARCH_BUILDER_VARIABLE_POSTING_BLOCKS |
Experimental bounded-window BM25F-aware posting partitioning for format5 or newer output. [builder.variable_posting_blocks; env YSEARCH_BUILDER_VARIABLE_POSTING_BLOCKS] |
--cache-block-bytes |
bytes | 2GiB |
cache.block_bytes |
YSEARCH_CACHE_BLOCK_BYTES |
Disk, not memory: bytes of verified decoded blocks this node may keep under cache.dir. This is the cheap half of block caching - it converts a remote read into a local one and costs no resident memory - so size it above one query's working set and leave cache.read_block_bytes to decide what stays in RAM. Measured on 294 segments: one single-term query touched about 363MB of term dictionary and postings and one scored two-term query about 544MB, so the default holds several such working sets. [cache.block_bytes; env YSEARCH_CACHE_BLOCK_BYTES] (positive) |
--cache-block-entries |
int | 1048576 |
cache.block_entries |
YSEARCH_CACHE_BLOCK_ENTRIES |
Disk, not memory: how many decoded blocks cache.block_bytes may be spread over. Whichever is reached first bounds the cache; at the measured ~237KiB per block the byte budget is reached first by a wide margin. [cache.block_entries; env YSEARCH_CACHE_BLOCK_ENTRIES] (positive) |
--cache-dir |
string | cache.dir |
YSEARCH_CACHE_DIR |
Disposable local cache directory; symlinks in its path are resolved once at startup and the cache then anchors there without following any. It holds the two disk budgets, cache.full_bytes and cache.block_bytes, and nothing else: every other cache.* budget is process memory. A relative value in a configuration file resolves against that file's directory. [cache.dir; env YSEARCH_CACHE_DIR] | |
--cache-full-bytes |
bytes | 8GiB |
cache.full_bytes |
YSEARCH_CACHE_FULL_BYTES |
Disk, not memory: bytes of whole hydrated segments this node may keep under cache.dir. With cache.block_bytes it is the whole of what the cache directory holds, so a volume smaller than their sum is an eviction loop the node cannot see. [cache.full_bytes; env YSEARCH_CACHE_FULL_BYTES] (positive) |
--cache-full-entries |
int | 1024 |
cache.full_entries |
YSEARCH_CACHE_FULL_ENTRIES |
Disk, not memory: how many whole segments cache.full_bytes may be spread over. Whichever of the two is reached first bounds the cache, and at the measured ~340MB per segment of a 101GB corpus the byte budget is reached long before this one. [cache.full_entries; env YSEARCH_CACHE_FULL_ENTRIES] (positive) |
--cache-lazy-readers |
bool | false |
cache.lazy_readers |
YSEARCH_CACHE_LAZY_READERS |
Experimental: acquire immutable segment readers and optional filter payloads only for admitted query work. It is also what routing.presence_bytes zero means: eager readers read that zero as unbounded and hold every segment's presence filter, lazy readers read it as none. [cache.lazy_readers; env YSEARCH_CACHE_LAZY_READERS] |
--cache-ordinal-bytes |
bytes | 64MiB |
cache.ordinal_bytes |
YSEARCH_CACHE_ORDINAL_BYTES |
Memory, not disk: process-wide verified ordinal-ID pages, including pinned pages and in-flight page workspace, shared across indexes and generations. [cache.ordinal_bytes; env YSEARCH_CACHE_ORDINAL_BYTES] (at least 327936) |
--cache-read-block-bytes |
bytes | 512MiB |
cache.read_block_bytes |
YSEARCH_CACHE_READ_BLOCK_BYTES |
Memory, not disk: process-wide decoded WavesDB blocks held resident and shared by immutable segment readers. This is what decides whether a repeated query is warm. Below one query's working set nothing survives to the next query and every query pays the cold price forever: measured on 294 segments, a 24MiB budget re-read all 214MB of term dictionary byte for byte while about 495MiB answered the repeat from 57,421 bytes. Size it from the corpus, not the machine, and from the layout its segments were built with. A term probe costs the same whatever the term, but what it costs depends on whether the segment carries a term-family Bloom filter: about 711KiB per segment on one built before builder.term_dictionary_bloom defaulted to false, and about 21KiB on one built since. The term dictionary alone needs segments times that figure, and the postings of the shape you serve come on top. A mixed corpus pays the older rate for the segments it has not rebuilt. [cache.read_block_bytes; env YSEARCH_CACHE_READ_BLOCK_BYTES] (positive) |
--cache-read-open-files |
int | 1024 |
cache.read_open_files |
YSEARCH_CACHE_READ_OPEN_FILES |
Process-wide open WavesDB table-file limit shared by immutable segment readers. It spends file descriptors, and nothing here raises RLIMIT_NOFILE, so the default sits at the 1024 a Linux process is commonly given with the listeners, connections and cache files sharing it: raise the limit before raising this. [cache.read_open_files; env YSEARCH_CACHE_READ_OPEN_FILES] (positive) |
--cache-read-open-readers |
int | 4098 |
cache.read_open_readers |
YSEARCH_CACHE_READ_OPEN_READERS |
Process-wide decoded WavesDB table-reader count limit. Each retained reader also spends cache.read_reader_bytes, and whichever of the two is reached first evicts. Unlike cache.read_open_files this spends memory rather than file descriptors, so size it from the corpus: a segment holds several table families, and a count that cannot hold them all evicts on every query. At 1024, which this defaulted to, a 253-segment corpus needing 1,321 readers held 77% of them and evicted 3,022 times while its byte budget sat 89% empty. That is dearer than it sounds, because a re-opened table re-reads its Bloom filter and block index through a path that bypasses the block cache, so the eviction becomes object reads that repeat for the life of the node: the same query read 62.8MiB in 275 range GETs every time it ran, and none after the count was raised. Measured resident cost is about 760KiB per reader. [cache.read_open_readers; env YSEARCH_CACHE_READ_OPEN_READERS] (positive) |
--cache-read-reader-bytes |
bytes | 2GiB |
cache.read_reader_bytes |
YSEARCH_CACHE_READ_READER_BYTES |
Memory, not disk: process-wide WavesDB table index and Bloom-filter bytes held resident. It is the only cache budget that scales with the corpus rather than with the query, at a measured ~14MiB per segment, so the default holds roughly 145 segments and a larger corpus re-reads a segment's index after evicting it. [cache.read_reader_bytes; env YSEARCH_CACHE_READ_READER_BYTES] (positive) |
--cache-result-enabled |
bool | true |
cache.result_enabled |
YSEARCH_CACHE_RESULT_ENABLED |
Cache generation and segment ranked results. Disable for execution benchmarks; reader, block, plan and stored-field caches remain active. [cache.result_enabled; env YSEARCH_CACHE_RESULT_ENABLED] |
--cache-scrub-entries |
int | 4 |
cache.scrub_entries |
YSEARCH_CACHE_SCRUB_ENTRIES |
How many cached full segments one scrubber pass re-reads. The scrubber walks the cache in a rotating cursor, so this and cache.scrub_interval together set how long a full sweep takes and how much disk read it costs; a segment currently in use is skipped and picked up on a later pass. [cache.scrub_entries; env YSEARCH_CACHE_SCRUB_ENTRIES] (in [0, 4096]) |
--cache-scrub-interval |
duration | 5m |
cache.scrub_interval |
YSEARCH_CACHE_SCRUB_INTERVAL |
How often the background scrubber re-reads cached full segments and checks them against their commits. This is the only thing that notices a cached segment rotting on disk: a query trusts an entry once it has been verified, because verifying costs the SHA-256 of every file in the segment and doing that per request made a many-segment query spend all its time hashing. Zero disables the scrubber, which leaves local corruption undetected until the entry is evicted. [cache.scrub_interval; env YSEARCH_CACHE_SCRUB_INTERVAL] (in [0s, 24h0m0s]) |
--cache-sidecar-bytes |
bytes | 8MiB |
cache.sidecar_bytes |
YSEARCH_CACHE_SIDECAR_BYTES |
Memory, not disk: process-wide optional exact-filter decoder and lease budget shared across indexes and generations. [cache.sidecar_bytes; env YSEARCH_CACHE_SIDECAR_BYTES] (positive) |
--cache-warm-prefetch-bytes |
bytes | 0 |
cache.warm_prefetch_bytes |
YSEARCH_CACHE_WARM_PREFETCH_BYTES |
Optional routing-page warmup byte limit after the first served query; zero disables. It spends object reads, not a budget of its own: warmed pages land in the process-wide routing page cache and are charged there, so warming past that cache only evicts what it just read. Shares foreground cache admission. [cache.warm_prefetch_bytes; env YSEARCH_CACHE_WARM_PREFETCH_BYTES] (in [0, 64MiB]) |
--cache-warm-prefetch-concurrency |
int | 1 |
cache.warm_prefetch_concurrency |
YSEARCH_CACHE_WARM_PREFETCH_CONCURRENCY |
Maximum concurrent optional warmup reads; foreground queries stop new prefetch work. [cache.warm_prefetch_concurrency; env YSEARCH_CACHE_WARM_PREFETCH_CONCURRENCY] (in [0, 8]) |
--compaction-cluster-field |
string | compaction.cluster_field |
YSEARCH_COMPACTION_CLUSTER_FIELD |
Existing scalar filterable string used by cluster layout; an absent field preserves order. [compaction.cluster_field; env YSEARCH_COMPACTION_CLUSTER_FIELD] | |
--compaction-document-layout |
enum | preserve |
compaction.document_layout |
YSEARCH_COMPACTION_DOCUMENT_LAYOUT |
Experimental survivor layout for new compaction outputs; preserve retains input order, cluster groups scalar categories, bisection uses a bounded sampled term graph. [compaction.document_layout; env YSEARCH_COMPACTION_DOCUMENT_LAYOUT] (one of preserve, cluster, bisection) |
--compaction-enabled |
bool | false |
compaction.enabled |
YSEARCH_COMPACTION_ENABLED |
Run single-flight size-tiered compaction inside all-in-one serve. The explicit node compactor role always runs; this switch stays off there and by default so production can isolate maintenance from query and ingest. [compaction.enabled; env YSEARCH_COMPACTION_ENABLED] |
--compaction-hydration-bytes |
bytes | 8GiB |
compaction.hydration_bytes |
YSEARCH_COMPACTION_HYDRATION_BYTES |
Maximum downloaded checkpoint payload retained per compaction job across all input hydrations. Borrowed resident inputs are not copied or charged. Filesystem metadata, output database and spill space have separate accounting. [compaction.hydration_bytes; env YSEARCH_COMPACTION_HYDRATION_BYTES] (positive) |
--compaction-hydration-workers |
int | 2 |
compaction.hydration_workers |
YSEARCH_COMPACTION_HYDRATION_WORKERS |
Maximum concurrent input hydrations per compaction job. [compaction.hydration_workers; env YSEARCH_COMPACTION_HYDRATION_WORKERS] (in [1, 8]) |
--compaction-interval |
duration | 1m |
compaction.interval |
YSEARCH_COMPACTION_INTERVAL |
Interval between background compaction eligibility checks. The all-in-one server waits for sustained ingest idleness; use the isolated compactor role when fan-out must be reduced during continuous ingest. [compaction.interval; env YSEARCH_COMPACTION_INTERVAL] (in [1s, 24h0m0s]) |
--compaction-max-active-segments |
int | 16 |
compaction.max_active_segments |
YSEARCH_COMPACTION_MAX_ACTIVE_SEGMENTS |
Active searchable segment fan-out above which the scheduler may compact. [compaction.max_active_segments; env YSEARCH_COMPACTION_MAX_ACTIVE_SEGMENTS] (positive) |
--compaction-max-concurrent-jobs |
int | 1 |
compaction.max_concurrent_jobs |
YSEARCH_COMPACTION_MAX_CONCURRENT_JOBS |
Shared background compaction job slots across hosted indexes; physical merges are serial and hydration has a separate worker cap. [compaction.max_concurrent_jobs; env YSEARCH_COMPACTION_MAX_CONCURRENT_JOBS] (in [1, 8]) |
--compaction-max-inputs |
int | 8 |
compaction.max_inputs |
YSEARCH_COMPACTION_MAX_INPUTS |
Maximum inputs in one compaction job; jobs are always single-flight. [compaction.max_inputs; env YSEARCH_COMPACTION_MAX_INPUTS] (in [2, 64]) |
--compaction-max-output-bytes |
bytes | 4GiB |
compaction.max_output_bytes |
YSEARCH_COMPACTION_MAX_OUTPUT_BYTES |
Maximum summed input bytes admitted to one compaction proposal. [compaction.max_output_bytes; env YSEARCH_COMPACTION_MAX_OUTPUT_BYTES] (positive) |
--compaction-max-size-ratio |
int | 2 |
compaction.max_size_ratio |
YSEARCH_COMPACTION_MAX_SIZE_RATIO |
Largest size ratio allowed between inputs in one tier. [compaction.max_size_ratio; env YSEARCH_COMPACTION_MAX_SIZE_RATIO] (in [1, 1024]) |
--compaction-min-inputs |
int | 4 |
compaction.min_inputs |
YSEARCH_COMPACTION_MIN_INPUTS |
Minimum adjacent similarly-sized inputs in one compaction job. [compaction.min_inputs; env YSEARCH_COMPACTION_MIN_INPUTS] (in [2, 64]) |
--compaction-read-inflight-bytes |
bytes | 64MiB |
compaction.read_inflight_bytes |
YSEARCH_COMPACTION_READ_INFLIGHT_BYTES |
Shared compaction read payload bytes in flight across jobs. Open reads hold credits until Close; an individual object or range larger than this limit is rejected. [compaction.read_inflight_bytes; env YSEARCH_COMPACTION_READ_INFLIGHT_BYTES] (at least 64KiB) |
--compaction-recent-delta |
int | 4 |
compaction.recent_delta |
YSEARCH_COMPACTION_RECENT_DELTA |
Newest active segments left uncompacted as an ingest delta tier. [compaction.recent_delta; env YSEARCH_COMPACTION_RECENT_DELTA] (in [0, 1024]) |
--compaction-reorder-leaf-documents |
int | 128 |
compaction.reorder_leaf_documents |
YSEARCH_COMPACTION_REORDER_LEAF_DOCUMENTS |
Maximum stable leaf size of experimental balanced graph bisection; each document samples at most 32 terms. [compaction.reorder_leaf_documents; env YSEARCH_COMPACTION_REORDER_LEAF_DOCUMENTS] (in [1, 4096]) |
--compaction-reorder-temp-bytes |
bytes | 1GiB |
compaction.reorder_temp_bytes |
YSEARCH_COMPACTION_REORDER_TEMP_BYTES |
Temporary spill cap for reordered outputs, including permutation, sampled graph and posting resort; the smaller compaction.temporary_bytes cap also applies. [compaction.reorder_temp_bytes; env YSEARCH_COMPACTION_REORDER_TEMP_BYTES] (positive) |
--compaction-routing-fragment-bytes |
bytes | 8MiB |
compaction.routing_fragment_bytes |
YSEARCH_COMPACTION_ROUTING_FRAGMENT_BYTES |
Optional routing fragment disk cap per compaction output segment; overrides builder.routing_fragment_bytes for compaction's own merges so background maintenance can carry its own share independent of foreground ingestion. Zero disables fragment writing for compaction outputs, which also stops this generation's routing descriptor from ever completing until every one of its segments gets a fragment some other way. [compaction.routing_fragment_bytes; env YSEARCH_COMPACTION_ROUTING_FRAGMENT_BYTES] (in [0, 64MiB]) |
--compaction-routing-memory-bytes |
bytes | 64MiB |
compaction.routing_memory_bytes |
YSEARCH_COMPACTION_ROUTING_MEMORY_BYTES |
Memory budget for assembling one generation's routing descriptor from its member segments' own fragments after a successful compaction. Separate from compaction.temporary_bytes and the segment-merge budgets: descriptor assembly reads small fragment objects, not segment checkpoints. [compaction.routing_memory_bytes; env YSEARCH_COMPACTION_ROUTING_MEMORY_BYTES] (at least 64MiB) |
--compaction-routing-temp-bytes |
bytes | 1GiB |
compaction.routing_temp_bytes |
YSEARCH_COMPACTION_ROUTING_TEMP_BYTES |
Spill and page-file budget for the same post-compaction descriptor assembly. Bounded well below compaction.temporary_bytes: a table assembled from fragments alone is the right-sized presence table (internal/routing/value.go), not the segments' own content. [compaction.routing_temp_bytes; env YSEARCH_COMPACTION_ROUTING_TEMP_BYTES] (positive) |
--compaction-target-bytes |
bytes | 512MiB |
compaction.target_bytes |
YSEARCH_COMPACTION_TARGET_BYTES |
Approximate input-byte target for one size-tiered compaction group. [compaction.target_bytes; env YSEARCH_COMPACTION_TARGET_BYTES] (positive) |
--compaction-temporary-bytes |
bytes | 8GiB |
compaction.temporary_bytes |
YSEARCH_COMPACTION_TEMPORARY_BYTES |
Shared accounted spill-byte limit within one physical compaction; hydration and final database storage are separate from spill space. [compaction.temporary_bytes; env YSEARCH_COMPACTION_TEMPORARY_BYTES] (positive) |
--compaction-write-inflight-bytes |
bytes | 64MiB |
compaction.write_inflight_bytes |
YSEARCH_COMPACTION_WRITE_INFLIGHT_BYTES |
Shared compaction write payload bytes in flight across jobs. An individual object larger than this limit is rejected before upload. [compaction.write_inflight_bytes; env YSEARCH_COMPACTION_WRITE_INFLIGHT_BYTES] (at least 64KiB) |
--config-watch |
bool | true |
config.watch |
YSEARCH_CONFIG_WATCH |
Reload the discovered configuration files when any of them changes. [config.watch; env YSEARCH_CONFIG_WATCH] |
--pprof-listen |
string | debug.pprof_listen |
YSEARCH_DEBUG_PPROF_LISTEN |
host:port serving net/http/pprof profiles; empty disables it. It binds before the catalog is opened, so a slow start can be profiled, and an address with no host (:6060) binds loopback. Profiles expose heap contents and goroutine stacks, so keep it on loopback and never on a public interface. [debug.pprof_listen; env YSEARCH_DEBUG_PPROF_LISTEN] | |
--embedding-external-allow-http |
bool | false |
embedding.external_allow_http |
YSEARCH_EMBEDDING_EXTERNAL_ALLOW_HTTP |
Allow plain HTTP external embedding endpoints for trusted development networks. [embedding.external_allow_http; env YSEARCH_EMBEDDING_EXTERNAL_ALLOW_HTTP] |
--embedding-external-batch-size |
int | 128 |
embedding.external_batch_size |
YSEARCH_EMBEDDING_EXTERNAL_BATCH_SIZE |
Maximum texts in one external embedding request. [embedding.external_batch_size; env YSEARCH_EMBEDDING_EXTERNAL_BATCH_SIZE] (in [1, 4096]) |
--embedding-external-concurrency |
int | 8 |
embedding.external_concurrency |
YSEARCH_EMBEDDING_EXTERNAL_CONCURRENCY |
Concurrent external embedding requests per process. [embedding.external_concurrency; env YSEARCH_EMBEDDING_EXTERNAL_CONCURRENCY] (in [1, 1024]) |
--embedding-external-max-retry-after |
duration | 2s |
embedding.external_max_retry_after |
YSEARCH_EMBEDDING_EXTERNAL_MAX_RETRY_AFTER |
Largest Retry-After delay accepted from an external embedding endpoint. [embedding.external_max_retry_after; env YSEARCH_EMBEDDING_EXTERNAL_MAX_RETRY_AFTER] (positive) |
--embedding-external-request-bytes |
bytes | 8MiB |
embedding.external_request_bytes |
YSEARCH_EMBEDDING_EXTERNAL_REQUEST_BYTES |
Maximum encoded external embedding request bytes. [embedding.external_request_bytes; env YSEARCH_EMBEDDING_EXTERNAL_REQUEST_BYTES] (positive) |
--embedding-external-response-bytes |
bytes | 64MiB |
embedding.external_response_bytes |
YSEARCH_EMBEDDING_EXTERNAL_RESPONSE_BYTES |
Maximum external embedding response bytes read before JSON decoding. [embedding.external_response_bytes; env YSEARCH_EMBEDDING_EXTERNAL_RESPONSE_BYTES] (positive) |
--embedding-external-retries |
int | 2 |
embedding.external_retries |
YSEARCH_EMBEDDING_EXTERNAL_RETRIES |
Retry attempts after the first retryable external embedding failure. [embedding.external_retries; env YSEARCH_EMBEDDING_EXTERNAL_RETRIES] (in [0, 16]) |
--embedding-external-retry-base |
duration | 50ms |
embedding.external_retry_base |
YSEARCH_EMBEDDING_EXTERNAL_RETRY_BASE |
Base exponential backoff for external embedding retries. [embedding.external_retry_base; env YSEARCH_EMBEDDING_EXTERNAL_RETRY_BASE] (positive) |
--embedding-external-timeout |
duration | 30s |
embedding.external_timeout |
YSEARCH_EMBEDDING_EXTERNAL_TIMEOUT |
Deadline for one external embedding HTTP attempt sequence. [embedding.external_timeout; env YSEARCH_EMBEDDING_EXTERNAL_TIMEOUT] (positive) |
--embedding-grpc-allow-insecure |
bool | false |
embedding.grpc_allow_insecure |
YSEARCH_EMBEDDING_GRPC_ALLOW_INSECURE |
Allow plaintext gRPC embedding endpoints on trusted internal networks. [embedding.grpc_allow_insecure; env YSEARCH_EMBEDDING_GRPC_ALLOW_INSECURE] |
--embedding-grpc-batch-size |
int | 128 |
embedding.grpc_batch_size |
YSEARCH_EMBEDDING_GRPC_BATCH_SIZE |
Maximum texts in one gRPC embedding request. [embedding.grpc_batch_size; env YSEARCH_EMBEDDING_GRPC_BATCH_SIZE] (in [1, 4096]) |
--embedding-grpc-concurrency |
int | 8 |
embedding.grpc_concurrency |
YSEARCH_EMBEDDING_GRPC_CONCURRENCY |
Concurrent gRPC embedding requests per process. [embedding.grpc_concurrency; env YSEARCH_EMBEDDING_GRPC_CONCURRENCY] (in [1, 1024]) |
--embedding-grpc-request-bytes |
bytes | 8MiB |
embedding.grpc_request_bytes |
YSEARCH_EMBEDDING_GRPC_REQUEST_BYTES |
Maximum encoded gRPC embedding request bytes. [embedding.grpc_request_bytes; env YSEARCH_EMBEDDING_GRPC_REQUEST_BYTES] (positive) |
--embedding-grpc-response-bytes |
bytes | 64MiB |
embedding.grpc_response_bytes |
YSEARCH_EMBEDDING_GRPC_RESPONSE_BYTES |
Maximum encoded gRPC embedding response bytes. [embedding.grpc_response_bytes; env YSEARCH_EMBEDDING_GRPC_RESPONSE_BYTES] (positive) |
--embedding-grpc-timeout |
duration | 30s |
embedding.grpc_timeout |
YSEARCH_EMBEDDING_GRPC_TIMEOUT |
Deadline for one gRPC embedding request. [embedding.grpc_timeout; env YSEARCH_EMBEDDING_GRPC_TIMEOUT] (positive) |
--embedding-grpc-work-class |
enum | auto |
embedding.grpc_work_class |
YSEARCH_EMBEDDING_GRPC_WORK_CLASS |
gRPC embedding scheduler class; auto maps queries to interactive and indexing to bulk. [embedding.grpc_work_class; env YSEARCH_EMBEDDING_GRPC_WORK_CLASS] (one of auto, interactive, bulk) |
--embedding-internal-batch-size |
int | 32 |
embedding.internal_batch_size |
YSEARCH_EMBEDDING_INTERNAL_BATCH_SIZE |
Maximum texts in one internal embedding batch. [embedding.internal_batch_size; env YSEARCH_EMBEDDING_INTERNAL_BATCH_SIZE] (in [1, 4096]) |
--embedding-internal-concurrency |
int | 2 |
embedding.internal_concurrency |
YSEARCH_EMBEDDING_INTERNAL_CONCURRENCY |
Concurrent pure-Go internal embedding batches. [embedding.internal_concurrency; env YSEARCH_EMBEDDING_INTERNAL_CONCURRENCY] (in [1, 256]) |
--embedding-internal-enabled |
bool | false |
embedding.internal_enabled |
YSEARCH_EMBEDDING_INTERNAL_ENABLED |
Enable the pure-Go internal embedding runtime. Models remain lazy and checksum-pinned by schema profiles. [embedding.internal_enabled; env YSEARCH_EMBEDDING_INTERNAL_ENABLED] |
--embedding-model-cache-bytes |
bytes | 10GiB |
embedding.model_cache_bytes |
YSEARCH_EMBEDDING_MODEL_CACHE_BYTES |
Maximum installed bytes in the internal-model cache. [embedding.model_cache_bytes; env YSEARCH_EMBEDDING_MODEL_CACHE_BYTES] (positive) |
--embedding-model-cache-dir |
string | embedding.model_cache_dir |
YSEARCH_EMBEDDING_MODEL_CACHE_DIR |
Checksum-addressed internal-model cache directory. Empty disables internal embedding; keep it distinct from cache.dir. A relative value in a configuration file resolves against that file's directory. [embedding.model_cache_dir; env YSEARCH_EMBEDDING_MODEL_CACHE_DIR] | |
--embedding-model-cache-packages |
int | 8 |
embedding.model_cache_packages |
YSEARCH_EMBEDDING_MODEL_CACHE_PACKAGES |
Maximum installed internal-model packages. [embedding.model_cache_packages; env YSEARCH_EMBEDDING_MODEL_CACHE_PACKAGES] (positive) |
--embedding-model-download-allow-http |
bool | false |
embedding.model_download_allow_http |
YSEARCH_EMBEDDING_MODEL_DOWNLOAD_ALLOW_HTTP |
Allow plain HTTP model manifests and artifacts for trusted development networks. [embedding.model_download_allow_http; env YSEARCH_EMBEDDING_MODEL_DOWNLOAD_ALLOW_HTTP] |
--embedding-model-download-concurrency |
int | 2 |
embedding.model_download_concurrency |
YSEARCH_EMBEDDING_MODEL_DOWNLOAD_CONCURRENCY |
Concurrent verified internal-model artifact downloads. [embedding.model_download_concurrency; env YSEARCH_EMBEDDING_MODEL_DOWNLOAD_CONCURRENCY] (in [1, 64]) |
--embedding-model-download-timeout |
duration | 10m |
embedding.model_download_timeout |
YSEARCH_EMBEDDING_MODEL_DOWNLOAD_TIMEOUT |
Deadline for one internal-model package installation. [embedding.model_download_timeout; env YSEARCH_EMBEDDING_MODEL_DOWNLOAD_TIMEOUT] (positive) |
--embedding-model-manifest-bytes |
bytes | 1MiB |
embedding.model_manifest_bytes |
YSEARCH_EMBEDDING_MODEL_MANIFEST_BYTES |
Maximum bytes in one internal-model manifest. [embedding.model_manifest_bytes; env YSEARCH_EMBEDDING_MODEL_MANIFEST_BYTES] (positive) |
--embedding-model-package-bytes |
bytes | 4GiB |
embedding.model_package_bytes |
YSEARCH_EMBEDDING_MODEL_PACKAGE_BYTES |
Maximum bytes in one downloaded internal-model package. [embedding.model_package_bytes; env YSEARCH_EMBEDDING_MODEL_PACKAGE_BYTES] (positive) |
--embedding-query-cache-bytes |
bytes | 64MiB |
embedding.query_cache_bytes |
YSEARCH_EMBEDDING_QUERY_CACHE_BYTES |
Maximum float-vector bytes retained by the text-query embedding cache. [embedding.query_cache_bytes; env YSEARCH_EMBEDDING_QUERY_CACHE_BYTES] (positive) |
--embedding-query-cache-entries |
int | 4096 |
embedding.query_cache_entries |
YSEARCH_EMBEDDING_QUERY_CACHE_ENTRIES |
Maximum completed text-query embeddings retained per process. [embedding.query_cache_entries; env YSEARCH_EMBEDDING_QUERY_CACHE_ENTRIES] (positive) |
--embedding-query-cache-ttl |
duration | 10m |
embedding.query_cache_ttl |
YSEARCH_EMBEDDING_QUERY_CACHE_TTL |
Lifetime of a completed text-query embedding cache entry. [embedding.query_cache_ttl; env YSEARCH_EMBEDDING_QUERY_CACHE_TTL] (positive) |
--admin-fleet |
list | fleet.admin_fleet |
YSEARCH_FLEET_ADMIN_FLEET |
Node host:port endpoints StreamFleetStats fans in; empty refuses the fleet stream. [fleet.admin_fleet; env YSEARCH_FLEET_ADMIN_FLEET] | |
--aggregators |
list | fleet.aggregators |
YSEARCH_FLEET_AGGREGATORS |
Aggregator host:port endpoints. [fleet.aggregators; env YSEARCH_FLEET_AGGREGATORS] | |
--builders |
list | fleet.builders |
YSEARCH_FLEET_BUILDERS |
Builder host:port endpoints the router polls and rendezvous-routes batches across. [fleet.builders; env YSEARCH_FLEET_BUILDERS] | |
--fallback-workers |
list | fleet.fallback_workers |
YSEARCH_FLEET_FALLBACK_WORKERS |
Worker host:port endpoints: the dispatch universe and the cache-oblivious fallback. [fleet.fallback_workers; env YSEARCH_FLEET_FALLBACK_WORKERS] | |
--fan-in |
int | 0 |
fleet.fan_in |
YSEARCH_FLEET_FAN_IN |
Children per merge node in coordinator plans; zero means the planner's default, otherwise at least 2. [fleet.fan_in; env YSEARCH_FLEET_FAN_IN] (in [0, 1024]) |
--lane-slots |
string | interactive=4,streaming=2 |
fleet.lane_slots |
YSEARCH_FLEET_LANE_SLOTS |
Per-lane worker slot pools, lane=count. [fleet.lane_slots; env YSEARCH_FLEET_LANE_SLOTS] |
--mergers |
list | fleet.mergers |
YSEARCH_FLEET_MERGERS |
Merge host:port endpoints: the coordinator's merge tier, a merger's delegation peers. [fleet.mergers; env YSEARCH_FLEET_MERGERS] | |
--follower-discovery-interval |
duration | 30s |
follower.discovery_interval |
YSEARCH_FOLLOWER_DISCOVERY_INTERVAL |
How often a root attachment looks for indexes that appeared or disappeared under it. Separate from follower.poll_interval because discovery lists prefixes while a poll reads one pointer, and listing is the more expensive and more rate-limited of the two. [follower.discovery_interval; env YSEARCH_FOLLOWER_DISCOVERY_INTERVAL] (positive) |
--follower-generation-overlap |
duration | 30s |
follower.generation_overlap |
YSEARCH_FOLLOWER_GENERATION_OVERLAP |
Maximum age of an unseen catalog generation a worker may resolve on demand; in-flight references may keep its engine beyond this window. [follower.generation_overlap; env YSEARCH_FOLLOWER_GENERATION_OVERLAP] (positive) |
--follower-max-staleness |
duration | 5m |
follower.max_staleness |
YSEARCH_FOLLOWER_MAX_STALENESS |
How long a follower may go without confirming its installed generation is still current before it refuses new queries. A reader that cannot reach its source keeps answering from cached data indefinitely otherwise, which is worse than an error: the results look fine and are silently frozen. Status stays readable past this point so an operator can see why. [follower.max_staleness; env YSEARCH_FOLLOWER_MAX_STALENESS] (positive) |
--follower-poll-interval |
duration | 2s |
follower.poll_interval |
YSEARCH_FOLLOWER_POLL_INTERVAL |
How often a node checks the catalog's latest pointer. [follower.poll_interval; env YSEARCH_FOLLOWER_POLL_INTERVAL] (positive) |
--follower-retired-generation-grace |
duration | 30s |
follower.retired_generation_grace |
YSEARCH_FOLLOWER_RETIRED_GENERATION_GRACE |
How long a superseded generation's engine stays open after its last query. [follower.retired_generation_grace; env YSEARCH_FOLLOWER_RETIRED_GENERATION_GRACE] (positive) |
--gc-grace |
duration | 1h |
gc.grace |
YSEARCH_GC_GRACE |
Additional safety margin added to every scheduled GC reachability horizon. [gc.grace; env YSEARCH_GC_GRACE] (in [0s, 168h0m0s]) |
--gc-interval |
duration | 1h |
gc.interval |
YSEARCH_GC_INTERVAL |
Cadence at which the dedicated compactor role writes a GC proposal and considers a quarantined older proposal. [gc.interval; env YSEARCH_GC_INTERVAL] (in [1s, 168h0m0s]) |
--gc-maximum-stream-lifetime |
duration | 1h |
gc.maximum_stream_lifetime |
YSEARCH_GC_MAXIMUM_STREAM_LIFETIME |
Longest query-stream lifetime protected when marking superseded generations for scheduled GC. [gc.maximum_stream_lifetime; env YSEARCH_GC_MAXIMUM_STREAM_LIFETIME] (in [0s, 168h0m0s]) |
--gc-minimum-upload-age |
duration | 24h |
gc.minimum_upload_age |
YSEARCH_GC_MINIMUM_UPLOAD_AGE |
Minimum age before an unreferenced object can enter a scheduled GC proposal. [gc.minimum_upload_age; env YSEARCH_GC_MINIMUM_UPLOAD_AGE] (in [0s, 720h0m0s]) |
--gc-quarantine-age |
duration | 24h |
gc.quarantine_age |
YSEARCH_GC_QUARANTINE_AGE |
Minimum age of an immutable GC proposal before a fresh mark may authorize deleting its still-unreachable exact keys. [gc.quarantine_age; env YSEARCH_GC_QUARANTINE_AGE] (in [1s, 720h0m0s]) |
--gc-retained-generations |
int | 2 |
gc.retained_generations |
YSEARCH_GC_RETAINED_GENERATIONS |
Historical catalog generations retained in addition to latest during scheduled GC. [gc.retained_generations; env YSEARCH_GC_RETAINED_GENERATIONS] (in [0, 1024]) |
--gc-sweep-enabled |
bool | false |
gc.sweep_enabled |
YSEARCH_GC_SWEEP_ENABLED |
Allow the dedicated compactor role to delete freshly re-proven orphan objects after an immutable dry-run proposal passes quarantine. Disabled by default. [gc.sweep_enabled; env YSEARCH_GC_SWEEP_ENABLED] |
--generation |
string | index.generation |
YSEARCH_INDEX_GENERATION |
Exact generation to pin, or empty for the latest. [index.generation; env YSEARCH_INDEX_GENERATION] | |
--index |
string | index.name |
YSEARCH_INDEX_NAME |
Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles. [index.name; env YSEARCH_INDEX_NAME] | |
--ingest-burst-documents |
int | 100000 |
ingest.burst_documents |
YSEARCH_INGEST_BURST_DOCUMENTS |
Per-index document tokens available for an ingest burst when the rate quota is enabled. [ingest.burst_documents; env YSEARCH_INGEST_BURST_DOCUMENTS] (positive) |
--ingest-dir |
string | ingest.dir |
YSEARCH_INGEST_DIR |
Ingest spool/build directory for builders and scratch root for the dedicated compactor role. A relative value in a configuration file resolves against that file's directory. [ingest.dir; env YSEARCH_INGEST_DIR] | |
--ingest-documents-per-second |
int | 0 |
ingest.documents_per_second |
YSEARCH_INGEST_DOCUMENTS_PER_SECOND |
Per-router, per-index document admission rate; zero disables the rate quota. [ingest.documents_per_second; env YSEARCH_INGEST_DOCUMENTS_PER_SECOND] (in [0, 1099511627776]) |
--ingest-global-queue-bytes |
bytes | 256MiB |
ingest.global_queue_bytes |
YSEARCH_INGEST_GLOBAL_QUEUE_BYTES |
Encoded ingest bytes all router sessions may hold while waiting for builders. [ingest.global_queue_bytes; env YSEARCH_INGEST_GLOBAL_QUEUE_BYTES] (positive) |
--ingest-index-queue-bytes |
bytes | 64MiB |
ingest.index_queue_bytes |
YSEARCH_INGEST_INDEX_QUEUE_BYTES |
Encoded ingest bytes one index may hold while waiting for builders. [ingest.index_queue_bytes; env YSEARCH_INGEST_INDEX_QUEUE_BYTES] (positive) |
--ingest-max-batch-bytes |
bytes | 4MiB |
ingest.max_batch_bytes |
YSEARCH_INGEST_MAX_BATCH_BYTES |
Largest accepted ingest batch. [ingest.max_batch_bytes; env YSEARCH_INGEST_MAX_BATCH_BYTES] (positive) |
--ingest-max-document-bytes |
bytes | 16MiB |
ingest.max_document_bytes |
YSEARCH_INGEST_MAX_DOCUMENT_BYTES |
Largest accepted document. [ingest.max_document_bytes; env YSEARCH_INGEST_MAX_DOCUMENT_BYTES] (positive) |
--ingest-seal-age |
duration | 30s |
ingest.seal_age |
YSEARCH_INGEST_SEAL_AGE |
Age at which an open build seals. [ingest.seal_age; env YSEARCH_INGEST_SEAL_AGE] (positive) |
--ingest-seal-bytes |
bytes | 0 |
ingest.seal_bytes |
YSEARCH_INGEST_SEAL_BYTES |
Spooled bytes at which an open build seals; zero derives it as a quarter of builder.sort_memory_bytes. A build's postings are about twice its spooled bytes and the partitions get roughly half the sort budget, so a spool larger than that quarter cannot be sorted in memory and the build spills instead — which is the difference between one file per build and hundreds, and measured 2.5x on the build itself. [ingest.seal_bytes; env YSEARCH_INGEST_SEAL_BYTES] (in [0, 1TiB]) |
--ingest-seal-documents |
int | 100000 |
ingest.seal_documents |
YSEARCH_INGEST_SEAL_DOCUMENTS |
Spooled documents at which an open build seals. [ingest.seal_documents; env YSEARCH_INGEST_SEAL_DOCUMENTS] (positive) |
--log-format |
enum | text |
log.format |
YSEARCH_LOG_FORMAT |
Log line format. [log.format; env YSEARCH_LOG_FORMAT] (one of text, json) |
--log-level |
enum | info |
log.level |
YSEARCH_LOG_LEVEL |
Minimum level written to stderr. [log.level; env YSEARCH_LOG_LEVEL] (one of error, warn, info, debug) |
--object-backend |
enum | fs |
object.backend |
YSEARCH_OBJECT_BACKEND |
Object store backend. [object.backend; env YSEARCH_OBJECT_BACKEND] (one of fs, s3) |
--object-dir |
string | object.dir |
YSEARCH_OBJECT_DIR |
Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory. [object.dir; env YSEARCH_OBJECT_DIR] | |
--object-root |
string | indexes |
object.root |
YSEARCH_OBJECT_ROOT |
Object key root. [object.root; env YSEARCH_OBJECT_ROOT] |
--s3-anonymous |
bool | false |
object.s3.anonymous |
YSEARCH_OBJECT_S3_ANONYMOUS |
Sign no requests at all, for a bucket that grants public reads. This is a deliberate choice, never a fallback: an unresolved credential chain already signs anonymously, and a reader that quietly degraded to unsigned requests would report a permissions problem as an empty index. [object.s3.anonymous; env YSEARCH_OBJECT_S3_ANONYMOUS] |
--s3-bucket |
string | object.s3.bucket |
YSEARCH_OBJECT_S3_BUCKET |
S3 bucket; required for the s3 backend. [object.s3.bucket; env YSEARCH_OBJECT_S3_BUCKET] | |
--s3-endpoint |
string | object.s3.endpoint |
YSEARCH_OBJECT_S3_ENDPOINT |
S3 endpoint host:port; required for the s3 backend. [object.s3.endpoint; env YSEARCH_OBJECT_S3_ENDPOINT] | |
--s3-path-style |
bool | false |
object.s3.path_style |
YSEARCH_OBJECT_S3_PATH_STYLE |
Use path-style S3 addressing. [object.s3.path_style; env YSEARCH_OBJECT_S3_PATH_STYLE] |
--s3-prefix |
string | object.s3.prefix |
YSEARCH_OBJECT_S3_PREFIX |
S3 key prefix. [object.s3.prefix; env YSEARCH_OBJECT_S3_PREFIX] | |
--s3-region |
string | object.s3.region |
YSEARCH_OBJECT_S3_REGION |
S3 region. [object.s3.region; env YSEARCH_OBJECT_S3_REGION] | |
--s3-use-ssl |
bool | true |
object.s3.use_ssl |
YSEARCH_OBJECT_S3_USE_SSL |
Use TLS to the S3 endpoint. [object.s3.use_ssl; env YSEARCH_OBJECT_S3_USE_SSL] |
--source |
string | object.source |
YSEARCH_OBJECT_SOURCE |
Dataset URL to attach read-only, such as s3://bucket/root/ for a whole root or s3://bucket/root/indexes/name/ for one index. It derives object.backend, the bucket, prefix and root, the index when the URL names one, and server.read_only, each only where nothing more specific was set. Reading someone else's published index is the whole purpose, so attaching one implies read-only and cannot be talked out of it. [object.source; env YSEARCH_OBJECT_SOURCE] | |
--metrics-listen |
string | :9550 |
observability.metrics_listen |
YSEARCH_OBSERVABILITY_METRICS_LISTEN |
host:port serving Prometheus exposition at /metrics; empty disables it. Unlike debug.pprof_listen this is on by default and binds every interface, because a metric carries no document text, no query, and no key material, and a scrape target that has to be switched on is one nobody switches on. Every series already carries the role label, so the scrape target only has to supply instance and pod. [observability.metrics_listen; env YSEARCH_OBSERVABILITY_METRICS_LISTEN] |
--publisher-announce-interval |
duration | 15s |
publisher.announce_interval |
YSEARCH_PUBLISHER_ANNOUNCE_INTERVAL |
Requested commit-marker publication cadence; the daemon floors it at follower.poll_interval and 15 seconds. [publisher.announce_interval; env YSEARCH_PUBLISHER_ANNOUNCE_INTERVAL] (in [1s, 1h0m0s]) |
--publisher-lease-ttl |
duration | 30s |
publisher.lease_ttl |
YSEARCH_PUBLISHER_LEASE_TTL |
Startup-fixed object-store lease lifetime for the catalog publisher; renewal runs at one third of this value. [publisher.lease_ttl; env YSEARCH_PUBLISHER_LEASE_TTL] (in [5s, 10m0s]) |
--collapse-key-versions |
bool | true |
query.collapse_key_versions |
YSEARCH_QUERY_COLLAPSE_KEY_VERSIONS |
Return one hit per document key, the copy with the greatest mutation version. A re-pushed document is stored as a new version rather than replacing the old one, so without this a key appears once per copy. Collapsing removes candidates after selection, so a request may return fewer than top_k. [query.collapse_key_versions; env YSEARCH_QUERY_COLLAPSE_KEY_VERSIONS] |
--query-compiled-cache |
bool | false |
query.compiled_cache |
YSEARCH_QUERY_COMPILED_CACHE |
Experimental leased compiled-query cache within the shared metadata allowance. Also reuses bounded dictionary plans for eager generation-owned readers; lazy reader plans stay request-owned. Cache pressure falls back to request-owned compilation or preparation. [query.compiled_cache; env YSEARCH_QUERY_COMPILED_CACHE] |
--query-default-top-k |
int | 10 |
query.default_top_k |
YSEARCH_QUERY_DEFAULT_TOP_K |
top_k when a request names none. [query.default_top_k; env YSEARCH_QUERY_DEFAULT_TOP_K] (in [1, 10000]) |
--query-defer-public-ids |
bool | true |
query.defer_public_ids |
YSEARCH_QUERY_DEFER_PUBLIC_IDS |
Resolve a segment survivor's public ID only when the global merge returns it or must break a score tie with it, instead of for every survivor of every segment. Results are identical either way; false restores eager resolution as a same-code control. [query.defer_public_ids; env YSEARCH_QUERY_DEFER_PUBLIC_IDS] |
--query-lexical-memory-bytes |
bytes | 384MiB |
query.lexical_memory_bytes |
YSEARCH_QUERY_LEXICAL_MEMORY_BYTES |
Process-wide lexical request, candidate, queue and merge memory admission budget. Storage blocks and ordinal pages have separate cache budgets; busy requests fail with resource exhaustion. Sized to admit one request merging 64 segments at the product's 100,000-result top_k ceiling (lexical.MaxResultLimit; estimateLexicalFanoutMemory(64, 100000) = 182,632,832 bytes) with room for a second concurrent one that size. [query.lexical_memory_bytes; env YSEARCH_QUERY_LEXICAL_MEMORY_BYTES] (positive) |
--query-lexical-strategy |
enum | block-max |
query.lexical_strategy |
YSEARCH_QUERY_LEXICAL_STRATEGY |
Experimental exact lexical traversal selection; unsupported query shapes conservatively fall back to block-max. [query.lexical_strategy; env YSEARCH_QUERY_LEXICAL_STRATEGY] (one of block-max, auto, single-term-block-max, conjunction, block-max-maxscore) |
--query-logical-bound-entries |
int | 0 |
query.logical_bound_entries |
YSEARCH_QUERY_LOGICAL_BOUND_ENTRIES |
Experimental score-bound subblock size within decoded postings; zero uses physical blocks. Does not reduce physical read size. [query.logical_bound_entries; env YSEARCH_QUERY_LOGICAL_BOUND_ENTRIES] (in [0, 256]) |
--query-max-ast-depth |
int | 32 |
query.max_ast_depth |
YSEARCH_QUERY_MAX_AST_DEPTH |
Deepest query nesting either grammar accepts. [query.max_ast_depth; env YSEARCH_QUERY_MAX_AST_DEPTH] (in [1, 1024]) |
--query-max-results |
int | 0 |
query.max_results |
YSEARCH_QUERY_MAX_RESULTS |
Ceiling on maximum_results per request; zero keeps the engine default. [query.max_results; env YSEARCH_QUERY_MAX_RESULTS] |
--query-ordinal-mode |
enum | pages |
query.ordinal_mode |
YSEARCH_QUERY_ORDINAL_MODE |
Experimental ID residency policy under the shared ordinal budget. Whole tables are capped at 8 MiB and fall back to pages; adaptive promotion requires repeated broad page coverage. [query.ordinal_mode; env YSEARCH_QUERY_ORDINAL_MODE] (one of pages, whole, adaptive) |
--query-packed-simd |
bool | false |
query.packed_simd |
YSEARCH_QUERY_PACKED_SIMD |
Experimental native packed-posting decoding on supported CPUs; preserves scalar fallback and semantic validation. [query.packed_simd; env YSEARCH_QUERY_PACKED_SIMD] |
--query-phrase-gap-expansion-limit |
int | 64 |
query.phrase_gap_expansion_limit |
YSEARCH_QUERY_PHRASE_GAP_EXPANSION_LIMIT |
Most exact gap variants a {m,n} quantifier may expand to. [query.phrase_gap_expansion_limit; env YSEARCH_QUERY_PHRASE_GAP_EXPANSION_LIMIT] (in [1, 4096]) |
--query-regex-max-expansions |
int | 256 |
query.regex_max_expansions |
YSEARCH_QUERY_REGEX_MAX_EXPANSIONS |
Most dictionary terms a regex or prefix may expand to before the query is refused. [query.regex_max_expansions; env YSEARCH_QUERY_REGEX_MAX_EXPANSIONS] (in [1, 65536]) |
--query-scoring-profile |
enum | bm25f-v1 |
query.scoring_profile |
YSEARCH_QUERY_SCORING_PROFILE |
Scoring profile for a request that names none. bm25f-v1 scores each segment with its own statistics; bm25f-pinned-v1 (spec/50 §2) scores every segment under the generation's pinned statistics epoch, so scores do not depend on segment layout. It needs stats.dir; without it a pinned request fails with a typed error, never with segment statistics. [query.scoring_profile; env YSEARCH_QUERY_SCORING_PROFILE] (one of bm25f-v1, bm25f-pinned-v1) |
--query-set-simd |
bool | false |
query.set_simd |
YSEARCH_QUERY_SET_SIMD |
Experimental native intersection for balanced sparse filter arrays; skewed arrays retain scalar galloping. [query.set_simd; env YSEARCH_QUERY_SET_SIMD] |
--routing-presence-bytes |
bytes | 0 |
routing.presence_bytes |
YSEARCH_ROUTING_PRESENCE_BYTES |
Memory, not disk: resident budget for per-segment term-presence filters, used only when the generation has no routing table. A generation that has one prunes through it instead and holds no filters at all, whatever this says, because the table is read through a small page cache rather than held. Zero means none under cache.lazy_readers and unbounded without it, which at 294 segments was 1.4GiB of resident filters. That promotion for eager readers stays on for now: builder.routing_fragment_bytes and compaction.routing_fragment_bytes only default on from 2026-09-23, nothing rewrites a segment built before that, and no existing corpus has been rebuilt or fully compacted since - so a generation with an unfragmented member still depends on this filter to prune anything, including the published demo image, which does not set this flag. Filters are loaded in catalog order until the budget is reached; segments without one stay unknown and are still executed, so results never change. Budget against the decoded size, not the transfer: 680MiB of admitted filters measured 1.4GiB resident, about 2.1 times what this charges them. [routing.presence_bytes; env YSEARCH_ROUTING_PRESENCE_BYTES] (in [0, 8GiB]) |
--data-dir |
string | server.data_dir |
YSEARCH_SERVER_DATA_DIR |
Developer shortcut: derives object.backend=fs, object.dir, cache.dir, ingest.dir, and config.file beneath one directory where nothing more specific is set. A relative value in a configuration file resolves against that file's directory. [server.data_dir; env YSEARCH_SERVER_DATA_DIR] | |
--grace-period |
duration | 5s |
server.grace_period |
YSEARCH_SERVER_GRACE_PERIOD |
Graceful shutdown period. [server.grace_period; env YSEARCH_SERVER_GRACE_PERIOD] (positive) |
--listen |
string | 127.0.0.1:9500 |
server.listen |
YSEARCH_SERVER_LISTEN |
gRPC listen host:port serve and node bind; the default is the address the client verbs dial (client.server). [server.listen; env YSEARCH_SERVER_LISTEN] |
--max-receive-bytes |
bytes | 4MiB |
server.max_receive_bytes |
YSEARCH_SERVER_MAX_RECEIVE_BYTES |
Maximum gRPC request bytes (at least 64KiB). [server.max_receive_bytes; env YSEARCH_SERVER_MAX_RECEIVE_BYTES] (at least 64KiB) |
--max-send-bytes |
bytes | 4MiB |
server.max_send_bytes |
YSEARCH_SERVER_MAX_SEND_BYTES |
Maximum gRPC response bytes (at least 64KiB, one result frame). [server.max_send_bytes; env YSEARCH_SERVER_MAX_SEND_BYTES] (at least 64KiB) |
--node-id |
string | server.node_id |
YSEARCH_SERVER_NODE_ID |
Node identity; empty defaults to the bound listen address. [server.node_id; env YSEARCH_SERVER_NODE_ID] | |
--server-query-receive-memory-bytes |
bytes | 320MiB |
server.query_receive_memory_bytes |
YSEARCH_SERVER_QUERY_RECEIVE_MEMORY_BYTES |
Shared request-memory allowance for Search, worker Execute, Merge, ValidateQuery, CacheState and FetchStored. Holds decoded requests until RPC completion. Receive workspace waits at most 5ms in a 64-call queue; decoded admission refuses immediately when full. Must fit three receive buffers (each at least 1MiB) plus decoded requests. Unary wire reception/decompression and HTTP/2 queues precede this admission. Sized for at least 24 concurrent full server.max_receive_bytes receives at its default (24 * 13,238,272 bytes = 303MiB, plus headroom): fewer than that admits only a handful of concurrent requests before refusing the rest with ResourceExhausted. [server.query_receive_memory_bytes; env YSEARCH_SERVER_QUERY_RECEIVE_MEMORY_BYTES] (positive) |
--read-only |
bool | false |
server.read_only |
YSEARCH_SERVER_READ_ONLY |
Refuse every object-store write for this process's lifetime. Enforced at the single store every writer resolves through, so background work that never touches an RPC - garbage collection, and the GC dry run, which writes a proposal object before any delete decision - fails closed too. Startup-fixed on purpose: a running process cannot be talked into writing by a config reload. [server.read_only; env YSEARCH_SERVER_READ_ONLY] |
--roles |
list | server.roles |
YSEARCH_SERVER_ROLES |
Comma-separated roles for node: coordinator, worker, merger, aggregator, compactor, router, builder, publisher. [server.roles; env YSEARCH_SERVER_ROLES] | |
--server-source-management |
enum | loopback |
server.source_management |
YSEARCH_SERVER_SOURCE_MANAGEMENT |
Which peers may call SourceService, the RPC that changes which datasets this process reads. loopback answers only a caller that reached this process without crossing a network, so binding server.listen to every interface still does not expose it. any serves it to anything that can reach the port: the service has no authentication of its own, so choose it only where something in front of the address authenticates. [server.source_management; env YSEARCH_SERVER_SOURCE_MANAGEMENT] (one of loopback, any) |
--zone |
string | default |
server.zone |
YSEARCH_SERVER_ZONE |
Placement zone this node advertises in. [server.zone; env YSEARCH_SERVER_ZONE] |
--stats-dir |
string | stats.dir |
YSEARCH_STATS_DIR |
Directory of this node's statistics databases, one per index (spec/50 §3.3). Every served generation is folded into it and its epoch pinned for bm25f-pinned-v1. Unlike cache.dir it is not disposable: a node that loses it refolds from the catalog. Empty disables epochs. A relative value in a configuration file resolves against that file's directory. [stats.dir; env YSEARCH_STATS_DIR] | |
--stats-history-generations |
int | 6000 |
stats.history_generations |
YSEARCH_STATS_HISTORY_GENERATIONS |
Generations of per-generation statistics deltas kept to reconstruct an earlier epoch (spec/50 §3.3); about two days at one generation per 30 s. [stats.history_generations; env YSEARCH_STATS_HISTORY_GENERATIONS] (in [1, 16777216]) |
--hydrate-throughput-floor |
bytes | 128MiB |
storage.hydrate_throughput_floor |
YSEARCH_STORAGE_HYDRATE_THROUGHPUT_FLOOR |
Lowest believable hydration throughput in bytes per second. [storage.hydrate_throughput_floor; env YSEARCH_STORAGE_HYDRATE_THROUGHPUT_FLOOR] (positive) |
--hysteresis-denominator |
int | 4 |
storage.hysteresis_denominator |
YSEARCH_STORAGE_HYSTERESIS_DENOMINATOR |
Hysteresis denominator; must be below the numerator. [storage.hysteresis_denominator; env YSEARCH_STORAGE_HYSTERESIS_DENOMINATOR] (in [1, 4294967295]) |
--hysteresis-numerator |
int | 5 |
storage.hysteresis_numerator |
YSEARCH_STORAGE_HYSTERESIS_NUMERATOR |
Hysteresis numerator; must exceed the denominator. [storage.hysteresis_numerator; env YSEARCH_STORAGE_HYSTERESIS_NUMERATOR] (in [1, 4294967295]) |
--mode |
enum | AUTO |
storage.mode |
YSEARCH_STORAGE_MODE |
Storage mode: HYDRATE_FULL, REMOTE_BLOCKS, or AUTO (AUTO is refused by the checkpoint-bound serve). [storage.mode; env YSEARCH_STORAGE_MODE] (one of HYDRATE_FULL, REMOTE_BLOCKS, AUTO) |
--remote-latency-floor |
duration | 2ms |
storage.remote_latency_floor |
YSEARCH_STORAGE_REMOTE_LATENCY_FLOOR |
Lowest believable remote request latency. [storage.remote_latency_floor; env YSEARCH_STORAGE_REMOTE_LATENCY_FLOOR] (positive) |
--remote-throughput-floor |
bytes | 64MiB |
storage.remote_throughput_floor |
YSEARCH_STORAGE_REMOTE_THROUGHPUT_FLOOR |
Lowest believable remote throughput in bytes per second. [storage.remote_throughput_floor; env YSEARCH_STORAGE_REMOTE_THROUGHPUT_FLOOR] (positive) |
--scan-threshold-permille |
int | 200 |
storage.scan_threshold_permille |
YSEARCH_STORAGE_SCAN_THRESHOLD_PERMILLE |
Scan fraction above which AUTO hydrates. [storage.scan_threshold_permille; env YSEARCH_STORAGE_SCAN_THRESHOLD_PERMILLE] (in [0, 1000]) |
--tail-impact-enabled |
bool | false |
tail.impact_enabled |
YSEARCH_TAIL_IMPACT_ENABLED |
Persist score-banded approximate-tail data. Disabled avoids two additional records per unique term when exact tails are sufficient. [tail.impact_enabled; env YSEARCH_TAIL_IMPACT_ENABLED] |
--tail-impact-maximum-bands |
int | 64 |
tail.impact_maximum_bands |
YSEARCH_TAIL_IMPACT_MAXIMUM_BANDS |
Maximum score-impact bands persisted for one term. [tail.impact_maximum_bands; env YSEARCH_TAIL_IMPACT_MAXIMUM_BANDS] (in [1, 4096]) |
--tail-impact-target-documents |
int | 4096 |
tail.impact_target_documents |
YSEARCH_TAIL_IMPACT_TARGET_DOCUMENTS |
Target postings per persisted impact run. [tail.impact_target_documents; env YSEARCH_TAIL_IMPACT_TARGET_DOCUMENTS] (in [1, 4294967295]) |
--tail-maximum-ordering-error |
float | 0 |
tail.maximum_ordering_error |
YSEARCH_TAIL_MAXIMUM_ORDERING_ERROR |
Server ceiling on accepted approximate-tail score-ordering error; zero requires exact fallback. [tail.maximum_ordering_error; env YSEARCH_TAIL_MAXIMUM_ORDERING_ERROR] (in [0, 1.7976931348623157e+308]) |
--vector-bits-per-code |
int | 8 |
vector.bits_per_code |
YSEARCH_VECTOR_BITS_PER_CODE |
Bits in each PQ subquantizer code. [vector.bits_per_code; env YSEARCH_VECTOR_BITS_PER_CODE] (in [1, 8]) |
--vector-build-memory-bytes |
bytes | 0 |
vector.build_memory_bytes |
YSEARCH_VECTOR_BUILD_MEMORY_BYTES |
Per-build vector training and assignment memory; zero derives a bounded share of builder.sort_memory_bytes. [vector.build_memory_bytes; env YSEARCH_VECTOR_BUILD_MEMORY_BYTES] (at least 0) |
--vector-centroids |
int | 0 |
vector.centroids |
YSEARCH_VECTOR_CENTROIDS |
IVF coarse centroid count; zero derives it deterministically from population. [vector.centroids; env YSEARCH_VECTOR_CENTROIDS] (in [0, 4294967295]) |
--vector-flat-threshold |
int | 10000 |
vector.flat_threshold |
YSEARCH_VECTOR_FLAT_THRESHOLD |
Per-segment vector population at or below which candidate generation stays exhaustive. [vector.flat_threshold; env YSEARCH_VECTOR_FLAT_THRESHOLD] (in [1, 4294967295]) |
--vector-list-block-documents |
int | 0 |
vector.list_block_documents |
YSEARCH_VECTOR_LIST_BLOCK_DOCUMENTS |
Target vector entries per IVF-list block; zero follows the document-value block geometry. [vector.list_block_documents; env YSEARCH_VECTOR_LIST_BLOCK_DOCUMENTS] (in [0, 4294967295]) |
--vector-maximum-training-vectors |
int | 4096 |
vector.maximum_training_vectors |
YSEARCH_VECTOR_MAXIMUM_TRAINING_VECTORS |
Maximum deterministic training samples retained per vector field. [vector.maximum_training_vectors; env YSEARCH_VECTOR_MAXIMUM_TRAINING_VECTORS] (in [1, 4294967295]) |
--vector-query-candidate-multiplier |
int | 10 |
vector.query_candidate_multiplier |
YSEARCH_VECTOR_QUERY_CANDIDATE_MULTIPLIER |
Default ANN candidates as a multiple of requested top_k. [vector.query_candidate_multiplier; env YSEARCH_VECTOR_QUERY_CANDIDATE_MULTIPLIER] (in [1, 10000]) |
--vector-query-default-probes |
int | 8 |
vector.query_default_probes |
YSEARCH_VECTOR_QUERY_DEFAULT_PROBES |
IVF coarse lists probed when a vector request does not specify probes. [vector.query_default_probes; env YSEARCH_VECTOR_QUERY_DEFAULT_PROBES] (in [1, 4294967295]) |
--vector-query-maximum-candidates |
int | 100000 |
vector.query_maximum_candidates |
YSEARCH_VECTOR_QUERY_MAXIMUM_CANDIDATES |
Hard per-request candidate generation and exact-rerank cap. [vector.query_maximum_candidates; env YSEARCH_VECTOR_QUERY_MAXIMUM_CANDIDATES] (in [1, 4294967295]) |
--vector-query-maximum-probes |
int | 1024 |
vector.query_maximum_probes |
YSEARCH_VECTOR_QUERY_MAXIMUM_PROBES |
Hard per-request IVF probe cap. [vector.query_maximum_probes; env YSEARCH_VECTOR_QUERY_MAXIMUM_PROBES] (in [1, 4294967295]) |
--vector-query-memory-bytes |
bytes | 256MiB |
vector.query_memory_bytes |
YSEARCH_VECTOR_QUERY_MEMORY_BYTES |
Per-process admission budget for decoded vector-query working sets. [vector.query_memory_bytes; env YSEARCH_VECTOR_QUERY_MEMORY_BYTES] (positive) |
--vector-subquantizers |
int | 0 |
vector.subquantizers |
YSEARCH_VECTOR_SUBQUANTIZERS |
PQ subquantizer count; zero derives a geometry compatible with each vector field's dimension. [vector.subquantizers; env YSEARCH_VECTOR_SUBQUANTIZERS] (in [0, 4294967295]) |
--vector-training-iterations |
int | 20 |
vector.training_iterations |
YSEARCH_VECTOR_TRAINING_ITERATIONS |
Maximum deterministic k-means iterations during IVF-PQ training. [vector.training_iterations; env YSEARCH_VECTOR_TRAINING_ITERATIONS] (in [1, 1000]) |
ysearch push <index> <files...|-> [flags]push reads JSONL, a JSON array, or a single JSON object (auto-detected), validates each document against the index's schema, converts it to a typed document, and streams the batches to the server. Unless --no-flush it flushes and waits for the segment to publish, printing the sealed segment and generation.
A file holding one pretty-printed object is one document; a file of one-line objects is one per line. To load compressed files or archives without uncompressing them first, use the admin console's Ingest section.
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--batch |
int | 500 |
documents per batch | ||
--batch-bytes |
int64 | 2097152 |
byte cap per batch | ||
--format |
string | auto |
input format: auto, jsonl, or json | ||
--no-flush |
bool | false |
accept ephemerally; do not flush or wait for publication | ||
--require-ack |
bool | false |
wait for PUBLISHED on every batch |
ysearch routing [flags]Build optional query routing artifacts from existing segments (offline)
Subcommands:
ysearch routing build— Build and publish exact presence routing for a catalog generation
ysearch routing build [flags]Build and publish exact presence routing for a catalog generation
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--generation |
string | index.generation |
YSEARCH_INDEX_GENERATION |
Exact generation to pin, or empty for the latest. [index.generation; env YSEARCH_INDEX_GENERATION] | |
--index |
string | index.name |
YSEARCH_INDEX_NAME |
Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles. [index.name; env YSEARCH_INDEX_NAME] | |
--legacy-value-encoding |
bool | false |
publish the pre-compaction format, whose every presence value is a full 4096-slot bitmap, for a reader too old to open the compact one | ||
--object-backend |
enum | fs |
object.backend |
YSEARCH_OBJECT_BACKEND |
Object store backend. [object.backend; env YSEARCH_OBJECT_BACKEND] (one of fs, s3) |
--object-dir |
string | object.dir |
YSEARCH_OBJECT_DIR |
Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory. [object.dir; env YSEARCH_OBJECT_DIR] | |
--object-root |
string | indexes |
object.root |
YSEARCH_OBJECT_ROOT |
Object key root. [object.root; env YSEARCH_OBJECT_ROOT] |
--routing-memory-bytes |
int64 | 67108864 |
budget for routing buffers and shared source caches | ||
--routing-temp-bytes |
int64 | 4294967296 |
maximum bytes of routing spill and page files | ||
--s3-anonymous |
bool | false |
object.s3.anonymous |
YSEARCH_OBJECT_S3_ANONYMOUS |
Sign no requests at all, for a bucket that grants public reads. This is a deliberate choice, never a fallback: an unresolved credential chain already signs anonymously, and a reader that quietly degraded to unsigned requests would report a permissions problem as an empty index. [object.s3.anonymous; env YSEARCH_OBJECT_S3_ANONYMOUS] |
--s3-bucket |
string | object.s3.bucket |
YSEARCH_OBJECT_S3_BUCKET |
S3 bucket; required for the s3 backend. [object.s3.bucket; env YSEARCH_OBJECT_S3_BUCKET] | |
--s3-endpoint |
string | object.s3.endpoint |
YSEARCH_OBJECT_S3_ENDPOINT |
S3 endpoint host:port; required for the s3 backend. [object.s3.endpoint; env YSEARCH_OBJECT_S3_ENDPOINT] | |
--s3-path-style |
bool | false |
object.s3.path_style |
YSEARCH_OBJECT_S3_PATH_STYLE |
Use path-style S3 addressing. [object.s3.path_style; env YSEARCH_OBJECT_S3_PATH_STYLE] |
--s3-prefix |
string | object.s3.prefix |
YSEARCH_OBJECT_S3_PREFIX |
S3 key prefix. [object.s3.prefix; env YSEARCH_OBJECT_S3_PREFIX] | |
--s3-region |
string | object.s3.region |
YSEARCH_OBJECT_S3_REGION |
S3 region. [object.s3.region; env YSEARCH_OBJECT_S3_REGION] | |
--s3-use-ssl |
bool | true |
object.s3.use_ssl |
YSEARCH_OBJECT_S3_USE_SSL |
Use TLS to the S3 endpoint. [object.s3.use_ssl; env YSEARCH_OBJECT_S3_USE_SSL] |
--score-bounds |
bool | false |
include query-dependent scoring statistics in a separate descriptor | ||
--scratch |
string | parent directory for temporary routing files | |||
--source |
string | object.source |
YSEARCH_OBJECT_SOURCE |
Dataset URL to attach read-only, such as s3://bucket/root/ for a whole root or s3://bucket/root/indexes/name/ for one index. It derives object.backend, the bucket, prefix and root, the index when the URL names one, and server.read_only, each only where nothing more specific was set. Reading someone else's published index is the whole purpose, so attaching one implies read-only and cannot be talked out of it. [object.source; env YSEARCH_OBJECT_SOURCE] |
ysearch schema [flags]schema talks to the IndexService of the server --server names. apply sends a .proto, a descriptor set, or an authored schema; changes are additive and auto-versioned, so re-applying an unchanged schema is a no-op and adding a field mints the next version. show prints one version, diff previews a change without writing it, history lists every version, and options prints the annotation .proto a document schema imports.
Subcommands:
ysearch schema apply— Apply a schema to an index (additive, auto-versioned)ysearch schema diff— Preview a schema change without applying itysearch schema history— List every version of an index's schemaysearch schema options— Print the annotation .proto a document schema importsysearch schema propose— Infer an editable schema and normalized JSONL from local documentsysearch schema show— Print one version of an index's schema
ysearch schema apply [file] [flags]apply sends a schema to the server's IndexService: a .proto compiled in-process, a descriptor set (.binpb), or an authored schema (.yaml, .json, .textproto), named positionally or with --proto/--schema. The index is the one the .proto's (ysearch.v1.document) option declares, or --index. An index that does not exist is created at version 1; re-applying an unchanged schema is a no-op; an additive change mints the next version; anything else is refused with the diff.
Example:
ysearch schema apply articles.proto
ysearch schema apply --proto articles.proto --index articles --dry-run
ysearch schema apply --schema articles.yaml --index articlesFlags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--dry-run |
bool | false |
show the diff and the would-be version without writing | ||
--index |
string | the index to apply to | |||
--message |
string | the document message when the file declares more than one | |||
--proto |
string | a .proto file compiled in-process | |||
--schema |
string | a descriptor set (.binpb) or authored schema (.yaml/.json/.textproto) |
ysearch schema diff [file] [flags]diff renders the change apply would make - the same table the server puts in a refusal - without writing anything, and exits 1 when the change is not additive. The file and index are named as for apply.
Example:
ysearch schema diff articles.proto
ysearch schema diff --schema articles.yaml --index articlesFlags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--index |
string | the index to diff against | |||
--message |
string | the document message when the file declares more than one | |||
--proto |
string | a .proto file compiled in-process | |||
--schema |
string | a descriptor set (.binpb) or authored schema |
ysearch schema history [flags]List every version of an index's schema
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--index |
string | the index whose history to list |
ysearch schema options [flags]Print the annotation .proto a document schema imports
ysearch schema propose <directory> [flags]Recursively analyze JSON objects, JSON arrays, JSONL, XML, and UTF-8 text without connecting to a server. Save the schema and normalized JSONL, then print commands to create the index and ingest the converted documents. Review the proposal before applying it. Existing output files are never overwritten. Limits: 8 MiB per file, 32 MiB total input, 10000 documents. Normalized output is capped at 64 MiB total and less than 16 MiB per record. Unsupported file extensions and symlinks are skipped. Identical document content shares a generated key.
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--index |
string | index namespace to propose | |||
--output |
string | new schema .json file (also writes FILE.documents.jsonl) |
ysearch schema show [flags]Print one version of an index's schema
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--index |
string | the index to show | |||
--version |
uint32 | 0 |
a specific schema version (default: latest) |
ysearch search <index> <query> [flags]search parses a Lucene or CQP query, lowers it to the structured request the server executes, and prints the hits — collapsed by key by default, or every hit in rank order with --no-collapse. --keys and --ids are line-oriented streaming modes for large result sets: --keys projects only the schema key, while --ids requests no stored documents or scores. Lowering happens client-side, so a typo lands a caret before any round trip. --request reads a protojson SearchRequest instead of a query, with output flags still overriding its result shape.
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--candidates |
uint64 | 0 |
ANN candidates to exact-rerank (zero uses the server default) | ||
--dialect |
string | lucene |
query dialect: lucene or cqp | ||
--exhaustive |
bool | false |
scan every covered vector instead of IVF-PQ candidate generation | ||
--fields |
string | comma-separated projected fields, or * for all stored | |||
--filter |
stringArray | [] |
an equality filter field=value (repeatable) | ||
--fusion |
string | weighted |
hybrid fusion: weighted or rrf | ||
--ids |
bool | false |
stream 128-bit public document IDs as lowercase hex, one per line | ||
--keys |
bool | false |
stream logical document keys, one per line | ||
--lexical-weight |
float64 | 1 |
lexical score weight for hybrid search; an explicit 0 scores every candidate 0 | ||
--maximum-ordering-error |
float64 | 0 |
maximum accepted score inversion in a banded tail | ||
--no-collapse |
bool | false |
print every hit in rank order without collapsing by key | ||
--probes |
uint32 | 0 |
IVF lists to probe (zero uses the server default) | ||
--request |
string | read a protojson SearchRequest from FILE instead of a query | |||
--score-ranges |
bool | false |
include conservative score ranges for an approximate tail | ||
--tail |
string | exact |
tail ordering: exact or banded | ||
--top-k |
int | 0 |
number of results (default 10) | ||
--vector-field |
string | vector field used for vector or hybrid search | |||
--vector-file |
string | read a JSON float array from FILE (or - for stdin) | |||
--vector-text |
string | embed this text with the selected vector field's schema profile | |||
--vector-weight |
float64 | 1 |
vector score weight; an explicit 0 drops the vector contribution |
ysearch segment [flags]Build and publish immutable segments (offline)
Subcommands:
ysearch segment build— Build one immutable segment from JSONL and write its checkpoint to the object directoryysearch segment publish— Publish a built segment commit-last and announce it to the catalog
ysearch segment build [flags]build analyzes documents (one JSON object per line), sorts and merges the postings within the builder limits, writes the segment beneath --work-dir, and checkpoints it under --checkpoint in the fs object directory, which it creates. The receipt on stdout carries the segment_id that publish requires. The builder limits are the builder.* settings: flags here, or a file, or the environment.
Accepted input (the M1 JSON forms, still accepted here and by push):
A schema file (--schema) is one JSON object:
{"version":1,"fields":[
{"id":1,"name":"title","indexed":true,"weight":2,"b":0.6},
{"id":2,"name":"body","indexed":true,"weight":1,"b":0.75}
]}
An input file (--input) is one JSON document per line; the members of "fields" are the schema's field names:
{"id":{"high":1,"low":1},"fields":{"title":"First","body":"alpha beta"}}
{"id":{"high":1,"low":2},"fields":{"title":"Second","body":"alpha gamma"}}
A schema authored from a .proto (the schema apply <file.proto> form) and
a document keyed by a string field are the modern forms; see the Getting
started section of the README and schema apply --help.
Example:
ysearch segment build --schema schema.json --input docs.jsonl --work-dir ./work --object-dir ./objects --checkpoint segments/demoFlags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--schema |
string | schema: .proto, .binpb, .yaml, .json (M1 or IndexSchema), or .textproto | |||
--input |
string | document JSONL path | |||
--work-dir |
string | build and local segment directory | |||
--checkpoint |
string | checkpoint key prefix | |||
--message |
string | document message when the .proto declares several | |||
--node-id |
string | mint a mutation_version for documents without one, tagged with this node identity; empty leaves them absent | |||
--max-line-bytes |
int | 16777216 |
maximum JSONL line size | ||
--analysis-batch-documents |
int | 0 |
builder.analysis_batch_documents |
YSEARCH_BUILDER_ANALYSIS_BATCH_DOCUMENTS |
Documents handed to the analysis workers at once; zero derives sixteen per worker. A batch is the unit that must fit in builder.analysis_memory_bytes, so a larger batch amortises the hand-off over more documents but raises the peak the analysis share has to cover. The derived shape is what the resource gates measure, so a corpus of unusually large documents is the case for lowering it rather than raising the share. [builder.analysis_batch_documents; env YSEARCH_BUILDER_ANALYSIS_BATCH_DOCUMENTS] (in [0, 1048576]) |
--analysis-memory-bytes |
bytes | 0 |
builder.analysis_memory_bytes |
YSEARCH_BUILDER_ANALYSIS_MEMORY_BYTES |
The share of builder.sort_memory_bytes reserved for documents in flight through analysis; zero derives a thirty-second of it, clamped to between 64KiB and 32MiB and never more than a quarter of what the public-id and docvalue spools leave. It only has to hold one bounded batch, and a document larger than the whole share still runs alone under builder.max_document_working_bytes, so the derived value is deliberately small: a three-million-document run peaked at 9.5MiB against a 128MiB share. Every byte reserved here is a byte the term partitions cannot use, which raises mini-run count and write amplification directly, so raise it only against a measured analysis stall. [builder.analysis_memory_bytes; env YSEARCH_BUILDER_ANALYSIS_MEMORY_BYTES] |
--analysis-workers |
int | 0 |
builder.analysis_workers |
YSEARCH_BUILDER_ANALYSIS_WORKERS |
Goroutines tokenising documents inside one build; zero derives GOMAXPROCS, bounded at eight. Analysis is the one parallel stage of an otherwise serial build, so this is per build and multiplies with builder.build_concurrency: the bound exists because a dozen builds each spawning a worker per core oversubscribes the machine and the scheduler churn costs more than the parallelism returns. Output order is preserved regardless of this value. [builder.analysis_workers; env YSEARCH_BUILDER_ANALYSIS_WORKERS] (in [0, 1024]) |
--blob-dictionary |
bool | true |
builder.blob_dictionary |
YSEARCH_BUILDER_BLOB_DICTIONARY |
Compress stored values against a dictionary trained per blob file. Denser on homogeneous documents, but the dictionary is coded on the build's hottest path, so turning it off trades index size for ingest throughput. [builder.blob_dictionary; env YSEARCH_BUILDER_BLOB_DICTIONARY] |
--blob-zstd-level |
int | 0 |
builder.blob_zstd_level |
YSEARCH_BUILDER_BLOB_ZSTD_LEVEL |
Zstd effort for stored values; zero keeps the storage default (7). Levels select different zstd encoders, and a build re-seeds the chosen encoder from the blob dictionary for every value it writes, so a lower level cuts build cost by more than the usual level trade-off suggests. [builder.blob_zstd_level; env YSEARCH_BUILDER_BLOB_ZSTD_LEVEL] (in [0, 11]) |
--build-concurrency |
int | 0 |
builder.build_concurrency |
YSEARCH_BUILDER_BUILD_CONCURRENCY |
Sealed builds that may run through the seal pipeline at once; zero derives one per CPU, bounded at twelve. One build is a mostly single-threaded chain of analysis, sort, merge and publish that spends about half its time blocked in file system calls, so a single pipeline leaves a multi-core host idle under bulk ingest. The builder's memory is this number times builder.sort_memory_bytes. [builder.build_concurrency; env YSEARCH_BUILDER_BUILD_CONCURRENCY] (in [0, 256]) |
--builder-catalog-publication |
enum | direct |
builder.catalog_publication |
YSEARCH_BUILDER_CATALOG_PUBLICATION |
Catalog writer mode: direct is the single-node compatibility path; external stops after commit markers for a lease-fenced publisher role. [builder.catalog_publication; env YSEARCH_BUILDER_CATALOG_PUBLICATION] (one of direct, external) |
--dedupe-index-identities |
int | 0 |
builder.dedupe_index_identities |
YSEARCH_BUILDER_DEDUPE_INDEX_IDENTITIES |
Distinct document keys one open spool's dedupe index may hold before it gives up; zero derives 1048576. A key spooled twice in one build must resolve to a single winner before analysis, or the segment's dense ordinal assignment refuses the build outright. The index resolves that as records are spooled, from identities ingest already holds, and the sealed build inherits the answer; past this bound it gives up and the build reconstructs the answer by reading its spool twice instead — slower, and exactly as correct. One entry is a 16-byte key hash, a sequence and a mutation version, so the default bounds it at tens of megabytes per open spool and is reached only by a spool of a million very small documents. Lower it to cap that memory on a host running many indexes; set it to one to force the scanning path. [builder.dedupe_index_identities; env YSEARCH_BUILDER_DEDUPE_INDEX_IDENTITIES] (in [0, 268435456]) |
--builder-fuse-memory-bytes |
bytes | 0 |
builder.fuse_memory_bytes |
YSEARCH_BUILDER_FUSE_MEMORY_BYTES |
Optional binary fuse construction workspace during publication; zero retains Bloom, failed admission retains Bloom. [builder.fuse_memory_bytes; env YSEARCH_BUILDER_FUSE_MEMORY_BYTES] (in [0, 64MiB]) |
--lexical-blob-threshold |
bytes | 0 |
builder.lexical_blob_threshold |
YSEARCH_BUILDER_LEXICAL_BLOB_THRESHOLD |
Size at which a posting, position or term value is stored in a blob file rather than inline in the key log; zero keeps the default of 64KiB. Separation exists to spare compaction from rewriting large values, and a segment is never compacted — while a blob value is compressed on its own, which with a trained dictionary costs an encoder reset each time, where key-log blocks are compressed in bulk. [builder.lexical_blob_threshold; env YSEARCH_BUILDER_LEXICAL_BLOB_THRESHOLD] |
--lexical-block-compression |
string | builder.lexical_block_compression |
YSEARCH_BUILDER_LEXICAL_BLOCK_COMPRESSION |
Codec the term, posting and position families compress key-log blocks with: none, snappy, lz4, lz4fast or zstd. Empty keeps the default of lz4. The storage engine's own default leaves the newest level raw because it expects compaction to rewrite it, and a segment stays where it lands. On 300k articles lz4 measured 24.8s and 1.0GB against zstd's 37.7s and 0.8GB, so zstd is the choice for an index written once and read for a long time. [builder.lexical_block_compression; env YSEARCH_BUILDER_LEXICAL_BLOCK_COMPRESSION] | |
--max-document-working-bytes |
bytes | 0 |
builder.max_document_working_bytes |
YSEARCH_BUILDER_MAX_DOCUMENT_WORKING_BYTES |
What one document may use beyond the partition budget while it is being analyzed; zero derives 64MiB, or a quarter of builder.sort_memory_bytes when that is smaller. It is an allowance rather than a reservation: it exists so a single document larger than the whole partition budget still builds, alone, instead of failing the build. Only a corpus with documents in the hundreds of megabytes needs it raised. [builder.max_document_working_bytes; env YSEARCH_BUILDER_MAX_DOCUMENT_WORKING_BYTES] |
--max-queued-builds |
int | 0 |
builder.max_queued_builds |
YSEARCH_BUILDER_MAX_QUEUED_BUILDS |
Sealed builds that may wait for or run in the pipeline before ingest is throttled; zero derives it as four times builder.build_concurrency. A waiting build is a spool on disk, not memory, so this buys ingest room across a build at the cost of ingest.seal_bytes of disk per queued build. Set too low, a bulk load throttles the moment the pipeline is full and ingest runs at the speed of the builds rather than ahead of them. [builder.max_queued_builds; env YSEARCH_BUILDER_MAX_QUEUED_BUILDS] (in [0, 1024]) |
--max-token-bytes |
bytes | 64KiB |
builder.max_token_bytes |
YSEARCH_BUILDER_MAX_TOKEN_BYTES |
Maximum analyzed token size. A build must be able to admit one token this large, so raising it raises the floor under builder.sort_memory_bytes: a budget that leaves the partitions less than one maximum term refuses to start rather than fail partway. Tokens are words after analysis, so the default is already far past any natural language; raise it only for a corpus with genuinely enormous unbroken tokens. [builder.max_token_bytes; env YSEARCH_BUILDER_MAX_TOKEN_BYTES] (positive) |
--merge-fan-in |
int | 0 |
builder.merge_fan_in |
YSEARCH_BUILDER_MERGE_FAN_IN |
Spilled mini-runs merged in one pass; zero derives as many as an eighth of the partition budget affords at builder.run_page_bytes plus 512 bytes of reader overhead each, capped at sixty-four and floored at two. Runs beyond the fan-in need further passes, and each pass rewrites the data, so a low fan-in on a build that spilled heavily shows up as write amplification rather than as a slow merge. The cap is a file-descriptor and seek-pattern bound, not a memory one. [builder.merge_fan_in; env YSEARCH_BUILDER_MERGE_FAN_IN] (in [0, 64]) |
--builder-output-format-version |
int | 0 |
builder.output_format_version |
YSEARCH_BUILDER_OUTPUT_FORMAT_VERSION |
Segment format emitted by builders and compactors; zero selects this binary's current format. The Kubernetes operator pins this to compatibility.writeFormat on writer roles during staged rollouts. Format 7 adds the stats, forward and hashterms families (spec/40 §3); a compaction that includes an older input writes format 6 instead, unless 7 or 8 is set explicitly, which refuses such a merge. Format 8 adds the exact vector lanes (canonical fp16 vectors, IVF radii, int8 codes; spec/40 §3.2). [builder.output_format_version; env YSEARCH_BUILDER_OUTPUT_FORMAT_VERSION] (in [0, 8]) |
--builder-paged-posting-directory |
bool | false |
builder.paged_posting_directory |
YSEARCH_BUILDER_PAGED_POSTING_DIRECTORY |
Experimental commit-anchored posting-directory pages under query admission and the existing persistent block quota; old commits retain canonical traversal. [builder.paged_posting_directory; env YSEARCH_BUILDER_PAGED_POSTING_DIRECTORY] |
--builder-posting-partition-penalty |
float | 4 |
builder.posting_partition_penalty |
YSEARCH_BUILDER_POSTING_PARTITION_PENALTY |
Metadata cost penalty for experimental variable posting blocks. [builder.posting_partition_penalty; env YSEARCH_BUILDER_POSTING_PARTITION_PENALTY] (in [0, 1e+06]) |
--publish-verification |
string | checksum |
builder.publish_verification |
YSEARCH_BUILDER_PUBLISH_VERIFICATION |
How a published segment is confirmed: checksum, sample, or readback. checksum compares every object against the checksum the object store reported when it accepted the write — S3 computes that server-side and refuses a mismatched write, and the filesystem backend computes it over the bytes it synced — so nothing is transferred back. sample additionally opens the published copy through the store and queries it; readback additionally fetches every object and rehashes it, which costs the whole index again on every build. An object whose store reports no comparable checksum is read back in any mode. [builder.publish_verification; env YSEARCH_BUILDER_PUBLISH_VERIFICATION] |
--builder-routing-fragment-bytes |
bytes | 8MiB |
builder.routing_fragment_bytes |
YSEARCH_BUILDER_ROUTING_FRAGMENT_BYTES |
Optional routing fragment disk cap per built segment; zero disables, overflow keeps canonical scan fallback. Matches compaction.routing_fragment_bytes so a freshly ingested segment and a freshly compacted one carry a fragment the same way; the two stay separate keys because a background merge must be able to carry its own share independent of foreground ingestion. Only a segment built or compacted after this defaulted on carries a fragment: nothing rewrites an existing one, so a settled corpus stays without a routing table until it is backfilled or compacted. [builder.routing_fragment_bytes; env YSEARCH_BUILDER_ROUTING_FRAGMENT_BYTES] (in [0, 64MiB]) |
--run-page-bytes |
bytes | 0 |
builder.run_page_bytes |
YSEARCH_BUILDER_RUN_PAGE_BYTES |
Read-ahead page one spilled mini-run is buffered in during the final merge; zero derives 64KiB, shrinking it when an eighth of the partition budget cannot hold sixty-four such pages. The merge reserves one page per open run for the whole build, so page size and builder.merge_fan_in trade against each other out of the same share: the derivation prefers smaller pages to a fan-in that would force extra compaction passes on a hot partition. [builder.run_page_bytes; env YSEARCH_BUILDER_RUN_PAGE_BYTES] |
--sort-memory-bytes |
bytes | 256MiB |
builder.sort_memory_bytes |
YSEARCH_BUILDER_SORT_MEMORY_BYTES |
Total accounted builder budget: one ledger every part of a build charges against, and the setting the other builder budgets derive from. It divides into the public-id sorter (an eighth, capped at 64MiB), the docvalue and lane spools (their own worst case), the analysis share (builder.analysis_memory_bytes), and the term partitions, which take what is left. A build that cannot hold its partitions in that remainder spills to disk instead, which is the difference between one file per build and hundreds. This is per build, so the builder's memory is builder.build_concurrency times this. [builder.sort_memory_bytes; env YSEARCH_BUILDER_SORT_MEMORY_BYTES] (positive) |
--builder-spill-merge-strategy |
enum | heap |
builder.spill_merge_strategy |
YSEARCH_BUILDER_SPILL_MERGE_STRATEGY |
Experimental spill merge selector; heap preserves the baseline until full ingestion benchmarks qualify an alternative. [builder.spill_merge_strategy; env YSEARCH_BUILDER_SPILL_MERGE_STRATEGY] (one of heap, replace-root, loser-tree) |
--builder-startup-bundles |
bool | false |
builder.startup_bundles |
YSEARCH_BUILDER_STARTUP_BUNDLES |
Asynchronously produce optional startup bundles after catalog publication. One bounded coalescing worker per publishing host; oversized sources retain canonical startup fallback. [builder.startup_bundles; env YSEARCH_BUILDER_STARTUP_BUNDLES] |
--term-dictionary-block-size |
bytes | 64KiB |
builder.term_dictionary_block_size |
YSEARCH_BUILDER_TERM_DICTIONARY_BLOCK_SIZE |
Key-log data-block size of the term family. A table carries one block-index entry per data block and reads the whole index before it can look up anything, so this is what a cold term probe pays to find out where to look. At the storage engine's 4KiB an 8MiB dictionary needs about two thousand entries — around 65KiB read on every open of the table and held in memory until it closes — where 64KiB needs about a sixteenth of that. A probe then reads a bigger block, which over an object store is the cheap side of the trade: measured on a 6MiB dictionary the block cost 17KiB compressed against the 48KiB of index it replaced. [builder.term_dictionary_block_size; env YSEARCH_BUILDER_TERM_DICTIONARY_BLOCK_SIZE] (positive) |
--term-dictionary-bloom |
bool | false |
builder.term_dictionary_bloom |
YSEARCH_BUILDER_TERM_DICTIONARY_BLOOM |
Write a Bloom filter over the term family. The storage engine writes one by default; a segment does not, because the filter is read whole — uncompressed, about 1.2 bytes per distinct term — when the table is opened, and kept in memory until it closes, to save at most one block read per probe against the single table a published segment's term family is. Measured, it was nine tenths of what a cold term probe read: 431KiB of 481KiB on a 360k-term dictionary. A table says in its own footer whether it has a filter, so segments published with one keep working unchanged. [builder.term_dictionary_bloom; env YSEARCH_BUILDER_TERM_DICTIONARY_BLOOM] |
--builder-variable-posting-blocks |
bool | false |
builder.variable_posting_blocks |
YSEARCH_BUILDER_VARIABLE_POSTING_BLOCKS |
Experimental bounded-window BM25F-aware posting partitioning for format5 or newer output. [builder.variable_posting_blocks; env YSEARCH_BUILDER_VARIABLE_POSTING_BLOCKS] |
--index |
string | index.name |
YSEARCH_INDEX_NAME |
Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles. [index.name; env YSEARCH_INDEX_NAME] | |
--object-backend |
enum | fs |
object.backend |
YSEARCH_OBJECT_BACKEND |
Object store backend. [object.backend; env YSEARCH_OBJECT_BACKEND] (one of fs, s3) |
--object-dir |
string | object.dir |
YSEARCH_OBJECT_DIR |
Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory. [object.dir; env YSEARCH_OBJECT_DIR] | |
--object-root |
string | indexes |
object.root |
YSEARCH_OBJECT_ROOT |
Object key root. [object.root; env YSEARCH_OBJECT_ROOT] |
--s3-anonymous |
bool | false |
object.s3.anonymous |
YSEARCH_OBJECT_S3_ANONYMOUS |
Sign no requests at all, for a bucket that grants public reads. This is a deliberate choice, never a fallback: an unresolved credential chain already signs anonymously, and a reader that quietly degraded to unsigned requests would report a permissions problem as an empty index. [object.s3.anonymous; env YSEARCH_OBJECT_S3_ANONYMOUS] |
--s3-bucket |
string | object.s3.bucket |
YSEARCH_OBJECT_S3_BUCKET |
S3 bucket; required for the s3 backend. [object.s3.bucket; env YSEARCH_OBJECT_S3_BUCKET] | |
--s3-endpoint |
string | object.s3.endpoint |
YSEARCH_OBJECT_S3_ENDPOINT |
S3 endpoint host:port; required for the s3 backend. [object.s3.endpoint; env YSEARCH_OBJECT_S3_ENDPOINT] | |
--s3-path-style |
bool | false |
object.s3.path_style |
YSEARCH_OBJECT_S3_PATH_STYLE |
Use path-style S3 addressing. [object.s3.path_style; env YSEARCH_OBJECT_S3_PATH_STYLE] |
--s3-prefix |
string | object.s3.prefix |
YSEARCH_OBJECT_S3_PREFIX |
S3 key prefix. [object.s3.prefix; env YSEARCH_OBJECT_S3_PREFIX] | |
--s3-region |
string | object.s3.region |
YSEARCH_OBJECT_S3_REGION |
S3 region. [object.s3.region; env YSEARCH_OBJECT_S3_REGION] | |
--s3-use-ssl |
bool | true |
object.s3.use_ssl |
YSEARCH_OBJECT_S3_USE_SSL |
Use TLS to the S3 endpoint. [object.s3.use_ssl; env YSEARCH_OBJECT_S3_USE_SSL] |
--source |
string | object.source |
YSEARCH_OBJECT_SOURCE |
Dataset URL to attach read-only, such as s3://bucket/root/ for a whole root or s3://bucket/root/indexes/name/ for one index. It derives object.backend, the bucket, prefix and root, the index when the URL names one, and server.read_only, each only where nothing more specific was set. Reading someone else's published index is the whole purpose, so attaching one implies read-only and cannot be talked out of it. [object.source; env YSEARCH_OBJECT_SOURCE] | |
--tail-impact-maximum-bands |
int | 64 |
tail.impact_maximum_bands |
YSEARCH_TAIL_IMPACT_MAXIMUM_BANDS |
Maximum score-impact bands persisted for one term. [tail.impact_maximum_bands; env YSEARCH_TAIL_IMPACT_MAXIMUM_BANDS] (in [1, 4096]) |
--tail-impact-target-documents |
int | 4096 |
tail.impact_target_documents |
YSEARCH_TAIL_IMPACT_TARGET_DOCUMENTS |
Target postings per persisted impact run. [tail.impact_target_documents; env YSEARCH_TAIL_IMPACT_TARGET_DOCUMENTS] (in [1, 4294967295]) |
ysearch segment publish [flags]publish uploads a locally built segment's objects, reads them back, writes the commit marker that makes them visible, and announces the segment to the catalog. Every step is idempotent, so the command can be run again after any failure. --segment-id must be the built segment's own identity from the build receipt.
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--segment-id |
string | 32 lowercase hex characters | |||
--segment-dir |
string | locally built segment directory | |||
--builder-version |
string | builder identity recorded in the commit | |||
--expected-parent |
string | generation this announcement expects to extend | |||
--announce |
bool | true |
announce the segment to the catalog after publishing | ||
--generation |
string | index.generation |
YSEARCH_INDEX_GENERATION |
Exact generation to pin, or empty for the latest. [index.generation; env YSEARCH_INDEX_GENERATION] | |
--index |
string | index.name |
YSEARCH_INDEX_NAME |
Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles. [index.name; env YSEARCH_INDEX_NAME] | |
--object-backend |
enum | fs |
object.backend |
YSEARCH_OBJECT_BACKEND |
Object store backend. [object.backend; env YSEARCH_OBJECT_BACKEND] (one of fs, s3) |
--object-dir |
string | object.dir |
YSEARCH_OBJECT_DIR |
Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory. [object.dir; env YSEARCH_OBJECT_DIR] | |
--object-root |
string | indexes |
object.root |
YSEARCH_OBJECT_ROOT |
Object key root. [object.root; env YSEARCH_OBJECT_ROOT] |
--s3-anonymous |
bool | false |
object.s3.anonymous |
YSEARCH_OBJECT_S3_ANONYMOUS |
Sign no requests at all, for a bucket that grants public reads. This is a deliberate choice, never a fallback: an unresolved credential chain already signs anonymously, and a reader that quietly degraded to unsigned requests would report a permissions problem as an empty index. [object.s3.anonymous; env YSEARCH_OBJECT_S3_ANONYMOUS] |
--s3-bucket |
string | object.s3.bucket |
YSEARCH_OBJECT_S3_BUCKET |
S3 bucket; required for the s3 backend. [object.s3.bucket; env YSEARCH_OBJECT_S3_BUCKET] | |
--s3-endpoint |
string | object.s3.endpoint |
YSEARCH_OBJECT_S3_ENDPOINT |
S3 endpoint host:port; required for the s3 backend. [object.s3.endpoint; env YSEARCH_OBJECT_S3_ENDPOINT] | |
--s3-path-style |
bool | false |
object.s3.path_style |
YSEARCH_OBJECT_S3_PATH_STYLE |
Use path-style S3 addressing. [object.s3.path_style; env YSEARCH_OBJECT_S3_PATH_STYLE] |
--s3-prefix |
string | object.s3.prefix |
YSEARCH_OBJECT_S3_PREFIX |
S3 key prefix. [object.s3.prefix; env YSEARCH_OBJECT_S3_PREFIX] | |
--s3-region |
string | object.s3.region |
YSEARCH_OBJECT_S3_REGION |
S3 region. [object.s3.region; env YSEARCH_OBJECT_S3_REGION] | |
--s3-use-ssl |
bool | true |
object.s3.use_ssl |
YSEARCH_OBJECT_S3_USE_SSL |
Use TLS to the S3 endpoint. [object.s3.use_ssl; env YSEARCH_OBJECT_S3_USE_SSL] |
--source |
string | object.source |
YSEARCH_OBJECT_SOURCE |
Dataset URL to attach read-only, such as s3://bucket/root/ for a whole root or s3://bucket/root/indexes/name/ for one index. It derives object.backend, the bucket, prefix and root, the index when the URL names one, and server.read_only, each only where nothing more specific was set. Reading someone else's published index is the whole purpose, so attaching one implies read-only and cannot be talked out of it. [object.source; env YSEARCH_OBJECT_SOURCE] |
ysearch serve [SOURCE_URL] [flags]serve hosts every index under the object root - or exactly one with --index - and answers SearchService, IngestService, IndexService, CatalogService, AdminService, and ConfigService for them. An empty object root is a valid start: schema apply creates an index while serving, push fills it, and each index follows the catalog so a published generation is served without a restart. With --checkpoint it is instead the Milestone 1 form serving one checkpoint (SearchService and ConfigService only). Settings come from the catalog - defaults, then the discovered files, the environment, and the flags - and the listening= line on stdout says where it serves once every hosted index is resolved and the socket is bound.
Example:
ysearch serve --data-dir ./ys --listen 127.0.0.1:9500
ysearch serve --index demo --listen 127.0.0.1:9500 --cache-dir ./cache --ingest-dir ./ingest --object-dir ./objects
ysearch --config ys.yml serve
ysearch serve s3://search-data/production/indexes/articles/Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--analysis-batch-documents |
int | 0 |
builder.analysis_batch_documents |
YSEARCH_BUILDER_ANALYSIS_BATCH_DOCUMENTS |
Documents handed to the analysis workers at once; zero derives sixteen per worker. A batch is the unit that must fit in builder.analysis_memory_bytes, so a larger batch amortises the hand-off over more documents but raises the peak the analysis share has to cover. The derived shape is what the resource gates measure, so a corpus of unusually large documents is the case for lowering it rather than raising the share. [builder.analysis_batch_documents; env YSEARCH_BUILDER_ANALYSIS_BATCH_DOCUMENTS] (in [0, 1048576]) |
--analysis-memory-bytes |
bytes | 0 |
builder.analysis_memory_bytes |
YSEARCH_BUILDER_ANALYSIS_MEMORY_BYTES |
The share of builder.sort_memory_bytes reserved for documents in flight through analysis; zero derives a thirty-second of it, clamped to between 64KiB and 32MiB and never more than a quarter of what the public-id and docvalue spools leave. It only has to hold one bounded batch, and a document larger than the whole share still runs alone under builder.max_document_working_bytes, so the derived value is deliberately small: a three-million-document run peaked at 9.5MiB against a 128MiB share. Every byte reserved here is a byte the term partitions cannot use, which raises mini-run count and write amplification directly, so raise it only against a measured analysis stall. [builder.analysis_memory_bytes; env YSEARCH_BUILDER_ANALYSIS_MEMORY_BYTES] |
--analysis-workers |
int | 0 |
builder.analysis_workers |
YSEARCH_BUILDER_ANALYSIS_WORKERS |
Goroutines tokenising documents inside one build; zero derives GOMAXPROCS, bounded at eight. Analysis is the one parallel stage of an otherwise serial build, so this is per build and multiplies with builder.build_concurrency: the bound exists because a dozen builds each spawning a worker per core oversubscribes the machine and the scheduler churn costs more than the parallelism returns. Output order is preserved regardless of this value. [builder.analysis_workers; env YSEARCH_BUILDER_ANALYSIS_WORKERS] (in [0, 1024]) |
--blob-dictionary |
bool | true |
builder.blob_dictionary |
YSEARCH_BUILDER_BLOB_DICTIONARY |
Compress stored values against a dictionary trained per blob file. Denser on homogeneous documents, but the dictionary is coded on the build's hottest path, so turning it off trades index size for ingest throughput. [builder.blob_dictionary; env YSEARCH_BUILDER_BLOB_DICTIONARY] |
--blob-zstd-level |
int | 0 |
builder.blob_zstd_level |
YSEARCH_BUILDER_BLOB_ZSTD_LEVEL |
Zstd effort for stored values; zero keeps the storage default (7). Levels select different zstd encoders, and a build re-seeds the chosen encoder from the blob dictionary for every value it writes, so a lower level cuts build cost by more than the usual level trade-off suggests. [builder.blob_zstd_level; env YSEARCH_BUILDER_BLOB_ZSTD_LEVEL] (in [0, 11]) |
--build-concurrency |
int | 0 |
builder.build_concurrency |
YSEARCH_BUILDER_BUILD_CONCURRENCY |
Sealed builds that may run through the seal pipeline at once; zero derives one per CPU, bounded at twelve. One build is a mostly single-threaded chain of analysis, sort, merge and publish that spends about half its time blocked in file system calls, so a single pipeline leaves a multi-core host idle under bulk ingest. The builder's memory is this number times builder.sort_memory_bytes. [builder.build_concurrency; env YSEARCH_BUILDER_BUILD_CONCURRENCY] (in [0, 256]) |
--builder-catalog-publication |
enum | direct |
builder.catalog_publication |
YSEARCH_BUILDER_CATALOG_PUBLICATION |
Catalog writer mode: direct is the single-node compatibility path; external stops after commit markers for a lease-fenced publisher role. [builder.catalog_publication; env YSEARCH_BUILDER_CATALOG_PUBLICATION] (one of direct, external) |
--dedupe-index-identities |
int | 0 |
builder.dedupe_index_identities |
YSEARCH_BUILDER_DEDUPE_INDEX_IDENTITIES |
Distinct document keys one open spool's dedupe index may hold before it gives up; zero derives 1048576. A key spooled twice in one build must resolve to a single winner before analysis, or the segment's dense ordinal assignment refuses the build outright. The index resolves that as records are spooled, from identities ingest already holds, and the sealed build inherits the answer; past this bound it gives up and the build reconstructs the answer by reading its spool twice instead — slower, and exactly as correct. One entry is a 16-byte key hash, a sequence and a mutation version, so the default bounds it at tens of megabytes per open spool and is reached only by a spool of a million very small documents. Lower it to cap that memory on a host running many indexes; set it to one to force the scanning path. [builder.dedupe_index_identities; env YSEARCH_BUILDER_DEDUPE_INDEX_IDENTITIES] (in [0, 268435456]) |
--builder-fuse-memory-bytes |
bytes | 0 |
builder.fuse_memory_bytes |
YSEARCH_BUILDER_FUSE_MEMORY_BYTES |
Optional binary fuse construction workspace during publication; zero retains Bloom, failed admission retains Bloom. [builder.fuse_memory_bytes; env YSEARCH_BUILDER_FUSE_MEMORY_BYTES] (in [0, 64MiB]) |
--lexical-blob-threshold |
bytes | 0 |
builder.lexical_blob_threshold |
YSEARCH_BUILDER_LEXICAL_BLOB_THRESHOLD |
Size at which a posting, position or term value is stored in a blob file rather than inline in the key log; zero keeps the default of 64KiB. Separation exists to spare compaction from rewriting large values, and a segment is never compacted — while a blob value is compressed on its own, which with a trained dictionary costs an encoder reset each time, where key-log blocks are compressed in bulk. [builder.lexical_blob_threshold; env YSEARCH_BUILDER_LEXICAL_BLOB_THRESHOLD] |
--lexical-block-compression |
string | builder.lexical_block_compression |
YSEARCH_BUILDER_LEXICAL_BLOCK_COMPRESSION |
Codec the term, posting and position families compress key-log blocks with: none, snappy, lz4, lz4fast or zstd. Empty keeps the default of lz4. The storage engine's own default leaves the newest level raw because it expects compaction to rewrite it, and a segment stays where it lands. On 300k articles lz4 measured 24.8s and 1.0GB against zstd's 37.7s and 0.8GB, so zstd is the choice for an index written once and read for a long time. [builder.lexical_block_compression; env YSEARCH_BUILDER_LEXICAL_BLOCK_COMPRESSION] | |
--max-document-working-bytes |
bytes | 0 |
builder.max_document_working_bytes |
YSEARCH_BUILDER_MAX_DOCUMENT_WORKING_BYTES |
What one document may use beyond the partition budget while it is being analyzed; zero derives 64MiB, or a quarter of builder.sort_memory_bytes when that is smaller. It is an allowance rather than a reservation: it exists so a single document larger than the whole partition budget still builds, alone, instead of failing the build. Only a corpus with documents in the hundreds of megabytes needs it raised. [builder.max_document_working_bytes; env YSEARCH_BUILDER_MAX_DOCUMENT_WORKING_BYTES] |
--max-queued-builds |
int | 0 |
builder.max_queued_builds |
YSEARCH_BUILDER_MAX_QUEUED_BUILDS |
Sealed builds that may wait for or run in the pipeline before ingest is throttled; zero derives it as four times builder.build_concurrency. A waiting build is a spool on disk, not memory, so this buys ingest room across a build at the cost of ingest.seal_bytes of disk per queued build. Set too low, a bulk load throttles the moment the pipeline is full and ingest runs at the speed of the builds rather than ahead of them. [builder.max_queued_builds; env YSEARCH_BUILDER_MAX_QUEUED_BUILDS] (in [0, 1024]) |
--max-token-bytes |
bytes | 64KiB |
builder.max_token_bytes |
YSEARCH_BUILDER_MAX_TOKEN_BYTES |
Maximum analyzed token size. A build must be able to admit one token this large, so raising it raises the floor under builder.sort_memory_bytes: a budget that leaves the partitions less than one maximum term refuses to start rather than fail partway. Tokens are words after analysis, so the default is already far past any natural language; raise it only for a corpus with genuinely enormous unbroken tokens. [builder.max_token_bytes; env YSEARCH_BUILDER_MAX_TOKEN_BYTES] (positive) |
--merge-fan-in |
int | 0 |
builder.merge_fan_in |
YSEARCH_BUILDER_MERGE_FAN_IN |
Spilled mini-runs merged in one pass; zero derives as many as an eighth of the partition budget affords at builder.run_page_bytes plus 512 bytes of reader overhead each, capped at sixty-four and floored at two. Runs beyond the fan-in need further passes, and each pass rewrites the data, so a low fan-in on a build that spilled heavily shows up as write amplification rather than as a slow merge. The cap is a file-descriptor and seek-pattern bound, not a memory one. [builder.merge_fan_in; env YSEARCH_BUILDER_MERGE_FAN_IN] (in [0, 64]) |
--builder-output-format-version |
int | 0 |
builder.output_format_version |
YSEARCH_BUILDER_OUTPUT_FORMAT_VERSION |
Segment format emitted by builders and compactors; zero selects this binary's current format. The Kubernetes operator pins this to compatibility.writeFormat on writer roles during staged rollouts. Format 7 adds the stats, forward and hashterms families (spec/40 §3); a compaction that includes an older input writes format 6 instead, unless 7 or 8 is set explicitly, which refuses such a merge. Format 8 adds the exact vector lanes (canonical fp16 vectors, IVF radii, int8 codes; spec/40 §3.2). [builder.output_format_version; env YSEARCH_BUILDER_OUTPUT_FORMAT_VERSION] (in [0, 8]) |
--builder-paged-posting-directory |
bool | false |
builder.paged_posting_directory |
YSEARCH_BUILDER_PAGED_POSTING_DIRECTORY |
Experimental commit-anchored posting-directory pages under query admission and the existing persistent block quota; old commits retain canonical traversal. [builder.paged_posting_directory; env YSEARCH_BUILDER_PAGED_POSTING_DIRECTORY] |
--builder-posting-partition-penalty |
float | 4 |
builder.posting_partition_penalty |
YSEARCH_BUILDER_POSTING_PARTITION_PENALTY |
Metadata cost penalty for experimental variable posting blocks. [builder.posting_partition_penalty; env YSEARCH_BUILDER_POSTING_PARTITION_PENALTY] (in [0, 1e+06]) |
--publish-verification |
string | checksum |
builder.publish_verification |
YSEARCH_BUILDER_PUBLISH_VERIFICATION |
How a published segment is confirmed: checksum, sample, or readback. checksum compares every object against the checksum the object store reported when it accepted the write — S3 computes that server-side and refuses a mismatched write, and the filesystem backend computes it over the bytes it synced — so nothing is transferred back. sample additionally opens the published copy through the store and queries it; readback additionally fetches every object and rehashes it, which costs the whole index again on every build. An object whose store reports no comparable checksum is read back in any mode. [builder.publish_verification; env YSEARCH_BUILDER_PUBLISH_VERIFICATION] |
--builder-routing-fragment-bytes |
bytes | 8MiB |
builder.routing_fragment_bytes |
YSEARCH_BUILDER_ROUTING_FRAGMENT_BYTES |
Optional routing fragment disk cap per built segment; zero disables, overflow keeps canonical scan fallback. Matches compaction.routing_fragment_bytes so a freshly ingested segment and a freshly compacted one carry a fragment the same way; the two stay separate keys because a background merge must be able to carry its own share independent of foreground ingestion. Only a segment built or compacted after this defaulted on carries a fragment: nothing rewrites an existing one, so a settled corpus stays without a routing table until it is backfilled or compacted. [builder.routing_fragment_bytes; env YSEARCH_BUILDER_ROUTING_FRAGMENT_BYTES] (in [0, 64MiB]) |
--run-page-bytes |
bytes | 0 |
builder.run_page_bytes |
YSEARCH_BUILDER_RUN_PAGE_BYTES |
Read-ahead page one spilled mini-run is buffered in during the final merge; zero derives 64KiB, shrinking it when an eighth of the partition budget cannot hold sixty-four such pages. The merge reserves one page per open run for the whole build, so page size and builder.merge_fan_in trade against each other out of the same share: the derivation prefers smaller pages to a fan-in that would force extra compaction passes on a hot partition. [builder.run_page_bytes; env YSEARCH_BUILDER_RUN_PAGE_BYTES] |
--sort-memory-bytes |
bytes | 256MiB |
builder.sort_memory_bytes |
YSEARCH_BUILDER_SORT_MEMORY_BYTES |
Total accounted builder budget: one ledger every part of a build charges against, and the setting the other builder budgets derive from. It divides into the public-id sorter (an eighth, capped at 64MiB), the docvalue and lane spools (their own worst case), the analysis share (builder.analysis_memory_bytes), and the term partitions, which take what is left. A build that cannot hold its partitions in that remainder spills to disk instead, which is the difference between one file per build and hundreds. This is per build, so the builder's memory is builder.build_concurrency times this. [builder.sort_memory_bytes; env YSEARCH_BUILDER_SORT_MEMORY_BYTES] (positive) |
--builder-spill-merge-strategy |
enum | heap |
builder.spill_merge_strategy |
YSEARCH_BUILDER_SPILL_MERGE_STRATEGY |
Experimental spill merge selector; heap preserves the baseline until full ingestion benchmarks qualify an alternative. [builder.spill_merge_strategy; env YSEARCH_BUILDER_SPILL_MERGE_STRATEGY] (one of heap, replace-root, loser-tree) |
--builder-startup-bundles |
bool | false |
builder.startup_bundles |
YSEARCH_BUILDER_STARTUP_BUNDLES |
Asynchronously produce optional startup bundles after catalog publication. One bounded coalescing worker per publishing host; oversized sources retain canonical startup fallback. [builder.startup_bundles; env YSEARCH_BUILDER_STARTUP_BUNDLES] |
--term-dictionary-block-size |
bytes | 64KiB |
builder.term_dictionary_block_size |
YSEARCH_BUILDER_TERM_DICTIONARY_BLOCK_SIZE |
Key-log data-block size of the term family. A table carries one block-index entry per data block and reads the whole index before it can look up anything, so this is what a cold term probe pays to find out where to look. At the storage engine's 4KiB an 8MiB dictionary needs about two thousand entries — around 65KiB read on every open of the table and held in memory until it closes — where 64KiB needs about a sixteenth of that. A probe then reads a bigger block, which over an object store is the cheap side of the trade: measured on a 6MiB dictionary the block cost 17KiB compressed against the 48KiB of index it replaced. [builder.term_dictionary_block_size; env YSEARCH_BUILDER_TERM_DICTIONARY_BLOCK_SIZE] (positive) |
--term-dictionary-bloom |
bool | false |
builder.term_dictionary_bloom |
YSEARCH_BUILDER_TERM_DICTIONARY_BLOOM |
Write a Bloom filter over the term family. The storage engine writes one by default; a segment does not, because the filter is read whole — uncompressed, about 1.2 bytes per distinct term — when the table is opened, and kept in memory until it closes, to save at most one block read per probe against the single table a published segment's term family is. Measured, it was nine tenths of what a cold term probe read: 431KiB of 481KiB on a 360k-term dictionary. A table says in its own footer whether it has a filter, so segments published with one keep working unchanged. [builder.term_dictionary_bloom; env YSEARCH_BUILDER_TERM_DICTIONARY_BLOOM] |
--builder-variable-posting-blocks |
bool | false |
builder.variable_posting_blocks |
YSEARCH_BUILDER_VARIABLE_POSTING_BLOCKS |
Experimental bounded-window BM25F-aware posting partitioning for format5 or newer output. [builder.variable_posting_blocks; env YSEARCH_BUILDER_VARIABLE_POSTING_BLOCKS] |
--cache-block-bytes |
bytes | 2GiB |
cache.block_bytes |
YSEARCH_CACHE_BLOCK_BYTES |
Disk, not memory: bytes of verified decoded blocks this node may keep under cache.dir. This is the cheap half of block caching - it converts a remote read into a local one and costs no resident memory - so size it above one query's working set and leave cache.read_block_bytes to decide what stays in RAM. Measured on 294 segments: one single-term query touched about 363MB of term dictionary and postings and one scored two-term query about 544MB, so the default holds several such working sets. [cache.block_bytes; env YSEARCH_CACHE_BLOCK_BYTES] (positive) |
--cache-block-entries |
int | 1048576 |
cache.block_entries |
YSEARCH_CACHE_BLOCK_ENTRIES |
Disk, not memory: how many decoded blocks cache.block_bytes may be spread over. Whichever is reached first bounds the cache; at the measured ~237KiB per block the byte budget is reached first by a wide margin. [cache.block_entries; env YSEARCH_CACHE_BLOCK_ENTRIES] (positive) |
--cache-dir |
string | cache.dir |
YSEARCH_CACHE_DIR |
Disposable local cache directory; symlinks in its path are resolved once at startup and the cache then anchors there without following any. It holds the two disk budgets, cache.full_bytes and cache.block_bytes, and nothing else: every other cache.* budget is process memory. A relative value in a configuration file resolves against that file's directory. [cache.dir; env YSEARCH_CACHE_DIR] | |
--cache-full-bytes |
bytes | 8GiB |
cache.full_bytes |
YSEARCH_CACHE_FULL_BYTES |
Disk, not memory: bytes of whole hydrated segments this node may keep under cache.dir. With cache.block_bytes it is the whole of what the cache directory holds, so a volume smaller than their sum is an eviction loop the node cannot see. [cache.full_bytes; env YSEARCH_CACHE_FULL_BYTES] (positive) |
--cache-full-entries |
int | 1024 |
cache.full_entries |
YSEARCH_CACHE_FULL_ENTRIES |
Disk, not memory: how many whole segments cache.full_bytes may be spread over. Whichever of the two is reached first bounds the cache, and at the measured ~340MB per segment of a 101GB corpus the byte budget is reached long before this one. [cache.full_entries; env YSEARCH_CACHE_FULL_ENTRIES] (positive) |
--cache-lazy-readers |
bool | false |
cache.lazy_readers |
YSEARCH_CACHE_LAZY_READERS |
Experimental: acquire immutable segment readers and optional filter payloads only for admitted query work. It is also what routing.presence_bytes zero means: eager readers read that zero as unbounded and hold every segment's presence filter, lazy readers read it as none. [cache.lazy_readers; env YSEARCH_CACHE_LAZY_READERS] |
--cache-ordinal-bytes |
bytes | 64MiB |
cache.ordinal_bytes |
YSEARCH_CACHE_ORDINAL_BYTES |
Memory, not disk: process-wide verified ordinal-ID pages, including pinned pages and in-flight page workspace, shared across indexes and generations. [cache.ordinal_bytes; env YSEARCH_CACHE_ORDINAL_BYTES] (at least 327936) |
--cache-read-block-bytes |
bytes | 512MiB |
cache.read_block_bytes |
YSEARCH_CACHE_READ_BLOCK_BYTES |
Memory, not disk: process-wide decoded WavesDB blocks held resident and shared by immutable segment readers. This is what decides whether a repeated query is warm. Below one query's working set nothing survives to the next query and every query pays the cold price forever: measured on 294 segments, a 24MiB budget re-read all 214MB of term dictionary byte for byte while about 495MiB answered the repeat from 57,421 bytes. Size it from the corpus, not the machine, and from the layout its segments were built with. A term probe costs the same whatever the term, but what it costs depends on whether the segment carries a term-family Bloom filter: about 711KiB per segment on one built before builder.term_dictionary_bloom defaulted to false, and about 21KiB on one built since. The term dictionary alone needs segments times that figure, and the postings of the shape you serve come on top. A mixed corpus pays the older rate for the segments it has not rebuilt. [cache.read_block_bytes; env YSEARCH_CACHE_READ_BLOCK_BYTES] (positive) |
--cache-read-open-files |
int | 1024 |
cache.read_open_files |
YSEARCH_CACHE_READ_OPEN_FILES |
Process-wide open WavesDB table-file limit shared by immutable segment readers. It spends file descriptors, and nothing here raises RLIMIT_NOFILE, so the default sits at the 1024 a Linux process is commonly given with the listeners, connections and cache files sharing it: raise the limit before raising this. [cache.read_open_files; env YSEARCH_CACHE_READ_OPEN_FILES] (positive) |
--cache-read-open-readers |
int | 4098 |
cache.read_open_readers |
YSEARCH_CACHE_READ_OPEN_READERS |
Process-wide decoded WavesDB table-reader count limit. Each retained reader also spends cache.read_reader_bytes, and whichever of the two is reached first evicts. Unlike cache.read_open_files this spends memory rather than file descriptors, so size it from the corpus: a segment holds several table families, and a count that cannot hold them all evicts on every query. At 1024, which this defaulted to, a 253-segment corpus needing 1,321 readers held 77% of them and evicted 3,022 times while its byte budget sat 89% empty. That is dearer than it sounds, because a re-opened table re-reads its Bloom filter and block index through a path that bypasses the block cache, so the eviction becomes object reads that repeat for the life of the node: the same query read 62.8MiB in 275 range GETs every time it ran, and none after the count was raised. Measured resident cost is about 760KiB per reader. [cache.read_open_readers; env YSEARCH_CACHE_READ_OPEN_READERS] (positive) |
--cache-read-reader-bytes |
bytes | 2GiB |
cache.read_reader_bytes |
YSEARCH_CACHE_READ_READER_BYTES |
Memory, not disk: process-wide WavesDB table index and Bloom-filter bytes held resident. It is the only cache budget that scales with the corpus rather than with the query, at a measured ~14MiB per segment, so the default holds roughly 145 segments and a larger corpus re-reads a segment's index after evicting it. [cache.read_reader_bytes; env YSEARCH_CACHE_READ_READER_BYTES] (positive) |
--cache-result-enabled |
bool | true |
cache.result_enabled |
YSEARCH_CACHE_RESULT_ENABLED |
Cache generation and segment ranked results. Disable for execution benchmarks; reader, block, plan and stored-field caches remain active. [cache.result_enabled; env YSEARCH_CACHE_RESULT_ENABLED] |
--cache-scrub-entries |
int | 4 |
cache.scrub_entries |
YSEARCH_CACHE_SCRUB_ENTRIES |
How many cached full segments one scrubber pass re-reads. The scrubber walks the cache in a rotating cursor, so this and cache.scrub_interval together set how long a full sweep takes and how much disk read it costs; a segment currently in use is skipped and picked up on a later pass. [cache.scrub_entries; env YSEARCH_CACHE_SCRUB_ENTRIES] (in [0, 4096]) |
--cache-scrub-interval |
duration | 5m |
cache.scrub_interval |
YSEARCH_CACHE_SCRUB_INTERVAL |
How often the background scrubber re-reads cached full segments and checks them against their commits. This is the only thing that notices a cached segment rotting on disk: a query trusts an entry once it has been verified, because verifying costs the SHA-256 of every file in the segment and doing that per request made a many-segment query spend all its time hashing. Zero disables the scrubber, which leaves local corruption undetected until the entry is evicted. [cache.scrub_interval; env YSEARCH_CACHE_SCRUB_INTERVAL] (in [0s, 24h0m0s]) |
--cache-sidecar-bytes |
bytes | 8MiB |
cache.sidecar_bytes |
YSEARCH_CACHE_SIDECAR_BYTES |
Memory, not disk: process-wide optional exact-filter decoder and lease budget shared across indexes and generations. [cache.sidecar_bytes; env YSEARCH_CACHE_SIDECAR_BYTES] (positive) |
--cache-warm-prefetch-bytes |
bytes | 0 |
cache.warm_prefetch_bytes |
YSEARCH_CACHE_WARM_PREFETCH_BYTES |
Optional routing-page warmup byte limit after the first served query; zero disables. It spends object reads, not a budget of its own: warmed pages land in the process-wide routing page cache and are charged there, so warming past that cache only evicts what it just read. Shares foreground cache admission. [cache.warm_prefetch_bytes; env YSEARCH_CACHE_WARM_PREFETCH_BYTES] (in [0, 64MiB]) |
--cache-warm-prefetch-concurrency |
int | 1 |
cache.warm_prefetch_concurrency |
YSEARCH_CACHE_WARM_PREFETCH_CONCURRENCY |
Maximum concurrent optional warmup reads; foreground queries stop new prefetch work. [cache.warm_prefetch_concurrency; env YSEARCH_CACHE_WARM_PREFETCH_CONCURRENCY] (in [0, 8]) |
--compaction-cluster-field |
string | compaction.cluster_field |
YSEARCH_COMPACTION_CLUSTER_FIELD |
Existing scalar filterable string used by cluster layout; an absent field preserves order. [compaction.cluster_field; env YSEARCH_COMPACTION_CLUSTER_FIELD] | |
--compaction-document-layout |
enum | preserve |
compaction.document_layout |
YSEARCH_COMPACTION_DOCUMENT_LAYOUT |
Experimental survivor layout for new compaction outputs; preserve retains input order, cluster groups scalar categories, bisection uses a bounded sampled term graph. [compaction.document_layout; env YSEARCH_COMPACTION_DOCUMENT_LAYOUT] (one of preserve, cluster, bisection) |
--compaction-enabled |
bool | false |
compaction.enabled |
YSEARCH_COMPACTION_ENABLED |
Run single-flight size-tiered compaction inside all-in-one serve. The explicit node compactor role always runs; this switch stays off there and by default so production can isolate maintenance from query and ingest. [compaction.enabled; env YSEARCH_COMPACTION_ENABLED] |
--compaction-hydration-bytes |
bytes | 8GiB |
compaction.hydration_bytes |
YSEARCH_COMPACTION_HYDRATION_BYTES |
Maximum downloaded checkpoint payload retained per compaction job across all input hydrations. Borrowed resident inputs are not copied or charged. Filesystem metadata, output database and spill space have separate accounting. [compaction.hydration_bytes; env YSEARCH_COMPACTION_HYDRATION_BYTES] (positive) |
--compaction-hydration-workers |
int | 2 |
compaction.hydration_workers |
YSEARCH_COMPACTION_HYDRATION_WORKERS |
Maximum concurrent input hydrations per compaction job. [compaction.hydration_workers; env YSEARCH_COMPACTION_HYDRATION_WORKERS] (in [1, 8]) |
--compaction-interval |
duration | 1m |
compaction.interval |
YSEARCH_COMPACTION_INTERVAL |
Interval between background compaction eligibility checks. The all-in-one server waits for sustained ingest idleness; use the isolated compactor role when fan-out must be reduced during continuous ingest. [compaction.interval; env YSEARCH_COMPACTION_INTERVAL] (in [1s, 24h0m0s]) |
--compaction-max-active-segments |
int | 16 |
compaction.max_active_segments |
YSEARCH_COMPACTION_MAX_ACTIVE_SEGMENTS |
Active searchable segment fan-out above which the scheduler may compact. [compaction.max_active_segments; env YSEARCH_COMPACTION_MAX_ACTIVE_SEGMENTS] (positive) |
--compaction-max-concurrent-jobs |
int | 1 |
compaction.max_concurrent_jobs |
YSEARCH_COMPACTION_MAX_CONCURRENT_JOBS |
Shared background compaction job slots across hosted indexes; physical merges are serial and hydration has a separate worker cap. [compaction.max_concurrent_jobs; env YSEARCH_COMPACTION_MAX_CONCURRENT_JOBS] (in [1, 8]) |
--compaction-max-inputs |
int | 8 |
compaction.max_inputs |
YSEARCH_COMPACTION_MAX_INPUTS |
Maximum inputs in one compaction job; jobs are always single-flight. [compaction.max_inputs; env YSEARCH_COMPACTION_MAX_INPUTS] (in [2, 64]) |
--compaction-max-output-bytes |
bytes | 4GiB |
compaction.max_output_bytes |
YSEARCH_COMPACTION_MAX_OUTPUT_BYTES |
Maximum summed input bytes admitted to one compaction proposal. [compaction.max_output_bytes; env YSEARCH_COMPACTION_MAX_OUTPUT_BYTES] (positive) |
--compaction-max-size-ratio |
int | 2 |
compaction.max_size_ratio |
YSEARCH_COMPACTION_MAX_SIZE_RATIO |
Largest size ratio allowed between inputs in one tier. [compaction.max_size_ratio; env YSEARCH_COMPACTION_MAX_SIZE_RATIO] (in [1, 1024]) |
--compaction-min-inputs |
int | 4 |
compaction.min_inputs |
YSEARCH_COMPACTION_MIN_INPUTS |
Minimum adjacent similarly-sized inputs in one compaction job. [compaction.min_inputs; env YSEARCH_COMPACTION_MIN_INPUTS] (in [2, 64]) |
--compaction-read-inflight-bytes |
bytes | 64MiB |
compaction.read_inflight_bytes |
YSEARCH_COMPACTION_READ_INFLIGHT_BYTES |
Shared compaction read payload bytes in flight across jobs. Open reads hold credits until Close; an individual object or range larger than this limit is rejected. [compaction.read_inflight_bytes; env YSEARCH_COMPACTION_READ_INFLIGHT_BYTES] (at least 64KiB) |
--compaction-recent-delta |
int | 4 |
compaction.recent_delta |
YSEARCH_COMPACTION_RECENT_DELTA |
Newest active segments left uncompacted as an ingest delta tier. [compaction.recent_delta; env YSEARCH_COMPACTION_RECENT_DELTA] (in [0, 1024]) |
--compaction-reorder-leaf-documents |
int | 128 |
compaction.reorder_leaf_documents |
YSEARCH_COMPACTION_REORDER_LEAF_DOCUMENTS |
Maximum stable leaf size of experimental balanced graph bisection; each document samples at most 32 terms. [compaction.reorder_leaf_documents; env YSEARCH_COMPACTION_REORDER_LEAF_DOCUMENTS] (in [1, 4096]) |
--compaction-reorder-temp-bytes |
bytes | 1GiB |
compaction.reorder_temp_bytes |
YSEARCH_COMPACTION_REORDER_TEMP_BYTES |
Temporary spill cap for reordered outputs, including permutation, sampled graph and posting resort; the smaller compaction.temporary_bytes cap also applies. [compaction.reorder_temp_bytes; env YSEARCH_COMPACTION_REORDER_TEMP_BYTES] (positive) |
--compaction-routing-fragment-bytes |
bytes | 8MiB |
compaction.routing_fragment_bytes |
YSEARCH_COMPACTION_ROUTING_FRAGMENT_BYTES |
Optional routing fragment disk cap per compaction output segment; overrides builder.routing_fragment_bytes for compaction's own merges so background maintenance can carry its own share independent of foreground ingestion. Zero disables fragment writing for compaction outputs, which also stops this generation's routing descriptor from ever completing until every one of its segments gets a fragment some other way. [compaction.routing_fragment_bytes; env YSEARCH_COMPACTION_ROUTING_FRAGMENT_BYTES] (in [0, 64MiB]) |
--compaction-routing-memory-bytes |
bytes | 64MiB |
compaction.routing_memory_bytes |
YSEARCH_COMPACTION_ROUTING_MEMORY_BYTES |
Memory budget for assembling one generation's routing descriptor from its member segments' own fragments after a successful compaction. Separate from compaction.temporary_bytes and the segment-merge budgets: descriptor assembly reads small fragment objects, not segment checkpoints. [compaction.routing_memory_bytes; env YSEARCH_COMPACTION_ROUTING_MEMORY_BYTES] (at least 64MiB) |
--compaction-routing-temp-bytes |
bytes | 1GiB |
compaction.routing_temp_bytes |
YSEARCH_COMPACTION_ROUTING_TEMP_BYTES |
Spill and page-file budget for the same post-compaction descriptor assembly. Bounded well below compaction.temporary_bytes: a table assembled from fragments alone is the right-sized presence table (internal/routing/value.go), not the segments' own content. [compaction.routing_temp_bytes; env YSEARCH_COMPACTION_ROUTING_TEMP_BYTES] (positive) |
--compaction-target-bytes |
bytes | 512MiB |
compaction.target_bytes |
YSEARCH_COMPACTION_TARGET_BYTES |
Approximate input-byte target for one size-tiered compaction group. [compaction.target_bytes; env YSEARCH_COMPACTION_TARGET_BYTES] (positive) |
--compaction-temporary-bytes |
bytes | 8GiB |
compaction.temporary_bytes |
YSEARCH_COMPACTION_TEMPORARY_BYTES |
Shared accounted spill-byte limit within one physical compaction; hydration and final database storage are separate from spill space. [compaction.temporary_bytes; env YSEARCH_COMPACTION_TEMPORARY_BYTES] (positive) |
--compaction-write-inflight-bytes |
bytes | 64MiB |
compaction.write_inflight_bytes |
YSEARCH_COMPACTION_WRITE_INFLIGHT_BYTES |
Shared compaction write payload bytes in flight across jobs. An individual object larger than this limit is rejected before upload. [compaction.write_inflight_bytes; env YSEARCH_COMPACTION_WRITE_INFLIGHT_BYTES] (at least 64KiB) |
--config-watch |
bool | true |
config.watch |
YSEARCH_CONFIG_WATCH |
Reload the discovered configuration files when any of them changes. [config.watch; env YSEARCH_CONFIG_WATCH] |
--pprof-listen |
string | debug.pprof_listen |
YSEARCH_DEBUG_PPROF_LISTEN |
host:port serving net/http/pprof profiles; empty disables it. It binds before the catalog is opened, so a slow start can be profiled, and an address with no host (:6060) binds loopback. Profiles expose heap contents and goroutine stacks, so keep it on loopback and never on a public interface. [debug.pprof_listen; env YSEARCH_DEBUG_PPROF_LISTEN] | |
--embedding-external-allow-http |
bool | false |
embedding.external_allow_http |
YSEARCH_EMBEDDING_EXTERNAL_ALLOW_HTTP |
Allow plain HTTP external embedding endpoints for trusted development networks. [embedding.external_allow_http; env YSEARCH_EMBEDDING_EXTERNAL_ALLOW_HTTP] |
--embedding-external-batch-size |
int | 128 |
embedding.external_batch_size |
YSEARCH_EMBEDDING_EXTERNAL_BATCH_SIZE |
Maximum texts in one external embedding request. [embedding.external_batch_size; env YSEARCH_EMBEDDING_EXTERNAL_BATCH_SIZE] (in [1, 4096]) |
--embedding-external-concurrency |
int | 8 |
embedding.external_concurrency |
YSEARCH_EMBEDDING_EXTERNAL_CONCURRENCY |
Concurrent external embedding requests per process. [embedding.external_concurrency; env YSEARCH_EMBEDDING_EXTERNAL_CONCURRENCY] (in [1, 1024]) |
--embedding-external-max-retry-after |
duration | 2s |
embedding.external_max_retry_after |
YSEARCH_EMBEDDING_EXTERNAL_MAX_RETRY_AFTER |
Largest Retry-After delay accepted from an external embedding endpoint. [embedding.external_max_retry_after; env YSEARCH_EMBEDDING_EXTERNAL_MAX_RETRY_AFTER] (positive) |
--embedding-external-request-bytes |
bytes | 8MiB |
embedding.external_request_bytes |
YSEARCH_EMBEDDING_EXTERNAL_REQUEST_BYTES |
Maximum encoded external embedding request bytes. [embedding.external_request_bytes; env YSEARCH_EMBEDDING_EXTERNAL_REQUEST_BYTES] (positive) |
--embedding-external-response-bytes |
bytes | 64MiB |
embedding.external_response_bytes |
YSEARCH_EMBEDDING_EXTERNAL_RESPONSE_BYTES |
Maximum external embedding response bytes read before JSON decoding. [embedding.external_response_bytes; env YSEARCH_EMBEDDING_EXTERNAL_RESPONSE_BYTES] (positive) |
--embedding-external-retries |
int | 2 |
embedding.external_retries |
YSEARCH_EMBEDDING_EXTERNAL_RETRIES |
Retry attempts after the first retryable external embedding failure. [embedding.external_retries; env YSEARCH_EMBEDDING_EXTERNAL_RETRIES] (in [0, 16]) |
--embedding-external-retry-base |
duration | 50ms |
embedding.external_retry_base |
YSEARCH_EMBEDDING_EXTERNAL_RETRY_BASE |
Base exponential backoff for external embedding retries. [embedding.external_retry_base; env YSEARCH_EMBEDDING_EXTERNAL_RETRY_BASE] (positive) |
--embedding-external-timeout |
duration | 30s |
embedding.external_timeout |
YSEARCH_EMBEDDING_EXTERNAL_TIMEOUT |
Deadline for one external embedding HTTP attempt sequence. [embedding.external_timeout; env YSEARCH_EMBEDDING_EXTERNAL_TIMEOUT] (positive) |
--embedding-grpc-allow-insecure |
bool | false |
embedding.grpc_allow_insecure |
YSEARCH_EMBEDDING_GRPC_ALLOW_INSECURE |
Allow plaintext gRPC embedding endpoints on trusted internal networks. [embedding.grpc_allow_insecure; env YSEARCH_EMBEDDING_GRPC_ALLOW_INSECURE] |
--embedding-grpc-batch-size |
int | 128 |
embedding.grpc_batch_size |
YSEARCH_EMBEDDING_GRPC_BATCH_SIZE |
Maximum texts in one gRPC embedding request. [embedding.grpc_batch_size; env YSEARCH_EMBEDDING_GRPC_BATCH_SIZE] (in [1, 4096]) |
--embedding-grpc-concurrency |
int | 8 |
embedding.grpc_concurrency |
YSEARCH_EMBEDDING_GRPC_CONCURRENCY |
Concurrent gRPC embedding requests per process. [embedding.grpc_concurrency; env YSEARCH_EMBEDDING_GRPC_CONCURRENCY] (in [1, 1024]) |
--embedding-grpc-request-bytes |
bytes | 8MiB |
embedding.grpc_request_bytes |
YSEARCH_EMBEDDING_GRPC_REQUEST_BYTES |
Maximum encoded gRPC embedding request bytes. [embedding.grpc_request_bytes; env YSEARCH_EMBEDDING_GRPC_REQUEST_BYTES] (positive) |
--embedding-grpc-response-bytes |
bytes | 64MiB |
embedding.grpc_response_bytes |
YSEARCH_EMBEDDING_GRPC_RESPONSE_BYTES |
Maximum encoded gRPC embedding response bytes. [embedding.grpc_response_bytes; env YSEARCH_EMBEDDING_GRPC_RESPONSE_BYTES] (positive) |
--embedding-grpc-timeout |
duration | 30s |
embedding.grpc_timeout |
YSEARCH_EMBEDDING_GRPC_TIMEOUT |
Deadline for one gRPC embedding request. [embedding.grpc_timeout; env YSEARCH_EMBEDDING_GRPC_TIMEOUT] (positive) |
--embedding-grpc-work-class |
enum | auto |
embedding.grpc_work_class |
YSEARCH_EMBEDDING_GRPC_WORK_CLASS |
gRPC embedding scheduler class; auto maps queries to interactive and indexing to bulk. [embedding.grpc_work_class; env YSEARCH_EMBEDDING_GRPC_WORK_CLASS] (one of auto, interactive, bulk) |
--embedding-internal-batch-size |
int | 32 |
embedding.internal_batch_size |
YSEARCH_EMBEDDING_INTERNAL_BATCH_SIZE |
Maximum texts in one internal embedding batch. [embedding.internal_batch_size; env YSEARCH_EMBEDDING_INTERNAL_BATCH_SIZE] (in [1, 4096]) |
--embedding-internal-concurrency |
int | 2 |
embedding.internal_concurrency |
YSEARCH_EMBEDDING_INTERNAL_CONCURRENCY |
Concurrent pure-Go internal embedding batches. [embedding.internal_concurrency; env YSEARCH_EMBEDDING_INTERNAL_CONCURRENCY] (in [1, 256]) |
--embedding-internal-enabled |
bool | false |
embedding.internal_enabled |
YSEARCH_EMBEDDING_INTERNAL_ENABLED |
Enable the pure-Go internal embedding runtime. Models remain lazy and checksum-pinned by schema profiles. [embedding.internal_enabled; env YSEARCH_EMBEDDING_INTERNAL_ENABLED] |
--embedding-model-cache-bytes |
bytes | 10GiB |
embedding.model_cache_bytes |
YSEARCH_EMBEDDING_MODEL_CACHE_BYTES |
Maximum installed bytes in the internal-model cache. [embedding.model_cache_bytes; env YSEARCH_EMBEDDING_MODEL_CACHE_BYTES] (positive) |
--embedding-model-cache-dir |
string | embedding.model_cache_dir |
YSEARCH_EMBEDDING_MODEL_CACHE_DIR |
Checksum-addressed internal-model cache directory. Empty disables internal embedding; keep it distinct from cache.dir. A relative value in a configuration file resolves against that file's directory. [embedding.model_cache_dir; env YSEARCH_EMBEDDING_MODEL_CACHE_DIR] | |
--embedding-model-cache-packages |
int | 8 |
embedding.model_cache_packages |
YSEARCH_EMBEDDING_MODEL_CACHE_PACKAGES |
Maximum installed internal-model packages. [embedding.model_cache_packages; env YSEARCH_EMBEDDING_MODEL_CACHE_PACKAGES] (positive) |
--embedding-model-download-allow-http |
bool | false |
embedding.model_download_allow_http |
YSEARCH_EMBEDDING_MODEL_DOWNLOAD_ALLOW_HTTP |
Allow plain HTTP model manifests and artifacts for trusted development networks. [embedding.model_download_allow_http; env YSEARCH_EMBEDDING_MODEL_DOWNLOAD_ALLOW_HTTP] |
--embedding-model-download-concurrency |
int | 2 |
embedding.model_download_concurrency |
YSEARCH_EMBEDDING_MODEL_DOWNLOAD_CONCURRENCY |
Concurrent verified internal-model artifact downloads. [embedding.model_download_concurrency; env YSEARCH_EMBEDDING_MODEL_DOWNLOAD_CONCURRENCY] (in [1, 64]) |
--embedding-model-download-timeout |
duration | 10m |
embedding.model_download_timeout |
YSEARCH_EMBEDDING_MODEL_DOWNLOAD_TIMEOUT |
Deadline for one internal-model package installation. [embedding.model_download_timeout; env YSEARCH_EMBEDDING_MODEL_DOWNLOAD_TIMEOUT] (positive) |
--embedding-model-manifest-bytes |
bytes | 1MiB |
embedding.model_manifest_bytes |
YSEARCH_EMBEDDING_MODEL_MANIFEST_BYTES |
Maximum bytes in one internal-model manifest. [embedding.model_manifest_bytes; env YSEARCH_EMBEDDING_MODEL_MANIFEST_BYTES] (positive) |
--embedding-model-package-bytes |
bytes | 4GiB |
embedding.model_package_bytes |
YSEARCH_EMBEDDING_MODEL_PACKAGE_BYTES |
Maximum bytes in one downloaded internal-model package. [embedding.model_package_bytes; env YSEARCH_EMBEDDING_MODEL_PACKAGE_BYTES] (positive) |
--embedding-query-cache-bytes |
bytes | 64MiB |
embedding.query_cache_bytes |
YSEARCH_EMBEDDING_QUERY_CACHE_BYTES |
Maximum float-vector bytes retained by the text-query embedding cache. [embedding.query_cache_bytes; env YSEARCH_EMBEDDING_QUERY_CACHE_BYTES] (positive) |
--embedding-query-cache-entries |
int | 4096 |
embedding.query_cache_entries |
YSEARCH_EMBEDDING_QUERY_CACHE_ENTRIES |
Maximum completed text-query embeddings retained per process. [embedding.query_cache_entries; env YSEARCH_EMBEDDING_QUERY_CACHE_ENTRIES] (positive) |
--embedding-query-cache-ttl |
duration | 10m |
embedding.query_cache_ttl |
YSEARCH_EMBEDDING_QUERY_CACHE_TTL |
Lifetime of a completed text-query embedding cache entry. [embedding.query_cache_ttl; env YSEARCH_EMBEDDING_QUERY_CACHE_TTL] (positive) |
--admin-fleet |
list | fleet.admin_fleet |
YSEARCH_FLEET_ADMIN_FLEET |
Node host:port endpoints StreamFleetStats fans in; empty refuses the fleet stream. [fleet.admin_fleet; env YSEARCH_FLEET_ADMIN_FLEET] | |
--aggregators |
list | fleet.aggregators |
YSEARCH_FLEET_AGGREGATORS |
Aggregator host:port endpoints. [fleet.aggregators; env YSEARCH_FLEET_AGGREGATORS] | |
--builders |
list | fleet.builders |
YSEARCH_FLEET_BUILDERS |
Builder host:port endpoints the router polls and rendezvous-routes batches across. [fleet.builders; env YSEARCH_FLEET_BUILDERS] | |
--fallback-workers |
list | fleet.fallback_workers |
YSEARCH_FLEET_FALLBACK_WORKERS |
Worker host:port endpoints: the dispatch universe and the cache-oblivious fallback. [fleet.fallback_workers; env YSEARCH_FLEET_FALLBACK_WORKERS] | |
--fan-in |
int | 0 |
fleet.fan_in |
YSEARCH_FLEET_FAN_IN |
Children per merge node in coordinator plans; zero means the planner's default, otherwise at least 2. [fleet.fan_in; env YSEARCH_FLEET_FAN_IN] (in [0, 1024]) |
--lane-slots |
string | interactive=4,streaming=2 |
fleet.lane_slots |
YSEARCH_FLEET_LANE_SLOTS |
Per-lane worker slot pools, lane=count. [fleet.lane_slots; env YSEARCH_FLEET_LANE_SLOTS] |
--mergers |
list | fleet.mergers |
YSEARCH_FLEET_MERGERS |
Merge host:port endpoints: the coordinator's merge tier, a merger's delegation peers. [fleet.mergers; env YSEARCH_FLEET_MERGERS] | |
--follower-discovery-interval |
duration | 30s |
follower.discovery_interval |
YSEARCH_FOLLOWER_DISCOVERY_INTERVAL |
How often a root attachment looks for indexes that appeared or disappeared under it. Separate from follower.poll_interval because discovery lists prefixes while a poll reads one pointer, and listing is the more expensive and more rate-limited of the two. [follower.discovery_interval; env YSEARCH_FOLLOWER_DISCOVERY_INTERVAL] (positive) |
--follower-generation-overlap |
duration | 30s |
follower.generation_overlap |
YSEARCH_FOLLOWER_GENERATION_OVERLAP |
Maximum age of an unseen catalog generation a worker may resolve on demand; in-flight references may keep its engine beyond this window. [follower.generation_overlap; env YSEARCH_FOLLOWER_GENERATION_OVERLAP] (positive) |
--follower-max-staleness |
duration | 5m |
follower.max_staleness |
YSEARCH_FOLLOWER_MAX_STALENESS |
How long a follower may go without confirming its installed generation is still current before it refuses new queries. A reader that cannot reach its source keeps answering from cached data indefinitely otherwise, which is worse than an error: the results look fine and are silently frozen. Status stays readable past this point so an operator can see why. [follower.max_staleness; env YSEARCH_FOLLOWER_MAX_STALENESS] (positive) |
--follower-poll-interval |
duration | 2s |
follower.poll_interval |
YSEARCH_FOLLOWER_POLL_INTERVAL |
How often a node checks the catalog's latest pointer. [follower.poll_interval; env YSEARCH_FOLLOWER_POLL_INTERVAL] (positive) |
--follower-retired-generation-grace |
duration | 30s |
follower.retired_generation_grace |
YSEARCH_FOLLOWER_RETIRED_GENERATION_GRACE |
How long a superseded generation's engine stays open after its last query. [follower.retired_generation_grace; env YSEARCH_FOLLOWER_RETIRED_GENERATION_GRACE] (positive) |
--gc-grace |
duration | 1h |
gc.grace |
YSEARCH_GC_GRACE |
Additional safety margin added to every scheduled GC reachability horizon. [gc.grace; env YSEARCH_GC_GRACE] (in [0s, 168h0m0s]) |
--gc-interval |
duration | 1h |
gc.interval |
YSEARCH_GC_INTERVAL |
Cadence at which the dedicated compactor role writes a GC proposal and considers a quarantined older proposal. [gc.interval; env YSEARCH_GC_INTERVAL] (in [1s, 168h0m0s]) |
--gc-maximum-stream-lifetime |
duration | 1h |
gc.maximum_stream_lifetime |
YSEARCH_GC_MAXIMUM_STREAM_LIFETIME |
Longest query-stream lifetime protected when marking superseded generations for scheduled GC. [gc.maximum_stream_lifetime; env YSEARCH_GC_MAXIMUM_STREAM_LIFETIME] (in [0s, 168h0m0s]) |
--gc-minimum-upload-age |
duration | 24h |
gc.minimum_upload_age |
YSEARCH_GC_MINIMUM_UPLOAD_AGE |
Minimum age before an unreferenced object can enter a scheduled GC proposal. [gc.minimum_upload_age; env YSEARCH_GC_MINIMUM_UPLOAD_AGE] (in [0s, 720h0m0s]) |
--gc-quarantine-age |
duration | 24h |
gc.quarantine_age |
YSEARCH_GC_QUARANTINE_AGE |
Minimum age of an immutable GC proposal before a fresh mark may authorize deleting its still-unreachable exact keys. [gc.quarantine_age; env YSEARCH_GC_QUARANTINE_AGE] (in [1s, 720h0m0s]) |
--gc-retained-generations |
int | 2 |
gc.retained_generations |
YSEARCH_GC_RETAINED_GENERATIONS |
Historical catalog generations retained in addition to latest during scheduled GC. [gc.retained_generations; env YSEARCH_GC_RETAINED_GENERATIONS] (in [0, 1024]) |
--gc-sweep-enabled |
bool | false |
gc.sweep_enabled |
YSEARCH_GC_SWEEP_ENABLED |
Allow the dedicated compactor role to delete freshly re-proven orphan objects after an immutable dry-run proposal passes quarantine. Disabled by default. [gc.sweep_enabled; env YSEARCH_GC_SWEEP_ENABLED] |
--generation |
string | index.generation |
YSEARCH_INDEX_GENERATION |
Exact generation to pin, or empty for the latest. [index.generation; env YSEARCH_INDEX_GENERATION] | |
--index |
string | index.name |
YSEARCH_INDEX_NAME |
Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles. [index.name; env YSEARCH_INDEX_NAME] | |
--ingest-burst-documents |
int | 100000 |
ingest.burst_documents |
YSEARCH_INGEST_BURST_DOCUMENTS |
Per-index document tokens available for an ingest burst when the rate quota is enabled. [ingest.burst_documents; env YSEARCH_INGEST_BURST_DOCUMENTS] (positive) |
--ingest-dir |
string | ingest.dir |
YSEARCH_INGEST_DIR |
Ingest spool/build directory for builders and scratch root for the dedicated compactor role. A relative value in a configuration file resolves against that file's directory. [ingest.dir; env YSEARCH_INGEST_DIR] | |
--ingest-documents-per-second |
int | 0 |
ingest.documents_per_second |
YSEARCH_INGEST_DOCUMENTS_PER_SECOND |
Per-router, per-index document admission rate; zero disables the rate quota. [ingest.documents_per_second; env YSEARCH_INGEST_DOCUMENTS_PER_SECOND] (in [0, 1099511627776]) |
--ingest-global-queue-bytes |
bytes | 256MiB |
ingest.global_queue_bytes |
YSEARCH_INGEST_GLOBAL_QUEUE_BYTES |
Encoded ingest bytes all router sessions may hold while waiting for builders. [ingest.global_queue_bytes; env YSEARCH_INGEST_GLOBAL_QUEUE_BYTES] (positive) |
--ingest-index-queue-bytes |
bytes | 64MiB |
ingest.index_queue_bytes |
YSEARCH_INGEST_INDEX_QUEUE_BYTES |
Encoded ingest bytes one index may hold while waiting for builders. [ingest.index_queue_bytes; env YSEARCH_INGEST_INDEX_QUEUE_BYTES] (positive) |
--ingest-max-batch-bytes |
bytes | 4MiB |
ingest.max_batch_bytes |
YSEARCH_INGEST_MAX_BATCH_BYTES |
Largest accepted ingest batch. [ingest.max_batch_bytes; env YSEARCH_INGEST_MAX_BATCH_BYTES] (positive) |
--ingest-max-document-bytes |
bytes | 16MiB |
ingest.max_document_bytes |
YSEARCH_INGEST_MAX_DOCUMENT_BYTES |
Largest accepted document. [ingest.max_document_bytes; env YSEARCH_INGEST_MAX_DOCUMENT_BYTES] (positive) |
--ingest-seal-age |
duration | 30s |
ingest.seal_age |
YSEARCH_INGEST_SEAL_AGE |
Age at which an open build seals. [ingest.seal_age; env YSEARCH_INGEST_SEAL_AGE] (positive) |
--ingest-seal-bytes |
bytes | 0 |
ingest.seal_bytes |
YSEARCH_INGEST_SEAL_BYTES |
Spooled bytes at which an open build seals; zero derives it as a quarter of builder.sort_memory_bytes. A build's postings are about twice its spooled bytes and the partitions get roughly half the sort budget, so a spool larger than that quarter cannot be sorted in memory and the build spills instead — which is the difference between one file per build and hundreds, and measured 2.5x on the build itself. [ingest.seal_bytes; env YSEARCH_INGEST_SEAL_BYTES] (in [0, 1TiB]) |
--ingest-seal-documents |
int | 100000 |
ingest.seal_documents |
YSEARCH_INGEST_SEAL_DOCUMENTS |
Spooled documents at which an open build seals. [ingest.seal_documents; env YSEARCH_INGEST_SEAL_DOCUMENTS] (positive) |
--log-format |
enum | text |
log.format |
YSEARCH_LOG_FORMAT |
Log line format. [log.format; env YSEARCH_LOG_FORMAT] (one of text, json) |
--log-level |
enum | info |
log.level |
YSEARCH_LOG_LEVEL |
Minimum level written to stderr. [log.level; env YSEARCH_LOG_LEVEL] (one of error, warn, info, debug) |
--object-backend |
enum | fs |
object.backend |
YSEARCH_OBJECT_BACKEND |
Object store backend. [object.backend; env YSEARCH_OBJECT_BACKEND] (one of fs, s3) |
--object-dir |
string | object.dir |
YSEARCH_OBJECT_DIR |
Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory. [object.dir; env YSEARCH_OBJECT_DIR] | |
--object-root |
string | indexes |
object.root |
YSEARCH_OBJECT_ROOT |
Object key root. [object.root; env YSEARCH_OBJECT_ROOT] |
--s3-anonymous |
bool | false |
object.s3.anonymous |
YSEARCH_OBJECT_S3_ANONYMOUS |
Sign no requests at all, for a bucket that grants public reads. This is a deliberate choice, never a fallback: an unresolved credential chain already signs anonymously, and a reader that quietly degraded to unsigned requests would report a permissions problem as an empty index. [object.s3.anonymous; env YSEARCH_OBJECT_S3_ANONYMOUS] |
--s3-bucket |
string | object.s3.bucket |
YSEARCH_OBJECT_S3_BUCKET |
S3 bucket; required for the s3 backend. [object.s3.bucket; env YSEARCH_OBJECT_S3_BUCKET] | |
--s3-endpoint |
string | object.s3.endpoint |
YSEARCH_OBJECT_S3_ENDPOINT |
S3 endpoint host:port; required for the s3 backend. [object.s3.endpoint; env YSEARCH_OBJECT_S3_ENDPOINT] | |
--s3-path-style |
bool | false |
object.s3.path_style |
YSEARCH_OBJECT_S3_PATH_STYLE |
Use path-style S3 addressing. [object.s3.path_style; env YSEARCH_OBJECT_S3_PATH_STYLE] |
--s3-prefix |
string | object.s3.prefix |
YSEARCH_OBJECT_S3_PREFIX |
S3 key prefix. [object.s3.prefix; env YSEARCH_OBJECT_S3_PREFIX] | |
--s3-region |
string | object.s3.region |
YSEARCH_OBJECT_S3_REGION |
S3 region. [object.s3.region; env YSEARCH_OBJECT_S3_REGION] | |
--s3-use-ssl |
bool | true |
object.s3.use_ssl |
YSEARCH_OBJECT_S3_USE_SSL |
Use TLS to the S3 endpoint. [object.s3.use_ssl; env YSEARCH_OBJECT_S3_USE_SSL] |
--source |
string | object.source |
YSEARCH_OBJECT_SOURCE |
Dataset URL to attach read-only, such as s3://bucket/root/ for a whole root or s3://bucket/root/indexes/name/ for one index. It derives object.backend, the bucket, prefix and root, the index when the URL names one, and server.read_only, each only where nothing more specific was set. Reading someone else's published index is the whole purpose, so attaching one implies read-only and cannot be talked out of it. [object.source; env YSEARCH_OBJECT_SOURCE] | |
--metrics-listen |
string | :9550 |
observability.metrics_listen |
YSEARCH_OBSERVABILITY_METRICS_LISTEN |
host:port serving Prometheus exposition at /metrics; empty disables it. Unlike debug.pprof_listen this is on by default and binds every interface, because a metric carries no document text, no query, and no key material, and a scrape target that has to be switched on is one nobody switches on. Every series already carries the role label, so the scrape target only has to supply instance and pod. [observability.metrics_listen; env YSEARCH_OBSERVABILITY_METRICS_LISTEN] |
--publisher-announce-interval |
duration | 15s |
publisher.announce_interval |
YSEARCH_PUBLISHER_ANNOUNCE_INTERVAL |
Requested commit-marker publication cadence; the daemon floors it at follower.poll_interval and 15 seconds. [publisher.announce_interval; env YSEARCH_PUBLISHER_ANNOUNCE_INTERVAL] (in [1s, 1h0m0s]) |
--publisher-lease-ttl |
duration | 30s |
publisher.lease_ttl |
YSEARCH_PUBLISHER_LEASE_TTL |
Startup-fixed object-store lease lifetime for the catalog publisher; renewal runs at one third of this value. [publisher.lease_ttl; env YSEARCH_PUBLISHER_LEASE_TTL] (in [5s, 10m0s]) |
--collapse-key-versions |
bool | true |
query.collapse_key_versions |
YSEARCH_QUERY_COLLAPSE_KEY_VERSIONS |
Return one hit per document key, the copy with the greatest mutation version. A re-pushed document is stored as a new version rather than replacing the old one, so without this a key appears once per copy. Collapsing removes candidates after selection, so a request may return fewer than top_k. [query.collapse_key_versions; env YSEARCH_QUERY_COLLAPSE_KEY_VERSIONS] |
--query-compiled-cache |
bool | false |
query.compiled_cache |
YSEARCH_QUERY_COMPILED_CACHE |
Experimental leased compiled-query cache within the shared metadata allowance. Also reuses bounded dictionary plans for eager generation-owned readers; lazy reader plans stay request-owned. Cache pressure falls back to request-owned compilation or preparation. [query.compiled_cache; env YSEARCH_QUERY_COMPILED_CACHE] |
--query-default-top-k |
int | 10 |
query.default_top_k |
YSEARCH_QUERY_DEFAULT_TOP_K |
top_k when a request names none. [query.default_top_k; env YSEARCH_QUERY_DEFAULT_TOP_K] (in [1, 10000]) |
--query-defer-public-ids |
bool | true |
query.defer_public_ids |
YSEARCH_QUERY_DEFER_PUBLIC_IDS |
Resolve a segment survivor's public ID only when the global merge returns it or must break a score tie with it, instead of for every survivor of every segment. Results are identical either way; false restores eager resolution as a same-code control. [query.defer_public_ids; env YSEARCH_QUERY_DEFER_PUBLIC_IDS] |
--query-lexical-memory-bytes |
bytes | 384MiB |
query.lexical_memory_bytes |
YSEARCH_QUERY_LEXICAL_MEMORY_BYTES |
Process-wide lexical request, candidate, queue and merge memory admission budget. Storage blocks and ordinal pages have separate cache budgets; busy requests fail with resource exhaustion. Sized to admit one request merging 64 segments at the product's 100,000-result top_k ceiling (lexical.MaxResultLimit; estimateLexicalFanoutMemory(64, 100000) = 182,632,832 bytes) with room for a second concurrent one that size. [query.lexical_memory_bytes; env YSEARCH_QUERY_LEXICAL_MEMORY_BYTES] (positive) |
--query-lexical-strategy |
enum | block-max |
query.lexical_strategy |
YSEARCH_QUERY_LEXICAL_STRATEGY |
Experimental exact lexical traversal selection; unsupported query shapes conservatively fall back to block-max. [query.lexical_strategy; env YSEARCH_QUERY_LEXICAL_STRATEGY] (one of block-max, auto, single-term-block-max, conjunction, block-max-maxscore) |
--query-logical-bound-entries |
int | 0 |
query.logical_bound_entries |
YSEARCH_QUERY_LOGICAL_BOUND_ENTRIES |
Experimental score-bound subblock size within decoded postings; zero uses physical blocks. Does not reduce physical read size. [query.logical_bound_entries; env YSEARCH_QUERY_LOGICAL_BOUND_ENTRIES] (in [0, 256]) |
--query-max-ast-depth |
int | 32 |
query.max_ast_depth |
YSEARCH_QUERY_MAX_AST_DEPTH |
Deepest query nesting either grammar accepts. [query.max_ast_depth; env YSEARCH_QUERY_MAX_AST_DEPTH] (in [1, 1024]) |
--query-max-results |
int | 0 |
query.max_results |
YSEARCH_QUERY_MAX_RESULTS |
Ceiling on maximum_results per request; zero keeps the engine default. [query.max_results; env YSEARCH_QUERY_MAX_RESULTS] |
--query-ordinal-mode |
enum | pages |
query.ordinal_mode |
YSEARCH_QUERY_ORDINAL_MODE |
Experimental ID residency policy under the shared ordinal budget. Whole tables are capped at 8 MiB and fall back to pages; adaptive promotion requires repeated broad page coverage. [query.ordinal_mode; env YSEARCH_QUERY_ORDINAL_MODE] (one of pages, whole, adaptive) |
--query-packed-simd |
bool | false |
query.packed_simd |
YSEARCH_QUERY_PACKED_SIMD |
Experimental native packed-posting decoding on supported CPUs; preserves scalar fallback and semantic validation. [query.packed_simd; env YSEARCH_QUERY_PACKED_SIMD] |
--query-phrase-gap-expansion-limit |
int | 64 |
query.phrase_gap_expansion_limit |
YSEARCH_QUERY_PHRASE_GAP_EXPANSION_LIMIT |
Most exact gap variants a {m,n} quantifier may expand to. [query.phrase_gap_expansion_limit; env YSEARCH_QUERY_PHRASE_GAP_EXPANSION_LIMIT] (in [1, 4096]) |
--query-regex-max-expansions |
int | 256 |
query.regex_max_expansions |
YSEARCH_QUERY_REGEX_MAX_EXPANSIONS |
Most dictionary terms a regex or prefix may expand to before the query is refused. [query.regex_max_expansions; env YSEARCH_QUERY_REGEX_MAX_EXPANSIONS] (in [1, 65536]) |
--query-scoring-profile |
enum | bm25f-v1 |
query.scoring_profile |
YSEARCH_QUERY_SCORING_PROFILE |
Scoring profile for a request that names none. bm25f-v1 scores each segment with its own statistics; bm25f-pinned-v1 (spec/50 §2) scores every segment under the generation's pinned statistics epoch, so scores do not depend on segment layout. It needs stats.dir; without it a pinned request fails with a typed error, never with segment statistics. [query.scoring_profile; env YSEARCH_QUERY_SCORING_PROFILE] (one of bm25f-v1, bm25f-pinned-v1) |
--query-set-simd |
bool | false |
query.set_simd |
YSEARCH_QUERY_SET_SIMD |
Experimental native intersection for balanced sparse filter arrays; skewed arrays retain scalar galloping. [query.set_simd; env YSEARCH_QUERY_SET_SIMD] |
--routing-presence-bytes |
bytes | 0 |
routing.presence_bytes |
YSEARCH_ROUTING_PRESENCE_BYTES |
Memory, not disk: resident budget for per-segment term-presence filters, used only when the generation has no routing table. A generation that has one prunes through it instead and holds no filters at all, whatever this says, because the table is read through a small page cache rather than held. Zero means none under cache.lazy_readers and unbounded without it, which at 294 segments was 1.4GiB of resident filters. That promotion for eager readers stays on for now: builder.routing_fragment_bytes and compaction.routing_fragment_bytes only default on from 2026-09-23, nothing rewrites a segment built before that, and no existing corpus has been rebuilt or fully compacted since - so a generation with an unfragmented member still depends on this filter to prune anything, including the published demo image, which does not set this flag. Filters are loaded in catalog order until the budget is reached; segments without one stay unknown and are still executed, so results never change. Budget against the decoded size, not the transfer: 680MiB of admitted filters measured 1.4GiB resident, about 2.1 times what this charges them. [routing.presence_bytes; env YSEARCH_ROUTING_PRESENCE_BYTES] (in [0, 8GiB]) |
--data-dir |
string | server.data_dir |
YSEARCH_SERVER_DATA_DIR |
Developer shortcut: derives object.backend=fs, object.dir, cache.dir, ingest.dir, and config.file beneath one directory where nothing more specific is set. A relative value in a configuration file resolves against that file's directory. [server.data_dir; env YSEARCH_SERVER_DATA_DIR] | |
--grace-period |
duration | 5s |
server.grace_period |
YSEARCH_SERVER_GRACE_PERIOD |
Graceful shutdown period. [server.grace_period; env YSEARCH_SERVER_GRACE_PERIOD] (positive) |
--listen |
string | 127.0.0.1:9500 |
server.listen |
YSEARCH_SERVER_LISTEN |
gRPC listen host:port serve and node bind; the default is the address the client verbs dial (client.server). [server.listen; env YSEARCH_SERVER_LISTEN] |
--max-receive-bytes |
bytes | 4MiB |
server.max_receive_bytes |
YSEARCH_SERVER_MAX_RECEIVE_BYTES |
Maximum gRPC request bytes (at least 64KiB). [server.max_receive_bytes; env YSEARCH_SERVER_MAX_RECEIVE_BYTES] (at least 64KiB) |
--max-send-bytes |
bytes | 4MiB |
server.max_send_bytes |
YSEARCH_SERVER_MAX_SEND_BYTES |
Maximum gRPC response bytes (at least 64KiB, one result frame). [server.max_send_bytes; env YSEARCH_SERVER_MAX_SEND_BYTES] (at least 64KiB) |
--node-id |
string | server.node_id |
YSEARCH_SERVER_NODE_ID |
Node identity; empty defaults to the bound listen address. [server.node_id; env YSEARCH_SERVER_NODE_ID] | |
--server-query-receive-memory-bytes |
bytes | 320MiB |
server.query_receive_memory_bytes |
YSEARCH_SERVER_QUERY_RECEIVE_MEMORY_BYTES |
Shared request-memory allowance for Search, worker Execute, Merge, ValidateQuery, CacheState and FetchStored. Holds decoded requests until RPC completion. Receive workspace waits at most 5ms in a 64-call queue; decoded admission refuses immediately when full. Must fit three receive buffers (each at least 1MiB) plus decoded requests. Unary wire reception/decompression and HTTP/2 queues precede this admission. Sized for at least 24 concurrent full server.max_receive_bytes receives at its default (24 * 13,238,272 bytes = 303MiB, plus headroom): fewer than that admits only a handful of concurrent requests before refusing the rest with ResourceExhausted. [server.query_receive_memory_bytes; env YSEARCH_SERVER_QUERY_RECEIVE_MEMORY_BYTES] (positive) |
--read-only |
bool | false |
server.read_only |
YSEARCH_SERVER_READ_ONLY |
Refuse every object-store write for this process's lifetime. Enforced at the single store every writer resolves through, so background work that never touches an RPC - garbage collection, and the GC dry run, which writes a proposal object before any delete decision - fails closed too. Startup-fixed on purpose: a running process cannot be talked into writing by a config reload. [server.read_only; env YSEARCH_SERVER_READ_ONLY] |
--roles |
list | server.roles |
YSEARCH_SERVER_ROLES |
Comma-separated roles for node: coordinator, worker, merger, aggregator, compactor, router, builder, publisher. [server.roles; env YSEARCH_SERVER_ROLES] | |
--server-source-management |
enum | loopback |
server.source_management |
YSEARCH_SERVER_SOURCE_MANAGEMENT |
Which peers may call SourceService, the RPC that changes which datasets this process reads. loopback answers only a caller that reached this process without crossing a network, so binding server.listen to every interface still does not expose it. any serves it to anything that can reach the port: the service has no authentication of its own, so choose it only where something in front of the address authenticates. [server.source_management; env YSEARCH_SERVER_SOURCE_MANAGEMENT] (one of loopback, any) |
--zone |
string | default |
server.zone |
YSEARCH_SERVER_ZONE |
Placement zone this node advertises in. [server.zone; env YSEARCH_SERVER_ZONE] |
--stats-dir |
string | stats.dir |
YSEARCH_STATS_DIR |
Directory of this node's statistics databases, one per index (spec/50 §3.3). Every served generation is folded into it and its epoch pinned for bm25f-pinned-v1. Unlike cache.dir it is not disposable: a node that loses it refolds from the catalog. Empty disables epochs. A relative value in a configuration file resolves against that file's directory. [stats.dir; env YSEARCH_STATS_DIR] | |
--stats-history-generations |
int | 6000 |
stats.history_generations |
YSEARCH_STATS_HISTORY_GENERATIONS |
Generations of per-generation statistics deltas kept to reconstruct an earlier epoch (spec/50 §3.3); about two days at one generation per 30 s. [stats.history_generations; env YSEARCH_STATS_HISTORY_GENERATIONS] (in [1, 16777216]) |
--hydrate-throughput-floor |
bytes | 128MiB |
storage.hydrate_throughput_floor |
YSEARCH_STORAGE_HYDRATE_THROUGHPUT_FLOOR |
Lowest believable hydration throughput in bytes per second. [storage.hydrate_throughput_floor; env YSEARCH_STORAGE_HYDRATE_THROUGHPUT_FLOOR] (positive) |
--hysteresis-denominator |
int | 4 |
storage.hysteresis_denominator |
YSEARCH_STORAGE_HYSTERESIS_DENOMINATOR |
Hysteresis denominator; must be below the numerator. [storage.hysteresis_denominator; env YSEARCH_STORAGE_HYSTERESIS_DENOMINATOR] (in [1, 4294967295]) |
--hysteresis-numerator |
int | 5 |
storage.hysteresis_numerator |
YSEARCH_STORAGE_HYSTERESIS_NUMERATOR |
Hysteresis numerator; must exceed the denominator. [storage.hysteresis_numerator; env YSEARCH_STORAGE_HYSTERESIS_NUMERATOR] (in [1, 4294967295]) |
--mode |
enum | AUTO |
storage.mode |
YSEARCH_STORAGE_MODE |
Storage mode: HYDRATE_FULL, REMOTE_BLOCKS, or AUTO (AUTO is refused by the checkpoint-bound serve). [storage.mode; env YSEARCH_STORAGE_MODE] (one of HYDRATE_FULL, REMOTE_BLOCKS, AUTO) |
--remote-latency-floor |
duration | 2ms |
storage.remote_latency_floor |
YSEARCH_STORAGE_REMOTE_LATENCY_FLOOR |
Lowest believable remote request latency. [storage.remote_latency_floor; env YSEARCH_STORAGE_REMOTE_LATENCY_FLOOR] (positive) |
--remote-throughput-floor |
bytes | 64MiB |
storage.remote_throughput_floor |
YSEARCH_STORAGE_REMOTE_THROUGHPUT_FLOOR |
Lowest believable remote throughput in bytes per second. [storage.remote_throughput_floor; env YSEARCH_STORAGE_REMOTE_THROUGHPUT_FLOOR] (positive) |
--scan-threshold-permille |
int | 200 |
storage.scan_threshold_permille |
YSEARCH_STORAGE_SCAN_THRESHOLD_PERMILLE |
Scan fraction above which AUTO hydrates. [storage.scan_threshold_permille; env YSEARCH_STORAGE_SCAN_THRESHOLD_PERMILLE] (in [0, 1000]) |
--tail-impact-enabled |
bool | false |
tail.impact_enabled |
YSEARCH_TAIL_IMPACT_ENABLED |
Persist score-banded approximate-tail data. Disabled avoids two additional records per unique term when exact tails are sufficient. [tail.impact_enabled; env YSEARCH_TAIL_IMPACT_ENABLED] |
--tail-impact-maximum-bands |
int | 64 |
tail.impact_maximum_bands |
YSEARCH_TAIL_IMPACT_MAXIMUM_BANDS |
Maximum score-impact bands persisted for one term. [tail.impact_maximum_bands; env YSEARCH_TAIL_IMPACT_MAXIMUM_BANDS] (in [1, 4096]) |
--tail-impact-target-documents |
int | 4096 |
tail.impact_target_documents |
YSEARCH_TAIL_IMPACT_TARGET_DOCUMENTS |
Target postings per persisted impact run. [tail.impact_target_documents; env YSEARCH_TAIL_IMPACT_TARGET_DOCUMENTS] (in [1, 4294967295]) |
--tail-maximum-ordering-error |
float | 0 |
tail.maximum_ordering_error |
YSEARCH_TAIL_MAXIMUM_ORDERING_ERROR |
Server ceiling on accepted approximate-tail score-ordering error; zero requires exact fallback. [tail.maximum_ordering_error; env YSEARCH_TAIL_MAXIMUM_ORDERING_ERROR] (in [0, 1.7976931348623157e+308]) |
--vector-bits-per-code |
int | 8 |
vector.bits_per_code |
YSEARCH_VECTOR_BITS_PER_CODE |
Bits in each PQ subquantizer code. [vector.bits_per_code; env YSEARCH_VECTOR_BITS_PER_CODE] (in [1, 8]) |
--vector-build-memory-bytes |
bytes | 0 |
vector.build_memory_bytes |
YSEARCH_VECTOR_BUILD_MEMORY_BYTES |
Per-build vector training and assignment memory; zero derives a bounded share of builder.sort_memory_bytes. [vector.build_memory_bytes; env YSEARCH_VECTOR_BUILD_MEMORY_BYTES] (at least 0) |
--vector-centroids |
int | 0 |
vector.centroids |
YSEARCH_VECTOR_CENTROIDS |
IVF coarse centroid count; zero derives it deterministically from population. [vector.centroids; env YSEARCH_VECTOR_CENTROIDS] (in [0, 4294967295]) |
--vector-flat-threshold |
int | 10000 |
vector.flat_threshold |
YSEARCH_VECTOR_FLAT_THRESHOLD |
Per-segment vector population at or below which candidate generation stays exhaustive. [vector.flat_threshold; env YSEARCH_VECTOR_FLAT_THRESHOLD] (in [1, 4294967295]) |
--vector-list-block-documents |
int | 0 |
vector.list_block_documents |
YSEARCH_VECTOR_LIST_BLOCK_DOCUMENTS |
Target vector entries per IVF-list block; zero follows the document-value block geometry. [vector.list_block_documents; env YSEARCH_VECTOR_LIST_BLOCK_DOCUMENTS] (in [0, 4294967295]) |
--vector-maximum-training-vectors |
int | 4096 |
vector.maximum_training_vectors |
YSEARCH_VECTOR_MAXIMUM_TRAINING_VECTORS |
Maximum deterministic training samples retained per vector field. [vector.maximum_training_vectors; env YSEARCH_VECTOR_MAXIMUM_TRAINING_VECTORS] (in [1, 4294967295]) |
--vector-query-candidate-multiplier |
int | 10 |
vector.query_candidate_multiplier |
YSEARCH_VECTOR_QUERY_CANDIDATE_MULTIPLIER |
Default ANN candidates as a multiple of requested top_k. [vector.query_candidate_multiplier; env YSEARCH_VECTOR_QUERY_CANDIDATE_MULTIPLIER] (in [1, 10000]) |
--vector-query-default-probes |
int | 8 |
vector.query_default_probes |
YSEARCH_VECTOR_QUERY_DEFAULT_PROBES |
IVF coarse lists probed when a vector request does not specify probes. [vector.query_default_probes; env YSEARCH_VECTOR_QUERY_DEFAULT_PROBES] (in [1, 4294967295]) |
--vector-query-maximum-candidates |
int | 100000 |
vector.query_maximum_candidates |
YSEARCH_VECTOR_QUERY_MAXIMUM_CANDIDATES |
Hard per-request candidate generation and exact-rerank cap. [vector.query_maximum_candidates; env YSEARCH_VECTOR_QUERY_MAXIMUM_CANDIDATES] (in [1, 4294967295]) |
--vector-query-maximum-probes |
int | 1024 |
vector.query_maximum_probes |
YSEARCH_VECTOR_QUERY_MAXIMUM_PROBES |
Hard per-request IVF probe cap. [vector.query_maximum_probes; env YSEARCH_VECTOR_QUERY_MAXIMUM_PROBES] (in [1, 4294967295]) |
--vector-query-memory-bytes |
bytes | 256MiB |
vector.query_memory_bytes |
YSEARCH_VECTOR_QUERY_MEMORY_BYTES |
Per-process admission budget for decoded vector-query working sets. [vector.query_memory_bytes; env YSEARCH_VECTOR_QUERY_MEMORY_BYTES] (positive) |
--vector-subquantizers |
int | 0 |
vector.subquantizers |
YSEARCH_VECTOR_SUBQUANTIZERS |
PQ subquantizer count; zero derives a geometry compatible with each vector field's dimension. [vector.subquantizers; env YSEARCH_VECTOR_SUBQUANTIZERS] (in [0, 4294967295]) |
--vector-training-iterations |
int | 20 |
vector.training_iterations |
YSEARCH_VECTOR_TRAINING_ITERATIONS |
Maximum deterministic k-means iterations during IVF-PQ training. [vector.training_iterations; env YSEARCH_VECTOR_TRAINING_ITERATIONS] (in [1, 1000]) |
--checkpoint |
string | checkpoint key prefix: serve one checkpoint directly (the Milestone 1 form) instead of the catalog |
ysearch sources [flags]sources talks to the SourceService of the server --server names. A source is one read-only S3 dataset the server attaches: list and get read the registry, add and replace declare one, remove withdraws it, and watch streams changes.
Only locally managed sources can be changed here. A source declared in a configuration file is reapplied on every reload, so changing it through the API would be silently reverted; those answer FAILED_PRECONDITION naming their owner.
Every change is a compare-and-swap against the registry revision. By default each verb reads the current revision and pins itself to it, so a change racing another one is refused with ABORTED rather than clobbering it; --revision pins explicitly. Source management answers only a local caller unless the server sets server.source_management=any.
Subcommands:
ysearch sources add— Declare a new source, refusing to replace an existing oneysearch sources get— Show one declared source in fullysearch sources list— List every declared source with its stateysearch sources remove— Withdraw a source and drain its in-flight readsysearch sources replace— Replace an existing source's declarationysearch sources watch— Stream the registry: a snapshot, then every change
ysearch sources add <source-id> <url> [flags]add declares a source that does not exist yet. Use replace to change one that does: keeping them apart means a typo in the id adds a second source instead of silently repointing the first.
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--anonymous |
bool | false |
sign no requests, for a bucket that grants public reads | ||
--endpoint |
string | S3 endpoint host:port for this source | |||
--path-style |
bool | false |
use path-style addressing for this source | ||
--persist |
bool | false |
keep this source across a restart; needs an installation directory | ||
--profile |
string | shared-credentials profile for this source alone | |||
--region |
string | S3 region for this source | |||
--revision |
uint64 | 0 |
registry revision to pin the change to (default: the revision read now) | ||
--use-ssl |
bool | true |
use TLS to this source's endpoint |
ysearch sources get <source-id> [flags]Show one declared source in full
ysearch sources list [flags]List every declared source with its state
ysearch sources remove <source-id> [flags]Withdraw a source and drain its in-flight reads
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--revision |
uint64 | 0 |
registry revision to pin the removal to (default: the revision read now) |
ysearch sources replace <source-id> <url> [flags]replace supplies the whole declaration, not a patch: every flag left unset takes its default rather than the stored value. A source that is serving keeps serving until the replacement is ready.
Flags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--anonymous |
bool | false |
sign no requests, for a bucket that grants public reads | ||
--endpoint |
string | S3 endpoint host:port for this source | |||
--path-style |
bool | false |
use path-style addressing for this source | ||
--persist |
bool | false |
keep this source across a restart; needs an installation directory | ||
--profile |
string | shared-credentials profile for this source alone | |||
--region |
string | S3 region for this source | |||
--revision |
uint64 | 0 |
registry revision to pin the change to (default: the revision read now) | ||
--use-ssl |
bool | true |
use TLS to this source's endpoint |
ysearch sources watch [flags]Stream the registry: a snapshot, then every change
ysearch stats [<index>] [flags]stats with no argument lists every index the server's object root holds with the totals of its active generation; an index the node does not serve is named as such rather than shown empty. stats <index> prints the detail and the head of the generation lineage. --node prints one frame of the node's own metrics; --fleet one assembled fleet frame with its completeness block (unreachable nodes are named, never zero-filled). --watch keeps the view live until q or ctrl-c.
Example:
ysearch stats
ysearch stats articles --json
ysearch stats --node --watchFlags:
| Flag | Type | Default | Key | Env | Description |
|---|---|---|---|---|---|
--fleet |
bool | false |
the fleet's assembled metrics and completeness (one StreamFleetStats frame) | ||
--generation |
string | describe this catalog generation instead of the latest (with <index>) | |||
--node |
bool | false |
this node's metrics (one StreamNodeStats frame) | ||
--watch |
bool | false |
redraw on every frame until q or ctrl-c |
ysearch version [flags]Print the build identity (the same line as --version)
Every setting, from the catalog. Precedence: default < file < environment < flag < runtime API (config set). Scope says what may change at runtime: only node-runtime keys accept config set. A secret is read from the environment only. A compile-time setting is display-only.
| Key | Kind | Scope | Default | Env | Flag | Constraint | Description |
|---|---|---|---|---|---|---|---|
builder.analysis_batch_documents |
int64 | node-runtime | 0 |
YSEARCH_BUILDER_ANALYSIS_BATCH_DOCUMENTS |
--analysis-batch-documents (--builder-analysis-batch-documents) |
in [0, 1.048576e+06] | Documents handed to the analysis workers at once; zero derives sixteen per worker. A batch is the unit that must fit in builder.analysis_memory_bytes, so a larger batch amortises the hand-off over more documents but raises the peak the analysis share has to cover. The derived shape is what the resource gates measure, so a corpus of unusually large documents is the case for lowering it rather than raising the share. |
builder.analysis_memory_bytes |
bytes size | node-runtime | 0 |
YSEARCH_BUILDER_ANALYSIS_MEMORY_BYTES |
--analysis-memory-bytes (--builder-analysis-memory-bytes) |
The share of builder.sort_memory_bytes reserved for documents in flight through analysis; zero derives a thirty-second of it, clamped to between 64KiB and 32MiB and never more than a quarter of what the public-id and docvalue spools leave. It only has to hold one bounded batch, and a document larger than the whole share still runs alone under builder.max_document_working_bytes, so the derived value is deliberately small: a three-million-document run peaked at 9.5MiB against a 128MiB share. Every byte reserved here is a byte the term partitions cannot use, which raises mini-run count and write amplification directly, so raise it only against a measured analysis stall. | |
builder.analysis_workers |
int64 | node-runtime | 0 |
YSEARCH_BUILDER_ANALYSIS_WORKERS |
--analysis-workers (--builder-analysis-workers) |
in [0, 1024] | Goroutines tokenising documents inside one build; zero derives GOMAXPROCS, bounded at eight. Analysis is the one parallel stage of an otherwise serial build, so this is per build and multiplies with builder.build_concurrency: the bound exists because a dozen builds each spawning a worker per core oversubscribes the machine and the scheduler churn costs more than the parallelism returns. Output order is preserved regardless of this value. |
builder.blob_dictionary |
bool | node-runtime | true |
YSEARCH_BUILDER_BLOB_DICTIONARY |
--blob-dictionary (--builder-blob-dictionary) |
Compress stored values against a dictionary trained per blob file. Denser on homogeneous documents, but the dictionary is coded on the build's hottest path, so turning it off trades index size for ingest throughput. | |
builder.blob_zstd_level |
int64 | node-runtime | 0 |
YSEARCH_BUILDER_BLOB_ZSTD_LEVEL |
--blob-zstd-level (--builder-blob-zstd-level) |
in [0, 11] | Zstd effort for stored values; zero keeps the storage default (7). Levels select different zstd encoders, and a build re-seeds the chosen encoder from the blob dictionary for every value it writes, so a lower level cuts build cost by more than the usual level trade-off suggests. |
builder.build_concurrency |
int64 | node-runtime | 0 |
YSEARCH_BUILDER_BUILD_CONCURRENCY |
--build-concurrency (--builder-build-concurrency) |
in [0, 256] | Sealed builds that may run through the seal pipeline at once; zero derives one per CPU, bounded at twelve. One build is a mostly single-threaded chain of analysis, sort, merge and publish that spends about half its time blocked in file system calls, so a single pipeline leaves a multi-core host idle under bulk ingest. The builder's memory is this number times builder.sort_memory_bytes. |
builder.catalog_publication |
enum | startup | direct |
YSEARCH_BUILDER_CATALOG_PUBLICATION |
builder-catalog-publication |
one of direct, external | Catalog writer mode: direct is the single-node compatibility path; external stops after commit markers for a lease-fenced publisher role. |
builder.dedupe_index_identities |
int64 | node-runtime | 0 |
YSEARCH_BUILDER_DEDUPE_INDEX_IDENTITIES |
--dedupe-index-identities (--builder-dedupe-index-identities) |
in [0, 2.68435456e+08] | Distinct document keys one open spool's dedupe index may hold before it gives up; zero derives 1048576. A key spooled twice in one build must resolve to a single winner before analysis, or the segment's dense ordinal assignment refuses the build outright. The index resolves that as records are spooled, from identities ingest already holds, and the sealed build inherits the answer; past this bound it gives up and the build reconstructs the answer by reading its spool twice instead — slower, and exactly as correct. One entry is a 16-byte key hash, a sequence and a mutation version, so the default bounds it at tens of megabytes per open spool and is reached only by a spool of a million very small documents. Lower it to cap that memory on a host running many indexes; set it to one to force the scanning path. |
builder.fuse_memory_bytes |
bytes size | startup | 0 |
YSEARCH_BUILDER_FUSE_MEMORY_BYTES |
builder-fuse-memory-bytes |
in [0, 6.7108864e+07] | Optional binary fuse construction workspace during publication; zero retains Bloom, failed admission retains Bloom. |
builder.lexical_blob_threshold |
bytes size | node-runtime | 0 |
YSEARCH_BUILDER_LEXICAL_BLOB_THRESHOLD |
--lexical-blob-threshold (--builder-lexical-blob-threshold) |
Size at which a posting, position or term value is stored in a blob file rather than inline in the key log; zero keeps the default of 64KiB. Separation exists to spare compaction from rewriting large values, and a segment is never compacted — while a blob value is compressed on its own, which with a trained dictionary costs an encoder reset each time, where key-log blocks are compressed in bulk. | |
builder.lexical_block_compression |
string | node-runtime | YSEARCH_BUILDER_LEXICAL_BLOCK_COMPRESSION |
--lexical-block-compression (--builder-lexical-block-compression) |
Codec the term, posting and position families compress key-log blocks with: none, snappy, lz4, lz4fast or zstd. Empty keeps the default of lz4. The storage engine's own default leaves the newest level raw because it expects compaction to rewrite it, and a segment stays where it lands. On 300k articles lz4 measured 24.8s and 1.0GB against zstd's 37.7s and 0.8GB, so zstd is the choice for an index written once and read for a long time. | ||
builder.max_document_working_bytes |
bytes size | node-runtime | 0 |
YSEARCH_BUILDER_MAX_DOCUMENT_WORKING_BYTES |
--max-document-working-bytes (--builder-max-document-working-bytes) |
What one document may use beyond the partition budget while it is being analyzed; zero derives 64MiB, or a quarter of builder.sort_memory_bytes when that is smaller. It is an allowance rather than a reservation: it exists so a single document larger than the whole partition budget still builds, alone, instead of failing the build. Only a corpus with documents in the hundreds of megabytes needs it raised. | |
builder.max_queued_builds |
int64 | node-runtime | 0 |
YSEARCH_BUILDER_MAX_QUEUED_BUILDS |
--max-queued-builds (--builder-max-queued-builds) |
in [0, 1024] | Sealed builds that may wait for or run in the pipeline before ingest is throttled; zero derives it as four times builder.build_concurrency. A waiting build is a spool on disk, not memory, so this buys ingest room across a build at the cost of ingest.seal_bytes of disk per queued build. Set too low, a bulk load throttles the moment the pipeline is full and ingest runs at the speed of the builds rather than ahead of them. |
builder.max_token_bytes |
bytes size | node-runtime | 64KiB |
YSEARCH_BUILDER_MAX_TOKEN_BYTES |
--max-token-bytes (--builder-max-token-bytes) |
positive | Maximum analyzed token size. A build must be able to admit one token this large, so raising it raises the floor under builder.sort_memory_bytes: a budget that leaves the partitions less than one maximum term refuses to start rather than fail partway. Tokens are words after analysis, so the default is already far past any natural language; raise it only for a corpus with genuinely enormous unbroken tokens. |
builder.merge_fan_in |
int64 | node-runtime | 0 |
YSEARCH_BUILDER_MERGE_FAN_IN |
--merge-fan-in (--builder-merge-fan-in) |
in [0, 64] | Spilled mini-runs merged in one pass; zero derives as many as an eighth of the partition budget affords at builder.run_page_bytes plus 512 bytes of reader overhead each, capped at sixty-four and floored at two. Runs beyond the fan-in need further passes, and each pass rewrites the data, so a low fan-in on a build that spilled heavily shows up as write amplification rather than as a slow merge. The cap is a file-descriptor and seek-pattern bound, not a memory one. |
builder.output_format_version |
uint64 | startup | 0 |
YSEARCH_BUILDER_OUTPUT_FORMAT_VERSION |
builder-output-format-version |
in [0, 8] | Segment format emitted by builders and compactors; zero selects this binary's current format. The Kubernetes operator pins this to compatibility.writeFormat on writer roles during staged rollouts. Format 7 adds the stats, forward and hashterms families (spec/40 §3); a compaction that includes an older input writes format 6 instead, unless 7 or 8 is set explicitly, which refuses such a merge. Format 8 adds the exact vector lanes (canonical fp16 vectors, IVF radii, int8 codes; spec/40 §3.2). |
builder.paged_posting_directory |
bool | startup | false |
YSEARCH_BUILDER_PAGED_POSTING_DIRECTORY |
builder-paged-posting-directory |
Experimental commit-anchored posting-directory pages under query admission and the existing persistent block quota; old commits retain canonical traversal. | |
builder.posting_partition_penalty |
float64 | node-runtime | 4 |
YSEARCH_BUILDER_POSTING_PARTITION_PENALTY |
builder-posting-partition-penalty |
in [0, 1e+06] | Metadata cost penalty for experimental variable posting blocks. |
builder.publish_verification |
string | node-runtime | checksum |
YSEARCH_BUILDER_PUBLISH_VERIFICATION |
--publish-verification (--builder-publish-verification) |
How a published segment is confirmed: checksum, sample, or readback. checksum compares every object against the checksum the object store reported when it accepted the write — S3 computes that server-side and refuses a mismatched write, and the filesystem backend computes it over the bytes it synced — so nothing is transferred back. sample additionally opens the published copy through the store and queries it; readback additionally fetches every object and rehashes it, which costs the whole index again on every build. An object whose store reports no comparable checksum is read back in any mode. | |
builder.routing_fragment_bytes |
bytes size | node-runtime | 8MiB |
YSEARCH_BUILDER_ROUTING_FRAGMENT_BYTES |
builder-routing-fragment-bytes |
in [0, 6.7108864e+07] | Optional routing fragment disk cap per built segment; zero disables, overflow keeps canonical scan fallback. Matches compaction.routing_fragment_bytes so a freshly ingested segment and a freshly compacted one carry a fragment the same way; the two stay separate keys because a background merge must be able to carry its own share independent of foreground ingestion. Only a segment built or compacted after this defaulted on carries a fragment: nothing rewrites an existing one, so a settled corpus stays without a routing table until it is backfilled or compacted. |
builder.run_page_bytes |
bytes size | node-runtime | 0 |
YSEARCH_BUILDER_RUN_PAGE_BYTES |
--run-page-bytes (--builder-run-page-bytes) |
Read-ahead page one spilled mini-run is buffered in during the final merge; zero derives 64KiB, shrinking it when an eighth of the partition budget cannot hold sixty-four such pages. The merge reserves one page per open run for the whole build, so page size and builder.merge_fan_in trade against each other out of the same share: the derivation prefers smaller pages to a fan-in that would force extra compaction passes on a hot partition. | |
builder.sort_memory_bytes |
bytes size | node-runtime | 256MiB |
YSEARCH_BUILDER_SORT_MEMORY_BYTES |
--sort-memory-bytes (--builder-sort-memory-bytes) |
positive | Total accounted builder budget: one ledger every part of a build charges against, and the setting the other builder budgets derive from. It divides into the public-id sorter (an eighth, capped at 64MiB), the docvalue and lane spools (their own worst case), the analysis share (builder.analysis_memory_bytes), and the term partitions, which take what is left. A build that cannot hold its partitions in that remainder spills to disk instead, which is the difference between one file per build and hundreds. This is per build, so the builder's memory is builder.build_concurrency times this. |
builder.spill_merge_strategy |
enum | node-runtime | heap |
YSEARCH_BUILDER_SPILL_MERGE_STRATEGY |
builder-spill-merge-strategy |
one of heap, replace-root, loser-tree | Experimental spill merge selector; heap preserves the baseline until full ingestion benchmarks qualify an alternative. |
builder.startup_bundles |
bool | startup | false |
YSEARCH_BUILDER_STARTUP_BUNDLES |
builder-startup-bundles |
Asynchronously produce optional startup bundles after catalog publication. One bounded coalescing worker per publishing host; oversized sources retain canonical startup fallback. | |
builder.term_dictionary_block_size |
bytes size | node-runtime | 64KiB |
YSEARCH_BUILDER_TERM_DICTIONARY_BLOCK_SIZE |
--term-dictionary-block-size (--builder-term-dictionary-block-size) |
positive | Key-log data-block size of the term family. A table carries one block-index entry per data block and reads the whole index before it can look up anything, so this is what a cold term probe pays to find out where to look. At the storage engine's 4KiB an 8MiB dictionary needs about two thousand entries — around 65KiB read on every open of the table and held in memory until it closes — where 64KiB needs about a sixteenth of that. A probe then reads a bigger block, which over an object store is the cheap side of the trade: measured on a 6MiB dictionary the block cost 17KiB compressed against the 48KiB of index it replaced. |
builder.term_dictionary_bloom |
bool | node-runtime | false |
YSEARCH_BUILDER_TERM_DICTIONARY_BLOOM |
--term-dictionary-bloom (--builder-term-dictionary-bloom) |
Write a Bloom filter over the term family. The storage engine writes one by default; a segment does not, because the filter is read whole — uncompressed, about 1.2 bytes per distinct term — when the table is opened, and kept in memory until it closes, to save at most one block read per probe against the single table a published segment's term family is. Measured, it was nine tenths of what a cold term probe read: 431KiB of 481KiB on a 360k-term dictionary. A table says in its own footer whether it has a filter, so segments published with one keep working unchanged. | |
builder.variable_posting_blocks |
bool | node-runtime | false |
YSEARCH_BUILDER_VARIABLE_POSTING_BLOCKS |
builder-variable-posting-blocks |
Experimental bounded-window BM25F-aware posting partitioning for format5 or newer output. | |
cache.block_bytes |
bytes size | startup | 2GiB |
YSEARCH_CACHE_BLOCK_BYTES |
cache-block-bytes |
positive | Disk, not memory: bytes of verified decoded blocks this node may keep under cache.dir. This is the cheap half of block caching - it converts a remote read into a local one and costs no resident memory - so size it above one query's working set and leave cache.read_block_bytes to decide what stays in RAM. Measured on 294 segments: one single-term query touched about 363MB of term dictionary and postings and one scored two-term query about 544MB, so the default holds several such working sets. |
cache.block_entries |
int64 | startup | 1048576 |
YSEARCH_CACHE_BLOCK_ENTRIES |
cache-block-entries |
positive | Disk, not memory: how many decoded blocks cache.block_bytes may be spread over. Whichever is reached first bounds the cache; at the measured ~237KiB per block the byte budget is reached first by a wide margin. |
cache.dir |
string | startup | YSEARCH_CACHE_DIR |
cache-dir |
Disposable local cache directory; symlinks in its path are resolved once at startup and the cache then anchors there without following any. It holds the two disk budgets, cache.full_bytes and cache.block_bytes, and nothing else: every other cache.* budget is process memory. A relative value in a configuration file resolves against that file's directory. | ||
cache.full_bytes |
bytes size | startup | 8GiB |
YSEARCH_CACHE_FULL_BYTES |
cache-full-bytes |
positive | Disk, not memory: bytes of whole hydrated segments this node may keep under cache.dir. With cache.block_bytes it is the whole of what the cache directory holds, so a volume smaller than their sum is an eviction loop the node cannot see. |
cache.full_entries |
int64 | startup | 1024 |
YSEARCH_CACHE_FULL_ENTRIES |
cache-full-entries |
positive | Disk, not memory: how many whole segments cache.full_bytes may be spread over. Whichever of the two is reached first bounds the cache, and at the measured ~340MB per segment of a 101GB corpus the byte budget is reached long before this one. |
cache.lazy_readers |
bool | startup | false |
YSEARCH_CACHE_LAZY_READERS |
cache-lazy-readers |
Experimental: acquire immutable segment readers and optional filter payloads only for admitted query work. It is also what routing.presence_bytes zero means: eager readers read that zero as unbounded and hold every segment's presence filter, lazy readers read it as none. | |
cache.ordinal_bytes |
bytes size | startup | 64MiB |
YSEARCH_CACHE_ORDINAL_BYTES |
cache-ordinal-bytes |
in [327936, 9.223372036854776e+18] | Memory, not disk: process-wide verified ordinal-ID pages, including pinned pages and in-flight page workspace, shared across indexes and generations. |
cache.read_block_bytes |
bytes size | startup | 512MiB |
YSEARCH_CACHE_READ_BLOCK_BYTES |
cache-read-block-bytes |
positive | Memory, not disk: process-wide decoded WavesDB blocks held resident and shared by immutable segment readers. This is what decides whether a repeated query is warm. Below one query's working set nothing survives to the next query and every query pays the cold price forever: measured on 294 segments, a 24MiB budget re-read all 214MB of term dictionary byte for byte while about 495MiB answered the repeat from 57,421 bytes. Size it from the corpus, not the machine, and from the layout its segments were built with. A term probe costs the same whatever the term, but what it costs depends on whether the segment carries a term-family Bloom filter: about 711KiB per segment on one built before builder.term_dictionary_bloom defaulted to false, and about 21KiB on one built since. The term dictionary alone needs segments times that figure, and the postings of the shape you serve come on top. A mixed corpus pays the older rate for the segments it has not rebuilt. |
cache.read_open_files |
int64 | startup | 1024 |
YSEARCH_CACHE_READ_OPEN_FILES |
cache-read-open-files |
positive | Process-wide open WavesDB table-file limit shared by immutable segment readers. It spends file descriptors, and nothing here raises RLIMIT_NOFILE, so the default sits at the 1024 a Linux process is commonly given with the listeners, connections and cache files sharing it: raise the limit before raising this. |
cache.read_open_readers |
int64 | startup | 4098 |
YSEARCH_CACHE_READ_OPEN_READERS |
cache-read-open-readers |
positive | Process-wide decoded WavesDB table-reader count limit. Each retained reader also spends cache.read_reader_bytes, and whichever of the two is reached first evicts. Unlike cache.read_open_files this spends memory rather than file descriptors, so size it from the corpus: a segment holds several table families, and a count that cannot hold them all evicts on every query. At 1024, which this defaulted to, a 253-segment corpus needing 1,321 readers held 77% of them and evicted 3,022 times while its byte budget sat 89% empty. That is dearer than it sounds, because a re-opened table re-reads its Bloom filter and block index through a path that bypasses the block cache, so the eviction becomes object reads that repeat for the life of the node: the same query read 62.8MiB in 275 range GETs every time it ran, and none after the count was raised. Measured resident cost is about 760KiB per reader. |
cache.read_reader_bytes |
bytes size | startup | 2GiB |
YSEARCH_CACHE_READ_READER_BYTES |
cache-read-reader-bytes |
positive | Memory, not disk: process-wide WavesDB table index and Bloom-filter bytes held resident. It is the only cache budget that scales with the corpus rather than with the query, at a measured ~14MiB per segment, so the default holds roughly 145 segments and a larger corpus re-reads a segment's index after evicting it. |
cache.result_enabled |
bool | startup | true |
YSEARCH_CACHE_RESULT_ENABLED |
cache-result-enabled |
Cache generation and segment ranked results. Disable for execution benchmarks; reader, block, plan and stored-field caches remain active. | |
cache.scrub_entries |
int64 | node-runtime | 4 |
YSEARCH_CACHE_SCRUB_ENTRIES |
cache-scrub-entries |
in [0, 4096] | How many cached full segments one scrubber pass re-reads. The scrubber walks the cache in a rotating cursor, so this and cache.scrub_interval together set how long a full sweep takes and how much disk read it costs; a segment currently in use is skipped and picked up on a later pass. |
cache.scrub_interval |
duration | node-runtime | 5m |
YSEARCH_CACHE_SCRUB_INTERVAL |
cache-scrub-interval |
in [0, 8.64e+13] | How often the background scrubber re-reads cached full segments and checks them against their commits. This is the only thing that notices a cached segment rotting on disk: a query trusts an entry once it has been verified, because verifying costs the SHA-256 of every file in the segment and doing that per request made a many-segment query spend all its time hashing. Zero disables the scrubber, which leaves local corruption undetected until the entry is evicted. |
cache.sidecar_bytes |
bytes size | startup | 8MiB |
YSEARCH_CACHE_SIDECAR_BYTES |
cache-sidecar-bytes |
positive | Memory, not disk: process-wide optional exact-filter decoder and lease budget shared across indexes and generations. |
cache.warm_prefetch_bytes |
bytes size | startup | 0 |
YSEARCH_CACHE_WARM_PREFETCH_BYTES |
cache-warm-prefetch-bytes |
in [0, 6.7108864e+07] | Optional routing-page warmup byte limit after the first served query; zero disables. It spends object reads, not a budget of its own: warmed pages land in the process-wide routing page cache and are charged there, so warming past that cache only evicts what it just read. Shares foreground cache admission. |
cache.warm_prefetch_concurrency |
int64 | startup | 1 |
YSEARCH_CACHE_WARM_PREFETCH_CONCURRENCY |
cache-warm-prefetch-concurrency |
in [0, 8] | Maximum concurrent optional warmup reads; foreground queries stop new prefetch work. |
client.json |
bool | startup | false |
YSEARCH_CLIENT_JSON |
--json (--client-json) |
Emit JSON instead of tables. | |
client.quiet |
bool | startup | false |
YSEARCH_CLIENT_QUIET |
--quiet (--client-quiet) |
Suppress progress output. | |
client.server |
string | startup | 127.0.0.1:9500 |
YSEARCH_CLIENT_SERVER |
--server (--client-server) |
Server address the client verbs dial. | |
client.timeout |
duration | startup | 30s |
YSEARCH_CLIENT_TIMEOUT |
--timeout (--client-timeout) |
positive | Client request timeout. |
compaction.cluster_field |
string | node-runtime | YSEARCH_COMPACTION_CLUSTER_FIELD |
compaction-cluster-field |
Existing scalar filterable string used by cluster layout; an absent field preserves order. | ||
compaction.document_layout |
enum | node-runtime | preserve |
YSEARCH_COMPACTION_DOCUMENT_LAYOUT |
compaction-document-layout |
one of preserve, cluster, bisection | Experimental survivor layout for new compaction outputs; preserve retains input order, cluster groups scalar categories, bisection uses a bounded sampled term graph. |
compaction.enabled |
bool | node-runtime | false |
YSEARCH_COMPACTION_ENABLED |
compaction-enabled |
Run single-flight size-tiered compaction inside all-in-one serve. The explicit node compactor role always runs; this switch stays off there and by default so production can isolate maintenance from query and ingest. | |
compaction.hydration_bytes |
bytes size | node-runtime | 8GiB |
YSEARCH_COMPACTION_HYDRATION_BYTES |
compaction-hydration-bytes |
positive | Maximum downloaded checkpoint payload retained per compaction job across all input hydrations. Borrowed resident inputs are not copied or charged. Filesystem metadata, output database and spill space have separate accounting. |
compaction.hydration_workers |
int64 | node-runtime | 2 |
YSEARCH_COMPACTION_HYDRATION_WORKERS |
compaction-hydration-workers |
in [1, 8] | Maximum concurrent input hydrations per compaction job. |
compaction.interval |
duration | node-runtime | 1m |
YSEARCH_COMPACTION_INTERVAL |
compaction-interval |
in [1e+09, 8.64e+13] | Interval between background compaction eligibility checks. The all-in-one server waits for sustained ingest idleness; use the isolated compactor role when fan-out must be reduced during continuous ingest. |
compaction.max_active_segments |
int64 | node-runtime | 16 |
YSEARCH_COMPACTION_MAX_ACTIVE_SEGMENTS |
compaction-max-active-segments |
positive | Active searchable segment fan-out above which the scheduler may compact. |
compaction.max_concurrent_jobs |
int64 | startup | 1 |
YSEARCH_COMPACTION_MAX_CONCURRENT_JOBS |
compaction-max-concurrent-jobs |
in [1, 8] | Shared background compaction job slots across hosted indexes; physical merges are serial and hydration has a separate worker cap. |
compaction.max_inputs |
int64 | node-runtime | 8 |
YSEARCH_COMPACTION_MAX_INPUTS |
compaction-max-inputs |
in [2, 64] | Maximum inputs in one compaction job; jobs are always single-flight. |
compaction.max_output_bytes |
bytes size | node-runtime | 4GiB |
YSEARCH_COMPACTION_MAX_OUTPUT_BYTES |
compaction-max-output-bytes |
positive | Maximum summed input bytes admitted to one compaction proposal. |
compaction.max_size_ratio |
uint64 | node-runtime | 2 |
YSEARCH_COMPACTION_MAX_SIZE_RATIO |
compaction-max-size-ratio |
in [1, 1024] | Largest size ratio allowed between inputs in one tier. |
compaction.min_inputs |
int64 | node-runtime | 4 |
YSEARCH_COMPACTION_MIN_INPUTS |
compaction-min-inputs |
in [2, 64] | Minimum adjacent similarly-sized inputs in one compaction job. |
compaction.read_inflight_bytes |
bytes size | startup | 64MiB |
YSEARCH_COMPACTION_READ_INFLIGHT_BYTES |
compaction-read-inflight-bytes |
in [65536, 9.223372036854776e+18] | Shared compaction read payload bytes in flight across jobs. Open reads hold credits until Close; an individual object or range larger than this limit is rejected. |
compaction.recent_delta |
int64 | node-runtime | 4 |
YSEARCH_COMPACTION_RECENT_DELTA |
compaction-recent-delta |
in [0, 1024] | Newest active segments left uncompacted as an ingest delta tier. |
compaction.reorder_leaf_documents |
uint64 | node-runtime | 128 |
YSEARCH_COMPACTION_REORDER_LEAF_DOCUMENTS |
compaction-reorder-leaf-documents |
in [1, 4096] | Maximum stable leaf size of experimental balanced graph bisection; each document samples at most 32 terms. |
compaction.reorder_temp_bytes |
bytes size | node-runtime | 1GiB |
YSEARCH_COMPACTION_REORDER_TEMP_BYTES |
compaction-reorder-temp-bytes |
positive | Temporary spill cap for reordered outputs, including permutation, sampled graph and posting resort; the smaller compaction.temporary_bytes cap also applies. |
compaction.routing_fragment_bytes |
bytes size | node-runtime | 8MiB |
YSEARCH_COMPACTION_ROUTING_FRAGMENT_BYTES |
compaction-routing-fragment-bytes |
in [0, 6.7108864e+07] | Optional routing fragment disk cap per compaction output segment; overrides builder.routing_fragment_bytes for compaction's own merges so background maintenance can carry its own share independent of foreground ingestion. Zero disables fragment writing for compaction outputs, which also stops this generation's routing descriptor from ever completing until every one of its segments gets a fragment some other way. |
compaction.routing_memory_bytes |
bytes size | node-runtime | 64MiB |
YSEARCH_COMPACTION_ROUTING_MEMORY_BYTES |
compaction-routing-memory-bytes |
in [6.7108864e+07, 9.223372036854776e+18] | Memory budget for assembling one generation's routing descriptor from its member segments' own fragments after a successful compaction. Separate from compaction.temporary_bytes and the segment-merge budgets: descriptor assembly reads small fragment objects, not segment checkpoints. |
compaction.routing_temp_bytes |
bytes size | node-runtime | 1GiB |
YSEARCH_COMPACTION_ROUTING_TEMP_BYTES |
compaction-routing-temp-bytes |
positive | Spill and page-file budget for the same post-compaction descriptor assembly. Bounded well below compaction.temporary_bytes: a table assembled from fragments alone is the right-sized presence table (internal/routing/value.go), not the segments' own content. |
compaction.target_bytes |
bytes size | node-runtime | 512MiB |
YSEARCH_COMPACTION_TARGET_BYTES |
compaction-target-bytes |
positive | Approximate input-byte target for one size-tiered compaction group. |
compaction.temporary_bytes |
bytes size | node-runtime | 8GiB |
YSEARCH_COMPACTION_TEMPORARY_BYTES |
compaction-temporary-bytes |
positive | Shared accounted spill-byte limit within one physical compaction; hydration and final database storage are separate from spill space. |
compaction.write_inflight_bytes |
bytes size | startup | 64MiB |
YSEARCH_COMPACTION_WRITE_INFLIGHT_BYTES |
compaction-write-inflight-bytes |
in [65536, 9.223372036854776e+18] | Shared compaction write payload bytes in flight across jobs. An individual object larger than this limit is rejected before upload. |
config.dir |
string | startup | YSEARCH_CONFIG_DIR |
config-dir |
Directory whose *.yml and *.yaml files are layered in name order after the default locations and before config.file. | ||
config.file |
string | startup | YSEARCH_CONFIG_FILE |
--config (--config-file) |
YAML configuration file layered last among files. | ||
config.search |
bool | startup | true |
YSEARCH_CONFIG_SEARCH |
config-search |
Probe /etc/ysearch, $XDG_CONFIG_HOME/ysearch (default ~/.config/ysearch), and ./ysearch.yml at startup. | |
config.watch |
bool | startup | true |
YSEARCH_CONFIG_WATCH |
config-watch |
Reload the discovered configuration files when any of them changes. | |
debug.pprof_listen |
string | startup | YSEARCH_DEBUG_PPROF_LISTEN |
--pprof-listen (--debug-pprof-listen) |
host:port serving net/http/pprof profiles; empty disables it. It binds before the catalog is opened, so a slow start can be profiled, and an address with no host (:6060) binds loopback. Profiles expose heap contents and goroutine stacks, so keep it on loopback and never on a public interface. | ||
embedding.credential |
string | startup | YSEARCH_EMBEDDING_CREDENTIAL |
env only | Optional external embedding bearer token. Environment only; reference YSEARCH_EMBEDDING_CREDENTIAL from an embedding profile. | ||
embedding.external_allow_http |
bool | startup | false |
YSEARCH_EMBEDDING_EXTERNAL_ALLOW_HTTP |
embedding-external-allow-http |
Allow plain HTTP external embedding endpoints for trusted development networks. | |
embedding.external_batch_size |
int64 | startup | 128 |
YSEARCH_EMBEDDING_EXTERNAL_BATCH_SIZE |
embedding-external-batch-size |
in [1, 4096] | Maximum texts in one external embedding request. |
embedding.external_concurrency |
int64 | startup | 8 |
YSEARCH_EMBEDDING_EXTERNAL_CONCURRENCY |
embedding-external-concurrency |
in [1, 1024] | Concurrent external embedding requests per process. |
embedding.external_max_retry_after |
duration | startup | 2s |
YSEARCH_EMBEDDING_EXTERNAL_MAX_RETRY_AFTER |
embedding-external-max-retry-after |
positive | Largest Retry-After delay accepted from an external embedding endpoint. |
embedding.external_request_bytes |
bytes size | startup | 8MiB |
YSEARCH_EMBEDDING_EXTERNAL_REQUEST_BYTES |
embedding-external-request-bytes |
positive | Maximum encoded external embedding request bytes. |
embedding.external_response_bytes |
bytes size | startup | 64MiB |
YSEARCH_EMBEDDING_EXTERNAL_RESPONSE_BYTES |
embedding-external-response-bytes |
positive | Maximum external embedding response bytes read before JSON decoding. |
embedding.external_retries |
int64 | startup | 2 |
YSEARCH_EMBEDDING_EXTERNAL_RETRIES |
embedding-external-retries |
in [0, 16] | Retry attempts after the first retryable external embedding failure. |
embedding.external_retry_base |
duration | startup | 50ms |
YSEARCH_EMBEDDING_EXTERNAL_RETRY_BASE |
embedding-external-retry-base |
positive | Base exponential backoff for external embedding retries. |
embedding.external_timeout |
duration | startup | 30s |
YSEARCH_EMBEDDING_EXTERNAL_TIMEOUT |
embedding-external-timeout |
positive | Deadline for one external embedding HTTP attempt sequence. |
embedding.grpc_allow_insecure |
bool | startup | false |
YSEARCH_EMBEDDING_GRPC_ALLOW_INSECURE |
embedding-grpc-allow-insecure |
Allow plaintext gRPC embedding endpoints on trusted internal networks. | |
embedding.grpc_batch_size |
int64 | startup | 128 |
YSEARCH_EMBEDDING_GRPC_BATCH_SIZE |
embedding-grpc-batch-size |
in [1, 4096] | Maximum texts in one gRPC embedding request. |
embedding.grpc_concurrency |
int64 | startup | 8 |
YSEARCH_EMBEDDING_GRPC_CONCURRENCY |
embedding-grpc-concurrency |
in [1, 1024] | Concurrent gRPC embedding requests per process. |
embedding.grpc_request_bytes |
bytes size | startup | 8MiB |
YSEARCH_EMBEDDING_GRPC_REQUEST_BYTES |
embedding-grpc-request-bytes |
positive | Maximum encoded gRPC embedding request bytes. |
embedding.grpc_response_bytes |
bytes size | startup | 64MiB |
YSEARCH_EMBEDDING_GRPC_RESPONSE_BYTES |
embedding-grpc-response-bytes |
positive | Maximum encoded gRPC embedding response bytes. |
embedding.grpc_timeout |
duration | startup | 30s |
YSEARCH_EMBEDDING_GRPC_TIMEOUT |
embedding-grpc-timeout |
positive | Deadline for one gRPC embedding request. |
embedding.grpc_work_class |
enum | startup | auto |
YSEARCH_EMBEDDING_GRPC_WORK_CLASS |
embedding-grpc-work-class |
one of auto, interactive, bulk | gRPC embedding scheduler class; auto maps queries to interactive and indexing to bulk. |
embedding.internal_batch_size |
int64 | startup | 32 |
YSEARCH_EMBEDDING_INTERNAL_BATCH_SIZE |
embedding-internal-batch-size |
in [1, 4096] | Maximum texts in one internal embedding batch. |
embedding.internal_concurrency |
int64 | startup | 2 |
YSEARCH_EMBEDDING_INTERNAL_CONCURRENCY |
embedding-internal-concurrency |
in [1, 256] | Concurrent pure-Go internal embedding batches. |
embedding.internal_enabled |
bool | startup | false |
YSEARCH_EMBEDDING_INTERNAL_ENABLED |
embedding-internal-enabled |
Enable the pure-Go internal embedding runtime. Models remain lazy and checksum-pinned by schema profiles. | |
embedding.model_cache_bytes |
bytes size | startup | 10GiB |
YSEARCH_EMBEDDING_MODEL_CACHE_BYTES |
embedding-model-cache-bytes |
positive | Maximum installed bytes in the internal-model cache. |
embedding.model_cache_dir |
string | startup | YSEARCH_EMBEDDING_MODEL_CACHE_DIR |
embedding-model-cache-dir |
Checksum-addressed internal-model cache directory. Empty disables internal embedding; keep it distinct from cache.dir. A relative value in a configuration file resolves against that file's directory. | ||
embedding.model_cache_packages |
int64 | startup | 8 |
YSEARCH_EMBEDDING_MODEL_CACHE_PACKAGES |
embedding-model-cache-packages |
positive | Maximum installed internal-model packages. |
embedding.model_download_allow_http |
bool | startup | false |
YSEARCH_EMBEDDING_MODEL_DOWNLOAD_ALLOW_HTTP |
embedding-model-download-allow-http |
Allow plain HTTP model manifests and artifacts for trusted development networks. | |
embedding.model_download_concurrency |
int64 | startup | 2 |
YSEARCH_EMBEDDING_MODEL_DOWNLOAD_CONCURRENCY |
embedding-model-download-concurrency |
in [1, 64] | Concurrent verified internal-model artifact downloads. |
embedding.model_download_timeout |
duration | startup | 10m |
YSEARCH_EMBEDDING_MODEL_DOWNLOAD_TIMEOUT |
embedding-model-download-timeout |
positive | Deadline for one internal-model package installation. |
embedding.model_manifest_bytes |
bytes size | startup | 1MiB |
YSEARCH_EMBEDDING_MODEL_MANIFEST_BYTES |
embedding-model-manifest-bytes |
positive | Maximum bytes in one internal-model manifest. |
embedding.model_package_bytes |
bytes size | startup | 4GiB |
YSEARCH_EMBEDDING_MODEL_PACKAGE_BYTES |
embedding-model-package-bytes |
positive | Maximum bytes in one downloaded internal-model package. |
embedding.query_cache_bytes |
bytes size | startup | 64MiB |
YSEARCH_EMBEDDING_QUERY_CACHE_BYTES |
embedding-query-cache-bytes |
positive | Maximum float-vector bytes retained by the text-query embedding cache. |
embedding.query_cache_entries |
int64 | startup | 4096 |
YSEARCH_EMBEDDING_QUERY_CACHE_ENTRIES |
embedding-query-cache-entries |
positive | Maximum completed text-query embeddings retained per process. |
embedding.query_cache_ttl |
duration | startup | 10m |
YSEARCH_EMBEDDING_QUERY_CACHE_TTL |
embedding-query-cache-ttl |
positive | Lifetime of a completed text-query embedding cache entry. |
fleet.admin_fleet |
string list | startup | YSEARCH_FLEET_ADMIN_FLEET |
--admin-fleet (--fleet-admin-fleet) |
Node host:port endpoints StreamFleetStats fans in; empty refuses the fleet stream. | ||
fleet.aggregators |
string list | startup | YSEARCH_FLEET_AGGREGATORS |
--aggregators (--fleet-aggregators) |
Aggregator host:port endpoints. | ||
fleet.builders |
string list | startup | YSEARCH_FLEET_BUILDERS |
--builders (--fleet-builders) |
Builder host:port endpoints the router polls and rendezvous-routes batches across. | ||
fleet.fallback_workers |
string list | startup | YSEARCH_FLEET_FALLBACK_WORKERS |
--fallback-workers (--fleet-fallback-workers) |
Worker host:port endpoints: the dispatch universe and the cache-oblivious fallback. | ||
fleet.fan_in |
int64 | startup | 0 |
YSEARCH_FLEET_FAN_IN |
--fan-in (--fleet-fan-in) |
in [0, 1024] | Children per merge node in coordinator plans; zero means the planner's default, otherwise at least 2. |
fleet.lane_slots |
string | startup | interactive=4,streaming=2 |
YSEARCH_FLEET_LANE_SLOTS |
--lane-slots (--fleet-lane-slots) |
Per-lane worker slot pools, lane=count. | |
fleet.mergers |
string list | startup | YSEARCH_FLEET_MERGERS |
--mergers (--fleet-mergers) |
Merge host:port endpoints: the coordinator's merge tier, a merger's delegation peers. | ||
follower.discovery_interval |
duration | node-runtime | 30s |
YSEARCH_FOLLOWER_DISCOVERY_INTERVAL |
follower-discovery-interval |
positive | How often a root attachment looks for indexes that appeared or disappeared under it. Separate from follower.poll_interval because discovery lists prefixes while a poll reads one pointer, and listing is the more expensive and more rate-limited of the two. |
follower.generation_overlap |
duration | node-runtime | 30s |
YSEARCH_FOLLOWER_GENERATION_OVERLAP |
follower-generation-overlap |
positive | Maximum age of an unseen catalog generation a worker may resolve on demand; in-flight references may keep its engine beyond this window. |
follower.max_staleness |
duration | node-runtime | 5m |
YSEARCH_FOLLOWER_MAX_STALENESS |
follower-max-staleness |
positive | How long a follower may go without confirming its installed generation is still current before it refuses new queries. A reader that cannot reach its source keeps answering from cached data indefinitely otherwise, which is worse than an error: the results look fine and are silently frozen. Status stays readable past this point so an operator can see why. |
follower.poll_interval |
duration | node-runtime | 2s |
YSEARCH_FOLLOWER_POLL_INTERVAL |
follower-poll-interval |
positive | How often a node checks the catalog's latest pointer. |
follower.retired_generation_grace |
duration | node-runtime | 30s |
YSEARCH_FOLLOWER_RETIRED_GENERATION_GRACE |
follower-retired-generation-grace |
positive | How long a superseded generation's engine stays open after its last query. |
format.minimum_reader_version |
uint64 | compile-time | 1 |
Oldest segment format this binary reads. | |||
format.segment_version |
uint64 | compile-time | 8 |
Segment format this binary writes. | |||
gc.grace |
duration | node-runtime | 1h |
YSEARCH_GC_GRACE |
gc-grace |
in [0, 6.048e+14] | Additional safety margin added to every scheduled GC reachability horizon. |
gc.interval |
duration | node-runtime | 1h |
YSEARCH_GC_INTERVAL |
gc-interval |
in [1e+09, 6.048e+14] | Cadence at which the dedicated compactor role writes a GC proposal and considers a quarantined older proposal. |
gc.maximum_stream_lifetime |
duration | node-runtime | 1h |
YSEARCH_GC_MAXIMUM_STREAM_LIFETIME |
gc-maximum-stream-lifetime |
in [0, 6.048e+14] | Longest query-stream lifetime protected when marking superseded generations for scheduled GC. |
gc.minimum_upload_age |
duration | node-runtime | 24h |
YSEARCH_GC_MINIMUM_UPLOAD_AGE |
gc-minimum-upload-age |
in [0, 2.592e+15] | Minimum age before an unreferenced object can enter a scheduled GC proposal. |
gc.quarantine_age |
duration | node-runtime | 24h |
YSEARCH_GC_QUARANTINE_AGE |
gc-quarantine-age |
in [1e+09, 2.592e+15] | Minimum age of an immutable GC proposal before a fresh mark may authorize deleting its still-unreachable exact keys. |
gc.retained_generations |
int64 | node-runtime | 2 |
YSEARCH_GC_RETAINED_GENERATIONS |
gc-retained-generations |
in [0, 1024] | Historical catalog generations retained in addition to latest during scheduled GC. |
gc.sweep_enabled |
bool | node-runtime | false |
YSEARCH_GC_SWEEP_ENABLED |
gc-sweep-enabled |
Allow the dedicated compactor role to delete freshly re-proven orphan objects after an immutable dry-run proposal passes quarantine. Disabled by default. | |
index.generation |
string | startup | YSEARCH_INDEX_GENERATION |
--generation (--index-generation) |
Exact generation to pin, or empty for the latest. | ||
index.name |
string | startup | YSEARCH_INDEX_NAME |
--index (--index-name) |
Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles. | ||
ingest.burst_documents |
int64 | node-runtime | 100000 |
YSEARCH_INGEST_BURST_DOCUMENTS |
ingest-burst-documents |
positive | Per-index document tokens available for an ingest burst when the rate quota is enabled. |
ingest.dir |
string | startup | YSEARCH_INGEST_DIR |
ingest-dir |
Ingest spool/build directory for builders and scratch root for the dedicated compactor role. A relative value in a configuration file resolves against that file's directory. | ||
ingest.documents_per_second |
int64 | node-runtime | 0 |
YSEARCH_INGEST_DOCUMENTS_PER_SECOND |
ingest-documents-per-second |
in [0, 1.099511627776e+12] | Per-router, per-index document admission rate; zero disables the rate quota. |
ingest.global_queue_bytes |
bytes size | node-runtime | 256MiB |
YSEARCH_INGEST_GLOBAL_QUEUE_BYTES |
ingest-global-queue-bytes |
positive | Encoded ingest bytes all router sessions may hold while waiting for builders. |
ingest.index_queue_bytes |
bytes size | node-runtime | 64MiB |
YSEARCH_INGEST_INDEX_QUEUE_BYTES |
ingest-index-queue-bytes |
positive | Encoded ingest bytes one index may hold while waiting for builders. |
ingest.max_batch_bytes |
bytes size | node-runtime | 4MiB |
YSEARCH_INGEST_MAX_BATCH_BYTES |
ingest-max-batch-bytes |
positive | Largest accepted ingest batch. |
ingest.max_document_bytes |
bytes size | node-runtime | 16MiB |
YSEARCH_INGEST_MAX_DOCUMENT_BYTES |
ingest-max-document-bytes |
positive | Largest accepted document. |
ingest.seal_age |
duration | node-runtime | 30s |
YSEARCH_INGEST_SEAL_AGE |
ingest-seal-age |
positive | Age at which an open build seals. |
ingest.seal_bytes |
bytes size | node-runtime | 0 |
YSEARCH_INGEST_SEAL_BYTES |
ingest-seal-bytes |
in [0, 1.099511627776e+12] | Spooled bytes at which an open build seals; zero derives it as a quarter of builder.sort_memory_bytes. A build's postings are about twice its spooled bytes and the partitions get roughly half the sort budget, so a spool larger than that quarter cannot be sorted in memory and the build spills instead — which is the difference between one file per build and hundreds, and measured 2.5x on the build itself. |
ingest.seal_documents |
int64 | node-runtime | 100000 |
YSEARCH_INGEST_SEAL_DOCUMENTS |
ingest-seal-documents |
positive | Spooled documents at which an open build seals. |
log.format |
enum | startup | text |
YSEARCH_LOG_FORMAT |
log-format |
one of text, json | Log line format. |
log.level |
enum | node-runtime | info |
YSEARCH_LOG_LEVEL |
log-level |
one of error, warn, info, debug | Minimum level written to stderr. |
object.backend |
enum | startup | fs |
YSEARCH_OBJECT_BACKEND |
object-backend |
one of fs, s3 | Object store backend. |
object.dir |
string | startup | YSEARCH_OBJECT_DIR |
object-dir |
Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory. | ||
object.root |
string | startup | indexes |
YSEARCH_OBJECT_ROOT |
object-root |
Object key root. | |
object.s3.access_key |
string | startup | YSEARCH_OBJECT_S3_ACCESS_KEY |
env only | S3 access key. Environment only (YSEARCH_OBJECT_S3_ACCESS_KEY, or the legacy YSEARCH_S3_ACCESS_KEY); never a flag, never in a file. | ||
object.s3.anonymous |
bool | startup | false |
YSEARCH_OBJECT_S3_ANONYMOUS |
--s3-anonymous (--object-s3-anonymous) |
Sign no requests at all, for a bucket that grants public reads. This is a deliberate choice, never a fallback: an unresolved credential chain already signs anonymously, and a reader that quietly degraded to unsigned requests would report a permissions problem as an empty index. | |
object.s3.bucket |
string | startup | YSEARCH_OBJECT_S3_BUCKET |
--s3-bucket (--object-s3-bucket) |
S3 bucket; required for the s3 backend. | ||
object.s3.endpoint |
string | startup | YSEARCH_OBJECT_S3_ENDPOINT |
--s3-endpoint (--object-s3-endpoint) |
S3 endpoint host:port; required for the s3 backend. | ||
object.s3.path_style |
bool | startup | false |
YSEARCH_OBJECT_S3_PATH_STYLE |
--s3-path-style (--object-s3-path-style) |
Use path-style S3 addressing. | |
object.s3.prefix |
string | startup | YSEARCH_OBJECT_S3_PREFIX |
--s3-prefix (--object-s3-prefix) |
S3 key prefix. | ||
object.s3.region |
string | startup | YSEARCH_OBJECT_S3_REGION |
--s3-region (--object-s3-region) |
S3 region. | ||
object.s3.secret_key |
string | startup | YSEARCH_OBJECT_S3_SECRET_KEY |
env only | S3 secret key. Environment only (YSEARCH_OBJECT_S3_SECRET_KEY, or the legacy YSEARCH_S3_SECRET_KEY). | ||
object.s3.session_token |
string | startup | YSEARCH_OBJECT_S3_SESSION_TOKEN |
env only | S3 session token accompanying a temporary access/secret pair, as issued by SSO, an assumed role, or a web identity. Environment only. Supplying an expiring credential without it is rejected by the provider; leave every credential setting empty instead to let the ambient chain resolve and refresh one. | ||
object.s3.use_ssl |
bool | startup | true |
YSEARCH_OBJECT_S3_USE_SSL |
--s3-use-ssl (--object-s3-use-ssl) |
Use TLS to the S3 endpoint. | |
object.source |
string | startup | YSEARCH_OBJECT_SOURCE |
--source (--object-source) |
Dataset URL to attach read-only, such as s3://bucket/root/ for a whole root or s3://bucket/root/indexes/name/ for one index. It derives object.backend, the bucket, prefix and root, the index when the URL names one, and server.read_only, each only where nothing more specific was set. Reading someone else's published index is the whole purpose, so attaching one implies read-only and cannot be talked out of it. | ||
observability.metrics_listen |
string | startup | :9550 |
YSEARCH_OBSERVABILITY_METRICS_LISTEN |
--metrics-listen (--observability-metrics-listen) |
host:port serving Prometheus exposition at /metrics; empty disables it. Unlike debug.pprof_listen this is on by default and binds every interface, because a metric carries no document text, no query, and no key material, and a scrape target that has to be switched on is one nobody switches on. Every series already carries the role label, so the scrape target only has to supply instance and pod. | |
prototype.adapter.batch_documents |
int64 | startup | 500 |
YSEARCH_PROTOTYPE_ADAPTER_BATCH_DOCUMENTS |
prototype-adapter-batch-documents |
in [1, 65536] | Documents per ingest request. |
prototype.adapter.brokers |
string list | startup | 127.0.0.1:9092 |
YSEARCH_PROTOTYPE_ADAPTER_BROKERS |
prototype-adapter-brokers |
Comma-separated Kafka-protocol seed brokers of the article topics. | |
prototype.adapter.group |
string | startup | ysearch-prototype-articles |
YSEARCH_PROTOTYPE_ADAPTER_GROUP |
prototype-adapter-group |
Consumer group id. Offsets are committed manually, only up to the last contiguously acknowledged record (spec/28 §4). | |
prototype.adapter.index |
string | startup | articles |
YSEARCH_PROTOTYPE_ADAPTER_INDEX |
prototype-adapter-index |
Index the adapter feeds through the ingest path. Its schema declares any subset of the article fields; its key field receives the document key. | |
prototype.adapter.ingest_server |
string | startup | 127.0.0.1:9500 |
YSEARCH_PROTOTYPE_ADAPTER_INGEST_SERVER |
prototype-adapter-ingest-server |
gRPC host:port of the ysearch server whose IngestService the adapter streams to. | |
prototype.adapter.namespace |
string | startup | articles |
YSEARCH_PROTOTYPE_ADAPTER_NAMESPACE |
prototype-adapter-namespace |
Document key prefix: an article's key is <namespace>:<article id> in the sidecar and in the index. | |
prototype.adapter.partitions |
int64 | startup | 0 |
YSEARCH_PROTOTYPE_ADAPTER_PARTITIONS |
prototype-adapter-partitions |
in [0, 65536] | Partition count of every article topic. 0 uses the topics as they are; a positive count creates a missing topic with it and refuses one with another count, since a count change needs a source epoch the prototype does not have (spec/28 §3.3). |
prototype.adapter.poll_records |
int64 | startup | 2000 |
YSEARCH_PROTOTYPE_ADAPTER_POLL_RECORDS |
prototype-adapter-poll-records |
in [1, 1.048576e+06] | Records per poll. One poll is one dual-write round: sidecar first, then ingest, then the offset commit. |
prototype.adapter.start |
enum | startup | earliest |
YSEARCH_PROTOTYPE_ADAPTER_START |
prototype-adapter-start |
one of earliest, latest | Where a group without committed offsets starts. Committed offsets always win, and an out-of-range committed offset stops its partition instead of jumping. |
prototype.adapter.tombstones_delete |
bool | startup | false |
YSEARCH_PROTOTYPE_ADAPTER_TOMBSTONES_DELETE |
prototype-adapter-tombstones-delete |
A null-value record deletes its article. Off, a tombstone is poison and stops its partition (spec/28 §2, §6). | |
prototype.adapter.topics |
string list | startup | articles |
YSEARCH_PROTOTYPE_ADAPTER_TOPICS |
prototype-adapter-topics |
Comma-separated article topics: ysearch.fixture.v1.Article protobufs, as tools/corpus replays them, keyed by article id (spec/28 §3.1). Topic names are deployment configuration. | |
prototype.sidecar.address |
string | startup | 127.0.0.1:6379 |
YSEARCH_PROTOTYPE_SIDECAR_ADDRESS |
prototype-sidecar-address |
RESP host:port of a marekvs 5df6ff5 node, the prototype's throwaway sidecar KV (docs/ysearch/05 §5). Any node serves any key. | |
prototype.sidecar.password |
string | startup | YSEARCH_PROTOTYPE_SIDECAR_PASSWORD |
env only | The sidecar's MAREKVS_REQUIREPASS. Environment only (YSEARCH_PROTOTYPE_SIDECAR_PASSWORD); never a flag, never in a file. | ||
prototype.sidecar.timeout |
duration | startup | 5s |
YSEARCH_PROTOTYPE_SIDECAR_TIMEOUT |
prototype-sidecar-timeout |
positive | Dial, read and write timeout of every sidecar call. |
publisher.announce_interval |
duration | node-runtime | 15s |
YSEARCH_PUBLISHER_ANNOUNCE_INTERVAL |
publisher-announce-interval |
in [1e+09, 3.6e+12] | Requested commit-marker publication cadence; the daemon floors it at follower.poll_interval and 15 seconds. |
publisher.lease_ttl |
duration | startup | 30s |
YSEARCH_PUBLISHER_LEASE_TTL |
publisher-lease-ttl |
in [5e+09, 6e+11] | Startup-fixed object-store lease lifetime for the catalog publisher; renewal runs at one third of this value. |
query.collapse_key_versions |
bool | startup | true |
YSEARCH_QUERY_COLLAPSE_KEY_VERSIONS |
--collapse-key-versions (--query-collapse-key-versions) |
Return one hit per document key, the copy with the greatest mutation version. A re-pushed document is stored as a new version rather than replacing the old one, so without this a key appears once per copy. Collapsing removes candidates after selection, so a request may return fewer than top_k. | |
query.compiled_cache |
bool | node-runtime | false |
YSEARCH_QUERY_COMPILED_CACHE |
query-compiled-cache |
Experimental leased compiled-query cache within the shared metadata allowance. Also reuses bounded dictionary plans for eager generation-owned readers; lazy reader plans stay request-owned. Cache pressure falls back to request-owned compilation or preparation. | |
query.default_top_k |
uint64 | node-runtime | 10 |
YSEARCH_QUERY_DEFAULT_TOP_K |
query-default-top-k |
in [1, 10000] | top_k when a request names none. |
query.defer_public_ids |
bool | startup | true |
YSEARCH_QUERY_DEFER_PUBLIC_IDS |
query-defer-public-ids |
Resolve a segment survivor's public ID only when the global merge returns it or must break a score tie with it, instead of for every survivor of every segment. Results are identical either way; false restores eager resolution as a same-code control. | |
query.lexical_memory_bytes |
bytes size | startup | 384MiB |
YSEARCH_QUERY_LEXICAL_MEMORY_BYTES |
query-lexical-memory-bytes |
positive | Process-wide lexical request, candidate, queue and merge memory admission budget. Storage blocks and ordinal pages have separate cache budgets; busy requests fail with resource exhaustion. Sized to admit one request merging 64 segments at the product's 100,000-result top_k ceiling (lexical.MaxResultLimit; estimateLexicalFanoutMemory(64, 100000) = 182,632,832 bytes) with room for a second concurrent one that size. |
query.lexical_strategy |
enum | startup | block-max |
YSEARCH_QUERY_LEXICAL_STRATEGY |
query-lexical-strategy |
one of block-max, auto, single-term-block-max, conjunction, block-max-maxscore | Experimental exact lexical traversal selection; unsupported query shapes conservatively fall back to block-max. |
query.logical_bound_entries |
uint64 | startup | 0 |
YSEARCH_QUERY_LOGICAL_BOUND_ENTRIES |
query-logical-bound-entries |
in [0, 256] | Experimental score-bound subblock size within decoded postings; zero uses physical blocks. Does not reduce physical read size. |
query.max_ast_depth |
uint64 | node-runtime | 32 |
YSEARCH_QUERY_MAX_AST_DEPTH |
query-max-ast-depth |
in [1, 1024] | Deepest query nesting either grammar accepts. |
query.max_results |
uint64 | node-runtime | 0 |
YSEARCH_QUERY_MAX_RESULTS |
query-max-results |
Ceiling on maximum_results per request; zero keeps the engine default. | |
query.ordinal_mode |
enum | node-runtime | pages |
YSEARCH_QUERY_ORDINAL_MODE |
query-ordinal-mode |
one of pages, whole, adaptive | Experimental ID residency policy under the shared ordinal budget. Whole tables are capped at 8 MiB and fall back to pages; adaptive promotion requires repeated broad page coverage. |
query.packed_simd |
bool | startup | false |
YSEARCH_QUERY_PACKED_SIMD |
query-packed-simd |
Experimental native packed-posting decoding on supported CPUs; preserves scalar fallback and semantic validation. | |
query.phrase_gap_expansion_limit |
uint64 | node-runtime | 64 |
YSEARCH_QUERY_PHRASE_GAP_EXPANSION_LIMIT |
query-phrase-gap-expansion-limit |
in [1, 4096] | Most exact gap variants a {m,n} quantifier may expand to. |
query.regex_max_expansions |
uint64 | node-runtime | 256 |
YSEARCH_QUERY_REGEX_MAX_EXPANSIONS |
query-regex-max-expansions |
in [1, 65536] | Most dictionary terms a regex or prefix may expand to before the query is refused. |
query.scoring_profile |
enum | startup | bm25f-v1 |
YSEARCH_QUERY_SCORING_PROFILE |
query-scoring-profile |
one of bm25f-v1, bm25f-pinned-v1 | Scoring profile for a request that names none. bm25f-v1 scores each segment with its own statistics; bm25f-pinned-v1 (spec/50 §2) scores every segment under the generation's pinned statistics epoch, so scores do not depend on segment layout. It needs stats.dir; without it a pinned request fails with a typed error, never with segment statistics. |
query.set_simd |
bool | startup | false |
YSEARCH_QUERY_SET_SIMD |
query-set-simd |
Experimental native intersection for balanced sparse filter arrays; skewed arrays retain scalar galloping. | |
routing.presence_bytes |
bytes size | startup | 0 |
YSEARCH_ROUTING_PRESENCE_BYTES |
routing-presence-bytes |
in [0, 8.589934592e+09] | Memory, not disk: resident budget for per-segment term-presence filters, used only when the generation has no routing table. A generation that has one prunes through it instead and holds no filters at all, whatever this says, because the table is read through a small page cache rather than held. Zero means none under cache.lazy_readers and unbounded without it, which at 294 segments was 1.4GiB of resident filters. That promotion for eager readers stays on for now: builder.routing_fragment_bytes and compaction.routing_fragment_bytes only default on from 2026-09-23, nothing rewrites a segment built before that, and no existing corpus has been rebuilt or fully compacted since - so a generation with an unfragmented member still depends on this filter to prune anything, including the published demo image, which does not set this flag. Filters are loaded in catalog order until the budget is reached; segments without one stay unknown and are still executed, so results never change. Budget against the decoded size, not the transfer: 680MiB of admitted filters measured 1.4GiB resident, about 2.1 times what this charges them. |
server.data_dir |
string | startup | YSEARCH_SERVER_DATA_DIR |
--data-dir (--server-data-dir) |
Developer shortcut: derives object.backend=fs, object.dir, cache.dir, ingest.dir, and config.file beneath one directory where nothing more specific is set. A relative value in a configuration file resolves against that file's directory. | ||
server.grace_period |
duration | startup | 5s |
YSEARCH_SERVER_GRACE_PERIOD |
--grace-period (--server-grace-period) |
positive | Graceful shutdown period. |
server.listen |
string | startup | 127.0.0.1:9500 |
YSEARCH_SERVER_LISTEN |
--listen (--server-listen) |
gRPC listen host:port serve and node bind; the default is the address the client verbs dial (client.server). | |
server.max_receive_bytes |
bytes size | startup | 4MiB |
YSEARCH_SERVER_MAX_RECEIVE_BYTES |
--max-receive-bytes (--server-max-receive-bytes) |
in [65536, 9.223372036854776e+18] | Maximum gRPC request bytes (at least 64KiB). |
server.max_send_bytes |
bytes size | startup | 4MiB |
YSEARCH_SERVER_MAX_SEND_BYTES |
--max-send-bytes (--server-max-send-bytes) |
in [65536, 9.223372036854776e+18] | Maximum gRPC response bytes (at least 64KiB, one result frame). |
server.node_id |
string | startup | YSEARCH_SERVER_NODE_ID |
--node-id (--server-node-id) |
Node identity; empty defaults to the bound listen address. | ||
server.query_receive_memory_bytes |
bytes size | startup | 320MiB |
YSEARCH_SERVER_QUERY_RECEIVE_MEMORY_BYTES |
server-query-receive-memory-bytes |
positive | Shared request-memory allowance for Search, worker Execute, Merge, ValidateQuery, CacheState and FetchStored. Holds decoded requests until RPC completion. Receive workspace waits at most 5ms in a 64-call queue; decoded admission refuses immediately when full. Must fit three receive buffers (each at least 1MiB) plus decoded requests. Unary wire reception/decompression and HTTP/2 queues precede this admission. Sized for at least 24 concurrent full server.max_receive_bytes receives at its default (24 * 13,238,272 bytes = 303MiB, plus headroom): fewer than that admits only a handful of concurrent requests before refusing the rest with ResourceExhausted. |
server.read_only |
bool | startup | false |
YSEARCH_SERVER_READ_ONLY |
--read-only (--server-read-only) |
Refuse every object-store write for this process's lifetime. Enforced at the single store every writer resolves through, so background work that never touches an RPC - garbage collection, and the GC dry run, which writes a proposal object before any delete decision - fails closed too. Startup-fixed on purpose: a running process cannot be talked into writing by a config reload. | |
server.roles |
string list | startup | YSEARCH_SERVER_ROLES |
--roles (--server-roles) |
Comma-separated roles for node: coordinator, worker, merger, aggregator, compactor, router, builder, publisher. | ||
server.source_management |
enum | startup | loopback |
YSEARCH_SERVER_SOURCE_MANAGEMENT |
server-source-management |
one of loopback, any | Which peers may call SourceService, the RPC that changes which datasets this process reads. loopback answers only a caller that reached this process without crossing a network, so binding server.listen to every interface still does not expose it. any serves it to anything that can reach the port: the service has no authentication of its own, so choose it only where something in front of the address authenticates. |
server.zone |
string | startup | default |
YSEARCH_SERVER_ZONE |
--zone (--server-zone) |
Placement zone this node advertises in. | |
stats.dir |
string | startup | YSEARCH_STATS_DIR |
stats-dir |
Directory of this node's statistics databases, one per index (spec/50 §3.3). Every served generation is folded into it and its epoch pinned for bm25f-pinned-v1. Unlike cache.dir it is not disposable: a node that loses it refolds from the catalog. Empty disables epochs. A relative value in a configuration file resolves against that file's directory. | ||
stats.history_generations |
uint64 | startup | 6000 |
YSEARCH_STATS_HISTORY_GENERATIONS |
stats-history-generations |
in [1, 1.6777216e+07] | Generations of per-generation statistics deltas kept to reconstruct an earlier epoch (spec/50 §3.3); about two days at one generation per 30 s. |
storage.hydrate_throughput_floor |
bytes size | node-runtime | 128MiB |
YSEARCH_STORAGE_HYDRATE_THROUGHPUT_FLOOR |
--hydrate-throughput-floor (--storage-hydrate-throughput-floor) |
positive | Lowest believable hydration throughput in bytes per second. |
storage.hysteresis_denominator |
uint64 | node-runtime | 4 |
YSEARCH_STORAGE_HYSTERESIS_DENOMINATOR |
--hysteresis-denominator (--storage-hysteresis-denominator) |
in [1, 4.294967295e+09] | Hysteresis denominator; must be below the numerator. |
storage.hysteresis_numerator |
uint64 | node-runtime | 5 |
YSEARCH_STORAGE_HYSTERESIS_NUMERATOR |
--hysteresis-numerator (--storage-hysteresis-numerator) |
in [1, 4.294967295e+09] | Hysteresis numerator; must exceed the denominator. |
storage.mode |
enum | startup | AUTO |
YSEARCH_STORAGE_MODE |
--mode (--storage-mode) |
one of HYDRATE_FULL, REMOTE_BLOCKS, AUTO | Storage mode: HYDRATE_FULL, REMOTE_BLOCKS, or AUTO (AUTO is refused by the checkpoint-bound serve). |
storage.remote_latency_floor |
duration | node-runtime | 2ms |
YSEARCH_STORAGE_REMOTE_LATENCY_FLOOR |
--remote-latency-floor (--storage-remote-latency-floor) |
positive | Lowest believable remote request latency. |
storage.remote_throughput_floor |
bytes size | node-runtime | 64MiB |
YSEARCH_STORAGE_REMOTE_THROUGHPUT_FLOOR |
--remote-throughput-floor (--storage-remote-throughput-floor) |
positive | Lowest believable remote throughput in bytes per second. |
storage.scan_threshold_permille |
uint64 | node-runtime | 200 |
YSEARCH_STORAGE_SCAN_THRESHOLD_PERMILLE |
--scan-threshold-permille (--storage-scan-threshold-permille) |
in [0, 1000] | Scan fraction above which AUTO hydrates. |
tail.impact_enabled |
bool | node-runtime | false |
YSEARCH_TAIL_IMPACT_ENABLED |
tail-impact-enabled |
Persist score-banded approximate-tail data. Disabled avoids two additional records per unique term when exact tails are sufficient. | |
tail.impact_maximum_bands |
uint64 | node-runtime | 64 |
YSEARCH_TAIL_IMPACT_MAXIMUM_BANDS |
tail-impact-maximum-bands |
in [1, 4096] | Maximum score-impact bands persisted for one term. |
tail.impact_target_documents |
uint64 | node-runtime | 4096 |
YSEARCH_TAIL_IMPACT_TARGET_DOCUMENTS |
tail-impact-target-documents |
in [1, 4.294967295e+09] | Target postings per persisted impact run. |
tail.maximum_ordering_error |
float64 | node-runtime | 0 |
YSEARCH_TAIL_MAXIMUM_ORDERING_ERROR |
tail-maximum-ordering-error |
in [0, 1.7976931348623157e+308] | Server ceiling on accepted approximate-tail score-ordering error; zero requires exact fallback. |
vector.bits_per_code |
uint64 | node-runtime | 8 |
YSEARCH_VECTOR_BITS_PER_CODE |
vector-bits-per-code |
in [1, 8] | Bits in each PQ subquantizer code. |
vector.build_memory_bytes |
bytes size | node-runtime | 0 |
YSEARCH_VECTOR_BUILD_MEMORY_BYTES |
vector-build-memory-bytes |
in [0, 9.223372036854776e+18] | Per-build vector training and assignment memory; zero derives a bounded share of builder.sort_memory_bytes. |
vector.centroids |
uint64 | node-runtime | 0 |
YSEARCH_VECTOR_CENTROIDS |
vector-centroids |
in [0, 4.294967295e+09] | IVF coarse centroid count; zero derives it deterministically from population. |
vector.flat_threshold |
uint64 | node-runtime | 10000 |
YSEARCH_VECTOR_FLAT_THRESHOLD |
vector-flat-threshold |
in [1, 4.294967295e+09] | Per-segment vector population at or below which candidate generation stays exhaustive. |
vector.list_block_documents |
uint64 | node-runtime | 0 |
YSEARCH_VECTOR_LIST_BLOCK_DOCUMENTS |
vector-list-block-documents |
in [0, 4.294967295e+09] | Target vector entries per IVF-list block; zero follows the document-value block geometry. |
vector.maximum_training_vectors |
uint64 | node-runtime | 4096 |
YSEARCH_VECTOR_MAXIMUM_TRAINING_VECTORS |
vector-maximum-training-vectors |
in [1, 4.294967295e+09] | Maximum deterministic training samples retained per vector field. |
vector.query_candidate_multiplier |
uint64 | node-runtime | 10 |
YSEARCH_VECTOR_QUERY_CANDIDATE_MULTIPLIER |
vector-query-candidate-multiplier |
in [1, 10000] | Default ANN candidates as a multiple of requested top_k. |
vector.query_default_probes |
uint64 | node-runtime | 8 |
YSEARCH_VECTOR_QUERY_DEFAULT_PROBES |
vector-query-default-probes |
in [1, 4.294967295e+09] | IVF coarse lists probed when a vector request does not specify probes. |
vector.query_maximum_candidates |
uint64 | node-runtime | 100000 |
YSEARCH_VECTOR_QUERY_MAXIMUM_CANDIDATES |
vector-query-maximum-candidates |
in [1, 4.294967295e+09] | Hard per-request candidate generation and exact-rerank cap. |
vector.query_maximum_probes |
uint64 | node-runtime | 1024 |
YSEARCH_VECTOR_QUERY_MAXIMUM_PROBES |
vector-query-maximum-probes |
in [1, 4.294967295e+09] | Hard per-request IVF probe cap. |
vector.query_memory_bytes |
bytes size | node-runtime | 256MiB |
YSEARCH_VECTOR_QUERY_MEMORY_BYTES |
vector-query-memory-bytes |
positive | Per-process admission budget for decoded vector-query working sets. |
vector.subquantizers |
uint64 | node-runtime | 0 |
YSEARCH_VECTOR_SUBQUANTIZERS |
vector-subquantizers |
in [0, 4.294967295e+09] | PQ subquantizer count; zero derives a geometry compatible with each vector field's dimension. |
vector.training_iterations |
uint64 | node-runtime | 20 |
YSEARCH_VECTOR_TRAINING_ITERATIONS |
vector-training-iterations |
in [1, 1000] | Maximum deterministic k-means iterations during IVF-PQ training. |
0— success;--helpanywhere.1— the command ran and failed (a refused request, an unreachable server, a bad file); the message names the cause and, for a server failure, its gRPC code and a remedy.2— the invocation was wrong (unknown command, missing subcommand, unknown flag, wrong argument count); the usage follows the message.
Files are discovered in a fixed order and later files override earlier ones: /etc/ysearch/ysearch.yml, then /etc/ysearch/conf.d/*.yml; $XDG_CONFIG_HOME/ysearch/ysearch.yml (default ~/.config/ysearch/), then its conf.d/*.yml; ./ysearch.yml; <data-dir>/config.yaml when --data-dir is set; --config-dir DIR's *.yml; --config FILE. .yaml is accepted wherever .yml is. --config-search=false (YSEARCH_CONFIG_SEARCH=false) skips the default locations. Then the environment (YSEARCH_<KEY> with dots and underscores as _), then the flags, then the runtime API. Every value carries its provenance; config get, config list, and config export show it.