TL;DR: Legacy Chains are the old way—rigid, class-heavy, and frustrating. LCEL is the new standard—visual, modular, and future-proof. Always choose LCEL for new projects.
😫 The Frustration (The Legacy Way)
Building a chain in LangChain used to feel like following a recipe where every ingredient was labeled differently in every cookbook.
"Add input_documents"—wait, is that the same as docs? What about context? And why does this chain expect llm but that one expects model?
- 🧠 You had to memorize specific class names (
LLMChain,ConversationChain). - 🙏 You prayed your inputs matched the variable names perfectly (
input_documentsvs.docs). - 🐛 Debugging meant printing variables mid-way through.
🏛️ What is the Legacy Chain?
It is the "Old Class Way." You tell the computer how to store memory and how to loop. You create an object, pass parameters to its constructor, and call .run().
⚡ What is LCEL?
It is the "New Pipe Way." You tell the computer what the flow is—LCEL optimizes the how for you. You define a sequence using the | symbol, like an assembly line where each component passes its output to the next.
💡 The "Aha!" Moment
LCEL fixes this by treating your workflow like a plumbing pipe—no more guesswork, just clear connections. You connect sections together using the | (pipe) operator. Data flows in one end and comes out the other. No magic, just plumbing.
⚔️ Side-by-Side Showdown
Legacy (Old):
from langchain.chains import LLMChain
chain = LLMChain(llm=llm, prompt=prompt)
result = chain.run("Hello")
LCEL(New):
from langchain_core.output_parsers import StrOutputParser
chain = prompt | llm | StrOutputParser()
result = chain.invoke({"input": "Hello"})
Notice the difference? No class names to memorize. No guessing about method names. Just a visual pipeline that reads like a recipe.
😱The Composability Nightmare (Legacy)
Imagine you have a chatbot that answers questions from documents. In Legacy, you'd write:
from langchain.chains import RetrievalQA
# One class for retrieval...
retrieval_chain = RetrievalQA.from_chain_type(llm, retriever=retriever)
Now imagine you want to:
📝 Add a summarization step?
📊 Log every prompt to a database?
🧠 Route questions to different models based on complexity?
In Legacy, each change required rewriting the entire class or hunting for a specific subclass.
🧱The Composability Paradise (LCEL)
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.
# LCEL: Mix, match, and extend
chain = (
retriever
| prompt
| logging_middleware # Your custom step!
| llm
| summarizer # Another custom step!
| output_parser
)
The magic: Every component in LCEL uses the same interface. That means:
🔄 You can reuse any chain inside another chain.
🌿 You can branch into parallel chains.
🔧 You can swap components without breaking everything.
Composability is not a feature; it's the architecture.
🏆 The 4 Core Upgrades
👀 Explicit over Implicit: LCEL shows the data flow visually. No more guessing what goes where.
📡 Built-in Streaming: Legacy forces you to wait. LCEL allows chain.stream() out of the box.
🧩 Composability: In LCEL, if you can pipe it, you can chain it. Mix and match components freely.
🎯 Standardized Interface: Everything uses the same methods (.invoke(), .stream(), .batch()). Learn once, use everywhere.
⚠️ Watch Out: The "Too Much Piping" Trap
LCEL is powerful, but don't overdo it. A chain with 10+ pipes becomes hard to debug.
Good:
chain = prompt | llm | parser # 3 steps
Bad:
chain = retriever | prompt | llm | parser | memory | router | fallback | logger # 8+ steps
Rule of thumb: If your chain doesn't fit on one screen, split it into smaller sub-chains.
✅ When to use which?
✅ Use LCEL: For new projects, production APIs, and streaming chatbots.
❌ Use Legacy: Only if you are patching a production bug in an old system and cannot refactor.
📚 Watch out for next article
- Runnables Explained: From Zero to Hero with .invoke(), .stream(), and .batch()
Feedback: Your opinion matters. Leave a comment with your biggest takeaway or a question you still have.
Top comments (0)