Chunking Strategies

By the Syncfusion DevTutorials team · Last updated

The main ways to split documents for RAG: fixed-length by characters or tokens with sentence fallbacks, sentence, paragraph, section and header-aware chunking, and semantic chunking at topic shifts.

Cutting a pizza is easy: same-size slices, straight lines. Cutting a cake with layers and decorations is harder. If you slice without looking, one piece gets all the cream and another gets half a strawberry. A careful baker cuts along the natural lines of the cake, so every piece is complete and looks right on the plate.

Chunking is cutting documents into pieces for search. You can cut by size, like the pizza, or along the document's natural lines, like the cake.

The main idea: there are three families of chunking. Fixed-length cuts by characters or tokens. It's simple and predictable, but it cuts through sentences. Structural chunking cuts at sentences, paragraphs and headings. It follows the writer's own boundaries. Semantic chunking cuts where the topic changes, measured by similarity between sentences. The right choice depends on your documents and questions.

A Real-World Example

Brightgrid first divided every article after a fixed number of characters. This sometimes cut useful information in the middle of a sentence or even in the middle of a word.

For example, a customer asked:

What should I do when the lamp blinks blue?

The retrieved text ended with:

In the app, press Add dev...

The rest of the instruction appeared in another chunk. Neither chunk contained the complete answer on its own.

To fix this, Brightgrid started dividing articles by headings and sentences. This approach is called structure-aware chunking.

Each section stays together when possible. If a section is too long, it is divided at a sentence boundary, and its heading is added to each resulting chunk.

The setup instructions now remain complete, making them easier for the search system to find and for the language model to understand.

In simple words: Split a document where one complete idea ends, not simply after a fixed number of characters.

What You Will Learn

In this lesson, you will learn:

  1. Fixed-length chunking by characters and tokens, its trade-offs, and sentence fallbacks.
  2. Structural chunking: sentence boundaries, paragraphs and sections, and header-aware chunking.
  3. Semantic chunking: topic segmentation, similarity boundaries and content-shift detection.

The RAG Lab's Chunker tab runs four strategies on any article or on the raw web page: fixed, sentence, section and semantic. Each chunk shows its length and warnings like "starts mid-sentence". Change the size and overlap sliders and watch the chunks change.

The same text cut three ways. Fixed-length cuts at a set size and can split words and sentences. Structural chunking follows sentences, paragraphs and headings. Semantic chunking starts a new chunk where the topic changes.

Fixed-Length Chunking

Character & Token Count Boundaries

The simplest method: take the next N characters, or the next N tokens, and repeat. Tokens matter more than characters, because models and costs are measured in tokens. For English, one token is about 4 characters, or 0.75 words.

Fixed chunks of 50 characters

// Fixed-length chunking by characters: simple, but it cuts words and sentences.
const text =
  "Plug in the lamp. It blinks blue when it is ready to pair. In the app, press Add device and follow the steps. Pairing usually takes under a minute.";

function fixedChunks(t, size) {
  const out = [];
  for (let i = 0; i < t.length; i += size) {
    out.push(t.slice(i, i + size));
  }
  return out;
}

fixedChunks(text, 50).forEach((c, i) => console.log(`#${i + 1} |${c}|`));

Expected output:

#1 |Plug in the lamp. It blinks blue when it is ready |
#2 |to pair. In the app, press Add device and follow t|
#3 |he steps. Pairing usually takes under a minute.|

Look at the cuts: "ready |to pair", "follow t|he steps". Each piece is incomplete.

Fixed Chunk Size Tradeoffs

SizeGoodBad
Small (100–200 tokens)Precise matches, cheap to sendPieces lack context, more chunks to store
Medium (200–500 tokens)A good default for help articlesCan mix two topics
Large (500–1,000+ tokens)Full context, fewer chunksDiluted matches, costly prompts, fewer chunks fit

Fixed-length chunking is still useful. It's fast, predictable, and works on any text, even text with no structure, like transcripts or logs.

Sentence Splitting Fallbacks

A common improvement: aim for a size, but only cut at sentence ends. Keep adding sentences until the next one would go over the limit, then start a new chunk. If a single sentence is longer than the limit, then cut it, as a last resort.

Token limit, but never mid-sentence

// Token-count chunks, with a fallback: never cut inside a sentence if you can avoid it.
const text =
  "Plug in the lamp. It blinks blue when it is ready to pair. In the app, press Add device and follow the steps. Pairing usually takes under a minute.";
const tokens = (s) => Math.ceil(s.split(/\s+/).length * 1.3); // rough: about 1.3 tokens per English word

function tokenChunks(t, maxTokens) {
  const sentences = t.match(/[^.!?]+[.!?]+/g).map((s) => s.trim());
  const out = [];
  let cur = "";
  for (const s of sentences) {
    const next = cur ? `${cur} ${s}` : s;
    if (cur && tokens(next) > maxTokens) {
      out.push(cur);
      cur = s;
    } else {
      cur = next;
    }
  }
  if (cur) {
    out.push(cur);
  }
  return out;
}

tokenChunks(text, 20).forEach((c, i) =>
  console.log(`#${i + 1} (${tokens(c)} tokens) ${c}`),
);

Expected output:

#1 (17 tokens) Plug in the lamp. It blinks blue when it is ready to pair.
#2 (13 tokens) In the app, press Add device and follow the steps.
#3 (8 tokens) Pairing usually takes under a minute.

Fixed chunks on a real article

Structural & Sentence Chunking

Sentence-Boundary Chunking

Splitting into sentences sounds easy: cut at ., ? and !. Real text has traps: "2.4 GHz", "e.g.", "Dr. Lee", "$3.99", and website names. Use a careful splitter: one that only cuts when the full stop is followed by a space or the end of the text, or a library built for sentence splitting.

Paragraph & Section-Based Splitting

Writers already group ideas into paragraphs and sections. Splitting there keeps related sentences together. Paragraph chunks are often small; section chunks are often a good size for help articles.

By paragraph and by section

// Paragraph and section splitting: use the writer's own breaks.
const doc = `## Before you start
You need the Brightgrid app and a 2.4 GHz Wi-Fi network.

The Lumo Lamp does not support 5 GHz networks.

## Steps
Plug in the lamp. It blinks blue when it is ready.

## Troubleshooting
If it does not blink, switch it off and on 5 times.`;

const byParagraph = doc.split(/\n\s*\n/).map((p) => p.replace(/^## .*\n/, "").trim());
console.log("paragraphs:", byParagraph.length);
byParagraph.forEach((p, i) => console.log(`  #${i + 1} ${p}`));

const bySection = doc.split(/\n(?=## )/).map((s) => {
  const [head, ...rest] = s.split("\n");
  return { section: head.slice(3), text: rest.join(" ").replace(/\s+/g, " ").trim() };
});
console.log("sections:", bySection.length);
bySection.forEach((s, i) => console.log(`  #${i + 1} [${s.section}] ${s.text}`));

Expected output:

paragraphs: 4
  #1 You need the Brightgrid app and a 2.4 GHz Wi-Fi network.
  #2 The Lumo Lamp does not support 5 GHz networks.
  #3 Plug in the lamp. It blinks blue when it is ready.
  #4 If it does not blink, switch it off and on 5 times.
sections: 3
  #1 [Before you start] You need the Brightgrid app and a 2.4 GHz Wi-Fi network. The Lumo Lamp does not support 5 GHz networks.
  #2 [Steps] Plug in the lamp. It blinks blue when it is ready.
  #3 [Troubleshooting] If it does not blink, switch it off and on 5 times.

Header-Aware Structural Chunking

Header-aware chunking combines the best of both:

  1. Split by heading first, so a chunk never mixes two sections.
  2. If a section is too long, split it at sentence ends.
  3. Add the heading path to every piece, so "Check that a 2.4 GHz network is on" still says it's from "Lamp will not connect to Wi-Fi > What to try".

The RAG Lab's index uses this strategy: one chunk per section, long sections split by sentences.

Split by headings, then by sentences

// Header-aware chunking: split by section, then split long sections by sentences,
// and keep the heading with every piece.
const doc = {
  title: "Lamp will not connect to Wi-Fi",
  sections: [
    {
      h: "Common causes",
      text: "Most failures happen because the network is 5 GHz only. The password may be wrong. The lamp may be too far away.",
    },
    {
      h: "What to try",
      text: "Move the lamp within 5 metres of the router. Check that a 2.4 GHz network is on.",
    },
  ],
};

function headerAware(d, maxChars) {
  const out = [];
  for (const s of d.sections) {
    let cur = "";
    for (const sent of s.text.match(/.+?\.(?=\s|$)/g).map((x) => x.trim())) {
      if (cur && (cur + " " + sent).length > maxChars) {
        out.push(`${d.title} > ${s.h}: ${cur}`);
        cur = sent;
      } else {
        cur = cur ? `${cur} ${sent}` : sent;
      }
    }
    out.push(`${d.title} > ${s.h}: ${cur}`);
  }
  return out;
}

headerAware(doc, 80).forEach((c, i) => console.log(`#${i + 1} ${c}`));

Expected output:

#1 Lamp will not connect to Wi-Fi > Common causes: Most failures happen because the network is 5 GHz only.
#2 Lamp will not connect to Wi-Fi > Common causes: The password may be wrong. The lamp may be too far away.
#3 Lamp will not connect to Wi-Fi > What to try: Move the lamp within 5 metres of the router. Check that a 2.4 GHz network is on.

Header-aware chunks

Semantic Chunking

Topic-Based Semantic Segmentation

Some text has no headings but still changes topic: a long FAQ page, a meeting transcript, a support chat. Semantic chunking reads it sentence by sentence and starts a new chunk when the topic shifts.

Embedding Similarity Chunk Boundaries

To spot a topic shift, compare each sentence with the one before it. If they're similar, they belong together. If similarity drops sharply, cut there. Real systems compare embeddings (Chapter 3). The cell below uses shared words, which is simpler but works the same way.

Content Shift Detection Mechanics

The steps:

  1. Split the text into sentences.
  2. Compute the similarity between each pair of neighbouring sentences.
  3. Cut where similarity falls below a threshold, or where it drops much lower than usual. That second rule adapts to each document.
  4. Merge pieces that come out too small, and split pieces that come out too large.

Cut where the topic shifts

// Semantic chunking: start a new chunk where the topic shifts.
// Here, "similar" means sharing words. Real systems compare embeddings instead.
const sentences = [
  "The Lumo Lamp needs a 2.4 GHz Wi-Fi network.",
  "Lumo Lamp pairing fails on 5 GHz Wi-Fi networks.",
  "Move the lamp closer to the Wi-Fi router.",
  "Brightgrid Plus costs $3.99 a month.",
  "Plus also adds energy reports.",
];
const stop = new Set(["the", "a", "on", "to", "also", "adds"]);
const words = (s) =>
  new Set(
    s
      .toLowerCase()
      .match(/[a-z0-9.]+/g)
      .filter((w) => !stop.has(w)),
  );

function similarity(a, b) {
  const A = words(a);
  const B = words(b);
  const shared = [...A].filter((w) => B.has(w)).length;
  return shared / Math.min(A.size, B.size);
}

const chunks = [[sentences[0]]];
for (let i = 1; i < sentences.length; i++) {
  const s = similarity(sentences[i - 1], sentences[i]);
  console.log(
    `sentence ${i} -> ${i + 1}: similarity ${s.toFixed(2)}${s < 0.2 ? "  <- topic shift, new chunk" : ""}`,
  );
  if (s < 0.2) {
    chunks.push([]);
  }
  chunks[chunks.length - 1].push(sentences[i]);
}
chunks.forEach((c, i) => console.log(`chunk ${i + 1}: ${c.join(" ")}`));

Expected output:

sentence 1 -> 2: similarity 0.63
sentence 2 -> 3: similarity 0.50
sentence 3 -> 4: similarity 0.00  <- topic shift, new chunk
sentence 4 -> 5: similarity 0.33
chunk 1: The Lumo Lamp needs a 2.4 GHz Wi-Fi network. Lumo Lamp pairing fails on 5 GHz Wi-Fi networks. Move the lamp closer to the Wi-Fi router.
chunk 2: Brightgrid Plus costs $3.99 a month. Plus also adds energy reports.

Semantic chunking costs more, because every sentence must be embedded before you can chunk. It's worth it for long text without structure. For documents with good headings, header-aware chunking is usually just as good and much cheaper.

Semantic chunks on the raw page

Which Strategy to Choose

Your documentsGood first choice
Help articles, docs and policies with headingsHeader-aware (sections, then sentences)
Plain text, transcripts and logsSentence-based with a token limit, or semantic
CodeSplit by function and class, never in the middle
Tables and spreadsheetsOne row or a small group of rows per chunk, with column names
Anything, when you need a quick baselineFixed-length with overlap (next lesson)

There's no single best chunk size. Measure it: run your gold set (Lesson 3) with two or three strategies and sizes, and keep the one that puts the right chunks in the top k most often.

Common mistakes

  • Cutting mid-sentence with fixed sizes, so answers are split across chunks.
  • Mixing two sections in one chunk, which blurs its meaning and its embedding.
  • A naive sentence splitter that breaks decimals, abbreviations and URLs.
  • Too-large chunks, so the matching sentence is buried among unrelated text.
  • Too-small chunks, which lose the subject, like "It costs $3.99."

Exercises

Each exercise ends with a value on the last line. Press Check to compare it with the expected answer.

What to Remember

  • Fixed-length chunking (characters or tokens) is simple and works on anything, but cuts through sentences. Add a sentence fallback.
  • Structural chunking follows sentences, paragraphs and sections. Header-aware chunking splits by heading, then by sentence, and keeps the heading path.
  • Semantic chunking cuts where similarity between neighbouring sentences drops, which is good for long text without headings.
  • Chunk size is a trade-off between precision and context. Measure it with a gold set.
  • Use a careful sentence splitter, and choose a strategy per document type.

Next: Chunk Optimization, overlap, size tuning and checking chunk quality.