Skip to content

Best Chunking Strategies for RAG: Sizes, Methods & Benchmarks

Swarnava Dutta9 min read

Chunking Strategies For RAGChunking Method In RagflowSemantic Chunking

Contents

Illustration of best chunking strategies for rag: A long manuscript ribbon spans a wide cutting table, divided at natural folds by

Your RAG system's retrieval quality tanked last week, and you've been staring at the same debugging loop for hours. The embeddings look fine. The vector database is healthy. The LLM generates reasonable answers when you feed it the right context manually. So why does production keep pulling irrelevant chunks?

The cause is usually duller than a broken embedding model: a chunker slicing documents at arbitrary character boundaries, fragmenting the exact sentences users are searching for. The best chunking strategies for RAG aren't about finding some magic number - they're about understanding how chunk boundaries determine whether your retriever finds what it needs or returns garbage.

Here's what actually works for chunking pipelines across technical documentation, legal contracts, and support ticket archives.

Quick answer

Recursive character splitting at 512 tokens with 50-token overlap is the default starting point for RAG chunking, handling 80% of use cases without tuning. LangChain's RecursiveCharacterTextSplitter is the standard implementation. Legal documents suit 768-1024 tokens and code files 256-384 tokens. Semantic chunking pays off only when a corpus mixes multiple topics per document and latency budget allows a second embedding pass. Retrieval precision@5 on real queries decides the winner.

What Is Chunking in RAG and Why It Determines Retrieval Quality

Chunking is the process of splitting your source documents into smaller segments that get embedded and stored in your vector database. When a user query arrives, your retriever searches these chunks - not your original documents. This means every chunking decision you make directly shapes what your system can retrieve.

Think of it as the hidden bottleneck in your RAG pipeline. The flow runs: ingestion → chunking → embedding → indexing → retrieval → generation. That split between offline indexing and retrieval at inference time goes back to the research that first formalized retrieval-augmented generation. If your chunks fragment a critical explanation across two segments, neither chunk contains enough context to be useful. If your chunks are too large, you waste your embedding model's capacity on irrelevant text that dilutes the semantic signal.

The core tradeoff governing all chunking decisions is cost versus quality. Smaller chunks mean more vectors to store and search, increasing latency and infrastructure costs. Larger chunks preserve more context but reduce retrieval precision. Every strategy I'll cover navigates this tension differently - and the right choice depends on your documents, your queries, and your latency budget.

Fixed-Size Chunking: The Baseline Approach

Fixed-size chunking does exactly what it sounds like: split your document every N characters or tokens, optionally overlapping adjacent chunks. It's the strategy most tutorials start with, and for good reason - it's fast, predictable, and requires zero understanding of your content.

For most embedding models, 512 tokens with 50-100 token overlap is a widely adopted starting point among practitioners. This aligns with the sequence lengths these models were trained on and gives you enough context per chunk without excessive redundancy.

Fixed-size works well when:

  • Your documents are homogeneous (all similar structure and density)
  • You're building a prototype and need something running today
  • Latency matters more than retrieval precision

The limitations become obvious fast. Fixed-size chunking will happily split mid-sentence, mid-paragraph, even mid-word if you're counting characters. A character-counting chunker will cut a technical definition at exactly the point where the explanation starts. The term lands in one chunk; its explanation lands in the next. Neither chunk alone answers the query.

Recursive Character Splitting: Structured Document Handling

Recursive splitting improves on fixed-size by respecting document structure. Instead of blindly counting characters, it attempts to split on paragraph breaks first, then sentences, then words, then characters - only falling back to smaller separators when larger ones don't fit your size constraints.

LangChain's RecursiveCharacterTextSplitter is the standard implementation most teams reach for. You define a hierarchy of separators (\n\n, \n, . , ) and a target chunk size, and the splitter works through your document trying to keep logical units intact.

from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,
    chunk_overlap=50,
    separators=["\n\n", "\n", ". ", " ", ""]
)
chunks = splitter.split_text(document)

This approach shines for markdown files, code, and anything with clear structural markers. The trade-off is slightly more compute overhead during ingestion - but for most pipelines, ingestion isn't your bottleneck anyway. If you're moving beyond a quick prototype, recursive splitting should be your default starting point, not fixed-size.

Semantic Chunking: Embedding-Aware Boundaries

Semantic chunking takes a fundamentally different approach: instead of using text patterns to find boundaries, it uses embedding similarity to detect where topics shift. You embed sentences or small segments, then split wherever the cosine similarity between adjacent segments drops below a threshold.

The implementation typically uses Hugging Face sentence-transformers for boundary detection:

from sentence_transformers import SentenceTransformer
import numpy as np

model = SentenceTransformer('all-MiniLM-L6-v2')
sentences = document.split('. ')
embeddings = model.encode(sentences)

# Find similarity drops between adjacent sentences
similarities = [np.dot(embeddings[i], embeddings[i+1]) 
                for i in range(len(embeddings)-1)]
Flow diagram of semantic RAG chunking, using embeddings and cosine similarity drops to detect topic shifts and split boundaries.
Semantic boundaries from similarity drops

Production systems using semantic chunking report meaningful retrieval gains on topic-diverse corpora compared to fixed-size approaches. The improvements are real - but so are the costs.

When to avoid semantic chunking:

  • It adds meaningful latency to ingestion (you're embedding twice)
  • It's overkill for uniform documents where topic boundaries are obvious
  • Tuning the similarity threshold requires experimentation per corpus

Set the threshold too high and chunks balloon toward 2,000 tokens, which defeats the purpose entirely. I start conservative (threshold around 0.7) and adjust based on the chunk size distribution.

Optimal Chunk Sizes: Benchmark-Driven Recommendations

The 256-512 token range hits the sweet spot for most embedding models, a consensus that's emerged across practitioner communities and framework defaults. This isn't arbitrary - it aligns with how these models were trained and where their semantic understanding is strongest. Push past 1,024 tokens and you're often exceeding the model's effective attention span.

But document type matters more than generic advice suggests:

  • Legal/regulatory documents: 768-1024 tokens. Dense, interconnected clauses need more context to be meaningful.
  • Code files: 256-384 tokens. Functions and classes have natural boundaries; smaller chunks preserve them.
  • Conversational content (chat logs, support tickets): 128-256 tokens. Exchanges are short; larger chunks add noise.
  • Technical documentation: 512-768 tokens. Balances explanation completeness with retrieval precision.

Your chunk size must also respect your embedding model's maximum sequence length. If you're using a model with a 512-token limit and chunking at 600 tokens, you're silently truncating every chunk and losing information. Always check your model's max_seq_length and chunk below it.

For overlap, 10-20% of your chunk size balances context preservation against redundancy. At 512 tokens, that's 50-100 tokens of overlap - enough to avoid fragmenting sentences at boundaries without bloating your index.

Document-Aware Chunking: Leveraging Structure and Metadata

Document-aware chunking goes beyond text patterns to leverage actual document structure - headers, tables, lists, and formatting. Tools like RAGFlow and similar systems parse document layout to create semantically meaningful segments that respect the author's organization. The comprehensive guide on chunking strategies from Databricks covers how these approaches handle complex document types.

One pattern worth adopting is parent-child chunking: store large chunks (1,000+ tokens) for context, but index and retrieve on smaller child chunks (256-512 tokens). When a child chunk matches, you pull its parent for generation, giving your LLM the surrounding context it needs.

Metadata enrichment makes your chunks more useful downstream. Attach section titles, page numbers, source URLs, and document types to each chunk. This enables filtered retrieval ("only search the API documentation section") and improves answer attribution.

For consistent token counting across your pipeline, use Hugging Face tokenizers matched to your embedding model:

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained('sentence-transformers/all-MiniLM-L6-v2')
token_count = len(tokenizer.encode(chunk, add_special_tokens=False))

Character counts lie. Token counts tell the truth about what your model actually sees.

Choosing the Best Chunking Strategy for RAG: A Decision Framework

Here's the decision process I'd use, biased hard against over-engineering chunking before it earns the complexity:

Start with recursive splitting at 512 tokens, 50 token overlap. This handles 80% of use cases without tuning. Measure your retrieval precision@5 on a test set of real queries before changing anything.

Upgrade to semantic chunking only if:

  • Your corpus mixes multiple topics per document
  • Recursive splitting produces chunks that fragment key explanations
  • You have the latency budget for double-embedding during ingestion

Consider document-aware chunking when:

  • Your documents have rich structure (headers, tables, nested lists)
  • Users ask questions that target specific sections
  • You need metadata filtering in retrieval

The evaluation metrics that actually matter: retrieval precision@k (are the top k chunks relevant?), answer faithfulness (does the LLM's answer match the retrieved context?), and p95 latency (how long do users wait?). If you're not measuring these, you're guessing.

The common mistakes worth checking for first:

  • Over-engineering chunking before validating that retrieval is actually the bottleneck
  • Ignoring overlap entirely, then wondering why context gets fragmented at boundaries
  • Using 1,024-token chunks with a 512-token embedding model (silent truncation)

Hugging Face Implementation: Putting It All Together

Here's a production-ready chunking pipeline using HF tokenizers and sentence-transformers. This combines recursive splitting with token-accurate counting and embedding generation:

from transformers import AutoTokenizer
from sentence_transformers import SentenceTransformer
from langchain.text_splitter import RecursiveCharacterTextSplitter

# Match tokenizer to your embedding model
tokenizer = AutoTokenizer.from_pretrained('sentence-transformers/all-mpnet-base-v2')
embed_model = SentenceTransformer('all-mpnet-base-v2')

def token_length(text: str) -> int:
    return len(tokenizer.encode(text, add_special_tokens=False))

splitter = RecursiveCharacterTextSplitter(
    chunk_size=450,  # Leave headroom for special tokens
    chunk_overlap=50,
    length_function=token_length,
    separators=["\n\n", "\n", ". ", " ", ""]
)

chunks = splitter.split_text(document)
embeddings = embed_model.encode(chunks, batch_size=32, show_progress_bar=True)

For production, batch your embedding calls, cache results aggressively, and monitor your chunk size distribution. A histogram of chunk lengths catches configuration errors fast - if you see spikes at your max length, you're truncating.

Pipeline showing Hugging Face RAG chunking: recursive splitting, token accurate counting, embedding generation, and storage in a vector database.
The production chunking pipeline

To benchmark strategies on your own corpus, create a test set of 50-100 query-answer pairs where you know which source chunks should be retrieved. Run each strategy, measure precision@5, and let the numbers decide. The strategy that retrieves the right chunks most often wins - regardless of what any guide (including this one) recommends.

For related optimization work, consider how your embedding model's attention mechanism affects chunk understanding - Flash Attention stability matters if you're running inference at scale. And if you're evaluating whether newer architectures might change chunking requirements, the comparison of state space models versus transformers covers the context window implications.

FAQ

What is chunking in RAG?

Chunking is the process of splitting source documents into smaller segments before embedding them for retrieval. These chunks become the atomic units your RAG system searches - when a user query arrives, the retriever finds relevant chunks, and those chunks provide context for the LLM's response. How you chunk directly determines what your system can retrieve.

What is the best chunking strategy for RAG?

Start with recursive character splitting at 512 tokens with 50-token overlap - this handles most use cases without tuning. Upgrade to semantic chunking only if your corpus mixes multiple topics per document and you have latency budget for the extra embedding pass. The best strategy is whichever produces the highest retrieval precision on your actual queries.

What is the optimal chunking size for RAG?

The 256-512 token range works best for most embedding models, aligning with their training data and practitioner consensus. Adjust based on document type: legal documents benefit from 768-1024 tokens, code works better at 256-384, and conversational content often needs only 128-256. Always stay below your embedding model's maximum sequence length to avoid silent truncation.

What is the chunking method in RAGFlow?

RAGFlow uses document-aware chunking that parses document structure - headers, tables, lists, and formatting - to create semantically meaningful segments. Rather than splitting on character counts or text patterns alone, it respects the author's organization and preserves logical units. This approach works particularly well for structured documents like technical manuals and reports.

Further Reading

  1. Token Weighting for Long-Range Language Modeling - Falko Helm, Nico Daheim, Iryna Gurevych (2025)
  2. Reconstructing Context: Evaluating Advanced Chunking Strategies for Retrieval-Augmented Generation - Carlo Merola, Jaspinder Singh (2025)

Keep reading

Illustration of ragflow chunking methods: A long wooden plank of text stretches across the frame; on the left a paperRagflow Chunking Methods

8 min read

RAGFlow Chunking Methods for Document Parser Selection

Learn RAGFlow chunking methods by file type, configure parser and chunk size settings, and test retrieval quality for PDFs, tables, and documents.

You swap RAGFlow's default parser for the "Book" template, re-ingest your PDFs, and watch retrieval scores drop. The chunks look cleaner, but answers got worse. Your retriever needed table rows and surrounding context intact, and the new parser split them apart. Choosing the right ragflow chunking methods starts with what your retriever needs to find, not what produces the tidiest…

Read more

Illustration of reranking vector search: A wide conveyor belt spans the frame carrying a loose cluster of fish; midway, aReranking Vector Search

11 min read

Reranking Vector Search: How Rerankers Improve RAG

Learn how reranking vector search rescoring improves RAG relevance, where rerankers fit, and how to balance retrieval accuracy, latency, and cost.

A RAG pipeline can look completely healthy and still return the wrong context. The retrieved chunks read fine individually, cosine similarity scores sit in a tight, healthy band, and the answers the LLM produces still ignore the one paragraph that actually contains the fix for the bug being chased. The instinct is to blame the embedding model, and that is…

Read more

Illustration of is rag still relevant: A wide library-card-catalog cabinet on the left connects via a curved rail to an openRAG vs Long Context

10 min read

Is RAG Still Relevant in 2026? When to Use or Replace It

Is RAG still relevant in 2026? Discover where retrieval wins, when long context or agentic search is better, and how to choose for production AI.

Teams rip out working RAG pipelines and replace them with a single long-context call, expecting to be free of chunking headaches and vector store bills. A common outcome is putting it back weeks later, after the long-context model invents a compliance clause that appears in none of the source documents and nobody catches it until a customer does. That's the…

Read more

All posts