Skip to content

Reference

Configuration reference

Every configuration key with its default, scope, environment variable, and flag, generated from the pinned ysearch revision.


ysearch reads 225 settings from one catalog. Each has a built-in default and can be set, lowest to highest precedence, by a file, an environment variable, a flag, or the runtime API: default < file < env < flag < api. How the layers work is in Configuration.

Secrets are read from the environment only, never from a flag or a file. Keys marked not from a file say why.

Section Keys
builder 27
cache 17
client 4
compaction 22
config 4
debug 1
embedding 31
fleet 7
follower 5
format 2
gc 7
index 2
ingest 10
log 2
object 14
observability 1
prototype 14
publisher 2
query 15
routing 1
server 11
stats 2
storage 7
tail 4
vector 13

builder

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.

Default 0 · Scope node-runtime · Env YSEARCH_BUILDER_ANALYSIS_BATCH_DOCUMENTS · Flag --builder-analysis-batch-documents (alias --analysis-batch-documents) · Allowed in [0, 1048576]

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.

Default 0 · Scope node-runtime · Env YSEARCH_BUILDER_ANALYSIS_MEMORY_BYTES · Flag --builder-analysis-memory-bytes (alias --analysis-memory-bytes)

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.

Default 0 · Scope node-runtime · Env YSEARCH_BUILDER_ANALYSIS_WORKERS · Flag --builder-analysis-workers (alias --analysis-workers) · Allowed in [0, 1024]

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.

Default true · Scope node-runtime · Env YSEARCH_BUILDER_BLOB_DICTIONARY · Flag --builder-blob-dictionary (alias --blob-dictionary)

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.

Default 0 · Scope node-runtime · Env YSEARCH_BUILDER_BLOB_ZSTD_LEVEL · Flag --builder-blob-zstd-level (alias --blob-zstd-level) · Allowed in [0, 11]

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.

Default 0 · Scope node-runtime · Env YSEARCH_BUILDER_BUILD_CONCURRENCY · Flag --builder-build-concurrency (alias --build-concurrency) · Allowed in [0, 256]

builder.catalog_publication

Catalog writer mode: direct is the single-node compatibility path; external stops after commit markers for a lease-fenced publisher role.

Default direct · Scope startup · Env YSEARCH_BUILDER_CATALOG_PUBLICATION · Flag --builder-catalog-publication · Allowed one of direct, external

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.

Default 0 · Scope node-runtime · Env YSEARCH_BUILDER_DEDUPE_INDEX_IDENTITIES · Flag --builder-dedupe-index-identities (alias --dedupe-index-identities) · Allowed in [0, 268435456]

builder.fuse_memory_bytes

Optional binary fuse construction workspace during publication; zero retains Bloom, failed admission retains Bloom.

Default 0 · Scope startup · Env YSEARCH_BUILDER_FUSE_MEMORY_BYTES · Flag --builder-fuse-memory-bytes · Allowed in [0, 64MiB]

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.

Default 0 · Scope node-runtime · Env YSEARCH_BUILDER_LEXICAL_BLOB_THRESHOLD · Flag --builder-lexical-blob-threshold (alias --lexical-blob-threshold)

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.

Default empty · Scope node-runtime · Env YSEARCH_BUILDER_LEXICAL_BLOCK_COMPRESSION · Flag --builder-lexical-block-compression (alias --lexical-block-compression)

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.

Default 0 · Scope node-runtime · Env YSEARCH_BUILDER_MAX_DOCUMENT_WORKING_BYTES · Flag --builder-max-document-working-bytes (alias --max-document-working-bytes)

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.

Default 0 · Scope node-runtime · Env YSEARCH_BUILDER_MAX_QUEUED_BUILDS · Flag --builder-max-queued-builds (alias --max-queued-builds) · Allowed in [0, 1024]

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.

Default 64KiB · Scope node-runtime · Env YSEARCH_BUILDER_MAX_TOKEN_BYTES · Flag --builder-max-token-bytes (alias --max-token-bytes) · Allowed positive

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.

Default 0 · Scope node-runtime · Env YSEARCH_BUILDER_MERGE_FAN_IN · Flag --builder-merge-fan-in (alias --merge-fan-in) · Allowed in [0, 64]

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).

Default 0 · Scope startup · Env YSEARCH_BUILDER_OUTPUT_FORMAT_VERSION · Flag --builder-output-format-version · Allowed in [0, 8]

builder.paged_posting_directory

Experimental commit-anchored posting-directory pages under query admission and the existing persistent block quota; old commits retain canonical traversal.

Default false · Scope startup · Env YSEARCH_BUILDER_PAGED_POSTING_DIRECTORY · Flag --builder-paged-posting-directory

builder.posting_partition_penalty

Metadata cost penalty for experimental variable posting blocks.

Default 4 · Scope node-runtime · Env YSEARCH_BUILDER_POSTING_PARTITION_PENALTY · Flag --builder-posting-partition-penalty · Allowed in [0, 1e+06]

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.

Default checksum · Scope node-runtime · Env YSEARCH_BUILDER_PUBLISH_VERIFICATION · Flag --builder-publish-verification (alias --publish-verification)

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.

Default 8MiB · Scope node-runtime · Env YSEARCH_BUILDER_ROUTING_FRAGMENT_BYTES · Flag --builder-routing-fragment-bytes · Allowed in [0, 64MiB]

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.

Default 0 · Scope node-runtime · Env YSEARCH_BUILDER_RUN_PAGE_BYTES · Flag --builder-run-page-bytes (alias --run-page-bytes)

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.

Default 256MiB · Scope node-runtime · Env YSEARCH_BUILDER_SORT_MEMORY_BYTES · Flag --builder-sort-memory-bytes (alias --sort-memory-bytes) · Allowed positive

builder.spill_merge_strategy

Experimental spill merge selector; heap preserves the baseline until full ingestion benchmarks qualify an alternative.

Default heap · Scope node-runtime · Env YSEARCH_BUILDER_SPILL_MERGE_STRATEGY · Flag --builder-spill-merge-strategy · Allowed one of heap, replace-root, loser-tree

builder.startup_bundles

Asynchronously produce optional startup bundles after catalog publication. One bounded coalescing worker per publishing host; oversized sources retain canonical startup fallback.

Default false · Scope startup · Env YSEARCH_BUILDER_STARTUP_BUNDLES · Flag --builder-startup-bundles

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.

Default 64KiB · Scope node-runtime · Env YSEARCH_BUILDER_TERM_DICTIONARY_BLOCK_SIZE · Flag --builder-term-dictionary-block-size (alias --term-dictionary-block-size) · Allowed positive

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.

Default false · Scope node-runtime · Env YSEARCH_BUILDER_TERM_DICTIONARY_BLOOM · Flag --builder-term-dictionary-bloom (alias --term-dictionary-bloom)

builder.variable_posting_blocks

Experimental bounded-window BM25F-aware posting partitioning for format5 or newer output.

Default false · Scope node-runtime · Env YSEARCH_BUILDER_VARIABLE_POSTING_BLOCKS · Flag --builder-variable-posting-blocks

cache

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.

Default 2GiB · Scope startup · Env YSEARCH_CACHE_BLOCK_BYTES · Flag --cache-block-bytes · Allowed positive

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.

Default 1048576 · Scope startup · Env YSEARCH_CACHE_BLOCK_ENTRIES · Flag --cache-block-entries · Allowed positive

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.

Default empty · Scope startup · Env YSEARCH_CACHE_DIR · Flag --cache-dir

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.

Default 8GiB · Scope startup · Env YSEARCH_CACHE_FULL_BYTES · Flag --cache-full-bytes · Allowed positive

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.

Default 1024 · Scope startup · Env YSEARCH_CACHE_FULL_ENTRIES · Flag --cache-full-entries · Allowed positive

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.

Default false · Scope startup · Env YSEARCH_CACHE_LAZY_READERS · Flag --cache-lazy-readers

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.

Default 64MiB · Scope startup · Env YSEARCH_CACHE_ORDINAL_BYTES · Flag --cache-ordinal-bytes · Allowed at least 327936

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.

Default 512MiB · Scope startup · Env YSEARCH_CACHE_READ_BLOCK_BYTES · Flag --cache-read-block-bytes · Allowed positive

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.

Default 1024 · Scope startup · Env YSEARCH_CACHE_READ_OPEN_FILES · Flag --cache-read-open-files · Allowed positive

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.

Default 4098 · Scope startup · Env YSEARCH_CACHE_READ_OPEN_READERS · Flag --cache-read-open-readers · Allowed positive

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.

Default 2GiB · Scope startup · Env YSEARCH_CACHE_READ_READER_BYTES · Flag --cache-read-reader-bytes · Allowed positive

cache.result_enabled

Cache generation and segment ranked results. Disable for execution benchmarks; reader, block, plan and stored-field caches remain active.

Default true · Scope startup · Env YSEARCH_CACHE_RESULT_ENABLED · Flag --cache-result-enabled

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.

Default 4 · Scope node-runtime · Env YSEARCH_CACHE_SCRUB_ENTRIES · Flag --cache-scrub-entries · Allowed in [0, 4096]

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.

Default 5m · Scope node-runtime · Env YSEARCH_CACHE_SCRUB_INTERVAL · Flag --cache-scrub-interval · Allowed in [0s, 24h0m0s]

cache.sidecar_bytes

Memory, not disk: process-wide optional exact-filter decoder and lease budget shared across indexes and generations.

Default 8MiB · Scope startup · Env YSEARCH_CACHE_SIDECAR_BYTES · Flag --cache-sidecar-bytes · Allowed positive

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.

Default 0 · Scope startup · Env YSEARCH_CACHE_WARM_PREFETCH_BYTES · Flag --cache-warm-prefetch-bytes · Allowed in [0, 64MiB]

cache.warm_prefetch_concurrency

Maximum concurrent optional warmup reads; foreground queries stop new prefetch work.

Default 1 · Scope startup · Env YSEARCH_CACHE_WARM_PREFETCH_CONCURRENCY · Flag --cache-warm-prefetch-concurrency · Allowed in [0, 8]

client

client.json

Emit JSON instead of tables.

Default false · Scope startup · Env YSEARCH_CLIENT_JSON · Flag --client-json (alias --json)

client.quiet

Suppress progress output.

Default false · Scope startup · Env YSEARCH_CLIENT_QUIET · Flag --client-quiet (alias --quiet)

client.server

Server address the client verbs dial.

Default 127.0.0.1:9500 · Scope startup · Env YSEARCH_CLIENT_SERVER · Flag --client-server (alias --server)

client.timeout

Client request timeout.

Default 30s · Scope startup · Env YSEARCH_CLIENT_TIMEOUT · Flag --client-timeout (alias --timeout) · Allowed positive

compaction

compaction.cluster_field

Existing scalar filterable string used by cluster layout; an absent field preserves order.

Default empty · Scope node-runtime · Env YSEARCH_COMPACTION_CLUSTER_FIELD · Flag --compaction-cluster-field

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.

Default preserve · Scope node-runtime · Env YSEARCH_COMPACTION_DOCUMENT_LAYOUT · Flag --compaction-document-layout · Allowed one of preserve, cluster, bisection

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.

Default false · Scope node-runtime · Env YSEARCH_COMPACTION_ENABLED · Flag --compaction-enabled

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.

Default 8GiB · Scope node-runtime · Env YSEARCH_COMPACTION_HYDRATION_BYTES · Flag --compaction-hydration-bytes · Allowed positive

compaction.hydration_workers

Maximum concurrent input hydrations per compaction job.

Default 2 · Scope node-runtime · Env YSEARCH_COMPACTION_HYDRATION_WORKERS · Flag --compaction-hydration-workers · Allowed in [1, 8]

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.

Default 1m · Scope node-runtime · Env YSEARCH_COMPACTION_INTERVAL · Flag --compaction-interval · Allowed in [1s, 24h0m0s]

compaction.max_active_segments

Active searchable segment fan-out above which the scheduler may compact.

Default 16 · Scope node-runtime · Env YSEARCH_COMPACTION_MAX_ACTIVE_SEGMENTS · Flag --compaction-max-active-segments · Allowed positive

compaction.max_concurrent_jobs

Shared background compaction job slots across hosted indexes; physical merges are serial and hydration has a separate worker cap.

Default 1 · Scope startup · Env YSEARCH_COMPACTION_MAX_CONCURRENT_JOBS · Flag --compaction-max-concurrent-jobs · Allowed in [1, 8]

compaction.max_inputs

Maximum inputs in one compaction job; jobs are always single-flight.

Default 8 · Scope node-runtime · Env YSEARCH_COMPACTION_MAX_INPUTS · Flag --compaction-max-inputs · Allowed in [2, 64]

compaction.max_output_bytes

Maximum summed input bytes admitted to one compaction proposal.

Default 4GiB · Scope node-runtime · Env YSEARCH_COMPACTION_MAX_OUTPUT_BYTES · Flag --compaction-max-output-bytes · Allowed positive

compaction.max_size_ratio

Largest size ratio allowed between inputs in one tier.

Default 2 · Scope node-runtime · Env YSEARCH_COMPACTION_MAX_SIZE_RATIO · Flag --compaction-max-size-ratio · Allowed in [1, 1024]

compaction.min_inputs

Minimum adjacent similarly-sized inputs in one compaction job.

Default 4 · Scope node-runtime · Env YSEARCH_COMPACTION_MIN_INPUTS · Flag --compaction-min-inputs · Allowed in [2, 64]

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.

Default 64MiB · Scope startup · Env YSEARCH_COMPACTION_READ_INFLIGHT_BYTES · Flag --compaction-read-inflight-bytes · Allowed at least 64KiB

compaction.recent_delta

Newest active segments left uncompacted as an ingest delta tier.

Default 4 · Scope node-runtime · Env YSEARCH_COMPACTION_RECENT_DELTA · Flag --compaction-recent-delta · Allowed in [0, 1024]

compaction.reorder_leaf_documents

Maximum stable leaf size of experimental balanced graph bisection; each document samples at most 32 terms.

Default 128 · Scope node-runtime · Env YSEARCH_COMPACTION_REORDER_LEAF_DOCUMENTS · Flag --compaction-reorder-leaf-documents · Allowed in [1, 4096]

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.

Default 1GiB · Scope node-runtime · Env YSEARCH_COMPACTION_REORDER_TEMP_BYTES · Flag --compaction-reorder-temp-bytes · Allowed positive

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.

Default 8MiB · Scope node-runtime · Env YSEARCH_COMPACTION_ROUTING_FRAGMENT_BYTES · Flag --compaction-routing-fragment-bytes · Allowed in [0, 64MiB]

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.

Default 64MiB · Scope node-runtime · Env YSEARCH_COMPACTION_ROUTING_MEMORY_BYTES · Flag --compaction-routing-memory-bytes · Allowed at least 64MiB

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.

Default 1GiB · Scope node-runtime · Env YSEARCH_COMPACTION_ROUTING_TEMP_BYTES · Flag --compaction-routing-temp-bytes · Allowed positive

compaction.target_bytes

Approximate input-byte target for one size-tiered compaction group.

Default 512MiB · Scope node-runtime · Env YSEARCH_COMPACTION_TARGET_BYTES · Flag --compaction-target-bytes · Allowed positive

compaction.temporary_bytes

Shared accounted spill-byte limit within one physical compaction; hydration and final database storage are separate from spill space.

Default 8GiB · Scope node-runtime · Env YSEARCH_COMPACTION_TEMPORARY_BYTES · Flag --compaction-temporary-bytes · Allowed positive

compaction.write_inflight_bytes

Shared compaction write payload bytes in flight across jobs. An individual object larger than this limit is rejected before upload.

Default 64MiB · Scope startup · Env YSEARCH_COMPACTION_WRITE_INFLIGHT_BYTES · Flag --compaction-write-inflight-bytes · Allowed at least 64KiB

config

config.dir

Directory whose *.yml and *.yaml files are layered in name order after the default locations and before config.file.

Default empty · Not from a file: discovery; set --config-dir or YSEARCH_CONFIG_DIR, never a file

config.file

YAML configuration file layered last among files.

Default empty · Not from a file: discovery; set --config-file (--config) or YSEARCH_CONFIG_FILE, never a file

Probe /etc/ysearch, $XDG_CONFIG_HOME/ysearch (default ~/.config/ysearch), and ./ysearch.yml at startup.

Default true · Not from a file: discovery; set --config-search or YSEARCH_CONFIG_SEARCH, never a file

config.watch

Reload the discovered configuration files when any of them changes.

Default true · Scope startup · Env YSEARCH_CONFIG_WATCH · Flag --config-watch

debug

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.

Default empty · Scope startup · Env YSEARCH_DEBUG_PPROF_LISTEN · Flag --debug-pprof-listen (alias --pprof-listen)

embedding

embedding.credential

Optional external embedding bearer token. Environment only; reference YSEARCH_EMBEDDING_CREDENTIAL from an embedding profile.

Default empty · Not from a file: secret; read from YSEARCH_EMBEDDING_CREDENTIAL only

embedding.external_allow_http

Allow plain HTTP external embedding endpoints for trusted development networks.

Default false · Scope startup · Env YSEARCH_EMBEDDING_EXTERNAL_ALLOW_HTTP · Flag --embedding-external-allow-http

embedding.external_batch_size

Maximum texts in one external embedding request.

Default 128 · Scope startup · Env YSEARCH_EMBEDDING_EXTERNAL_BATCH_SIZE · Flag --embedding-external-batch-size · Allowed in [1, 4096]

embedding.external_concurrency

Concurrent external embedding requests per process.

Default 8 · Scope startup · Env YSEARCH_EMBEDDING_EXTERNAL_CONCURRENCY · Flag --embedding-external-concurrency · Allowed in [1, 1024]

embedding.external_max_retry_after

Largest Retry-After delay accepted from an external embedding endpoint.

Default 2s · Scope startup · Env YSEARCH_EMBEDDING_EXTERNAL_MAX_RETRY_AFTER · Flag --embedding-external-max-retry-after · Allowed positive

embedding.external_request_bytes

Maximum encoded external embedding request bytes.

Default 8MiB · Scope startup · Env YSEARCH_EMBEDDING_EXTERNAL_REQUEST_BYTES · Flag --embedding-external-request-bytes · Allowed positive

embedding.external_response_bytes

Maximum external embedding response bytes read before JSON decoding.

Default 64MiB · Scope startup · Env YSEARCH_EMBEDDING_EXTERNAL_RESPONSE_BYTES · Flag --embedding-external-response-bytes · Allowed positive

embedding.external_retries

Retry attempts after the first retryable external embedding failure.

Default 2 · Scope startup · Env YSEARCH_EMBEDDING_EXTERNAL_RETRIES · Flag --embedding-external-retries · Allowed in [0, 16]

embedding.external_retry_base

Base exponential backoff for external embedding retries.

Default 50ms · Scope startup · Env YSEARCH_EMBEDDING_EXTERNAL_RETRY_BASE · Flag --embedding-external-retry-base · Allowed positive

embedding.external_timeout

Deadline for one external embedding HTTP attempt sequence.

Default 30s · Scope startup · Env YSEARCH_EMBEDDING_EXTERNAL_TIMEOUT · Flag --embedding-external-timeout · Allowed positive

embedding.grpc_allow_insecure

Allow plaintext gRPC embedding endpoints on trusted internal networks.

Default false · Scope startup · Env YSEARCH_EMBEDDING_GRPC_ALLOW_INSECURE · Flag --embedding-grpc-allow-insecure

embedding.grpc_batch_size

Maximum texts in one gRPC embedding request.

Default 128 · Scope startup · Env YSEARCH_EMBEDDING_GRPC_BATCH_SIZE · Flag --embedding-grpc-batch-size · Allowed in [1, 4096]

embedding.grpc_concurrency

Concurrent gRPC embedding requests per process.

Default 8 · Scope startup · Env YSEARCH_EMBEDDING_GRPC_CONCURRENCY · Flag --embedding-grpc-concurrency · Allowed in [1, 1024]

embedding.grpc_request_bytes

Maximum encoded gRPC embedding request bytes.

Default 8MiB · Scope startup · Env YSEARCH_EMBEDDING_GRPC_REQUEST_BYTES · Flag --embedding-grpc-request-bytes · Allowed positive

embedding.grpc_response_bytes

Maximum encoded gRPC embedding response bytes.

Default 64MiB · Scope startup · Env YSEARCH_EMBEDDING_GRPC_RESPONSE_BYTES · Flag --embedding-grpc-response-bytes · Allowed positive

embedding.grpc_timeout

Deadline for one gRPC embedding request.

Default 30s · Scope startup · Env YSEARCH_EMBEDDING_GRPC_TIMEOUT · Flag --embedding-grpc-timeout · Allowed positive

embedding.grpc_work_class

gRPC embedding scheduler class; auto maps queries to interactive and indexing to bulk.

Default auto · Scope startup · Env YSEARCH_EMBEDDING_GRPC_WORK_CLASS · Flag --embedding-grpc-work-class · Allowed one of auto, interactive, bulk

embedding.internal_batch_size

Maximum texts in one internal embedding batch.

Default 32 · Scope startup · Env YSEARCH_EMBEDDING_INTERNAL_BATCH_SIZE · Flag --embedding-internal-batch-size · Allowed in [1, 4096]

embedding.internal_concurrency

Concurrent pure-Go internal embedding batches.

Default 2 · Scope startup · Env YSEARCH_EMBEDDING_INTERNAL_CONCURRENCY · Flag --embedding-internal-concurrency · Allowed in [1, 256]

embedding.internal_enabled

Enable the pure-Go internal embedding runtime. Models remain lazy and checksum-pinned by schema profiles.

Default false · Scope startup · Env YSEARCH_EMBEDDING_INTERNAL_ENABLED · Flag --embedding-internal-enabled

embedding.model_cache_bytes

Maximum installed bytes in the internal-model cache.

Default 10GiB · Scope startup · Env YSEARCH_EMBEDDING_MODEL_CACHE_BYTES · Flag --embedding-model-cache-bytes · Allowed positive

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.

Default empty · Scope startup · Env YSEARCH_EMBEDDING_MODEL_CACHE_DIR · Flag --embedding-model-cache-dir

embedding.model_cache_packages

Maximum installed internal-model packages.

Default 8 · Scope startup · Env YSEARCH_EMBEDDING_MODEL_CACHE_PACKAGES · Flag --embedding-model-cache-packages · Allowed positive

embedding.model_download_allow_http

Allow plain HTTP model manifests and artifacts for trusted development networks.

Default false · Scope startup · Env YSEARCH_EMBEDDING_MODEL_DOWNLOAD_ALLOW_HTTP · Flag --embedding-model-download-allow-http

embedding.model_download_concurrency

Concurrent verified internal-model artifact downloads.

Default 2 · Scope startup · Env YSEARCH_EMBEDDING_MODEL_DOWNLOAD_CONCURRENCY · Flag --embedding-model-download-concurrency · Allowed in [1, 64]

embedding.model_download_timeout

Deadline for one internal-model package installation.

Default 10m · Scope startup · Env YSEARCH_EMBEDDING_MODEL_DOWNLOAD_TIMEOUT · Flag --embedding-model-download-timeout · Allowed positive

embedding.model_manifest_bytes

Maximum bytes in one internal-model manifest.

Default 1MiB · Scope startup · Env YSEARCH_EMBEDDING_MODEL_MANIFEST_BYTES · Flag --embedding-model-manifest-bytes · Allowed positive

embedding.model_package_bytes

Maximum bytes in one downloaded internal-model package.

Default 4GiB · Scope startup · Env YSEARCH_EMBEDDING_MODEL_PACKAGE_BYTES · Flag --embedding-model-package-bytes · Allowed positive

embedding.query_cache_bytes

Maximum float-vector bytes retained by the text-query embedding cache.

Default 64MiB · Scope startup · Env YSEARCH_EMBEDDING_QUERY_CACHE_BYTES · Flag --embedding-query-cache-bytes · Allowed positive

embedding.query_cache_entries

Maximum completed text-query embeddings retained per process.

Default 4096 · Scope startup · Env YSEARCH_EMBEDDING_QUERY_CACHE_ENTRIES · Flag --embedding-query-cache-entries · Allowed positive

embedding.query_cache_ttl

Lifetime of a completed text-query embedding cache entry.

Default 10m · Scope startup · Env YSEARCH_EMBEDDING_QUERY_CACHE_TTL · Flag --embedding-query-cache-ttl · Allowed positive

fleet

fleet.admin_fleet

Node host:port endpoints StreamFleetStats fans in; empty refuses the fleet stream.

Default empty · Scope startup · Env YSEARCH_FLEET_ADMIN_FLEET · Flag --fleet-admin-fleet (alias --admin-fleet)

fleet.aggregators

Aggregator host:port endpoints.

Default empty · Scope startup · Env YSEARCH_FLEET_AGGREGATORS · Flag --fleet-aggregators (alias --aggregators)

fleet.builders

Builder host:port endpoints the router polls and rendezvous-routes batches across.

Default empty · Scope startup · Env YSEARCH_FLEET_BUILDERS · Flag --fleet-builders (alias --builders)

fleet.fallback_workers

Worker host:port endpoints: the dispatch universe and the cache-oblivious fallback.

Default empty · Scope startup · Env YSEARCH_FLEET_FALLBACK_WORKERS · Flag --fleet-fallback-workers (alias --fallback-workers)

fleet.fan_in

Children per merge node in coordinator plans; zero means the planner's default, otherwise at least 2.

Default 0 · Scope startup · Env YSEARCH_FLEET_FAN_IN · Flag --fleet-fan-in (alias --fan-in) · Allowed in [0, 1024]

fleet.lane_slots

Per-lane worker slot pools, lane=count.

Default interactive=4,streaming=2 · Scope startup · Env YSEARCH_FLEET_LANE_SLOTS · Flag --fleet-lane-slots (alias --lane-slots)

fleet.mergers

Merge host:port endpoints: the coordinator's merge tier, a merger's delegation peers.

Default empty · Scope startup · Env YSEARCH_FLEET_MERGERS · Flag --fleet-mergers (alias --mergers)

follower

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.

Default 30s · Scope node-runtime · Env YSEARCH_FOLLOWER_DISCOVERY_INTERVAL · Flag --follower-discovery-interval · Allowed positive

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.

Default 30s · Scope node-runtime · Env YSEARCH_FOLLOWER_GENERATION_OVERLAP · Flag --follower-generation-overlap · Allowed positive

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.

Default 5m · Scope node-runtime · Env YSEARCH_FOLLOWER_MAX_STALENESS · Flag --follower-max-staleness · Allowed positive

follower.poll_interval

How often a node checks the catalog's latest pointer.

Default 2s · Scope node-runtime · Env YSEARCH_FOLLOWER_POLL_INTERVAL · Flag --follower-poll-interval · Allowed positive

follower.retired_generation_grace

How long a superseded generation's engine stays open after its last query.

Default 30s · Scope node-runtime · Env YSEARCH_FOLLOWER_RETIRED_GENERATION_GRACE · Flag --follower-retired-generation-grace · Allowed positive

format

format.minimum_reader_version

Oldest segment format this binary reads.

Default 1 · Not from a file: compile-time constant

format.segment_version

Segment format this binary writes.

Default 8 · Not from a file: compile-time constant

gc

gc.grace

Additional safety margin added to every scheduled GC reachability horizon.

Default 1h · Scope node-runtime · Env YSEARCH_GC_GRACE · Flag --gc-grace · Allowed in [0s, 168h0m0s]

gc.interval

Cadence at which the dedicated compactor role writes a GC proposal and considers a quarantined older proposal.

Default 1h · Scope node-runtime · Env YSEARCH_GC_INTERVAL · Flag --gc-interval · Allowed in [1s, 168h0m0s]

gc.maximum_stream_lifetime

Longest query-stream lifetime protected when marking superseded generations for scheduled GC.

Default 1h · Scope node-runtime · Env YSEARCH_GC_MAXIMUM_STREAM_LIFETIME · Flag --gc-maximum-stream-lifetime · Allowed in [0s, 168h0m0s]

gc.minimum_upload_age

Minimum age before an unreferenced object can enter a scheduled GC proposal.

Default 24h · Scope node-runtime · Env YSEARCH_GC_MINIMUM_UPLOAD_AGE · Flag --gc-minimum-upload-age · Allowed in [0s, 720h0m0s]

gc.quarantine_age

Minimum age of an immutable GC proposal before a fresh mark may authorize deleting its still-unreachable exact keys.

Default 24h · Scope node-runtime · Env YSEARCH_GC_QUARANTINE_AGE · Flag --gc-quarantine-age · Allowed in [1s, 720h0m0s]

gc.retained_generations

Historical catalog generations retained in addition to latest during scheduled GC.

Default 2 · Scope node-runtime · Env YSEARCH_GC_RETAINED_GENERATIONS · Flag --gc-retained-generations · Allowed in [0, 1024]

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.

Default false · Scope node-runtime · Env YSEARCH_GC_SWEEP_ENABLED · Flag --gc-sweep-enabled

index

index.generation

Exact generation to pin, or empty for the latest.

Default empty · Scope startup · Env YSEARCH_INDEX_GENERATION · Flag --index-generation (alias --generation)

Index name for catalog-bound serve, worker, coordinator, compactor, router, builder, and publisher roles.

Default empty · Scope startup · Env YSEARCH_INDEX_NAME · Flag --index-name (alias --index)

ingest

ingest.burst_documents

Per-index document tokens available for an ingest burst when the rate quota is enabled.

Default 100000 · Scope node-runtime · Env YSEARCH_INGEST_BURST_DOCUMENTS · Flag --ingest-burst-documents · Allowed positive

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.

Default empty · Scope startup · Env YSEARCH_INGEST_DIR · Flag --ingest-dir

ingest.documents_per_second

Per-router, per-index document admission rate; zero disables the rate quota.

Default 0 · Scope node-runtime · Env YSEARCH_INGEST_DOCUMENTS_PER_SECOND · Flag --ingest-documents-per-second · Allowed in [0, 1099511627776]

ingest.global_queue_bytes

Encoded ingest bytes all router sessions may hold while waiting for builders.

Default 256MiB · Scope node-runtime · Env YSEARCH_INGEST_GLOBAL_QUEUE_BYTES · Flag --ingest-global-queue-bytes · Allowed positive

ingest.index_queue_bytes

Encoded ingest bytes one index may hold while waiting for builders.

Default 64MiB · Scope node-runtime · Env YSEARCH_INGEST_INDEX_QUEUE_BYTES · Flag --ingest-index-queue-bytes · Allowed positive

ingest.max_batch_bytes

Largest accepted ingest batch.

Default 4MiB · Scope node-runtime · Env YSEARCH_INGEST_MAX_BATCH_BYTES · Flag --ingest-max-batch-bytes · Allowed positive

ingest.max_document_bytes

Largest accepted document.

Default 16MiB · Scope node-runtime · Env YSEARCH_INGEST_MAX_DOCUMENT_BYTES · Flag --ingest-max-document-bytes · Allowed positive

ingest.seal_age

Age at which an open build seals.

Default 30s · Scope node-runtime · Env YSEARCH_INGEST_SEAL_AGE · Flag --ingest-seal-age · Allowed positive

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.

Default 0 · Scope node-runtime · Env YSEARCH_INGEST_SEAL_BYTES · Flag --ingest-seal-bytes · Allowed in [0, 1TiB]

ingest.seal_documents

Spooled documents at which an open build seals.

Default 100000 · Scope node-runtime · Env YSEARCH_INGEST_SEAL_DOCUMENTS · Flag --ingest-seal-documents · Allowed positive

log

log.format

Log line format.

Default text · Scope startup · Env YSEARCH_LOG_FORMAT · Flag --log-format · Allowed one of text, json

log.level

Minimum level written to stderr.

Default info · Scope node-runtime · Env YSEARCH_LOG_LEVEL · Flag --log-level · Allowed one of error, warn, info, debug

object

object.backend

Object store backend.

Default fs · Scope startup · Env YSEARCH_OBJECT_BACKEND · Flag --object-backend · Allowed one of fs, s3

object.dir

Filesystem object-store directory; required for the fs backend. A relative value in a configuration file resolves against that file's directory.

Default empty · Scope startup · Env YSEARCH_OBJECT_DIR · Flag --object-dir

object.root

Object key root.

Default indexes · Scope startup · Env YSEARCH_OBJECT_ROOT · Flag --object-root

object.s3

object.s3.access_key

S3 access key. Environment only (YSEARCH_OBJECT_S3_ACCESS_KEY, or the legacy YSEARCH_S3_ACCESS_KEY); never a flag, never in a file.

Default empty · Not from a file: secret; read from YSEARCH_OBJECT_S3_ACCESS_KEY only

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.

Default false · Scope startup · Env YSEARCH_OBJECT_S3_ANONYMOUS · Flag --object-s3-anonymous (alias --s3-anonymous)

object.s3.bucket

S3 bucket; required for the s3 backend.

Default empty · Scope startup · Env YSEARCH_OBJECT_S3_BUCKET · Flag --object-s3-bucket (alias --s3-bucket)

object.s3.endpoint

S3 endpoint host:port; required for the s3 backend.

Default empty · Scope startup · Env YSEARCH_OBJECT_S3_ENDPOINT · Flag --object-s3-endpoint (alias --s3-endpoint)

object.s3.path_style

Use path-style S3 addressing.

Default false · Scope startup · Env YSEARCH_OBJECT_S3_PATH_STYLE · Flag --object-s3-path-style (alias --s3-path-style)

object.s3.prefix

S3 key prefix.

Default empty · Scope startup · Env YSEARCH_OBJECT_S3_PREFIX · Flag --object-s3-prefix (alias --s3-prefix)

object.s3.region

S3 region.

Default empty · Scope startup · Env YSEARCH_OBJECT_S3_REGION · Flag --object-s3-region (alias --s3-region)

object.s3.secret_key

S3 secret key. Environment only (YSEARCH_OBJECT_S3_SECRET_KEY, or the legacy YSEARCH_S3_SECRET_KEY).

Default empty · Not from a file: secret; read from YSEARCH_OBJECT_S3_SECRET_KEY only

object.s3.session_token

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.

Default empty · Not from a file: secret; read from YSEARCH_OBJECT_S3_SESSION_TOKEN only

object.s3.use_ssl

Use TLS to the S3 endpoint.

Default true · Scope startup · Env YSEARCH_OBJECT_S3_USE_SSL · Flag --object-s3-use-ssl (alias --s3-use-ssl)

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.

Default empty · Scope startup · Env YSEARCH_OBJECT_SOURCE · Flag --object-source (alias --source)

observability

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.

Default :9550 · Scope startup · Env YSEARCH_OBSERVABILITY_METRICS_LISTEN · Flag --observability-metrics-listen (alias --metrics-listen)

prototype

prototype.adapter

prototype.adapter.batch_documents

Documents per ingest request.

Default 500 · Scope startup · Env YSEARCH_PROTOTYPE_ADAPTER_BATCH_DOCUMENTS · Flag --prototype-adapter-batch-documents · Allowed in [1, 65536]

prototype.adapter.brokers

Comma-separated Kafka-protocol seed brokers of the article topics.

Default 127.0.0.1:9092 · Scope startup · Env YSEARCH_PROTOTYPE_ADAPTER_BROKERS · Flag --prototype-adapter-brokers

prototype.adapter.group

Consumer group id. Offsets are committed manually, only up to the last contiguously acknowledged record (spec/28 §4).

Default ysearch-prototype-articles · Scope startup · Env YSEARCH_PROTOTYPE_ADAPTER_GROUP · Flag --prototype-adapter-group

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.

Default articles · Scope startup · Env YSEARCH_PROTOTYPE_ADAPTER_INDEX · Flag --prototype-adapter-index

prototype.adapter.ingest_server

gRPC host:port of the ysearch server whose IngestService the adapter streams to.

Default 127.0.0.1:9500 · Scope startup · Env YSEARCH_PROTOTYPE_ADAPTER_INGEST_SERVER · Flag --prototype-adapter-ingest-server

prototype.adapter.namespace

Document key prefix: an article's key is <namespace>:<article id> in the sidecar and in the index.

Default articles · Scope startup · Env YSEARCH_PROTOTYPE_ADAPTER_NAMESPACE · Flag --prototype-adapter-namespace

prototype.adapter.partitions

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).

Default 0 · Scope startup · Env YSEARCH_PROTOTYPE_ADAPTER_PARTITIONS · Flag --prototype-adapter-partitions · Allowed in [0, 65536]

prototype.adapter.poll_records

Records per poll. One poll is one dual-write round: sidecar first, then ingest, then the offset commit.

Default 2000 · Scope startup · Env YSEARCH_PROTOTYPE_ADAPTER_POLL_RECORDS · Flag --prototype-adapter-poll-records · Allowed in [1, 1048576]

prototype.adapter.start

Where a group without committed offsets starts. Committed offsets always win, and an out-of-range committed offset stops its partition instead of jumping.

Default earliest · Scope startup · Env YSEARCH_PROTOTYPE_ADAPTER_START · Flag --prototype-adapter-start · Allowed one of earliest, latest

prototype.adapter.tombstones_delete

A null-value record deletes its article. Off, a tombstone is poison and stops its partition (spec/28 §2, §6).

Default false · Scope startup · Env YSEARCH_PROTOTYPE_ADAPTER_TOMBSTONES_DELETE · Flag --prototype-adapter-tombstones-delete

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.

Default articles · Scope startup · Env YSEARCH_PROTOTYPE_ADAPTER_TOPICS · Flag --prototype-adapter-topics

prototype.sidecar

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.

Default 127.0.0.1:6379 · Scope startup · Env YSEARCH_PROTOTYPE_SIDECAR_ADDRESS · Flag --prototype-sidecar-address

prototype.sidecar.password

The sidecar's MAREKVS_REQUIREPASS. Environment only (YSEARCH_PROTOTYPE_SIDECAR_PASSWORD); never a flag, never in a file.

Default empty · Not from a file: secret; read from YSEARCH_PROTOTYPE_SIDECAR_PASSWORD only

prototype.sidecar.timeout

Dial, read and write timeout of every sidecar call.

Default 5s · Scope startup · Env YSEARCH_PROTOTYPE_SIDECAR_TIMEOUT · Flag --prototype-sidecar-timeout · Allowed positive

publisher

publisher.announce_interval

Requested commit-marker publication cadence; the daemon floors it at follower.poll_interval and 15 seconds.

Default 15s · Scope node-runtime · Env YSEARCH_PUBLISHER_ANNOUNCE_INTERVAL · Flag --publisher-announce-interval · Allowed in [1s, 1h0m0s]

publisher.lease_ttl

Startup-fixed object-store lease lifetime for the catalog publisher; renewal runs at one third of this value.

Default 30s · Scope startup · Env YSEARCH_PUBLISHER_LEASE_TTL · Flag --publisher-lease-ttl · Allowed in [5s, 10m0s]

query

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.

Default true · Scope startup · Env YSEARCH_QUERY_COLLAPSE_KEY_VERSIONS · Flag --query-collapse-key-versions (alias --collapse-key-versions)

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.

Default false · Scope node-runtime · Env YSEARCH_QUERY_COMPILED_CACHE · Flag --query-compiled-cache

query.default_top_k

top_k when a request names none.

Default 10 · Scope node-runtime · Env YSEARCH_QUERY_DEFAULT_TOP_K · Flag --query-default-top-k · Allowed in [1, 10000]

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.

Default true · Scope startup · Env YSEARCH_QUERY_DEFER_PUBLIC_IDS · Flag --query-defer-public-ids

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.

Default 384MiB · Scope startup · Env YSEARCH_QUERY_LEXICAL_MEMORY_BYTES · Flag --query-lexical-memory-bytes · Allowed positive

query.lexical_strategy

Experimental exact lexical traversal selection; unsupported query shapes conservatively fall back to block-max.

Default block-max · Scope startup · Env YSEARCH_QUERY_LEXICAL_STRATEGY · Flag --query-lexical-strategy · Allowed one of block-max, auto, single-term-block-max, conjunction, block-max-maxscore

query.logical_bound_entries

Experimental score-bound subblock size within decoded postings; zero uses physical blocks. Does not reduce physical read size.

Default 0 · Scope startup · Env YSEARCH_QUERY_LOGICAL_BOUND_ENTRIES · Flag --query-logical-bound-entries · Allowed in [0, 256]

query.max_ast_depth

Deepest query nesting either grammar accepts.

Default 32 · Scope node-runtime · Env YSEARCH_QUERY_MAX_AST_DEPTH · Flag --query-max-ast-depth · Allowed in [1, 1024]

query.max_results

Ceiling on maximum_results per request; zero keeps the engine default.

Default 0 · Scope node-runtime · Env YSEARCH_QUERY_MAX_RESULTS · Flag --query-max-results

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.

Default pages · Scope node-runtime · Env YSEARCH_QUERY_ORDINAL_MODE · Flag --query-ordinal-mode · Allowed one of pages, whole, adaptive

query.packed_simd

Experimental native packed-posting decoding on supported CPUs; preserves scalar fallback and semantic validation.

Default false · Scope startup · Env YSEARCH_QUERY_PACKED_SIMD · Flag --query-packed-simd

query.phrase_gap_expansion_limit

Most exact gap variants a {m,n} quantifier may expand to.

Default 64 · Scope node-runtime · Env YSEARCH_QUERY_PHRASE_GAP_EXPANSION_LIMIT · Flag --query-phrase-gap-expansion-limit · Allowed in [1, 4096]

query.regex_max_expansions

Most dictionary terms a regex or prefix may expand to before the query is refused.

Default 256 · Scope node-runtime · Env YSEARCH_QUERY_REGEX_MAX_EXPANSIONS · Flag --query-regex-max-expansions · Allowed in [1, 65536]

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.

Default bm25f-v1 · Scope startup · Env YSEARCH_QUERY_SCORING_PROFILE · Flag --query-scoring-profile · Allowed one of bm25f-v1, bm25f-pinned-v1

query.set_simd

Experimental native intersection for balanced sparse filter arrays; skewed arrays retain scalar galloping.

Default false · Scope startup · Env YSEARCH_QUERY_SET_SIMD · Flag --query-set-simd

routing

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.

Default 0 · Scope startup · Env YSEARCH_ROUTING_PRESENCE_BYTES · Flag --routing-presence-bytes · Allowed in [0, 8GiB]

server

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.

Default empty · Scope startup · Env YSEARCH_SERVER_DATA_DIR · Flag --server-data-dir (alias --data-dir)

server.grace_period

Graceful shutdown period.

Default 5s · Scope startup · Env YSEARCH_SERVER_GRACE_PERIOD · Flag --server-grace-period (alias --grace-period) · Allowed positive

server.listen

gRPC listen host:port serve and node bind; the default is the address the client verbs dial (client.server).

Default 127.0.0.1:9500 · Scope startup · Env YSEARCH_SERVER_LISTEN · Flag --server-listen (alias --listen)

server.max_receive_bytes

Maximum gRPC request bytes (at least 64KiB).

Default 4MiB · Scope startup · Env YSEARCH_SERVER_MAX_RECEIVE_BYTES · Flag --server-max-receive-bytes (alias --max-receive-bytes) · Allowed at least 64KiB

server.max_send_bytes

Maximum gRPC response bytes (at least 64KiB, one result frame).

Default 4MiB · Scope startup · Env YSEARCH_SERVER_MAX_SEND_BYTES · Flag --server-max-send-bytes (alias --max-send-bytes) · Allowed at least 64KiB

server.node_id

Node identity; empty defaults to the bound listen address.

Default empty · Scope startup · Env YSEARCH_SERVER_NODE_ID · Flag --server-node-id (alias --node-id)

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.

Default 320MiB · Scope startup · Env YSEARCH_SERVER_QUERY_RECEIVE_MEMORY_BYTES · Flag --server-query-receive-memory-bytes · Allowed positive

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.

Default false · Scope startup · Env YSEARCH_SERVER_READ_ONLY · Flag --server-read-only (alias --read-only)

server.roles

Comma-separated roles for node: coordinator, worker, merger, aggregator, compactor, router, builder, publisher.

Default empty · Scope startup · Env YSEARCH_SERVER_ROLES · Flag --server-roles (alias --roles)

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.

Default loopback · Scope startup · Env YSEARCH_SERVER_SOURCE_MANAGEMENT · Flag --server-source-management · Allowed one of loopback, any

server.zone

Placement zone this node advertises in.

Default default · Scope startup · Env YSEARCH_SERVER_ZONE · Flag --server-zone (alias --zone)

stats

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.

Default empty · Scope startup · Env YSEARCH_STATS_DIR · Flag --stats-dir

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.

Default 6000 · Scope startup · Env YSEARCH_STATS_HISTORY_GENERATIONS · Flag --stats-history-generations · Allowed in [1, 16777216]

storage

storage.hydrate_throughput_floor

Lowest believable hydration throughput in bytes per second.

Default 128MiB · Scope node-runtime · Env YSEARCH_STORAGE_HYDRATE_THROUGHPUT_FLOOR · Flag --storage-hydrate-throughput-floor (alias --hydrate-throughput-floor) · Allowed positive

storage.hysteresis_denominator

Hysteresis denominator; must be below the numerator.

Default 4 · Scope node-runtime · Env YSEARCH_STORAGE_HYSTERESIS_DENOMINATOR · Flag --storage-hysteresis-denominator (alias --hysteresis-denominator) · Allowed in [1, 4294967295]

storage.hysteresis_numerator

Hysteresis numerator; must exceed the denominator.

Default 5 · Scope node-runtime · Env YSEARCH_STORAGE_HYSTERESIS_NUMERATOR · Flag --storage-hysteresis-numerator (alias --hysteresis-numerator) · Allowed in [1, 4294967295]

storage.mode

Storage mode: HYDRATE_FULL, REMOTE_BLOCKS, or AUTO (AUTO is refused by the checkpoint-bound serve).

Default AUTO · Scope startup · Env YSEARCH_STORAGE_MODE · Flag --storage-mode (alias --mode) · Allowed one of HYDRATE_FULL, REMOTE_BLOCKS, AUTO

storage.remote_latency_floor

Lowest believable remote request latency.

Default 2ms · Scope node-runtime · Env YSEARCH_STORAGE_REMOTE_LATENCY_FLOOR · Flag --storage-remote-latency-floor (alias --remote-latency-floor) · Allowed positive

storage.remote_throughput_floor

Lowest believable remote throughput in bytes per second.

Default 64MiB · Scope node-runtime · Env YSEARCH_STORAGE_REMOTE_THROUGHPUT_FLOOR · Flag --storage-remote-throughput-floor (alias --remote-throughput-floor) · Allowed positive

storage.scan_threshold_permille

Scan fraction above which AUTO hydrates.

Default 200 · Scope node-runtime · Env YSEARCH_STORAGE_SCAN_THRESHOLD_PERMILLE · Flag --storage-scan-threshold-permille (alias --scan-threshold-permille) · Allowed in [0, 1000]

tail

tail.impact_enabled

Persist score-banded approximate-tail data. Disabled avoids two additional records per unique term when exact tails are sufficient.

Default false · Scope node-runtime · Env YSEARCH_TAIL_IMPACT_ENABLED · Flag --tail-impact-enabled

tail.impact_maximum_bands

Maximum score-impact bands persisted for one term.

Default 64 · Scope node-runtime · Env YSEARCH_TAIL_IMPACT_MAXIMUM_BANDS · Flag --tail-impact-maximum-bands · Allowed in [1, 4096]

tail.impact_target_documents

Target postings per persisted impact run.

Default 4096 · Scope node-runtime · Env YSEARCH_TAIL_IMPACT_TARGET_DOCUMENTS · Flag --tail-impact-target-documents · Allowed in [1, 4294967295]

tail.maximum_ordering_error

Server ceiling on accepted approximate-tail score-ordering error; zero requires exact fallback.

Default 0 · Scope node-runtime · Env YSEARCH_TAIL_MAXIMUM_ORDERING_ERROR · Flag --tail-maximum-ordering-error · Allowed in [0, 1.7976931348623157e+308]

vector

vector.bits_per_code

Bits in each PQ subquantizer code.

Default 8 · Scope node-runtime · Env YSEARCH_VECTOR_BITS_PER_CODE · Flag --vector-bits-per-code · Allowed in [1, 8]

vector.build_memory_bytes

Per-build vector training and assignment memory; zero derives a bounded share of builder.sort_memory_bytes.

Default 0 · Scope node-runtime · Env YSEARCH_VECTOR_BUILD_MEMORY_BYTES · Flag --vector-build-memory-bytes · Allowed at least 0

vector.centroids

IVF coarse centroid count; zero derives it deterministically from population.

Default 0 · Scope node-runtime · Env YSEARCH_VECTOR_CENTROIDS · Flag --vector-centroids · Allowed in [0, 4294967295]

vector.flat_threshold

Per-segment vector population at or below which candidate generation stays exhaustive.

Default 10000 · Scope node-runtime · Env YSEARCH_VECTOR_FLAT_THRESHOLD · Flag --vector-flat-threshold · Allowed in [1, 4294967295]

vector.list_block_documents

Target vector entries per IVF-list block; zero follows the document-value block geometry.

Default 0 · Scope node-runtime · Env YSEARCH_VECTOR_LIST_BLOCK_DOCUMENTS · Flag --vector-list-block-documents · Allowed in [0, 4294967295]

vector.maximum_training_vectors

Maximum deterministic training samples retained per vector field.

Default 4096 · Scope node-runtime · Env YSEARCH_VECTOR_MAXIMUM_TRAINING_VECTORS · Flag --vector-maximum-training-vectors · Allowed in [1, 4294967295]

vector.query_candidate_multiplier

Default ANN candidates as a multiple of requested top_k.

Default 10 · Scope node-runtime · Env YSEARCH_VECTOR_QUERY_CANDIDATE_MULTIPLIER · Flag --vector-query-candidate-multiplier · Allowed in [1, 10000]

vector.query_default_probes

IVF coarse lists probed when a vector request does not specify probes.

Default 8 · Scope node-runtime · Env YSEARCH_VECTOR_QUERY_DEFAULT_PROBES · Flag --vector-query-default-probes · Allowed in [1, 4294967295]

vector.query_maximum_candidates

Hard per-request candidate generation and exact-rerank cap.

Default 100000 · Scope node-runtime · Env YSEARCH_VECTOR_QUERY_MAXIMUM_CANDIDATES · Flag --vector-query-maximum-candidates · Allowed in [1, 4294967295]

vector.query_maximum_probes

Hard per-request IVF probe cap.

Default 1024 · Scope node-runtime · Env YSEARCH_VECTOR_QUERY_MAXIMUM_PROBES · Flag --vector-query-maximum-probes · Allowed in [1, 4294967295]

vector.query_memory_bytes

Per-process admission budget for decoded vector-query working sets.

Default 256MiB · Scope node-runtime · Env YSEARCH_VECTOR_QUERY_MEMORY_BYTES · Flag --vector-query-memory-bytes · Allowed positive

vector.subquantizers

PQ subquantizer count; zero derives a geometry compatible with each vector field's dimension.

Default 0 · Scope node-runtime · Env YSEARCH_VECTOR_SUBQUANTIZERS · Flag --vector-subquantizers · Allowed in [0, 4294967295]

vector.training_iterations

Maximum deterministic k-means iterations during IVF-PQ training.

Default 20 · Scope node-runtime · Env YSEARCH_VECTOR_TRAINING_ITERATIONS · Flag --vector-training-iterations · Allowed in [1, 1000]