<?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: Charles Uwagbale</title>
    <description>The latest articles on DEV Community by Charles Uwagbale (@anetor).</description>
    <link>https://dev.to/anetor</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4073392%2F515df2f8-8935-4933-a783-e9cebed8bbaf.png</url>
      <title>DEV Community: Charles Uwagbale</title>
      <link>https://dev.to/anetor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anetor"/>
    <language>en</language>
    <item>
      <title>LCEL vs. Legacy Chains: From Recipe Confusion to Clear Pipelines 🚀</title>
      <dc:creator>Charles Uwagbale</dc:creator>
      <pubDate>Wed, 12 Aug 2026 01:02:56 +0000</pubDate>
      <link>https://dev.to/anetor/-lcel-vs-legacy-chains-from-recipe-confusion-to-clear-pipelines-3f</link>
      <guid>https://dev.to/anetor/-lcel-vs-legacy-chains-from-recipe-confusion-to-clear-pipelines-3f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Legacy Chains are the old way—rigid, class-heavy, and frustrating. LCEL is the new standard—visual, modular, and future-proof. &lt;strong&gt;Always choose LCEL for new projects.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  😫 The Frustration (The Legacy Way)
&lt;/h2&gt;

&lt;p&gt;Building a chain in LangChain used to feel like following a recipe where every ingredient was labeled differently in every cookbook. &lt;/p&gt;

&lt;p&gt;"Add &lt;code&gt;input_documents&lt;/code&gt;"—wait, is that the same as &lt;code&gt;docs&lt;/code&gt;? What about &lt;code&gt;context&lt;/code&gt;? And why does this chain expect &lt;code&gt;llm&lt;/code&gt; but that one expects &lt;code&gt;model&lt;/code&gt;?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧠 You had to memorize specific class names (&lt;code&gt;LLMChain&lt;/code&gt;, &lt;code&gt;ConversationChain&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;🙏 You prayed your inputs matched the variable names perfectly (&lt;code&gt;input_documents&lt;/code&gt; vs. &lt;code&gt;docs&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;🐛 Debugging meant printing variables mid-way through.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🏛️ What is the Legacy Chain?
&lt;/h2&gt;

&lt;p&gt;It is the "Old Class Way." You tell the computer &lt;em&gt;how&lt;/em&gt; to store memory and &lt;em&gt;how&lt;/em&gt; to loop. You create an object, pass parameters to its constructor, and call &lt;code&gt;.run()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ What is LCEL?
&lt;/h2&gt;

&lt;p&gt;It is the "New Pipe Way." You tell the computer &lt;em&gt;what&lt;/em&gt; the flow is—LCEL optimizes the &lt;em&gt;how&lt;/em&gt; for you. You define a sequence using the &lt;code&gt;|&lt;/code&gt; symbol, like an assembly line where each component passes its output to the next.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 The "Aha!" Moment
&lt;/h2&gt;

&lt;p&gt;LCEL fixes this by treating your workflow like a &lt;strong&gt;plumbing pipe&lt;/strong&gt;—no more guesswork, just clear connections. You connect sections together using the &lt;code&gt;|&lt;/code&gt; (pipe) operator. Data flows in one end and comes out the other. No magic, just plumbing.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚔️ Side-by-Side Showdown
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Legacy (Old):&lt;/strong&gt;&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="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="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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&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;LCEL(New):&lt;/strong&gt;&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_core.output_parsers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StrOutputParser&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;prompt&lt;/span&gt; &lt;span class="o"&gt;|&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;StrOutputParser&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;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;input&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;Hello&lt;/span&gt;&lt;span class="sh"&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;em&gt;Notice the difference? No class names to memorize. No guessing about method names. Just a visual pipeline that reads like a recipe.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;😱The Composability Nightmare (Legacy)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you have a chatbot that answers questions from documents. In Legacy, you'd write:&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;RetrievalQA&lt;/span&gt;
&lt;span class="c1"&gt;# One class for retrieval...
&lt;/span&gt;&lt;span class="n"&gt;retrieval_chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RetrievalQA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_chain_type&lt;/span&gt;&lt;span class="p"&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;retriever&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;retriever&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine you want to:&lt;/p&gt;

&lt;p&gt;📝 Add a summarization step?&lt;/p&gt;

&lt;p&gt;📊 Log every prompt to a database?&lt;/p&gt;

&lt;p&gt;🧠 Route questions to different models based on complexity?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Legacy, each change required rewriting the entire class or hunting for a specific subclass&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧱The Composability Paradise (LCEL)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In LCEL, everything is a LEGO brick. Need to add a summarizer? | it in. Want to log prompts? | a logger between the prompt and the LLM.&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="c1"&gt;# LCEL: Mix, match, and extend
&lt;/span&gt;&lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="o"&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;prompt&lt;/span&gt; 
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;logging_middleware&lt;/span&gt;   &lt;span class="c1"&gt;# Your custom step!
&lt;/span&gt;    &lt;span class="o"&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;summarizer&lt;/span&gt;           &lt;span class="c1"&gt;# Another custom step!
&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;output_parser&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;The magic&lt;/strong&gt;: Every component in LCEL uses the same interface. That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🔄 You can reuse any chain inside another chain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🌿 You can branch into parallel chains.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🔧 You can swap components without breaking everything.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Composability is not a feature; it's the architecture.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🏆 The 4 Core Upgrades
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;👀 Explicit over Implicit: LCEL shows the data flow visually. No more guessing what goes where.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📡 Built-in Streaming: Legacy forces you to wait. LCEL allows chain.stream() out of the box.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧩 Composability: In LCEL, if you can pipe it, you can chain it. Mix and match components freely.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🎯 Standardized Interface: Everything uses the same methods (.invoke(), .stream(), .batch()). Learn once, use everywhere.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚠️ Watch Out: The "Too Much Piping" Trap
&lt;/h2&gt;

&lt;p&gt;LCEL is powerful, but don't overdo it. A chain with 10+ pipes becomes hard to debug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good:&lt;/strong&gt;&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="n"&gt;chain&lt;/span&gt; &lt;span class="o"&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;llm&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;  &lt;span class="c1"&gt;# 3 steps
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bad:&lt;/strong&gt;&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="n"&gt;chain&lt;/span&gt; &lt;span class="o"&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;prompt&lt;/span&gt; &lt;span class="o"&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;parser&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;  &lt;span class="c1"&gt;# 8+ steps
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt; If your chain doesn't fit on one screen, split it into smaller sub-chains.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ When to use which?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;✅ Use LCEL: For new projects, production APIs, and streaming chatbots.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;❌ Use Legacy: Only if you are patching a production bug in an old system and cannot refactor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📚 Watch out for next article
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Runnables Explained: From Zero to Hero with .invoke(), .stream(), and .batch()&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Feedback:&lt;/strong&gt; Your opinion matters. Leave a comment with your biggest takeaway or a question you still have.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>langchain</category>
      <category>python</category>
    </item>
  </channel>
</rss>
