Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Limits and Defaults

Status: Baseline 1.0 (2026-09-30). Values were provisional until the M1 and M3 measurements, as confirmed by the owner on 2026-09-30. The measurements were taken and left the values they tested unchanged: at M1 the cold start (729 ms, 2026-10-20) kept LIM-S4 and LIM-S6, and at M3 the fetch memory report (release 0.3.0, 2026-10-27) proposed no change to LIM-F10 and derived the ceiling from LIM-C3, LIM-C5 and LIM-F3. M8 measures again (RFC 020, handoff 020e). Governs: every number that the requirements and the external design refer to by a LIM- identifier.

A bare D-nn in this book is a decision of the startup review that fixed the first requirements. That review is not a page of this book and no page lists its decisions; the requirements quote what they need. The decisions of the audit (RFC 020) are written RFC 020, D-n. (Requirements says the same in its introduction.)

Every value here is a starting point. It is confirmed or corrected by measurement in milestones M1 and M3 (see ROADMAP.md). The requirements do not repeat the values; they cite the identifier, so that a value changes in one place only.

“Range” is what an operator may configure, through the key the configuration reference names for the row. Where a range is “operator”, the operator may choose any value; where it is “fixed”, no configuration changes it (RFC 020, D-9: a row that is not backed by a key is “fixed”).

Units

IDQuantityUnit
LIM-U1Text budgetsUnicode scalar values, cut only at a character boundary
LIM-U2Byte budgetsBytes after decompression
LIM-U3TimeMilliseconds, measured on a monotonic clock
LIM-U4Timestamps in outputRFC 3339, UTC
IDParameterDefaultRangeBasis
LIM-S1Length of query400 characters1–600Brave accepts 600 characters and 75 words; an engine with a lower limit is skipped for a longer query
LIM-S2max_results51–20Study example; Brave returns at most 20
LIM-S3Results requested from each engine105–20Overlap for ranking
LIM-S4Overall deadline of a search2500 ms500–10000Study proposes 1500 ms (R-10). Measured: cold start to the first answer 729 ms at M1 and 715 ms at M8; rypsok’s own share about 6 ms (RFC 020, 020e)
LIM-S5Timeout of one engine request2000 ms≤ LIM-S4 − LIM-S6C-14
LIM-S6Reserve for post-processing200 ms50–1000Architecture overview §4.6. Measured (RFC 020, 020e): post-processing took 0.64 ms median and 5.11 ms at most, with mock engine answers; larger real answers were not measured. Kept at 200 ms (RFC 020, PRF-5)
LIM-S7Maximum duration of a web_search callLIM-S4 + 300 msderivedX-04
LIM-S8Engines queried per request81–16Bounded fan-out
LIM-S9Length of a snippet300 characters50–1000Context budget
LIM-S10Length of a title150 characters50–300Context budget
LIM-S11Window for the typical latency of an enginelast 20 completed requestsfixedMedian over the window
LIM-S12Connect timeout of an engine request (search.connect_timeout_ms)1000 ms200–5000—
LIM-S13Maximum duration of an engine_status call200 msderivedX-04

Fetch

IDParameterDefaultRangeBasis
LIM-F1max_chars3000500 to LIM-F2Draft external design §4.2 and §15; mimlys study; X-06
LIM-F2Ceiling of max_chars20000500–100000M-02
LIM-F3Response bytes after decompression5 MiB64 KiB–10 MiBStudy; the ceiling is 10 MiB since RFC 020, D-20: four 20 MiB pages need 265 to 282 MiB (audit 020e), more than the 256 MiB of the documented unit
LIM-F4Overall deadline of a fetch10000 ms1000–30000—
LIM-F5Maximum duration of a web_fetch callLIM-F4 + 1000 msderivedX-04, R-04
LIM-F6Connect timeout3000 ms500–10000—
LIM-F7Redirects followed50–10Draft external design §15
LIM-F8Ports80, 443operatorM-07
LIM-F9Length of url2048 charactersfixed—
LIM-F10HTML nodes parsed100000fixedR-04
LIM-F11HTML nesting depth; enforced while parsing, a deeper page is read in part256fixedR-04; RFC 020, D-3
LIM-F12robots.txt kept in memory24 hoursfixedRFC 9309 §2.4
LIM-F13Size of a robots.txt read512 KiBfixedParser bound
LIM-F14URLs remembered for strict mode10000operatorREQ-SEC-021; bounded memory (RFC 011)
LIM-F15robots.txt entries kept in memory1000 originsoperatorREQ-CMP-005; bounded memory (RFC 011)

Concurrency and rates

IDParameterDefaultRangeBasis
LIM-C1Outbound requests in flight, whole process321–256REQ-SEC-012
LIM-C2Requests in flight per engine21–8, lower where the provider demands itProvider terms
LIM-C3Fetches in flight, whole process41–64REQ-SEC-012
LIM-C4Fetches in flight per host1fixedPoliteness
LIM-C5Parsing tasks in flight21–16R-04
LIM-C6web_search calls accepted60 per minute1–6000 per minuteMCP: servers must rate limit tool invocations
LIM-C7web_fetch calls accepted30 per minute1–6000 per minuteSame
LIM-C8engine_status calls accepted30 per minute1–6000 per minuteSame
LIM-C9Requests to one engineper engine, from its admission recordfixed (the provider’s limit)REQ-CMP-002

HTTP listener (M4)

IDParameterDefaultRangeBasis
LIM-H1HTTP connections accepted at once641–4096REQ-SEC-018; bounded memory (RFC 013)
LIM-H2Size of an HTTP request body65536 bytes4096–1048576A tool call is small; THR-11 (RFC 013)
LIM-H3Idle HTTP connection timeout, including a connection that has sent nothing or only the first bytes of the HTTP/2 preface (HTTP/1: close after; HTTP/2: keep-alive ping after, close when unanswered)60 s5–600 sResource hygiene (RFC 013)
LIM-H4Streams one HTTP/2 connection may open161–256THR-26 (RFC 018)
LIM-H5Time one HTTP request may take, whatever its state30 s3–600 s, at least fetch.deadline_ms + 2 sTHR-26 (RFC 018)
LIM-H6Live sessions of the handshake-based revisions over HTTP; each costs about 60 KiB2561–2048THR-27 (RFC 019); the ceiling is 2048 since RFC 020, D-21: 65536 sessions need 3.7 GiB (audit 020e), 2048 about 120 MiB
LIM-H7Size of the header block of an HTTP request (HTTP/1: request line and headers; HTTP/2: the header list)16384 bytesfixedNET-12 (audit 020b); the same bound on both protocols

Circuit breaker

IDParameterDefaultRangeBasis
LIM-B1Consecutive failures that open the circuit31–10—
LIM-B2First cooldown60 s10–600 s—
LIM-B3Cooldown growthdoubling, up to 900 soperator—
LIM-B4Retry-After from a providerhonored, up to LIM-B3’s maximumfixedM-15
LIM-B5Probe after cooldownone real requestfixedD-33

Interface size and shape

IDParameterBudgetRangeBasis
LIM-I1Names, descriptions and input schemas of all tools, plus the server instructions, together2000 charactersfixedR-15, X-06
LIM-I2Parameters of one tool5 at mostfixedClarity rule 8
LIM-I3Nesting of a tool’s input schemanone: flat object of primitives and enumerationsfixedX-06
LIM-I4Length of a notice or error message200 charactersfixedContext budget

Operation

IDParameterDefaultRangeBasis
LIM-O1Time to exit after end of file on stdin or SIGTERM (service.shutdown_ms)3000 ms500–10000REQ-OPS-002
LIM-O2Time until a cancelled call has aborted its outbound requests500 msfixedREQ-MCP-007
LIM-O3Largest line of the stdio transport, newline included; a longer line is dropped without an answer and the server reads on16 MiBfixed022a; the protocol library’s bound (rmcp 3.6.0), not ours; 0.9.0 had none

Privacy and logging

IDParameterDefaultRangeBasis
LIM-P1Secret detectionon, refuseoff, warn, mask, refuseD-10
LIM-P2Log levelinfoerror, warn, info, debugD-19
LIM-P3Query text in logsneveronly in debug mode, which warns at startD-19

Cache (not before M5)

IDParameterDefaultRangeBasis
LIM-K1Cacheoffon, offD-28
LIM-K2Lifetime of an entry300 s10–3600 sDraft external design §15
LIM-K3Entries10001–100000Bounded memory (RFC 014)
LIM-K4Size of one entry (raw titles, snippets, URLs)32768 bytes1024–1048576Memory at most LIM-K3 × LIM-K4 (RFC 014)

Scraping (M5)

IDParameterDefaultRangeBasis
LIM-G1Scraping driversoffon, offD-06, DR-006 (RFC 015)

Measured costs (the memory estimate of rypsok check)

These are not limits an operator sets. They are the costs that the audit measured (handoff 020e, the delivered musl release build of 0.8.0, and handoff 020x, which fitted both sets by one method), rounded up, and rypsok check combines them with the effective settings into the worst-case memory it prints and compares with MemoryMax of the documented unit (RFC 020, D-20, D-21):

13 MiB + fetches_in_flight × max_bytes + parsing_in_flight × (5.2 × max_bytes + 11 MiB) + max_sessions × 60 KiB (the sessions only while legacy_revisions is on), plus cache.max_entries × cache.max_entry_bytes (LIM-K3 × LIM-K4) when the cache is on. It is an estimate, not a guarantee.

The allocator decides how much a process holds after a parse, so the costs exist twice (RFC 020, 020x): LIM-M1 to LIM-M3 for a Linux musl build (the release binaries and the image), LIM-M6 to LIM-M8 for a Linux glibc build (what cargo install makes there), which replace the three in the formula above (14 MiB, 10.6 × max_bytes + 21 MiB). Both sets are fitted by the same method, and without the sessions the estimate is above every measured peak. rypsok check uses the set of the build it runs as and says which. On a platform that was not measured it prints the larger set with the note “measured on Linux; not measured for this platform” and does not compare it with the unit.

IDParameterDefaultRangeBasis
LIM-M1The process at rest (musl)13 MiBfixedIdle 10.0 to 12.05 MiB in 20 runs (020x; audit 020e: 10 to 12, median 10.9), and a margin
LIM-M2The part of one parse that does not grow with the page (musl)11 MiBfixed020x: see below (audit 020e, on one fetch: the line crossed at 12.4 MiB)
LIM-M3The part of one parse that grows with the page, in tenths of a byte per byte of page (musl)52fixed020x: see below (audit 020e, on one fetch: 4.34 per byte)
LIM-M4One live session of the handshake-based revisions60 KiBfixedAudit 020e: 58.5 KiB measured (56.7 to 60.6)
LIM-M5MemoryMax of the documented systemd unit, the figure the estimate is compared with256 MiBfixeddeployment.md
LIM-M6The process at rest (glibc)14 MiBfixed020x: idle 12.8 to 13.4 MiB in 20 runs, and a margin
LIM-M7The part of one parse that does not grow with the page (glibc)21 MiBfixed020x: see below
LIM-M8The part of one parse that grows with the page, in tenths of a byte per byte of page (glibc)106fixed020x: see below

Basis of LIM-M2, LIM-M3 and LIM-M6 to LIM-M8 (RFC 020, 020x, F-4 and C1). tools/measure-memory --defaults --page-mib=N on the host glibc release build, with the defaults (four fetches from four hosts, two parses at once), five runs at a 5 MiB page and five at a 10 MiB page (the ceiling of fetch.max_bytes; LIM-F3’s old top of 20 MiB is no longer configurable). Peaks: 153.4 to 178.0 MiB at 5 MiB and 268.6 to 301.9 MiB at 10 MiB. The maximum of each size, less the idle base (14 MiB) and the four bodies, is the cost of two parses: 144.1 and 248.1 MiB, that is 72.0 and 124.0 MiB per parse, a line of 10.49 per byte of page crossing at 19.6 MiB, rounded up to 10.6 and 21 MiB so that the estimate is above every run (182 and 307 MiB against 178.0 and 301.9). The line is fitted on the delivered concurrency of two parses; a single fetch costs less on glibc (52 to 57 MiB at 5 MiB, 79 to 106 at 10 MiB) because the allocator keeps what earlier parses freed, and the estimate is for the concurrent case. For other numbers of parses it extrapolates, as the musl set does. The musl set is fitted the same way on the musl binary: peaks 99.4 to 104.6 MiB (5 MiB) and 172.9 to 175.3 MiB (10 MiB); less the idle base (13 MiB) and the four bodies, the maxima are 71.6 and 122.5 MiB for two parses (35.8 and 61.3 per parse), a line of 5.13 per byte crossing at 10.2 MiB, rounded up to 5.2 and 11 MiB. The estimate without sessions is 107 and 179 MiB, above the maxima 104.6 and 175.3. A unit test pins the rule for both builds with these peaks.