Skip to content

Build1 publisher3 min readPublished

Dropping the vector database hands chunk boundaries to Google's whitespace rule

Maneshwar's Go build answers questions over 1.4 million tokens of internal docs through a hosted Gemini File Search store, paying for embeddings once at indexing and giving up every retrieval knob except the markdown.

The Engineer · Build desk

Illustration accompanying Dropping the vector database hands chunk boundaries to Google's whitespace rule

What happened

  • Maneshwar published a Go tool that answers questions over about 1.4 million tokens of internal books, essays and postmortems using Gemini File Search, with no vector database, chunker or reranker.
  • Google charges once at indexing time at embedding prices, keeps storage and query-time embeddings free, and bills the chunks the model retrieves as ordinary context tokens on the same call.
  • The implementation is one Go binary with SQLite through modernc.org/sqlite, a hand-rolled REST client so request and response bodies can be logged verbatim, and two model calls per question.
  • Of three PDF converters tried, pymupdf4llm found forty-four real headings in one essay, where markitdown glued words to their neighbours and pdftotext discarded headings entirely.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • decision Chunk quality is now decided in the document converter, which moves retrieval tuning out of query-time code and into a make target that nobody reviews.
  • cost Teams that keep spare keys for headroom have to budget ingest as an N-times operation, so a corpus that changes weekly makes re-indexing the expensive part of the design.
  • constraint The design holds only while the corpus stays under the store cap and the question rate stays under the per-minute quota, and neither limit can be relieved by adding capacity you control.
  • capability For a corpus this size a team can get grounded, cited answers without ever choosing an embedding model, so building a vector store turns into a question about corpus size and request rate.

The chunking decision moved in this build. File Search chunks uploaded documents on whitespace with a token budget [7]. That rule belongs to Google. The one input still under the builder's control is the whitespace in the markdown he uploads, and that is where an evening went [8].

markitdown gave him headings of a sort, and it also gave him this out of a PDF: `Theubiquityoffrustrating,unhelpfulsoftwareinterfaceshasmotivateddecadesofresearch` [8]. Maneshwar wrote that the embedding model does not know what `Theubiquityoffrustrating` is, and neither does the retrieval [9]. pdftotext fixed the spacing and threw away every heading, so a 300-page book became one undifferentiated scroll [10]. pymupdf4llm reads font sizes to decide what is a heading, keeps bold and italics, and handled the spacing on the same PDF [11]. On one essay it found 44 real headings where the others found none [12]. "A chunk that starts at a heading is a chunk that means something on its own," he wrote [13]. The conversion now sits behind `make process-data`, with EPUBs, PDFs and a sync of the blog repos landing in one markdown tree [14].

That count measures the converter. Forty-four headings tell you the chunk boundaries fell on section starts; whether the right chunk comes back for a given question is a separate measurement.

The second thing I would check before adopting this is where the store lives. A File Search store sits inside the Google Cloud project behind the API key that created it [15]. Create a store with key A, search it with key B from a different project, and the error tells you nothing useful: as far as key B is concerned, the store is simply not there [15]. Free-tier per-minute caps are real, and the usual fix is rotating requests across several keys, which a tool-attached call cannot do [16]. So the keys got roles: `keys/store.txt` lists keys that each own a complete copy of the corpus in their own store, ingest uploads to all of them, and the search call tries store 0 with key 0, falling through to store 1 with key 1 on a quota or auth failure [17].

Indexing is the one step you pay for [4]. A fallback chain of N keys pays that one-time embedding bill N times, and every corpus update re-indexes N stores [19].

The storage cap has slack at this size. A 1 GB free-tier store against 5.3 MB of markdown leaves room for roughly 190 copies of the whole shelf [18]. The per-minute rate is the limit the key chain exists to work around [16].

For this to transfer, your corpus has to fit under the cap, change rarely enough that re-ingesting every store stays cheap, sit inside the per-minute quota at your question volume, and survive being cut on whitespace against someone else's token budget. Retrieval is free at query time; the chunks the model pulls in are billed as ordinary context tokens on the call you were already making [4].

What to watch

  • Whether Google exposes chunking parameters or lets one store be shared across projects. Either change removes the copy-per-key workaround.
  • Paid-tier quota and store limits: the build is described entirely on the free tier, so cost per question at volume is untested here.
  • A retrieval accuracy comparison on the same corpus against a self-hosted pgvector baseline. That comparison would price what the hosted chunker costs in answer quality.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories