<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community</title>
    <description>The most recent home feed on DEV Community.</description>
    <link>https://dev.to</link>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed"/>
    <language>en</language>
    <item>
      <title>Choosing the Right RAG Strategy A Complete Decision Guide to Chunking, Agentic RAG, and GraphRAG</title>
      <dc:creator>Seenivasa Ramadurai</dc:creator>
      <pubDate>Wed, 20 May 2026 21:37:54 +0000</pubDate>
      <link>https://dev.to/sreeni5018/choosing-the-right-rag-strategy-a-complete-decision-guide-to-chunking-agentic-rag-and-graphrag-386d</link>
      <guid>https://dev.to/sreeni5018/choosing-the-right-rag-strategy-a-complete-decision-guide-to-chunking-agentic-rag-and-graphrag-386d</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Here is a scenario many RAG builders know well,&lt;/strong&gt; you wire up a pipeline, load your documents, ask a question and the answer is wrong, vague, or &lt;strong&gt;confidently&lt;/strong&gt; &lt;strong&gt;hallucinated&lt;/strong&gt;. The information was right there in your knowledge base. So what went wrong?&lt;/p&gt;

&lt;p&gt;In most cases the &lt;strong&gt;problem is not your embedding model&lt;/strong&gt;. It is not your &lt;strong&gt;LLM&lt;/strong&gt;. It is how you &lt;strong&gt;cut up your documents before storing them the under appreciated craft called chunking&lt;/strong&gt; and whether the retrieval architecture you chose actually matches the complexity of your queries.&lt;/p&gt;

&lt;p&gt;This blog walks you through every major &lt;strong&gt;chunking strategy&lt;/strong&gt;, explains how &lt;strong&gt;retrieval&lt;/strong&gt; and &lt;strong&gt;augmentation&lt;/strong&gt; work on top of those chunks, covers two advanced architectures &lt;strong&gt;Agentic RAG&lt;/strong&gt; and &lt;strong&gt;GraphRAG&lt;/strong&gt; and most importantly gives you a complete decision framework so you can walk away knowing exactly which combination fits your use case.&lt;/p&gt;

&lt;h1&gt;
  
  
  🐘  The Elephant &amp;amp; The LEGO Pieces
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3o3ig9kxtz8pbllt882.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3o3ig9kxtz8pbllt882.png" alt=" " width="799" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your document is an elephant.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;200+ pages&lt;/strong&gt; of &lt;strong&gt;legal contract&lt;/strong&gt;, a dense &lt;strong&gt;research paper&lt;/strong&gt;, a &lt;strong&gt;massive product manual&lt;/strong&gt;, or years of enterprise knowledge large, complex, interconnected, and full of valuable information.&lt;/p&gt;

&lt;p&gt;A Large Language Model cannot effectively consume the entire elephant at once because of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Context window limitations&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Retrieval precision constraints&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Latency considerations&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Token cost optimization&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context dilution and retrieval noise&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;So the elephant must be divided into smaller pieces.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But this is where most RAG systems fail.&lt;/p&gt;

&lt;p&gt;If you &lt;strong&gt;cut&lt;/strong&gt; the elephant &lt;strong&gt;randomly&lt;/strong&gt;, you &lt;strong&gt;destroy meaning&lt;/strong&gt;.&lt;br&gt;
Sentences &lt;strong&gt;lose context&lt;/strong&gt;. Ideas become &lt;strong&gt;fragmented&lt;/strong&gt;. &lt;strong&gt;Relationships disappear&lt;/strong&gt;. &lt;strong&gt;Retrieval&lt;/strong&gt; quality collapses.&lt;/p&gt;

&lt;p&gt;Good chunking is not about making text smaller.&lt;br&gt;
It is about &lt;strong&gt;preserving meaning while making retrieval efficient&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That is why chunking is better understood as turning the elephant into LEGO pieces.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LEGO pieces are:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modular&lt;/strong&gt; — each piece can stand on its own&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured&lt;/strong&gt; — pieces connect cleanly to related pieces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent&lt;/strong&gt; — standardized enough for reliable retrieval&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Meaningful&lt;/strong&gt; — each piece preserves semantic value&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composable&lt;/strong&gt; — you assemble only the pieces needed for the task&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good chunking works the same way.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;well designed chunk&lt;/strong&gt; should preserve &lt;strong&gt;structure&lt;/strong&gt;, &lt;strong&gt;semantics&lt;/strong&gt;, &lt;strong&gt;relationships&lt;/strong&gt;, and &lt;strong&gt;surrounding&lt;/strong&gt; context while remaining small enough for efficient retrieval and generation.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;real goal of chunking in RAG systems is&lt;/strong&gt; not simply splitting documents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chunking is not simply about making documents smaller.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The actual goals are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Preserve&lt;/strong&gt; semantic meaning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improve&lt;/strong&gt; &lt;strong&gt;retrieval&lt;/strong&gt; precision&lt;/li&gt;
&lt;li&gt;Reduce hallucinations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimize&lt;/strong&gt; &lt;strong&gt;context&lt;/strong&gt; windows&lt;/li&gt;
&lt;li&gt;Improve grounding quality&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Balance latency and cost&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In practice:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better chunks lead to better retrieval, better prompts, and better answers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal is to retrieve:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the right piece,&lt;/li&gt;
&lt;li&gt;with the right context,&lt;/li&gt;
&lt;li&gt;from the right section,&lt;/li&gt;
&lt;li&gt;at the right time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the foundation of effective &lt;strong&gt;Retrieval Augmented Generation (RAG).&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  The RAG Pipeline:End to End
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwjdfbfdgt3sz7e5560uc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwjdfbfdgt3sz7e5560uc.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every RAG system regardless of complexity follows the same four stage flow.&lt;/strong&gt; Understanding each stage makes chunking and architecture decisions obvious rather than arbitrary.&lt;/p&gt;
&lt;h3&gt;
  
  
  Stage 1: Document
&lt;/h3&gt;

&lt;p&gt;Your raw source material: PDFs, Word files, web pages, transcripts, database exports. Too large to pass directly to an LLM. &lt;strong&gt;Needs to be broken into chunks before it can be indexed or searched.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Stage 2: Chunking and Embedding
&lt;/h3&gt;

&lt;p&gt;Documents are cut into units and each unit is &lt;strong&gt;converted into a vector embedding a numerical representation of its meaning.&lt;/strong&gt; These embeddings are stored in a &lt;strong&gt;vector database and form your searchable index.&lt;/strong&gt; Your chunking strategy here determines everything that follows.&lt;/p&gt;
&lt;h3&gt;
  
  
  Stage 3: Retrieval
&lt;/h3&gt;

&lt;p&gt;When a user asks a question, &lt;strong&gt;the query is also embedded.&lt;/strong&gt; The vector database returns the chunks &lt;strong&gt;whose embeddings are closest in meaning to the query. These are your retrieved LEGO pieces.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Stage 4: Augmentation and Generation
&lt;/h3&gt;

&lt;p&gt;The retrieved chunks along with surrounding parent &lt;strong&gt;context&lt;/strong&gt; are assembled into a &lt;strong&gt;prompt&lt;/strong&gt; and sent to the LLM. &lt;strong&gt;The model generates an accurate, grounded answer from the material it receives.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core insight:&lt;/strong&gt; The quality of your answer is bounded by retrieval quality, which is bounded by chunk quality. Better chunks → better retrieval → better answers. Every architectural decision downstream is built on this foundation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fspfkxyl7y1k8zcm2fahu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fspfkxyl7y1k8zcm2fahu.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Fixed-Size Chunking
&lt;/h2&gt;

&lt;p&gt;The simplest and most widely used strategy. Documents are split into equal sized blocks by token count, character count, or word count without regard for meaning, sentence boundaries, or document structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangChain Methods&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;CharacterTextSplitter:&lt;/strong&gt;  splits on a single separator (default \n\n), then enforces chunk_size by character count.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TokenTextSplitter:&lt;/strong&gt; splits by token count using a tokenizer (e.g. tiktoken for OpenAI models); more accurate for LLM context budgets than character based splitting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.text_splitter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TokenTextSplitter&lt;/span&gt;


&lt;span class="c1"&gt;# Character-based
&lt;/span&gt;&lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;# max characters per chunk
&lt;/span&gt;    &lt;span class="n"&gt;chunk_overlap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# characters repeated at chunk boundaries
&lt;/span&gt;    &lt;span class="n"&gt;separator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Token-based
&lt;/span&gt;&lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TokenTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# max tokens per chunk
&lt;/span&gt;    &lt;span class="n"&gt;chunk_overlap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="c1"&gt;# tokens repeated at chunk boundaries
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Overlap guidance:&lt;/strong&gt; A 10–20% overlap is typical. For chunk_size=1000, set chunk_overlap between 100–200. Overlap reduces the risk of a relevant answer being split across two chunks, at the cost of minor redundancy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; Simple to implement, fast, predictable, easy to scale.&lt;br&gt;
&lt;strong&gt;Weaknesses:&lt;/strong&gt; Frequently breaks sentences mid-way, degrading semantic continuity and retrieval quality on complex documents.&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Logs, telemetry, JSON, CSV, and other uniform structured content.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Recursive Chunking
&lt;/h2&gt;

&lt;p&gt;Rather than splitting blindly, recursive chunking respects natural document structure. It works down a priority list of separators — \n\n, then \n, then . / ! / ?, then spaces — only moving to a finer separator when a chunk still exceeds the size limit.&lt;br&gt;
This is the recommended default strategy in LangChain for most document types.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangChain Methods&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;RecursiveCharacterTextSplitter:&lt;/strong&gt; The primary implementation; tries each separator in the list before falling back to the next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RecursiveCharacterTextSplitter.from_language():&lt;/strong&gt; pre-configured separator lists for specific programming languages (Python, JS, Markdown, HTML, etc.).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.text_splitter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Language&lt;/span&gt;

&lt;span class="c1"&gt;# General prose
&lt;/span&gt;&lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;chunk_overlap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;separators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Language-aware (e.g. Python source code)
&lt;/span&gt;&lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_language&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Language&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PYTHON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;chunk_overlap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Overlap guidance:&lt;/strong&gt; 10–15% overlap works well for most prose. For code, keep overlap low (50–100 tokens) to avoid duplicating function signatures across chunks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; Better semantic retention than fixed size chunking; good general-purpose strategy; improves retrieval coherence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weaknesses:&lt;/strong&gt; Structure aware rather than meaning aware; performance depends on document formatting quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Documentation, PDFs, articles, knowledge bases, and web pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Semantic Chunking
&lt;/h2&gt;

&lt;p&gt;Instead of asking how large should the chunk be, semantic chunking asks which sentences belong together.&lt;br&gt;
Sentences are converted into vector embeddings, similarity is measured between adjacent sentences, and chunk boundaries are drawn where similarity drops below a threshold — indicating a topic transition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangChain Methods&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SemanticChunker (from langchain_experimental) — supports three breakpoint detection strategies: percentile, standard_deviation, and interquartile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_experimental.text_splitter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SemanticChunker&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAIEmbeddings&lt;/span&gt;

&lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SemanticChunker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;OpenAIEmbeddings&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;breakpoint_threshold_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;percentile&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# or "standard_deviation", "interquartile"
&lt;/span&gt;    &lt;span class="n"&gt;breakpoint_threshold_amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;95&lt;/span&gt;           &lt;span class="c1"&gt;# top 5% of similarity drops become boundaries
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Overlap guidance:&lt;/strong&gt; Semantic chunking does not use a fixed &lt;strong&gt;chunk_overlap&lt;/strong&gt; boundaries are drawn on meaning, so overlapping would undermine the approach. If continuity is needed at boundaries, consider appending the last sentence of the previous chunk manually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; High retrieval relevance; strong semantic continuity; well-suited to precision-sensitive systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weaknesses:&lt;/strong&gt; Computationally expensive; requires an embedding model at chunking time; similarity thresholds need tuning per dataset.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Enterprise knowledge systems, research platforms, policy documents, and AI assistants requiring contextual precision.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Hierarchical Chunking
&lt;/h2&gt;

&lt;p&gt;Creates two levels of chunks: large parent chunks for context, and smaller child chunks for precision.&lt;/p&gt;

&lt;p&gt;Retrieval targets the child level to find relevant passages, then expands to the parent level to return surrounding context. This directly addresses the core RAG trade off: small chunks improve precision, large chunks preserve context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangChain Methods&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ParentDocumentRetriever:&lt;/strong&gt;  stores parent chunks in a document store and child chunks in a vector store, then links them at retrieval time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.retrievers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ParentDocumentRetriever&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.text_splitter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.storage&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;InMemoryStore&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_community.vectorstores&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Chroma&lt;/span&gt;

&lt;span class="n"&gt;parent_splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# large context chunks
&lt;/span&gt;&lt;span class="n"&gt;child_splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# precise retrieval chunks
&lt;/span&gt;
&lt;span class="n"&gt;retriever&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ParentDocumentRetriever&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;vectorstore&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Chroma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embedding_function&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;docstore&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;InMemoryStore&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;child_splitter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;child_splitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;parent_splitter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;parent_splitter&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Overlap guidance:&lt;/strong&gt; Apply overlap only on the child splitter (typically 10–15%). Parent chunks are retrieved wholesale for context, so overlap there adds noise rather than value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; Strong retrieval precision without sacrificing context; effective for long documents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weaknesses:&lt;/strong&gt; More complex to index and retrieve; requires additional storage and orchestration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Legal documents, technical manuals, books, enterprise documentation, and compliance systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Structure and Metadata Aware Chunking
&lt;/h2&gt;

&lt;p&gt;Uses the document's own structure &lt;strong&gt;titles&lt;/strong&gt;, &lt;strong&gt;headers&lt;/strong&gt;, &lt;strong&gt;sections&lt;/strong&gt;, &lt;strong&gt;tables&lt;/strong&gt;, and page layout as natural chunk boundaries rather than treating the document as plain text.&lt;br&gt;
Especially important for enterprise PDFs and structured reports, where layout carries semantic meaning that arbitrary splits would destroy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangChain Methods&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MarkdownHeaderTextSplitter:&lt;/strong&gt; splits on Markdown heading levels and attaches header text as metadata to each chunk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTMLHeaderTextSplitter:&lt;/strong&gt; same pattern for HTML documents, splitting on &lt;strong&gt;&lt;code&gt;'&amp;lt;h1&amp;gt;-&amp;lt;h4&amp;gt;'&lt;/code&gt;&lt;/strong&gt; tags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.text_splitter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MarkdownHeaderTextSplitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HTMLHeaderTextSplitter&lt;/span&gt;

&lt;span class="c1"&gt;# Markdown
&lt;/span&gt;&lt;span class="n"&gt;md_splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MarkdownHeaderTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;headers_to_split_on&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;##&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;###&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;md_splitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;markdown_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Each chunk carries metadata: {"h1": "Section Title", "h2": "Subsection"}
&lt;/span&gt;
&lt;span class="c1"&gt;# HTML
&lt;/span&gt;&lt;span class="n"&gt;html_splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HTMLHeaderTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;headers_to_split_on&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Overlap guidance:&lt;/strong&gt; These splitters produce structurally bounded chunks rather than size bounded ones. If downstream chunks are still too large, pipe the output into a RecursiveCharacterTextSplitter with a modest overlap (100–150 characters) as a second pass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; Preserves layout semantics; keeps tables intact; improves retrieval quality for structured enterprise documents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weaknesses:&lt;/strong&gt; Requires a capable document parser; parser quality directly limits performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Financial reports, compliance documents, technical PDFs, medical documentation, and enterprise records.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Hybrid Chunking
&lt;/h2&gt;

&lt;p&gt;Applies different chunking strategies based on content type within the same corpus fixed-size for logs, recursive for documentation, semantic for research papers, structure aware for Markdown or HTML.&lt;br&gt;
LangChain does not have a dedicated hybrid splitter. Hybrid pipelines are composed manually using the building blocks above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.text_splitter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;TokenTextSplitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;MarkdownHeaderTextSplitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_experimental.text_splitter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SemanticChunker&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hybrid_chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;content_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;content_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;log&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;TokenTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_overlap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split_documents&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;content_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;markdown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;MarkdownHeaderTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;headers_to_split_on&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;##&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;content_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;SemanticChunker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;breakpoint_threshold_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;percentile&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split_documents&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_overlap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split_documents&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overlap guidance: Set overlap per strategy based on content type. Logs and structured data: zero or minimal overlap. Prose and documentation: 10–15%. Code: 5–10%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; Flexible and adaptable; better performance across mixed-content corpora.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weaknesses:&lt;/strong&gt; Higher engineering complexity; harder to evaluate and tune consistently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Enterprise AI platforms, large mixed content corpora, knowledge management systems, and multi source RAG pipelines.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Agentic Chunking
&lt;/h2&gt;

&lt;p&gt;An emerging approach where an LLM dynamically determines what information belongs together, how chunks should be formed, and how retrieval should adapt to user intent. This transforms chunking from static preprocessing into query aware reasoning at inference time.&lt;br&gt;
LangChain supports this through its agent and chain abstractions rather than a dedicated splitter class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.chains&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LLMChain&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.prompts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PromptTemplate&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PromptTemplate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
You are a document analyst. Split the following text into coherent topical sections.
Return ONLY a JSON list of objects, each with a &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; and &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; key.

Text:
{text}
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LLMChain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;agentic_chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Overlap guidance:&lt;/strong&gt; Not applicable in the traditional sense the LLM determines boundaries based on meaning. To preserve continuity between sections, include a brief summary of the prior section in the prompt context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; Highly adaptive; strong semantic preservation; query aware retrieval.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weaknesses:&lt;/strong&gt; Higher compute cost and latency; requires orchestration and guardrails; not yet widely proven in production at scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; AI copilots, multi-agent systems, research assistants, and enterprise reasoning workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Agentic RAG
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Not to be confused with Agentic Chunking (#7).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agentic Chunking is about how documents are split at index time. Agentic RAG is about how an LLM decides what to retrieve at query time and whether what it found is good enough to answer with.&lt;/p&gt;

&lt;p&gt;Standard RAG pipelines are static: a query comes in, a fixed retrieval step runs, the &lt;strong&gt;top-k chunks&lt;/strong&gt; are passed to the LLM, and an answer comes out. Agentic RAG breaks that linearity. An LLM agent decides when to retrieve, what to search for, whether the results are sufficient, and whether to &lt;strong&gt;re-query&lt;/strong&gt; with a refined question before generating an answer.&lt;/p&gt;

&lt;p&gt;Common patterns built on this idea include &lt;strong&gt;Corrective RAG (CRAG&lt;/strong&gt;)  which scores retrieved documents for relevance and falls back to a web search if they are poor and &lt;strong&gt;Self-RAG&lt;/strong&gt;, where the LLM reflects on its own output and decides whether it needs to retrieve again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangChain Methods&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;create_retriever_tool&lt;/strong&gt;  wraps any retriever as a tool an agent can call on demand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AgentExecutor&lt;/strong&gt; the classic LangChain agent loop; the agent decides which tools to call and when.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangGraph&lt;/strong&gt; — the recommended approach for production Agentic RAG; models retrieval as a stateful graph of nodes (retrieve → grade → rewrite → retrieve again) with explicit conditional edges.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.tools.retriever&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_retriever_tool&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.messages&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseMessage&lt;/span&gt;

&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Wrap retriever as a tool
&lt;/span&gt;&lt;span class="n"&gt;retriever_tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_retriever_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;retriever&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_retriever&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_kwargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;k&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Search the knowledge base for relevant information.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# --- LangGraph: Corrective RAG pattern ---
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;generation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;rewrite_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;similarity_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;grade_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# LLM scores each doc for relevance; filters out poor ones
&lt;/span&gt;    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Is this document relevant to the question &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;? Answer yes or no.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;{{doc}}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;relevant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_content&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;relevant&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rewrite_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# If docs were poor, rewrite the question before re-retrieving
&lt;/span&gt;    &lt;span class="n"&gt;rewritten&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rewrite this question to improve retrieval: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rewritten&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rewrite_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rewrite_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_content&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Answer using this context:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;Question: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;should_rewrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rewrite_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rewrite&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Build the graph
&lt;/span&gt;&lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retrieve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grade&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grade_documents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rewrite&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rewrite_query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_entry_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retrieve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retrieve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grade&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_conditional_edges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grade&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;should_rewrite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rewrite&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rewrite&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rewrite&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retrieve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What are the risks of GraphRAG?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rewrite_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overlap guidance: Overlap is set on the underlying retriever's chunking strategy — not on the agent itself. The agent layer operates above chunking. Use whatever overlap matches the chunking strategy feeding the vector store (typically 10–15% for recursive or fixed-size chunks).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; Handles multi-step and ambiguous queries that single-pass retrieval fails on; self-corrects when initial retrieval is poor; can combine multiple retrieval sources (vector DB, web search, SQL) in one query cycle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weaknesses:&lt;/strong&gt; Higher latency per query due to multiple LLM calls; harder to debug than a linear pipeline; requires careful graph design to avoid infinite retrieval loops.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Complex Q&amp;amp;A systems, enterprise copilots where queries are open-ended, research assistants, and any pipeline where retrieval quality is highly variable.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. GraphRAG
&lt;/h2&gt;

&lt;p&gt;GraphRAG, originally developed by Microsoft Research, moves beyond treating documents as flat text sequences. Instead of chunking text into linear passages, it extracts entities and relationships from documents and stores them as a knowledge graph. Retrieval then traverses the graph to answer questions that require connecting information across multiple sources or document sections — something vector search alone handles poorly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are two primary retrieval modes:&lt;/strong&gt; &lt;strong&gt;local search&lt;/strong&gt;, which answers specific entity-level questions by traversing nearby graph nodes, and &lt;strong&gt;global search&lt;/strong&gt;, which synthesizes themes across the entire corpus using community summaries generated at indexing time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangChain Methods&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LangChain integrates with graph databases (Neo4j, Amazon Neptune, ArangoDB) and provides tooling to build graph-based RAG pipelines.&lt;br&gt;
LLMGraphTransformer uses an LLM to extract entities and relationships from text and convert them into graph documents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Neo4jGraph + GraphCypherQAChain&lt;/strong&gt; store the graph in Neo4j and query it in natural language via generated Cypher queries.&lt;br&gt;
Neo4jVector — hybrid approach that combines vector similarity search with graph traversal on a Neo4j backend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_experimental.graph_transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LLMGraphTransformer&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_community.graphs&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Neo4jGraph&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.chains&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GraphCypherQAChain&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt;

&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Step 1: Extract entities and relationships from chunks
&lt;/span&gt;&lt;span class="n"&gt;transformer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LLMGraphTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph_docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transformer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert_to_graph_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Step 2: Store in Neo4j
&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Neo4jGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bolt://localhost:7687&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;neo4j&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_graph_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_docs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Step 3: Query the graph in natural language
&lt;/span&gt;&lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GraphCypherQAChain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;return_intermediate_steps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Which authors collaborated with researchers at MIT?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;hybrid&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="n"&gt;retrieval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;pythonfrom&lt;/span&gt; &lt;span class="n"&gt;langchain_community&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vectorstores&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Neo4jVector&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAIEmbeddings&lt;/span&gt;

&lt;span class="c1"&gt;# Store chunks as vectors alongside the graph
&lt;/span&gt;&lt;span class="n"&gt;vector_store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Neo4jVector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;OpenAIEmbeddings&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bolt://localhost:7687&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;neo4j&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;index_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;document_chunks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;node_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Chunk&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;embedding_node_property&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;embedding&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;retriever&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_retriever&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_kwargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;k&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Overlap guidance:&lt;/strong&gt; GraphRAG does not rely on chunk overlap for continuity — relationships between entities bridge that gap structurally. When pre-chunking documents before graph extraction, use a RecursiveCharacterTextSplitter with modest overlap (100–150 characters) to ensure entity mentions near chunk boundaries are captured in at least one chunk before the LLM extracts them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; Excels at multi-hop reasoning (e.g. "find all projects involving X that also relate to Y"); surfaces cross-document relationships invisible to vector search; global search enables corpus-wide thematic synthesis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weaknesses:&lt;/strong&gt; Significantly higher indexing cost and complexity; graph quality depends on LLM extraction accuracy; Cypher query generation can be brittle on complex schemas; not well-suited to simple factual lookups where vector search is faster and cheaper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Knowledge graphs, research corpora, compliance and regulatory systems, enterprise wikis with dense cross-references, and any domain where answering questions requires connecting facts across multiple documents.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Trade-Off
&lt;/h2&gt;

&lt;p&gt;A common misconception is that smaller chunks always improve retrieval. In practice, chunks that are too small lose context, fragment meaning, and can increase hallucinations.&lt;/p&gt;

&lt;p&gt;Chunking is a balancing act across four competing factors:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0ncnmwid0pcauix3d6t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0ncnmwid0pcauix3d6t.png" alt=" " width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is no universally optimal strategy. The right choice depends on your data characteristics, query patterns, retrieval architecture, and business requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Reference
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fir6yvwxx78ho10stwsky.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fir6yvwxx78ho10stwsky.png" alt=" " width="800" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The strongest production RAG systems rarely rely on a single chunking strategy. A robust architecture typically combines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Recursive chunking&lt;/strong&gt; for general prose&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic chunking&lt;/strong&gt; for precision-sensitive content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hierarchical retrieval&lt;/strong&gt; for long or dense documents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structure-aware parsing&lt;/strong&gt; for enterprise PDFs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid orchestration&lt;/strong&gt; where content types vary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As enterprise AI matures, retrieval architecture is becoming just as important as model selection. And intelligent retrieval begins with intelligent chunking.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>llm</category>
      <category>rag</category>
    </item>
    <item>
      <title>The Egregious Cost of Compliance: One Platform's Overly Broad Restrictions</title>
      <dc:creator>Faith Sithole</dc:creator>
      <pubDate>Wed, 20 May 2026 21:37:36 +0000</pubDate>
      <link>https://dev.to/interface-profit/the-egregious-cost-of-compliance-one-platforms-overly-broad-restrictions-5g2g</link>
      <guid>https://dev.to/interface-profit/the-egregious-cost-of-compliance-one-platforms-overly-broad-restrictions-5g2g</guid>
      <description>&lt;h2&gt;
  
  
  The Problem We Were Actually Solving
&lt;/h2&gt;

&lt;p&gt;We were actually trying to solve the classic problem of onboarding new creators. We believed that by supporting PayPal and Stripe, we'd open the door for more users. In our minds, the added security and flexibility these payment processors offered would be a huge win for our platform. But what we failed to consider was the fine print – or rather, the broad brushstrokes those payment processors use to restrict access.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Tried First (And Why It Failed)
&lt;/h2&gt;

&lt;p&gt;We initially tried to get around these restrictions by manually adding creators' countries as exceptions. This approach didn't work for several reasons. Firstly, it was a manual, error-prone process that didn't scale. Secondly, the payment processors have an ever-changing list of restricted countries, making it difficult to stay up-to-date. Lastly, this approach compromised our platform's core principle of automating onboarding to make it easier for creators to start selling.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture Decision
&lt;/h2&gt;

&lt;p&gt;In hindsight, our architecture decision was flawed. We prioritized integrating with well-known payment processors over addressing the underlying issue – the restrictions themselves. By not scrutinizing these restrictions, we inadvertently created a bottleneck in our onboarding process. This decision not only frustrated our creators but also exposed our platform to supply chain risks we'd rather not have.&lt;/p&gt;

&lt;h2&gt;
  
  
  What The Numbers Said After
&lt;/h2&gt;

&lt;p&gt;We analyzed our onboarding data for a three-month period and found a stark contrast between the countries we restricted (and subsequently allowed) vs. those we didn't. Specifically, for a country like Nigeria, which has a significant number of digital creators, we saw a 40% reduction in successful onboarding due to PayPal's restrictions. When we finally switched to a more Africa-friendly payment processor, our success rate shot up by 65%.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Would Do Differently
&lt;/h2&gt;

&lt;p&gt;In retrospect, we should have taken a different approach from the very beginning. We should have scrutinized the payment processors we chose, weighing their benefits against the restrictions they imposed. We should have also considered open-source alternatives that focus on inclusivity, such as Stripe's own competitor, Mollie, which has a more relaxed approach to country restrictions. Had we done so, we might have avoided the costly delays, reputational damage, and missed opportunities that ultimately came with trying to work around these restrictions.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>security</category>
      <category>appsec</category>
    </item>
    <item>
      <title>GitHub Breach via VSCode Extension, ZTE Router CVE-2026-34472, &amp; Public Repo Secrets Leaks</title>
      <dc:creator>soy</dc:creator>
      <pubDate>Wed, 20 May 2026 21:36:39 +0000</pubDate>
      <link>https://dev.to/soytuber/github-breach-via-vscode-extension-zte-router-cve-2026-34472-public-repo-secrets-leaks-14c4</link>
      <guid>https://dev.to/soytuber/github-breach-via-vscode-extension-zte-router-cve-2026-34472-public-repo-secrets-leaks-14c4</guid>
      <description>&lt;h2&gt;
  
  
  GitHub Breach via VSCode Extension, ZTE Router CVE-2026-34472, &amp;amp; Public Repo Secrets Leaks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Today's Highlights
&lt;/h3&gt;

&lt;p&gt;Today's security news highlights a significant GitHub internal breach traced to a compromised VSCode extension, underscoring supply chain risks. Additionally, a new CVE affects ZTE routers with pre-auth credential exposure, alongside a prominent example of critical secrets exposed in public GitHub repositories.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub hit by a compromised VSCode extension (r/netsec)
&lt;/h2&gt;

&lt;p&gt;Source: &lt;a href="https://reddit.com/r/netsec/comments/1tiiyxq/github_hit_by_a_compromised_vscode_extension/" rel="noopener noreferrer"&gt;https://reddit.com/r/netsec/comments/1tiiyxq/github_hit_by_a_compromised_vscode_extension/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tech community is abuzz with news of a significant internal breach at GitHub, reportedly stemming from a compromised VSCode extension. This incident allowed unauthorized access to GitHub's internal repositories, showcasing a critical vulnerability in the software supply chain. Attackers exploited this vector to potentially exfiltrate sensitive data, including an unspecified number of private repositories, although GitHub has stated there's no current evidence of impact to customer information. This marks a concerning development as it targets the very tools developers rely on daily.&lt;/p&gt;

&lt;p&gt;This breach underscores the escalating risks associated with developer tooling, where malicious extensions or compromised components can act as sophisticated entry points into corporate networks. The incident highlights the challenge of securing complex development environments and the need for rigorous vetting of all third-party dependencies, from development libraries to IDE plugins. Such supply chain attacks are increasingly common and bypass traditional perimeter defenses by targeting trusted components. Organizations must adopt a zero-trust mindset towards their development ecosystems to mitigate these evolving threats.&lt;/p&gt;

&lt;p&gt;Comment: Developers must scrutinize VSCode extensions and other third-party tools for potential supply chain risks. This incident reinforces the need for robust endpoint security, strict access controls, and regular audits of integrated development environment (IDE) components to prevent similar breaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  CVE-2026-34472: Pre-auth credential exposure and auth bypass in ZTE H188A V6 routers (r/netsec)
&lt;/h2&gt;

&lt;p&gt;Source: &lt;a href="https://reddit.com/r/netsec/comments/1timb3b/cve202634472_pre2auth_credential_exposure_and_auth/" rel="noopener noreferrer"&gt;https://reddit.com/r/netsec/comments/1timb3b/cve202634472_pre2auth_credential_exposure_and_auth/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A newly disclosed vulnerability, identified as CVE-2026-34472, has been found to impact ZTE H188A V6 routers, presenting a significant security risk through pre-authentication credential exposure and an authentication bypass. Detailed technical analysis indicates that a routing flaw is the core issue, allowing unauthenticated attackers to gain access to sensitive administrative interfaces and functions without requiring prior authentication. This critical flaw, if exploited, could grant full control over the affected router, enabling malicious actors to manipulate its configuration and compromise the network it serves.&lt;/p&gt;

&lt;p&gt;Such a compromise on a network edge device like a home or small business router has severe implications. Attackers could manipulate network settings, redirect internet traffic to malicious sites, launch further attacks on internal networks, or even monitor sensitive communications passing through the device. This vulnerability emphasizes the critical importance of keeping networking hardware patched and regularly monitored, as these devices often represent the first line of defense against external threats and are frequently overlooked in regular security audits, despite their critical role in network security.&lt;/p&gt;

&lt;p&gt;Comment: Users of ZTE H188A V6 routers should immediately check for and apply any available firmware updates to patch CVE-2026-34472. This vulnerability underscores the importance of regularly reviewing and updating network edge devices, as they often serve as critical entry points for attackers.&lt;/p&gt;

&lt;h2&gt;
  
  
  America's top cyber-defense agency left a GitHub repo open with with passwords, keys, tokens – and incredibly obvious filenames (r/cybersecurity)
&lt;/h2&gt;

&lt;p&gt;Source: &lt;a href="https://reddit.com/r/cybersecurity/comments/1ticxu3/americas_top_cyberdefense_agency_left_a_github/" rel="noopener noreferrer"&gt;https://reddit.com/r/cybersecurity/comments/1ticxu3/americas_top_cyberdefense_agency_left_a_github/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a concerning disclosure, a leading US cyber-defense agency was found to have inadvertently exposed critical secrets within a publicly accessible GitHub repository. The leaked data reportedly included passwords, API keys, and authentication tokens, further compounded by the use of 'incredibly obvious filenames' that clearly indicated their sensitive nature. This incident serves as a prominent real-world example of how even highly security-conscious organizations with robust cyber defenses can fall prey to fundamental misconfigurations and lapses in secrets management practices, impacting national security.&lt;/p&gt;

&lt;p&gt;The implications of such an exposure are profound, potentially leading to widespread unauthorized access, compromise of internal systems, and severe data breaches for the affected agency and its partners. This event powerfully highlights that technical prowess in cybersecurity does not negate the need for stringent adherence to basic security hygiene, particularly in managing developer secrets across the software development lifecycle. It underscores the ongoing challenge of enforcing secure coding and deployment practices within large, complex organizations, emphasizing the human element in operational security.&lt;/p&gt;

&lt;p&gt;Comment: This is a critical lesson for all developers and organizations: never store sensitive credentials directly in source code repositories, even private ones, and especially not in public ones. Implement robust secrets management solutions (like HashiCorp Vault, AWS Secrets Manager, Azure Key Vault) and automate credential rotation to mitigate this common and highly dangerous vulnerability.&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>vulnerability</category>
    </item>
    <item>
      <title>Applied AI: From Agent Orchestration to Workflow Automation &amp; Code Generation</title>
      <dc:creator>soy</dc:creator>
      <pubDate>Wed, 20 May 2026 21:36:08 +0000</pubDate>
      <link>https://dev.to/soytuber/applied-ai-from-agent-orchestration-to-workflow-automation-code-generation-7jl</link>
      <guid>https://dev.to/soytuber/applied-ai-from-agent-orchestration-to-workflow-automation-code-generation-7jl</guid>
      <description>&lt;h2&gt;
  
  
  Applied AI: From Agent Orchestration to Workflow Automation &amp;amp; Code Generation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Today's Highlights
&lt;/h3&gt;

&lt;p&gt;This week, we explore the practical applications of AI, from leveraging LLMs for business workflow automation to integrating AI agents into open-source projects. We also discuss the evolving role of AI in professional code generation, highlighting the need for structured approaches in development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source Contribution: Seeking AI Agent &amp;amp; FastAPI Projects (r/Python)
&lt;/h2&gt;

&lt;p&gt;Source: &lt;a href="https://reddit.com/r/Python/comments/1ti9dbd/open_source_contribution/" rel="noopener noreferrer"&gt;https://reddit.com/r/Python/comments/1ti9dbd/open_source_contribution/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A developer is actively seeking open-source projects to contribute to, specifically mentioning AI agents, Python, and FastAPI backends. This highlights a growing demand for and active development in the realm of AI agent orchestration and robust Python tooling for applied AI systems. Projects in this space typically involve orchestrating Large Language Models (LLMs) to perform complex tasks, often requiring integration with external APIs, data sources (potentially RAG frameworks), and user interfaces.&lt;/p&gt;

&lt;p&gt;Such AI agent systems built with Python and FastAPI serve as powerful backends for production-grade AI applications. Developers contribute to components like task planning modules, memory management, tool integration (e.g., for search, data analysis, or code execution), and API endpoints for seamless interaction. This focus on practical, deployable systems using popular Python frameworks is crucial for moving AI research into real-world workflows and production environments. Contributing to these projects offers hands-on experience in building the next generation of intelligent automation tools that can be easily containerized and scaled.&lt;/p&gt;

&lt;p&gt;Comment: This signals a vibrant community building practical AI agent solutions. Diving into such a repo would be a fantastic way to learn about agent design and FastAPI deployment patterns firsthand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Streamlining RV Rental Business with Claude AI for Workflow Automation (r/ClaudeAI)
&lt;/h2&gt;

&lt;p&gt;Source: &lt;a href="https://reddit.com/r/ClaudeAI/comments/1ti9xo5/claude_is_improving_my_rv_rental_business_but/" rel="noopener noreferrer"&gt;https://reddit.com/r/ClaudeAI/comments/1ti9xo5/claude_is_improving_my_rv_rental_business_but/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An RV rental business owner shares an experience of using Claude AI to significantly improve their operations, despite the owner feeling overwhelmed by the resulting workload. This anecdotal account demonstrates a clear applied use case for AI in workflow automation, where an LLM is directly impacting a real-world business process. The AI is likely handling tasks such as customer communication, answering frequently asked questions, managing inquiries, or even assisting with scheduling and booking logistics.&lt;/p&gt;

&lt;p&gt;While the original post doesn't detail specific AI frameworks, this scenario is ripe for structured application using tools from our category focus. For instance, a RAG framework could be employed to allow Claude to query specific rental agreements, maintenance schedules, or localized rules, ensuring accurate and consistent responses. AI agents could be orchestrated to automate follow-up emails, update booking calendars, or flag urgent customer requests. The challenge of feeling 'worked to death' indicates the current ad-hoc integration of AI, underscoring the need for more sophisticated workflow automation and RPA patterns to truly scale and optimize such operations.&lt;/p&gt;

&lt;p&gt;Comment: This is a great example of an LLM enabling tangible business benefits, but it also highlights where proper workflow automation frameworks could alleviate manual overhead and scale the solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing AI-Assisted Code Generation in Professional Developer Workflows (r/ClaudeAI)
&lt;/h2&gt;

&lt;p&gt;Source: &lt;a href="https://reddit.com/r/ClaudeAI/comments/1tis9s6/how_to_address_vibe_coding_at_the_professional/" rel="noopener noreferrer"&gt;https://reddit.com/r/ClaudeAI/comments/1tis9s6/how_to_address_vibe_coding_at_the_professional/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The discussion revolves around the practice of 'vibe coding'—a term used to describe rapid, often improvisational, code generation with the assistance of AI in a professional setting. The user observed a colleague generating substantial code quickly (30 minutes, one shot) using AI without extensive prior planning. This highlights the transformative impact of AI on developer workflows, specifically in the realm of code generation.&lt;/p&gt;

&lt;p&gt;Integrating AI-generated code effectively into production deployment patterns presents both opportunities and challenges. While AI accelerates development, questions arise regarding code quality, maintainability, testing, and compliance with architectural standards. Frameworks and best practices for integrating AI into the software development lifecycle (SDLC) are becoming critical. This includes implementing automated testing for AI-generated code, establishing clear review processes, and potentially leveraging specialized tools that can validate, refactor, or even explain the AI's output to ensure it aligns with project requirements and company standards. Addressing 'vibe coding' professionally means developing structured approaches to harness AI's power while mitigating potential risks to project integrity.&lt;/p&gt;

&lt;p&gt;Comment: AI's impact on code generation is undeniable. The real work now is in building frameworks and processes to ensure this rapid output is robust, testable, and maintainable in professional environments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>automation</category>
    </item>
    <item>
      <title>SQLite Journaling on SMB, TypeGraph for SQL Graphs, Cross-Engine Migrations</title>
      <dc:creator>soy</dc:creator>
      <pubDate>Wed, 20 May 2026 21:35:37 +0000</pubDate>
      <link>https://dev.to/soytuber/sqlite-journaling-on-smb-typegraph-for-sql-graphs-cross-engine-migrations-3elb</link>
      <guid>https://dev.to/soytuber/sqlite-journaling-on-smb-typegraph-for-sql-graphs-cross-engine-migrations-3elb</guid>
      <description>&lt;h2&gt;
  
  
  SQLite Journaling on SMB, TypeGraph for SQL Graphs, Cross-Engine Migrations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Today's Highlights
&lt;/h3&gt;

&lt;p&gt;This week's highlights include advanced SQL techniques for graph queries in PostgreSQL and SQLite, deep dives into SQLite's journaling behavior on network shares, and a strategic framework for cross-database synchronization and migration.&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeGraph: graph queries that compile to a single recursive CTE on Postgres/SQLite (r/PostgreSQL)
&lt;/h2&gt;

&lt;p&gt;Source: &lt;a href="https://reddit.com/r/PostgreSQL/comments/1tiszu2/typegraph_graph_queries_that_compile_to_a_single/" rel="noopener noreferrer"&gt;https://reddit.com/r/PostgreSQL/comments/1tiszu2/typegraph_graph_queries_that_compile_to_a_single/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This insightful discussion highlights &lt;code&gt;TypeGraph&lt;/code&gt;, a method for performing complex graph queries directly within traditional relational databases like PostgreSQL and SQLite. Instead of resorting to specialized graph databases, this approach leverages the power of SQL's recursive Common Table Expressions (CTEs) to model and query relationships. This allows developers to handle intricate data connections, such as inheritance in permissions systems, content relationships, or entities for Retrieval-Augmented Generation (RAG), using their existing SQL database infrastructure.&lt;/p&gt;

&lt;p&gt;The core idea is to translate graph traversals into a single, efficient recursive CTE. This method simplifies data modeling by preserving optionality when the schema is uncertain, and it avoids the overhead and complexity of managing an additional graph database system. For those already deeply invested in the SQLite or PostgreSQL ecosystem, TypeGraph presents a powerful technique to extend the capabilities of their databases without introducing new dependencies, making the existing stack more versatile for various data relationship challenges.&lt;/p&gt;

&lt;p&gt;Comment: This technique is powerful for avoiding specialized graph databases when your data is already in SQL. Mastering recursive CTEs unlocks new ways to model complex relationships directly within SQLite or Postgres, making your existing stack more versatile and efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  SQLite journal files on read-only SMB share — can they be redirected to a local path? (SQLite Forum)
&lt;/h2&gt;

&lt;p&gt;Source: &lt;a href="https://sqlite.org/forum/info/05b54df8420cdb25ebcbe507dcace4dc66dddf017db2594e13c2e1fcae6752c2" rel="noopener noreferrer"&gt;https://sqlite.org/forum/info/05b54df8420cdb25ebcbe507dcace4dc66dddf017db2594e13c2e1fcae6752c2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This forum discussion addresses a critical operational challenge for SQLite deployments: managing journal files, especially when the main database file resides on a read-only network share like SMB. SQLite's default transaction model relies on journal files (or WAL files) to ensure atomicity and durability, typically created alongside the database file. When the main directory is read-only, SQLite cannot create these temporary files, leading to operational failures or unexpected behavior.&lt;/p&gt;

&lt;p&gt;The discussion explores solutions and workarounds for this embedded database pattern, focusing on how to redirect SQLite's temporary files and journal data to a writable local path. Techniques such as using the &lt;code&gt;PRAGMA temp_store_directory&lt;/code&gt; or &lt;code&gt;SQLITE_TEMP_STORE&lt;/code&gt; compile-time options are implicitly or explicitly considered. Understanding how SQLite handles journaling and temporary files is crucial for maintaining data integrity and achieving optimal performance in constrained or shared network environments, offering valuable insights for developers deploying SQLite in complex system architectures.&lt;/p&gt;

&lt;p&gt;Comment: Anyone deploying SQLite in less-than-ideal network environments, particularly with shared storage, will appreciate this discussion. Understanding SQLite's journaling and temp file handling is crucial for robust and performant embedded applications, especially in read-only scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecting a 3-stage framework for cross-engine DB synchronization and migration. (r/database)
&lt;/h2&gt;

&lt;p&gt;Source: &lt;a href="https://reddit.com/r/Database/comments/1tizn6x/architecting_a_3stage_framework_for_crossengine/" rel="noopener noreferrer"&gt;https://reddit.com/r/Database/comments/1tizn6x/architecting_a_3stage_framework_for_crossengine/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post delves into the complexities of modernizing legacy systems, specifically tackling the persistent headaches associated with database schema evolution and cross-engine synchronization. The author proposes a &lt;code&gt;3-stage framework&lt;/code&gt; designed to streamline this often-fraught process, aiming to reduce friction and improve reliability during significant database changes across disparate systems. The framework likely outlines distinct phases such as discovery, transformation, and application, providing a structured approach to what can otherwise be an chaotic undertaking.&lt;/p&gt;

&lt;p&gt;Such a framework is invaluable for teams dealing with migration strategies and the development of robust data pipeline tools. It offers a blueprint for how to systematically manage changes when moving data between different database engines – for instance, migrating from an older system to PostgreSQL, or synchronizing data with DuckDB or SQLite in a microservices architecture. By formalizing the process, this architectural pattern helps ensure data consistency, minimize downtime, and ultimately achieve a smoother transition when modernizing database infrastructure.&lt;/p&gt;

&lt;p&gt;Comment: This framework provides a methodical approach to tackle the often painful process of schema migration and data synchronization across disparate databases. It’s a great read for data engineers looking to standardize their migration pipelines and reduce operational headaches, especially when dealing with legacy systems.&lt;/p&gt;

</description>
      <category>database</category>
      <category>sql</category>
      <category>sqlite</category>
    </item>
    <item>
      <title>How to Deploy a Virtual Machine in Azure</title>
      <dc:creator>Noble</dc:creator>
      <pubDate>Wed, 20 May 2026 21:35:31 +0000</pubDate>
      <link>https://dev.to/wokoma/steps-to-deploying-a-virtual-machine-in-linux-1ll6</link>
      <guid>https://dev.to/wokoma/steps-to-deploying-a-virtual-machine-in-linux-1ll6</guid>
      <description>&lt;p&gt;A virtual machine is a mini computer inside another computer in the cloud. Now we are deploying this virtual machine in an operating system called Linux. Linux is a free, open sourced operating system family used on computers, servers, smartphones and even supercomputers. Let me give you a hint, the very popular Android is built on the Linux Kernel.&lt;br&gt;
Okay that's enough intro for now, let's get started.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;: Login in to the[(&lt;a href="https://portal.azure.com/#home)" rel="noopener noreferrer"&gt;https://portal.azure.com/#home)&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;: Look up for virtual machine on the search bar just atop and start creating your Linux virtual machine.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F945l0epuqzivggjq1i0y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F945l0epuqzivggjq1i0y.png" alt="linux virtual machine" width="243" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;select the &lt;strong&gt;+create&lt;/strong&gt; icon which enables you to create a new VM&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsg4zqvovriv30leedj32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsg4zqvovriv30leedj32.png" alt="selecting +create" width="397" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;:I am assuming this is your first time creating a Linux virtual machine, it is best to create a new "resource group" as seen in the image below , one might wonder what a resource group is?. A resource group is the container that will be holding the virtual machine, so in layman terms the resource group is just like the "pot" and the Linux virtual machine is what we are cooking inside this pot.&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlf587h1ukg75mzgpv5t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlf587h1ukg75mzgpv5t.png" alt="Resource group creation" width="790" height="427"&gt;&lt;/a&gt;&lt;br&gt;
so you create a new resource group, in my case I create one called "mylinuxvirtualmachinegroup" and I selected it, so create yours and select it.&lt;br&gt;
&lt;strong&gt;Step 4&lt;/strong&gt;: Configuring instance details&lt;br&gt;
       &lt;em&gt;a: create a name for your VM that suits you&lt;/em&gt;&lt;br&gt;
       &lt;em&gt;b: select a location that befits you&lt;/em&gt;&lt;br&gt;
       &lt;em&gt;c: I chose the first option for the zone options, you can use the drop down and choose '&lt;strong&gt;no infrastructure redundancy&lt;/strong&gt;" required if you are on a free trial account. _&lt;br&gt;
      _ d: for security type; I used the Trusted launch virtual machine as this is basic security for Linux VM.&lt;/em&gt;&lt;br&gt;
       &lt;em&gt;e: for Image; Ubuntu is encouraged as that is the operating system Linux works on so everything rhymes.&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2ozyh4lrg1g3ex8gpn2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2ozyh4lrg1g3ex8gpn2.png" alt="Configuring instance details" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5&lt;/strong&gt;: Login method and Network access configuration&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secure Safe Shell SSH Key (More Secure)&lt;/li&gt;
&lt;li&gt;Password (Simpler for first timers)
The choice is yours, personally I would use password as its easier and not so demanding.
Create a username (like azureadmin)
Create a strong password (write it down!)
Public inbound ports: Select Allow selected ports
Select inbound ports: Choose HTTP (80) and SSH (22)
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8d3owtobj8egxzfktldp.png" alt="port selection" width="800" height="593"&gt;
scroll back to the monitoring tab to disable diagnostics after that click review and create
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbafm1y7zeatyrwydv2r.png" alt="disbabling " width="779" height="521"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz07t05lmwcpwzyu8niod.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz07t05lmwcpwzyu8niod.png" alt=" " width="434" height="506"&gt;&lt;/a&gt;&lt;br&gt;
go to Resource to see, learn and understand everything about the Linux VM you just created&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgg5mn7wfsxnwbvqemwb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgg5mn7wfsxnwbvqemwb.png" alt=" " width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6&lt;/strong&gt;:Open the public IP address as shown&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0cebtxx9uvqbr6zwodo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0cebtxx9uvqbr6zwodo.png" alt="Resource" width="799" height="288"&gt;&lt;/a&gt;&lt;br&gt;
then click connect and click check access&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl469om4n7tn5qjp0yf6z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl469om4n7tn5qjp0yf6z.png" alt=" " width="799" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9jyq5xzn91rfm4e6btb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9jyq5xzn91rfm4e6btb.png" alt=" " width="749" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fncynx1osk6q45yjk6bu5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fncynx1osk6q45yjk6bu5.png" width="749" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7&lt;/strong&gt;: Now open Powershell on Windows or Terminal on Mac to connect to Linux with your IP address you just copied in image@9 above&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favyoiqonqn1hpgsyz3f7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favyoiqonqn1hpgsyz3f7.png" alt=" " width="800" height="523"&gt;&lt;/a&gt;&lt;br&gt;
click enter after pasting your IP address&lt;br&gt;
after that a question pops up, are you sure you want to continue connecting? type in YES,&lt;br&gt;
then the next prompt is to type in the password you used for your azure admin access, Linux wont show the normal asterisk ***** for password, don't be restless its working in the background, this is a security measure to protect you, if your password is type correctly, hit enter and you would see the your IP address and port 22&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2j4ajbmqllx7s6ny3u2w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2j4ajbmqllx7s6ny3u2w.png" alt=" " width="800" height="658"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;type in &lt;strong&gt;sudo su&lt;/strong&gt; to run command as root. Becoming a root user makes our commands run smoothly.&lt;br&gt;
next step is to run &lt;strong&gt;apt update&lt;/strong&gt;, (Advanced Package Tool) is a command-line utility for managing software on Debian-based Linux distributions, such as Ubuntu and Linux Mint, Kali Mint, etc. It handles installation, removal, upgrading, and dependency management of .deb packages by automating retrieval from online repositories. It also tells you the status of your Linux Virtual Machine and if everything is running very well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0y5uqw62qwasgft1hwu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0y5uqw62qwasgft1hwu.png" alt=" " width="800" height="407"&gt;&lt;/a&gt;&lt;br&gt;
next install &lt;strong&gt;nginx&lt;/strong&gt; which is a high performance web server software used to host websites, serve web applications, act as reverse proxy, load balance traffic, and improve overall performance and security, &lt;strong&gt;nginx&lt;/strong&gt; is one of the most widely used servers in the world.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fts1puqy2466z4dbc1k5r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fts1puqy2466z4dbc1k5r.png" alt=" " width="800" height="448"&gt;&lt;/a&gt;&lt;br&gt;
when prompted, confirm with a Y&lt;br&gt;
Although optional, you can also install &lt;strong&gt;Vim&lt;/strong&gt; which is a text editor used in Linux and Unix systems which makes your layout more colorful, developers and system administrators use it to edit configuration, write code, manage servers and also modify scripts directly from terminal.&lt;br&gt;
when prompted, confirm with a Y&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Febndly05neai8i0xvesk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Febndly05neai8i0xvesk.png" alt=" " width="799" height="543"&gt;&lt;/a&gt;&lt;br&gt;
Finally copy your IP address in image number 9 above.&lt;br&gt;
load it on your browser and paste.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs5sso8t1a0sc8j0sa02o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs5sso8t1a0sc8j0sa02o.png" alt=" " width="572" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Voila&lt;/strong&gt;, if you see the image above, you did everything correctly.&lt;/p&gt;

&lt;p&gt;This is a beautiful introduction to Linux, the operating system that hosts most tech products you are using everyday like &lt;strong&gt;open AI&lt;/strong&gt;, &lt;strong&gt;LinkedIN&lt;/strong&gt;, &lt;strong&gt;YouTube&lt;/strong&gt; etcetera.&lt;/p&gt;

&lt;p&gt;Mr &lt;strong&gt;LINUX&lt;/strong&gt; says welcome!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>virtualmachine</category>
      <category>cloudnative</category>
      <category>azure</category>
    </item>
    <item>
      <title>Stop Putting dd() Everywhere Debug the Database From the Source Instead</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Wed, 20 May 2026 21:33:32 +0000</pubDate>
      <link>https://dev.to/tahsin000/stop-putting-dd-everywhere-debug-the-database-from-the-source-instead-4n8o</link>
      <guid>https://dev.to/tahsin000/stop-putting-dd-everywhere-debug-the-database-from-the-source-instead-4n8o</guid>
      <description>&lt;p&gt;Every backend developer has done this at some point.&lt;/p&gt;

&lt;p&gt;A request fails.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrsm9ndz7n8osm2hi1wt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrsm9ndz7n8osm2hi1wt.png" alt="diagram" width="800" height="878"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Something is not inserting into the database.&lt;/p&gt;

&lt;p&gt;And suddenly the codebase turns into this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nf"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$campaign&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You add logs in controllers.&lt;/p&gt;

&lt;p&gt;Then services.&lt;/p&gt;

&lt;p&gt;Then repositories.&lt;/p&gt;

&lt;p&gt;Then queue workers.&lt;/p&gt;

&lt;p&gt;Then event listeners.&lt;/p&gt;

&lt;p&gt;And after two hours, you are still confused.&lt;/p&gt;

&lt;p&gt;Because the real problem is not where you are looking.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Day I Realized Controller Debugging Wasn’t Enough
&lt;/h2&gt;

&lt;p&gt;A few months ago, a developer on a team I worked with faced a strange issue.&lt;/p&gt;

&lt;p&gt;A simple form submission was supposed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a user&lt;/li&gt;
&lt;li&gt;assign a campaign&lt;/li&gt;
&lt;li&gt;generate a lead&lt;/li&gt;
&lt;li&gt;push a welcome email into queue&lt;/li&gt;
&lt;li&gt;write an activity log&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pretty normal workflow.&lt;/p&gt;

&lt;p&gt;But randomly, some users were being created without campaign data.&lt;/p&gt;

&lt;p&gt;Sometimes the queue job worked.&lt;/p&gt;

&lt;p&gt;Sometimes it didn’t.&lt;/p&gt;

&lt;p&gt;Sometimes the transaction rolled back silently.&lt;/p&gt;

&lt;p&gt;The first reaction?&lt;/p&gt;

&lt;p&gt;Start adding logs everywhere.&lt;/p&gt;

&lt;p&gt;Inside controllers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Controller hit'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Campaign assigned'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside queue workers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Email queued'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside transactions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;beginTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code became a forest of debugging statements.&lt;/p&gt;

&lt;p&gt;Still no clear answer.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Problem
&lt;/h2&gt;

&lt;p&gt;Here’s what most developers forget:&lt;/p&gt;

&lt;p&gt;No matter how beautiful your architecture is…&lt;/p&gt;

&lt;p&gt;No matter whether you use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Laravel&lt;/li&gt;
&lt;li&gt;Raw PHP&lt;/li&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end of the day, every query goes to one place:&lt;/p&gt;

&lt;p&gt;MySQL.&lt;/p&gt;

&lt;p&gt;Always.&lt;/p&gt;

&lt;p&gt;Your application is just the messenger.&lt;/p&gt;

&lt;p&gt;The database sees everything.&lt;/p&gt;

&lt;p&gt;That realization changes how you debug systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Instead of Guessing, Watch the Database Directly
&lt;/h2&gt;

&lt;p&gt;The moment we enabled MySQL General Query Log, everything became obvious.&lt;/p&gt;

&lt;p&gt;We literally watched the queries execute live.&lt;/p&gt;

&lt;p&gt;One terminal command showed the full story.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/lib/mysql/hostname.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And suddenly we could see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;campaigns&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;ROLLBACK&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last line explained everything.&lt;/p&gt;

&lt;p&gt;The transaction was rolling back because another process locked a table for a few seconds.&lt;/p&gt;

&lt;p&gt;No controller log would have shown the full picture that clearly.&lt;/p&gt;




&lt;h2&gt;
  
  
  This Is Why Framework-Level Debugging Often Fails
&lt;/h2&gt;

&lt;p&gt;Modern applications are no longer simple.&lt;/p&gt;

&lt;p&gt;A single request may involve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;queues&lt;/li&gt;
&lt;li&gt;events&lt;/li&gt;
&lt;li&gt;transactions&lt;/li&gt;
&lt;li&gt;scheduled jobs&lt;/li&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;li&gt;background workers&lt;/li&gt;
&lt;li&gt;third-party APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the time you debug from inside the controller, the actual issue may already be happening somewhere else entirely.&lt;/p&gt;

&lt;p&gt;This is why developers sometimes spend hours debugging “application logic” when the real problem is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a deadlock&lt;/li&gt;
&lt;li&gt;a lock wait&lt;/li&gt;
&lt;li&gt;a slow query&lt;/li&gt;
&lt;li&gt;missing index&lt;/li&gt;
&lt;li&gt;rollback&lt;/li&gt;
&lt;li&gt;transaction conflict&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And MySQL already knows all of this.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Most Useful MySQL Debugging Tools
&lt;/h2&gt;

&lt;p&gt;Honestly, there are four MySQL features every backend developer should know.&lt;/p&gt;

&lt;p&gt;Not just DBAs.&lt;/p&gt;

&lt;p&gt;Actual application developers.&lt;/p&gt;

&lt;p&gt;Because these tools solve real-world production headaches.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. General Query Log See Everything
&lt;/h2&gt;

&lt;p&gt;This is the closest thing to “watching the database think.”&lt;/p&gt;

&lt;p&gt;Enable it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now every query gets logged.&lt;/p&gt;

&lt;p&gt;You can literally submit a form and watch the database flow in real time.&lt;/p&gt;

&lt;p&gt;This becomes incredibly useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one request touches multiple tables&lt;/li&gt;
&lt;li&gt;transactions fail&lt;/li&gt;
&lt;li&gt;duplicate queries happen&lt;/li&gt;
&lt;li&gt;hidden queries execute behind ORM magic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Especially in large Laravel applications where Eloquent sometimes hides too much.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Slow Query Log Find Hidden Performance Problems
&lt;/h2&gt;

&lt;p&gt;This one saves applications.&lt;/p&gt;

&lt;p&gt;Seriously.&lt;/p&gt;

&lt;p&gt;Sometimes developers optimize controllers endlessly while the real problem is one terrible query.&lt;/p&gt;

&lt;p&gt;Enable it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;slow_query_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;long_query_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now MySQL logs anything slower than one second.&lt;/p&gt;

&lt;p&gt;This helps identify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing indexes&lt;/li&gt;
&lt;li&gt;N+1 problems&lt;/li&gt;
&lt;li&gt;huge scans&lt;/li&gt;
&lt;li&gt;inefficient joins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I once saw a dashboard drop from 12 seconds to under 800ms just because a slow query log exposed a missing index.&lt;/p&gt;

&lt;p&gt;The application code itself was completely fine.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. InnoDB Status Understand Deadlocks &amp;amp; Locks
&lt;/h2&gt;

&lt;p&gt;This command feels like magic the first time you use it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;ENGINE&lt;/span&gt; &lt;span class="n"&gt;INNODB&lt;/span&gt; &lt;span class="n"&gt;STATUS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your application ever experiences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hanging requests&lt;/li&gt;
&lt;li&gt;frozen queues&lt;/li&gt;
&lt;li&gt;stuck inserts&lt;/li&gt;
&lt;li&gt;transaction conflicts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This command can immediately reveal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LATEST DETECTED DEADLOCK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LOCK WAIT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And suddenly the mystery disappears.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Audit Tables &amp;amp; Triggers Permanent Visibility
&lt;/h2&gt;

&lt;p&gt;This is where things become enterprise-level.&lt;/p&gt;

&lt;p&gt;Sometimes you need permanent tracking.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;who changed data&lt;/li&gt;
&lt;li&gt;when it changed&lt;/li&gt;
&lt;li&gt;which table changed&lt;/li&gt;
&lt;li&gt;what action happened&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of depending on controller logs forever, you let MySQL automatically track important events.&lt;/p&gt;

&lt;p&gt;Using triggers.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TRIGGER&lt;/span&gt; &lt;span class="n"&gt;users_after_insert&lt;/span&gt;
&lt;span class="k"&gt;AFTER&lt;/span&gt; &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;EACH&lt;/span&gt; &lt;span class="k"&gt;ROW&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;audit_logs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'INSERT'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the database tracks itself.&lt;/p&gt;

&lt;p&gt;Clean.&lt;/p&gt;

&lt;p&gt;Reliable.&lt;/p&gt;

&lt;p&gt;Framework-independent.&lt;/p&gt;




&lt;h2&gt;
  
  
  One Important Thing Most Developers Ignore
&lt;/h2&gt;

&lt;p&gt;Do not leave &lt;code&gt;general_log&lt;/code&gt; permanently enabled in production.&lt;/p&gt;

&lt;p&gt;That is a bad idea.&lt;/p&gt;

&lt;p&gt;Because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;logs become massive&lt;/li&gt;
&lt;li&gt;storage grows quickly&lt;/li&gt;
&lt;li&gt;performance can suffer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The smarter workflow is:&lt;/p&gt;

&lt;h2&gt;
  
  
  Temporary Debugging
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Investigate the issue.&lt;/p&gt;

&lt;p&gt;Then disable it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'OFF'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>mysql</category>
      <category>debugging</category>
      <category>backend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Africa's Digital Ecosystem is Not Dead</title>
      <dc:creator>mary moloyi</dc:creator>
      <pubDate>Wed, 20 May 2026 21:32:42 +0000</pubDate>
      <link>https://dev.to/nomad-revenue/africas-digital-ecosystem-is-not-dead-4hac</link>
      <guid>https://dev.to/nomad-revenue/africas-digital-ecosystem-is-not-dead-4hac</guid>
      <description>&lt;h2&gt;
  
  
  The Problem We Were Actually Solving
&lt;/h2&gt;

&lt;p&gt;We were trying to build a platform that made it easy for African digital creators to sell their courses, ebooks, and music online. But our platform's payment gateways were failing, resulting in frustrated users and lost sales. We thought our problem was with our users, but it turned out that the issue was with the payment providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Tried First (And Why It Failed)
&lt;/h2&gt;

&lt;p&gt;We tried using PayPal's "Borderless Payments" feature, thinking that it would solve our problem. However, we quickly realized that it was not enabled for our users' countries. We then switched to Stripe, hoping that their more robust infrastructure would work. But Stripe's "Risk and Compliance" team flagged our users' transactions as "high-risk," effectively blocking them. We tried to work around this by implementing additional verification checks, but it only made things worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture Decision
&lt;/h2&gt;

&lt;p&gt;After weeks of debugging and trying different approaches, we finally decided to abandon the popular digital service providers and build our own payment processing system using Adyen and Paystack. Adyen's global reach and Paystack's expertise in African payment systems made it possible for us to process transactions from users in over 20 African countries. We also implemented a fallback system that used local payment methods like mobile money and bank transfers, ensuring that our users had a seamless payment experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What The Numbers Said After
&lt;/h2&gt;

&lt;p&gt;After implementing our custom payment processing system, our transaction success rate improved by 80%. Our users were no longer facing payment failures, and our sales increased by 25%. We also saw a significant decrease in support tickets related to payment issues. The numbers were clear: our homegrown solution was working, and it was time to let go of the limitations of the popular digital service providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Would Do Differently
&lt;/h2&gt;

&lt;p&gt;In hindsight, I would have invested more time upfront in researching the limitations of popular digital service providers. I would have also considered using local payment providers from the start, rather than trying to work around their limitations. But I learned a valuable lesson: when it comes to building a platform that serves a specific region or community, you can't rely on generic solutions. You need to build a solution that is tailored to the specific needs of your users, and that requires a deep understanding of the underlying technology and infrastructure.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>devops</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Digital Payments in Africa: A System Designer's Lament</title>
      <dc:creator>pretty ncube</dc:creator>
      <pubDate>Wed, 20 May 2026 21:32:14 +0000</pubDate>
      <link>https://dev.to/built-from-africa/digital-payments-in-africa-a-system-designers-lament-kg9</link>
      <guid>https://dev.to/built-from-africa/digital-payments-in-africa-a-system-designers-lament-kg9</guid>
      <description>&lt;h2&gt;
  
  
  The Problem We Were Actually Solving
&lt;/h2&gt;

&lt;p&gt;Our client pool was largely made up of African creatives trying to monetize their work online. But when we tried to integrate the usual payment processors, we hit a brick wall: no matter what combination of payment flows and API keys we tried, we just couldn't get it to work. The errors were always the same: "payment declined due to regional restrictions" or simply "your account has been flagged for suspicious activity." It was as if we were trying to solve a problem that didn't exist, but clearly did.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Tried First (And Why It Failed)
&lt;/h2&gt;

&lt;p&gt;We started by trying to massage the existing payment flows to work around the region restrictions. We tweaked the API requests, adjusted the currencies, and even tried using different payment gateways (e.g., Paystack for Nigeria, M-Pesa for Kenya). But no matter what we did, we just couldn't get it to work. It wasn't until we started digging deeper into the problem that we realized the issue wasn't with our code or the payment processors – it was with the underlying architecture of the system itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture Decision
&lt;/h2&gt;

&lt;p&gt;We decided to take a step back and rethink the entire payment processing system from the ground up. We opted to use Mollie, a Dutch-based payment processor that specialized in multi-currency transactions and regional-specific payment flows. The decision was based largely on their experience with African markets and their ability to bypass the usual regional restrictions. We also implemented a custom payment flow using the Interchangeable Payment Interface (IPI), a set of APIs that allowed us to swap out different payment processors as needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What The Numbers Said After
&lt;/h2&gt;

&lt;p&gt;After implementing the new payment processing system, we saw a significant decrease in payment errors (from 25% to 5%) and an increase in successful transactions (from 40% to 75%). We also saw a corresponding decrease in support requests related to payment issues (from 30% to 10%). The numbers spoke for themselves: our new system was not only more reliable but also more user-friendly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Would Do Differently
&lt;/h2&gt;

&lt;p&gt;Looking back, I wish we'd taken a more aggressive approach to identifying and mitigating regional restrictions from the outset. We could have saved a significant amount of time and resources by focusing on finding a payment processor that specialized in African markets from the get-go. That being said, the experience taught us a valuable lesson about the importance of system architecture and the need to think beyond the constraints of existing systems. As engineers, we need to be willing to challenge assumptions and explore new solutions – even if it means starting from scratch.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>rust</category>
      <category>performance</category>
    </item>
    <item>
      <title># How to Validate UK VAT Numbers, NINO, Company Numbers and UTR in Any Language (2026)</title>
      <dc:creator>ValidatorAPI</dc:creator>
      <pubDate>Wed, 20 May 2026 21:31:10 +0000</pubDate>
      <link>https://dev.to/night18158/-how-to-validate-uk-vat-numbers-nino-company-numbers-and-utr-in-any-language-2026-2b06</link>
      <guid>https://dev.to/night18158/-how-to-validate-uk-vat-numbers-nino-company-numbers-and-utr-in-any-language-2026-2b06</guid>
      <description>&lt;h1&gt;
  
  
  How to Validate UK VAT Numbers, NINO, Company Numbers and UTR in Any Language (2026)
&lt;/h1&gt;

&lt;p&gt;If you're building software for the UK market, you'll eventually need to validate fiscal and identification documents. This guide covers the algorithms, code examples, and the fastest way to add validation to any project.&lt;/p&gt;




&lt;h2&gt;
  
  
  What are these documents?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VAT number&lt;/strong&gt; — Tax ID for UK businesses registered for VAT. Format: &lt;code&gt;GB&lt;/code&gt; + 9 digits (e.g. &lt;code&gt;GB123456789&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NINO&lt;/strong&gt; — National Insurance Number, used for tax and social security. Format: 2 letters + 6 digits + letter (e.g. &lt;code&gt;AB123456C&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Company Number&lt;/strong&gt; — Companies House registration number. Format: 8 digits or prefix + 6 digits (e.g. &lt;code&gt;SC123456&lt;/code&gt; for Scottish companies)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UTR&lt;/strong&gt; — Unique Taxpayer Reference, used for Self Assessment. Format: 10 digits (e.g. &lt;code&gt;1234567890&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Option 1: Implement it yourself
&lt;/h2&gt;

&lt;h3&gt;
  
  
  VAT number validation (Python)
&lt;/h3&gt;

&lt;p&gt;UK VAT numbers use HMRC's mod-97 checksum on the first 7 digits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_uk_vat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;vat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;vat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;vat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vat&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;vat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isdigit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="n"&gt;digits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;vat&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="n"&gt;weights&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vat&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;97&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;97&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;97&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;97&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  NINO validation (JavaScript)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;validateNINO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nino&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;nino&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nino&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;invalidFirst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;DFIQUV&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;invalidSecond&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;DFIOQUV&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;invalidPrefixes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BG&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NK&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;KN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ZZ&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Z&lt;/span&gt;&lt;span class="se"&gt;]{2}\d{6}[&lt;/span&gt;&lt;span class="sr"&gt;ABCD&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nino&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;invalidFirst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nino&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;invalidSecond&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nino&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;invalidPrefixes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nino&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Company number validation (Python)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;PREFIXES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SC&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NI&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OC&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SO&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;FC&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;BR&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_company_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;PREFIXES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:].&lt;/span&gt;&lt;span class="nf"&gt;isdigit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isdigit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Option 2: Use an API (3 lines of code)
&lt;/h2&gt;

&lt;p&gt;For VAT the algorithm is manageable, but NINO has 15+ edge cases and Company Numbers have 15+ prefix types. If you don't want to maintain all of this, the &lt;a href="https://rapidapi.com/Validatorapi/api/uk-document-validator" rel="noopener noreferrer"&gt;UK Document Validator API&lt;/a&gt; handles everything:&lt;/p&gt;

&lt;h3&gt;
  
  
  Python
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://uk-document-validator1.p.rapidapi.com/validate/vat&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GB123456789&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;X-RapidAPI-Key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;X-RapidAPI-Host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;uk-document-validator1.p.rapidapi.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c1"&gt;# {'input': 'GB123456789', 'valid': True, 'type': 'VAT', 'country': 'GB', 'formatted': 'GB123 456 789'}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  JavaScript
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://uk-document-validator1.p.rapidapi.com/validate/nino?value=AB123456C&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-RapidAPI-Key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-RapidAPI-Host&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uk-document-validator1.p.rapidapi.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// { valid: true, type: 'NINO', formatted: 'AB 12 34 56 C' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  PHP
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nb"&gt;curl_setopt_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="no"&gt;CURLOPT_URL&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'https://uk-document-validator1.p.rapidapi.com/validate/company?value=SC123456'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;CURLOPT_RETURNTRANSFER&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;CURLOPT_HTTPHEADER&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'X-RapidAPI-Key: YOUR_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'X-RapidAPI-Host: uk-document-validator1.p.rapidapi.com'&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nv"&gt;$r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;curl_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// $r-&amp;gt;company_type = "Scottish company"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  API response examples
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;VAT:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GB123456789"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"valid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VAT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GB"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"formatted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GB123 456 789"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NINO:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AB123456C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"valid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NINO"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"formatted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AB 12 34 56 C"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Company Number:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SC123456"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"valid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"COMPANY_NUMBER"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"company_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Scottish company"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"formatted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SC123456"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Auto-detect (any document type):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1234567890"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"valid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"UTR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"detected_as"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"UTR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"formatted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12345 67890"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  When to use the API vs DIY
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;DIY&lt;/th&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VAT validation&lt;/td&gt;
&lt;td&gt;~15 lines&lt;/td&gt;
&lt;td&gt;3 lines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NINO edge cases&lt;/td&gt;
&lt;td&gt;15+ rules to implement&lt;/td&gt;
&lt;td&gt;Included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Company prefix types&lt;/td&gt;
&lt;td&gt;15+ prefixes&lt;/td&gt;
&lt;td&gt;Included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UTR checksum&lt;/td&gt;
&lt;td&gt;Complex&lt;/td&gt;
&lt;td&gt;Included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auto-detect document type&lt;/td&gt;
&lt;td&gt;Extra logic&lt;/td&gt;
&lt;td&gt;Included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;Your problem&lt;/td&gt;
&lt;td&gt;Automatic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Free tier: 500 requests/month. &lt;a href="https://rapidapi.com/Validatorapi/api/uk-document-validator" rel="noopener noreferrer"&gt;Subscribe here.&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Full docs and interactive playground: &lt;a href="https://uk-validation-api.vercel.app/docs" rel="noopener noreferrer"&gt;uk-validation-api.vercel.app/docs&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>python</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Chat with your database in plain English — locally, for free</title>
      <dc:creator>retrovirusretro</dc:creator>
      <pubDate>Wed, 20 May 2026 21:28:03 +0000</pubDate>
      <link>https://dev.to/retrovirusretro/chat-with-your-database-in-plain-english-locally-for-free-2l0c</link>
      <guid>https://dev.to/retrovirusretro/chat-with-your-database-in-plain-english-locally-for-free-2l0c</guid>
      <description>&lt;p&gt;"What were our top 10 customers last quarter by revenue, as a bar chart?"&lt;/p&gt;

&lt;p&gt;DB-GPT translates that to SQL, runs it against your database, and renders the chart. No SQL knowledge required. Fully local. MIT licensed. 17K GitHub stars — almost no English content.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is DB-GPT?
&lt;/h2&gt;

&lt;p&gt;DB-GPT is an open-source framework that puts a natural language interface on top of your databases. You connect PostgreSQL, MySQL, SQLite, or others — then ask questions in plain English. It generates the SQL, executes it, and can visualize results automatically.&lt;/p&gt;

&lt;p&gt;Think Metabase meets AI, but fully self-hosted and free.&lt;/p&gt;




&lt;h2&gt;
  
  
  Supported Databases
&lt;/h2&gt;

&lt;p&gt;PostgreSQL · MySQL · MariaDB · SQLite · ClickHouse · DuckDB · Spark SQL&lt;/p&gt;




&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Clone the repo, copy &lt;code&gt;.env.example&lt;/code&gt; to &lt;code&gt;.env&lt;/code&gt;, add your database connection string, then &lt;code&gt;docker compose up -d&lt;/code&gt;. Open &lt;code&gt;localhost:5670&lt;/code&gt; → &lt;code&gt;admin / admin&lt;/code&gt; → Settings → Database → Add → paste connection string.&lt;/p&gt;

&lt;p&gt;Full docker-compose: &lt;a href="https://github.com/retrovirusretro/chinese-ai-tools-english-guide" rel="noopener noreferrer"&gt;chinese-ai-tools-english-guide/tools/db-gpt&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Example Queries
&lt;/h2&gt;

&lt;p&gt;Once your database is connected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"Show total sales by month for the last 12 months as a bar chart"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Which products have inventory below 10 units?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Top 5 customers by order value with their email addresses"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Average order fulfillment time grouped by warehouse"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DB-GPT generates SQL for each, runs it, returns results. Charts render automatically in the UI.&lt;/p&gt;




&lt;h2&gt;
  
  
  Connecting Ollama
&lt;/h2&gt;

&lt;p&gt;Settings → LLM Provider → Ollama → Base URL: &lt;code&gt;http://ollama:11434/v1&lt;/code&gt; → Model: &lt;code&gt;llama3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For best SQL accuracy use &lt;code&gt;sqlcoder&lt;/code&gt; — fine-tuned specifically for SQL generation. Pull it with &lt;code&gt;docker exec -it ollama ollama pull sqlcoder&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  DB-GPT vs Vanna.ai
&lt;/h2&gt;

&lt;p&gt;Both let you query databases with natural language:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;DB-GPT&lt;/th&gt;
&lt;th&gt;Vanna.ai&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;MIT&lt;/td&gt;
&lt;td&gt;MIT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Built-in UI&lt;/td&gt;
&lt;td&gt;✅ Full app&lt;/td&gt;
&lt;td&gt;Minimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Charts&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;❌ External&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visual pipeline&lt;/td&gt;
&lt;td&gt;✅ AWEL&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-hosted&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;DB-GPT if you want a complete self-contained app. Vanna.ai if you're embedding the capability programmatically into your own product.&lt;/p&gt;




&lt;h2&gt;
  
  
  n8n Automation
&lt;/h2&gt;

&lt;p&gt;A ready-to-import workflow JSON is in the repo (&lt;code&gt;integration/n8n-workflows/db-gpt-query.json&lt;/code&gt;). POST &lt;code&gt;{question, db_name}&lt;/code&gt; → returns &lt;code&gt;{answer, sql, data}&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Full Guide
&lt;/h2&gt;

&lt;p&gt;→ &lt;a href="https://github.com/retrovirusretro/chinese-ai-tools-english-guide" rel="noopener noreferrer"&gt;chinese-ai-tools-english-guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Previous articles in this series:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/retrovirusretro"&gt;5 Chinese AI tools the West is ignoring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/retrovirusretro"&gt;WeKnora — Tencent's RAG framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/retrovirusretro"&gt;MaxKB — simplest self-hosted RAG&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Your data never leaves your machine. No API keys, no cloud, no SQL knowledge needed.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>docker</category>
      <category>ollama</category>
      <category>database</category>
    </item>
    <item>
      <title>The simplest self-hosted RAG you'll ever set up (Apache 2.0, 20K stars)</title>
      <dc:creator>retrovirusretro</dc:creator>
      <pubDate>Wed, 20 May 2026 21:24:39 +0000</pubDate>
      <link>https://dev.to/retrovirusretro/the-simplest-self-hosted-rag-youll-ever-set-up-apache-20-20k-stars-2m2h</link>
      <guid>https://dev.to/retrovirusretro/the-simplest-self-hosted-rag-youll-ever-set-up-apache-20-20k-stars-2m2h</guid>
      <description>&lt;p&gt;Most RAG tools make you choose between simplicity and power. MaxKB doesn't try to be powerful — it tries to be simple, and it nails it.&lt;/p&gt;

&lt;p&gt;20K+ GitHub stars. Apache 2.0. Almost no English content. Here's the guide.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is MaxKB?
&lt;/h2&gt;

&lt;p&gt;MaxKB (Max Knowledge Base) is a knowledge base Q&amp;amp;A system by the 1Panel team. It connects to any OpenAI-compatible API — including Ollama — and lets you upload documents, ask questions, and embed a chat widget into any website.&lt;/p&gt;

&lt;p&gt;That last part is the killer feature: MaxKB generates a JavaScript snippet that drops a chat widget into any HTML page. One script tag. No iframe, no backend changes needed. Apache 2.0 means you can embed this in commercial products with no restrictions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;3 commands, under 5 minutes.&lt;/p&gt;

&lt;p&gt;Clone the repo, copy &lt;code&gt;.env.example&lt;/code&gt; to &lt;code&gt;.env&lt;/code&gt;, then &lt;code&gt;docker compose up -d&lt;/code&gt;. Open &lt;code&gt;localhost:8081&lt;/code&gt; → &lt;code&gt;admin / admin123&lt;/code&gt; → Settings → Model Provider → Ollama → &lt;code&gt;http://ollama:11434&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create a knowledge base, upload a PDF, start asking questions. That's the entire setup.&lt;/p&gt;

&lt;p&gt;Full docker-compose: &lt;a href="https://github.com/retrovirusretro/maxkb-english-guide" rel="noopener noreferrer"&gt;maxkb-english-guide&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Embed Widget
&lt;/h2&gt;

&lt;p&gt;MaxKB generates a JavaScript snippet — drop it into any HTML page and a chat widget appears bottom-right. No iframe, no backend changes. This is what makes MaxKB unique among RAG tools: it's designed to be embedded.&lt;/p&gt;

&lt;p&gt;Go to: Application → your app → Embed → copy the script tag → paste into any HTML page.&lt;/p&gt;




&lt;h2&gt;
  
  
  API
&lt;/h2&gt;

&lt;p&gt;Works from Python, JavaScript, curl, n8n — anything that speaks HTTP. POST your question to &lt;code&gt;/api/application/{app_id}/chat/completions&lt;/code&gt; with a Bearer token. Returns &lt;code&gt;{"content": "the answer"}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Full Python + JavaScript examples in the repo.&lt;/p&gt;




&lt;h2&gt;
  
  
  MaxKB vs the Alternatives
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;MaxKB&lt;/th&gt;
&lt;th&gt;WeKnora&lt;/th&gt;
&lt;th&gt;FastGPT&lt;/th&gt;
&lt;th&gt;RAGFlow&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup time&lt;/td&gt;
&lt;td&gt;⚡ 3 min&lt;/td&gt;
&lt;td&gt;5 min&lt;/td&gt;
&lt;td&gt;10 min&lt;/td&gt;
&lt;td&gt;15 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Apache 2.0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MIT&lt;/td&gt;
&lt;td&gt;Custom*&lt;/td&gt;
&lt;td&gt;Apache 2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Embed widget&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Autonomous agent&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PDF table parsing&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Commercial embed&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;*FastGPT prohibits SaaS resale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pick MaxKB when:&lt;/strong&gt; working knowledge base in 5 minutes, embed widget needed, Apache 2.0 matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pick something else when:&lt;/strong&gt; complex PDFs → RAGFlow · pipeline builder → FastGPT · multi-hop reasoning → WeKnora&lt;/p&gt;




&lt;h2&gt;
  
  
  Supported LLM Providers
&lt;/h2&gt;

&lt;p&gt;MaxKB works with any OpenAI-compatible API: Ollama (local, free), OpenAI, Groq, Together, or Anthropic via LiteLLM proxy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Full Guide
&lt;/h2&gt;

&lt;p&gt;→ &lt;a href="https://github.com/retrovirusretro/maxkb-english-guide" rel="noopener noreferrer"&gt;github.com/retrovirusretro/maxkb-english-guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part of a broader series:&lt;br&gt;
→ &lt;a href="https://github.com/retrovirusretro/chinese-ai-tools-english-guide" rel="noopener noreferrer"&gt;chinese-ai-tools-english-guide&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;MaxKB is the tool I recommend to people who just want RAG working quickly without reading 40 pages of docs.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>docker</category>
      <category>ollama</category>
      <category>selfhosted</category>
    </item>
  </channel>
</rss>
