← all writing

Where you cut the text

Your retrieval is returning junk.

The obvious suspect is the embedding model. So you swap it for a better one. Almost nothing changes.

The real culprit is usually a decision made much earlier, with far less thought: where you cut the text.

Chunking strategies for RAG get treated as plumbing — a line of setup code copied from a tutorial and never revisited. But the cut decides what your system can find. And a better embedding model won’t rescue a bad one.

The good news: it’s one idea, not ten.

In one breath: Chunking strategies for RAG come down to one trade-off, not a menu of ten. Small chunks match a question precisely but arrive without enough context to answer it. Large chunks carry the context but blur the match and cost more to run. The reliable default is recursive splitting at roughly 512 tokens — it cuts on paragraph and sentence boundaries, so it respects the structure the author already put there, and costs nothing extra to compute. Attach metadata to every chunk — source, section, date — so answers can be filtered and cited. Then measure before you get clever: peer-reviewed evaluations keep finding that expensive semantic chunking fails to justify its cost, and one 2026 benchmark put recursive splitting at 69% end-to-end accuracy against semantic chunking’s 54%. Blind fixed-length cutting is the one genuinely bad option.

What a chunk actually is

A chunk isn’t “a piece of text.” It’s two things at once.

First, it’s the unit of retrieval — the smallest thing your system can find. Nothing smaller ever comes back. Nothing larger comes back without dragging its neighbours along.

Second, and this is the half that gets missed, it’s the unit of citation. When your app says “according to this source,” the chunk is what it points at.

Split a claim across two chunks and there’s nothing clean to cite.

This is also why you can’t skip chunking by embedding whole documents. An embedding is a single point in meaning-space. A 3,000-word document covering ten topics collapses into one blurry average of all ten — close to nothing in particular.

Chunk it, and each idea becomes its own findable point.

I built how retrieval works end to end — embeddings, vectors, similarity — from scratch in an earlier post. This one is about the decision sitting a layer beneath it. (Still weighing whether to retrieve at all? Start there instead.)

Pause & recall. Why does one embedding for a long, multi-topic document retrieve badly — even with an excellent embedding model?

Reveal the answer

Because the embedding is a single point averaging every topic in the document. The average sits near none of them, so a question about any one topic matches it only weakly. The model isn’t the problem; the unit is.

The one dial: precision versus context

Small chunks retrieve precisely and answer poorly. The vector is sharp because the chunk is about one thing. But what arrives may be a fragment — the answer, stripped of the setup that makes it usable.

Large chunks answer well and retrieve poorly. The context is definitely in there. But the vector averages everything inside, so it matches nothing sharply, and you pay for the irrelevant majority.

Watch it happen on one passage.

The text we’re cutting

"Recursive splitting cuts on paragraph breaks
 first. If a chunk is still too big, it falls
 back to sentences, then to words. The Writing
 Bed uses it at ~1,500 characters."

The question we’ll ask it: “What does recursive splitting fall back to?”

Cut small — around 128 tokens

chunk → "back to sentences, then to words."

A perfect keyword match. But falls back from what? The chunk can’t say. Precise, and useless.

Cut medium — around 512 tokens

chunk → the whole passage above

Matches the question, and contains the answer. This is the usable middle.

Cut large — around 2,000 tokens

chunk → the passage + 12 unrelated paragraphs

The answer is in there. But the vector now averages thirteen topics, so it matches the question weakly — and you paid for twelve paragraphs nobody asked for.

The chunking trade-off between retrieval precision and generation contextOne document split three ways. Small chunks of about 128 tokens give a sharp vector and precise matching but often lack the context needed to answer. Medium chunks of about 512 tokens balance a good match with enough context, which is why they are the recommended default. Large chunks of about 2000 tokens carry plenty of context but their vector is an average of many topics, so matching is weak and cost and noise both rise.

One document

Small chunks · ~128 tokens

Medium chunks · ~512 tokens

Large chunks · ~2,000 tokens

Sharp vector, precise match

Often too little context to answer

Good match

Enough context to answer

Blurred vector, weak match

Context-rich, but costly and noisy

The usable middle

Every chunking strategy is an attempt to cheat this trade-off — precision of small chunks, context of large ones.

Hold that, and you can judge any strategy without anyone explaining it: which end of the dial is it buying back, and what does it charge you?

The strategies, boring to clever

StrategyHow it cutsCostWhen it earns its place
Fixed-sizeEvery N characters, structure be damnedTrivialUniform text; a baseline to beat
RecursiveParagraphs, then sentences, then words — until chunks fitTrivialThe default. Respects structure, costs nothing
SentenceOn sentence boundaries, grouped to a target sizeTrivialDense prose; strong cost-to-quality ratio
Document-awareOn the document’s own structure — headings, code blocksLowMarkdown, HTML, code
SemanticEmbeds sentences, cuts where meaning shiftsHigh — embeds everything twiceUnstructured text where topics drift mid-page
LLM-basedA model reads the document and picks boundariesVery highSmall, high-value corpora
Late chunkingEmbeds the whole document first, then pools per chunkModerate; needs long-context embeddingText thick with pronouns and back-references

You rarely implement these by hand. Recursive splitting is RecursiveCharacterTextSplitter in LangChain, or the equivalent node parsers in LlamaIndex. Messy PDFs need a parser like Unstructured first, so there’s real structure to cut on.

The strategy is your decision. The library call is one line of config.

What “recursive” actually does

The name sounds clever. The mechanism is a ladder of fallbacks.

The ladder

Target: 512 tokens. Try in order —

  1. Split on "\n\n"   (paragraphs)
  2. Split on "\n"     (lines)
  3. Split on ". "     (sentences)
  4. Split on " "      (words)

It stops at the first level where the chunks fit.

Why that matters

It always cuts at the biggest natural boundary available. So chunks land on paragraph breaks rather than mid-sentence — and it costs nothing, because the structure was already in the text. Recursive splitting simply doesn’t destroy it.

Late chunking, properly explained

The newest strategy and the most misunderstood. Worth doing slowly.

Step 1 — the document

"The Writing Bed indexes every post I publish.
 It cut answer time by 40%."

Two sentences. The second depends entirely on the first.

Step 2 — cut it the normal way

chunk 1 → "The Writing Bed indexes every post I publish."
chunk 2 → "It cut answer time by 40%."

Chunk 2 is orphaned. On its own, “It” means nothing.

Step 3 — watch the answer disappear

Search: "Writing Bed performance"

  chunk 1 → strong match
            (names it, says nothing about speed)
  chunk 2 → near zero
            (holds the answer, names no subject)

The only chunk containing the answer is invisible to the search. That’s the failure normal chunking can’t fix.

Step 4 — what late chunking changes

Embed the WHOLE document first
  → "It" is encoded while "The Writing Bed"
    is still visible to the model

Then slice into chunks
  → chunk 2 keeps that knowledge

Search: "Writing Bed performance"
  chunk 2 → matches

Same text. Same boundaries. Same number of chunks. The only change is when you embed — before the cut instead of after.

The catch

It needs a long-context embedding model, and there’s little independent benchmarking behind it yet. Worth watching. Not yet worth defaulting to.

What the benchmarks actually say

The literature is more interesting than the guides suggest. The answer isn’t simply “simple wins.”

StudySetupFinding
Qu, Tu & Bao, Oct 2024 (arXiv 2410.13070)Semantic vs fixed-size across document retrieval, evidence retrieval and answer generationFixed-size consistently outperformed semantic chunking on realistic documents; “the computational costs associated with semantic chunking are not justified by consistent performance gains”
Bennani & Moslonka, Jan 2026 (arXiv 2601.14123)Natural Questions, SPLADE retrieval, Mistral-8B generatorSentence chunking is the most cost-effective method, matching semantic up to ~5k tokens; overlap gave no measurable benefit; a “context cliff” degrades quality beyond ~2.5k tokens
Shaukat, Adnan & Kuhn, Mar 2026 (arXiv 2603.06976)36 segmentation methods × 5 embedding modelsContent-aware chunking significantly beat naive fixed-length splitting (nDCG@5 ≈ 0.459 vs below 0.244). Bigger embedding models scored higher but stayed “sensitive to suboptimal segmentation”

Together they say something sharper than “keep it simple.”

Respecting structure matters. Paying a model to find the structure usually doesn’t.

Cutting blindly every N characters is genuinely bad — the March 2026 study nearly doubled retrieval quality just by moving off it. But the expensive end keeps failing to justify itself. The 2024 study found fixed-size beating semantic outright. The 2026 one found plain sentence chunking matching it, far more cheaply.

Recursive splitting sits exactly in that gap. Content-aware, but free.

A better embedding model won’t save bad chunking. Larger models scored higher overall, yet stayed sensitive to poor segmentation. A team testing three embedding models while never testing a chunk size is tuning the wrong dial.

Most teams I meet are doing precisely that.

Third-party benchmarks agree. A February 2026 FloTorch run over 50 academic papers put recursive splitting at 512 tokens on 69% end-to-end accuracy against semantic chunking’s 54%. It’s reported through Prem AI’s round-up rather than a paper I can link directly, so weigh it accordingly.

The most telling number: the semantic chunker produced fragments averaging 43 tokens.

That’s the mechanism in miniature. Cut precisely where meaning shifts and you get chunks that are correct and far too small to answer from. Precision won. Context lost. Answers worse.

The overlap myth

Nearly every guide — mine included, until I checked — tells you to overlap adjacent chunks by 10–20%, so an idea straddling a boundary isn’t sliced in half.

Without overlap

chunk 1: "...cosine similarity measures the angle"
chunk 2: "between two vectors, ignoring length."

Ask “what is cosine similarity?” and neither chunk answers. The definition was cut down the middle.

With 20% overlap

chunk 1: "...cosine similarity measures the angle
          between two vectors, ignoring length."
chunk 2: "between two vectors, ignoring length.
          Nearest neighbours are the smallest angles."

Chunk 1 now answers it. That rescue is what you’re paying for.

What the evidence says

The January 2026 analysis varied overlap systematically and found it gave no measurable benefit while increasing indexing cost. Every overlapped token is one you embed, store and pay for twice.

Scope that honestly — one study isn’t a law. It used a sparse retriever (SPLADE), which matches on terms rather than dense semantic similarity, on a single dataset. Teams running dense retrieval still report overlap helping.

So overlap is a hedge, not a law. The rescue above is real. It may just not happen often enough to pay for itself.

Test it on your own corpus. If your documents are well-structured, the paragraph boundaries recursive splitting already respects may be doing the job you’re paying overlap for.

The half everyone forgets: metadata

Chunking isn’t only about where you cut. It’s about what you attach — and this is where the cheapest wins hide.

A bare chunk

"Start at 512 tokens and measure."

Can’t filter by date. Can’t prefer the canonical source. Can’t check permissions. Can’t cite.

The same chunk, enriched

text:    "Start at 512 tokens and measure."
source:  "Where you cut the text"
section: "Where to start"
date:    2026-08-27

Four things the second one can do that the first can’t:

  • Filter before searching. “Only 2026 policies” becomes a cheap metadata filter — instead of hoping the embedding encodes recency. It doesn’t.
  • Rank on more than similarity. Prefer newer. Prefer canonical over a stale duplicate.
  • Respect permissions. Retrieval that ignores who’s asking is a data leak with good UX.
  • Cite. The Writing Bed can name the post an answer came from purely because every chunk carries its source.

That last one connects chunking to trust. Citations are how an honest system ships something that can still occasionally be wrong — and the chunk is what a citation points at.

One free trick: prepend the section heading to the chunk’s text before embedding it. Costs nothing, gives the vector real context.

Do that before you go anywhere near a semantic chunker.

What I chose for the Writing Bed, and why

Roughly 1,500-character chunks — about 375 tokens — recursive, with overlap, each carrying the post it came from.

The reasoning is simple. These essays are structured prose where one idea usually runs two to four paragraphs. Recursive splitting cuts on paragraph breaks, so chunks land on real boundaries. At ~375 tokens a chunk is a complete argument: big enough to answer from, small enough that its vector is about one thing.

And the corpus is tiny. Fancier methods would cost more in complexity than they could return.

Now the honest part: the overlap is an unexamined default.

I set it because it sounded prudent. Then I read a peer-reviewed paper suggesting it may be buying me nothing but index size. My corpus is dense, structured essays — roughly the case where paragraph-aware splitting should already handle boundary problems.

What would change my mind is evidence, not argument: twenty golden questions, run with overlap and without, comparing whether the right chunk comes back.

Until I run that, I’m reporting a choice, not defending one.

How to actually pick

Your documentsStart withBecause
Anything, no strong opinionRecursive, ~512 tokensThe default the benchmarks keep validating
Essays, articles, proseRecursive or sentence, 400–800Ideas run in paragraphs; cut on them
Markdown, HTML, codeDocument-awareThe structure is already there
Short factual Q&A~256 tokensFactoid queries reward precision
Legal, financial, technical1,024, document-awareA clause is meaningless without its surroundings
Transcripts, chat logsSentence or semanticNo structure to lean on; topics drift
Small, high-value corpusConsider LLM-basedThe only place the cost can be justified

Two rules outrank the table.

Stay under the cliff. Quality degrades past roughly 2.5k tokens of retrieved context. Retrieving eight 1,000-token chunks is likely making answers worse, not better informed.

Change one variable at a time. Otherwise you’ll never know which change helped.

You can’t tune what you don’t measure

Chunk size is a hyperparameter. Treat it like one: baseline, change one thing, measure, keep what wins.

The trap is measuring the wrong layer.

If you only score the final answer, you can’t tell a retrieval failure from a generation failure. Score retrieval on its own first. For questions where you know which chunk should come back — does it?

Fix that before touching the prompt.

Twenty golden questions is enough to start. I wrote a full guide to building that eval from scratch.

Plainly: if you’re not going to measure, stop reading comparisons of chunking strategies. You won’t be able to tell whether any of them helped.

What I watch teams get wrong

  • Blaming the embedding model. It’s usually the chunking. Cheaper to test, too.
  • Cutting by character count alone. Slices tables, code and clauses in half.
  • Reaching for semantic chunking first. The expensive option that keeps losing. Earn your way there.
  • Bare chunks. No source, no section, no date — so no filtering, no ranking, no citations.
  • Retrieving more chunks to be safe. Past the cliff, that’s noise, not knowledge.
  • Re-chunking without re-embedding. New chunks need new vectors. Mixed generations break similarity silently.
  • Tuning by vibes. “That feels better” isn’t a result you can defend.

Where to start

Split recursively at 512 tokens. Attach source and section to every chunk, and prepend that heading to the text you embed. Write twenty questions you know the answers to. Check whether the right chunk comes back.

Only then change one variable — size first, then overlap, then strategy.

That’s a day’s work, and it beats most pipelines I’m shown.

The advanced strategies aren’t wrong. They’re answers to a question most teams haven’t yet earned the right to ask.

Check yourself.

  1. What are the two things a chunk is the unit of — and why does the second matter for trust?
  2. State the core trade-off in one sentence. Which end does a 128-token chunk win, and which does it lose?
  3. Semantic chunking is theoretically better and empirically worse. What does the 43-token fragment finding suggest about why?
  4. In the late chunking example, why can’t chunk 2 be found — and what fixes it?

Anything that won’t come is your reread map.

Want to see one of these decisions running? The Writing Bed is ~1,500-character recursive chunks with the source attached, live in the Greenhouse.

Ask it something specific and watch which post it cites. That’s a chunk, doing exactly the job it was cut for. 📚

Say hello

Let's grow something together.

Consulting, teaching, speaking, or a product idea that needs an AI brain — my inbox is open.

us — Usama Shahid © 2026 Usama Shahid — reachusama.com 🌱