<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Anass Ez-zouaine — Senior Backend Engineer · Software Architect · AI Engineer — AI</title><description>AI posts from Anass Ez-zouaine — Senior Backend Engineer · Software Architect · AI Engineer.</description><link>https://ansezz.com/</link><item><title>Claude MCP: why I&apos;m connecting my dev tools to LLMs for real-time context</title><link>https://ansezz.com/blog/claude-mcp-dev-tools/</link><guid isPermaLink="true">https://ansezz.com/blog/claude-mcp-dev-tools/</guid><description>The Model Context Protocol is the USB port for LLMs. One MCP server, any MCP-aware host — killing the M×N integration tax. How the host/client/server architecture works, the servers I run daily, and why the sandbox model makes it safe enough to plug into production.</description><pubDate>Wed, 27 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Every time I have to build a custom integration for a new tool, a little piece of my developer soul dies. It is a maintenance nightmare that never ends. We have reached a point where building the actual product is often faster than setting up the pipes to make it work with our data.&lt;/p&gt;
&lt;p&gt;If you have spent any time building &lt;a href=&quot;https://ansezz.com/blog/agentic-workflows-vibe-coding/&quot;&gt;agentic workflows and vibe coding&lt;/a&gt;, you know exactly what I am talking about. You have an LLM like Claude that is incredibly smart but essentially locked in a room with no windows. To give it context, you have to manually copy-paste code, export CSV files, or spend three days writing a brittle wrapper for a third-party API just so your assistant can &quot;see&quot; your work.&lt;/p&gt;
&lt;p&gt;This fragmentation is the biggest bottleneck in modern software development. We have powerful models, but they are isolated from our local files, our databases, and our production logs. It is like having a world-class architect who isn&apos;t allowed to visit the construction site. They are just guessing based on the photos you decide to send them.&lt;/p&gt;
&lt;p&gt;Enter the Model Context Protocol — or as I have been calling it: the USB port for LLMs.&lt;/p&gt;
&lt;h2&gt;The fragmentation tax is killing your productivity&lt;/h2&gt;
&lt;p&gt;The problem is simple but massive. Every AI application — whether it is Claude Desktop, a custom agent, or an IDE extension — wants to talk to your data. On the other side, every data source — your GitHub repos, your Postgres databases, your Slack channels — has its own specific API and authentication flow.&lt;/p&gt;
&lt;p&gt;Without a standard, we are stuck in an M×N problem. If you have 5 AI apps and 10 data sources, you need 50 different integrations. This is why most &quot;AI-powered&quot; tools feel shallow. They only support a few basic integrations, and if you want to use your internal company data, you are back to writing custom glue code.&lt;/p&gt;
&lt;p&gt;This agitation is real. We are wasting hours building the same connectors over and over again. We are worried about security because every new integration is another potential leak. And we are frustrated because the &quot;magic&quot; of AI disappears the moment we hit a data silo.&lt;/p&gt;
&lt;h2&gt;The solution: MCP as a universal standard&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/claude-mcp-dev-tools/architecture.webp&quot; alt=&quot;MCP sitting between data sources and AI hosts as a universal translator&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Claude MCP (Model Context Protocol) is the first serious attempt to standardize how AI applications discover and interact with data and tools. Instead of building a specific connector for every model and every tool, you build an MCP server.&lt;/p&gt;
&lt;p&gt;This server acts as a translator. It sits between your data and the AI, exposing a consistent interface that any MCP-compliant host (like Claude Desktop) can understand. It is exactly like the USB standard. It doesn&apos;t matter if you are plugging in a mouse, a keyboard, or an external drive. The protocol is the same, so it just works.&lt;/p&gt;
&lt;p&gt;This shifts the entire paradigm of &lt;a href=&quot;https://ansezz.com/blog/mcp-context-aware-agents/&quot;&gt;context-aware agents&lt;/a&gt;. Instead of hard-coding logic into the agent, you simply &quot;plug in&quot; the servers you need.&lt;/p&gt;
&lt;h3&gt;How the architecture actually works&lt;/h3&gt;
&lt;p&gt;There are three main players in the MCP ecosystem:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The host&lt;/strong&gt; — this is the environment the user interacts with. It could be Claude Desktop, a terminal, or an IDE like Cursor. The host is responsible for managing the lifecycle of the connection.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The client&lt;/strong&gt; — this is the part of the host that speaks the protocol. It does the &quot;handshake&quot; with the server to find out what it can do.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The server&lt;/strong&gt; — this is a lightweight program that provides context (resources), actions (tools), and prompt templates.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For example, if I want Claude to have access to my local project files, I run a local MCP server that exposes those files as &quot;resources.&quot; The host (Claude Desktop) asks the server: &quot;what do you have?&quot; The server replies: &quot;I have these 10 files and a tool to run grep searches.&quot;&lt;/p&gt;
&lt;p&gt;The model can then decide to call the &quot;grep&quot; tool whenever it needs to find a specific function definition. I didn&apos;t have to write a single line of logic inside Claude to make that happen. I just connected the server.&lt;/p&gt;
&lt;h2&gt;Modularity and the MCP server ecosystem&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/claude-mcp-dev-tools/servers.webp&quot; alt=&quot;A grid of MCP servers — Postgres, GitHub, Google Drive — ready to plug in&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The beauty of this modularity is that once a server is built, anyone can use it. The community has already started building servers for everything you can imagine. I have been using a few in my daily workflow that have completely changed how I code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Postgres MCP&lt;/strong&gt; — I can point Claude at a local or remote database. It can inspect schemas and even run queries to help me debug data issues without me leaving the chat.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitHub MCP&lt;/strong&gt; — this allows the model to search through my repositories, list issues, and even create pull requests. It is like having a junior dev who actually knows where the code is.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Google Drive MCP&lt;/strong&gt; — perfect for when I need to cross-reference technical documentation stored in docs with the actual implementation in my IDE.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This also solves a massive pain point in &lt;a href=&quot;https://ansezz.com/blog/agentic-commerce-shopify/&quot;&gt;agentic commerce for Shopify&lt;/a&gt;. Imagine an agent that can talk directly to your Shopify store via MCP to check inventory levels or update product descriptions in real-time, all while maintaining a secure, standardized connection.&lt;/p&gt;
&lt;h2&gt;Security first: the sandbox model&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/claude-mcp-dev-tools/security.webp&quot; alt=&quot;Sandboxed MCP server communicating through a narrow pipe to the host&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The biggest question I get when I talk about connecting dev tools to an LLM is: &quot;is it safe?&quot;&lt;/p&gt;
&lt;p&gt;Security is baked into the design of MCP. Because the server is a separate process, it runs in its own sandbox. It only has access to the specific resources you grant it.&lt;/p&gt;
&lt;p&gt;For local servers, the protocol typically uses &lt;code&gt;stdio&lt;/code&gt; (stdin/stdout). This means the server can only talk to the host through a very narrow pipe. It doesn&apos;t have open network ports listening for connections. It only exists as long as the host is running it.&lt;/p&gt;
&lt;p&gt;For remote servers, MCP uses OAuth 2.1. This allows for fine-grained permissions. You can authorize a GitHub MCP server to only read public repositories, or a database server to only access specific tables.&lt;/p&gt;
&lt;p&gt;This is a huge improvement over the &quot;give me your master API key&quot; approach that we have seen in the past. We can now treat AI tools with the same &quot;least privilege&quot; mindset we use for any other service in our stack. This is especially important when you are trying to avoid &lt;a href=&quot;https://ansezz.com/blog/7-rag-mistakes-production/&quot;&gt;RAG mistakes in production&lt;/a&gt;, where data leakage is a top-tier risk.&lt;/p&gt;
&lt;h2&gt;Why I am betting on MCP&lt;/h2&gt;
&lt;p&gt;I have been a developer for over a decade, and I have seen plenty of &quot;standards&quot; come and go. What makes MCP different is its simplicity and its backers. Anthropic has made this open source because they realize that the more context a model has, the more valuable it becomes.&lt;/p&gt;
&lt;p&gt;We are moving toward a world of &quot;agentic&quot; software development. In this world, we don&apos;t just use AI to write snippets of code. We use AI as an orchestrator that can reach into our cloud infrastructure on GCP, check our Docker logs, and suggest fixes for a failing Laravel app.&lt;/p&gt;
&lt;p&gt;Without a protocol like MCP, that vision is impossible to scale. It would be too expensive and too risky to build. But with MCP, we are building a world where tools are plug-and-play.&lt;/p&gt;
&lt;h3&gt;Practical takeaways for senior engineers&lt;/h3&gt;
&lt;p&gt;If you are ready to start experimenting with this, here is what I recommend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Install the Claude Desktop app&lt;/strong&gt; — it is currently the most mature host for MCP.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Try the filesystem server&lt;/strong&gt; — this is the easiest way to feel the power. Give Claude access to a specific folder and watch it navigate your codebase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Don&apos;t build, search first&lt;/strong&gt; — check the official MCP GitHub repository. There are already servers for Brave search, Postgres, Slack, and more.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Think in tools, not just prompts&lt;/strong&gt; — start thinking about what &quot;tools&quot; your internal systems could expose. If you have a custom admin panel, could it be an MCP server?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Connecting your dev tools to an LLM isn&apos;t just about speed. It is about reducing the cognitive load of switching between tabs, terminals, and documentation. It allows you to stay in the &quot;flow&quot; longer.&lt;/p&gt;
&lt;p&gt;Are you ready to stop copy-pasting your code into a chat box and start connecting your tools directly to the brain? What is the one internal tool you wish you could &quot;plug in&quot; to Claude right now? Drop a note via &lt;a href=&quot;https://ansezz.com/contact/&quot;&gt;contact&lt;/a&gt; — let&apos;s figure it out. 🤘&lt;/p&gt;
</content:encoded><category>ai</category><category>mcp</category><category>claude</category><category>anthropic</category><category>agentic-ai</category><category>tool-use</category><category>context</category><category>dev-tools</category><category>integrations</category></item><item><title>7 mistakes you&apos;re making with your production RAG stack (and how to fix them)</title><link>https://ansezz.com/blog/7-rag-mistakes-production/</link><guid isPermaLink="true">https://ansezz.com/blog/7-rag-mistakes-production/</guid><description>Naive chunking, no reranker, embedding drift, latency blowups, vibe-checking — the seven structural mistakes that turn a slick RAG demo into a production nightmare, and the fixes that actually ship.</description><pubDate>Sun, 17 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Getting a RAG (retrieval-augmented generation) demo working is easy. You take a few PDFs, throw them into a vector database like Chroma or Pinecone, and ask a question. It feels like magic.&lt;/p&gt;
&lt;p&gt;But shipping RAG to production is where the magic dies.&lt;/p&gt;
&lt;p&gt;I&apos;ve seen too many teams launch a feature only to realize that their users are getting irrelevant answers, waiting 10 seconds for a response, or worse, getting hit with &quot;I don&apos;t know&quot; for questions that are clearly in the documentation. When the &quot;vibe check&quot; fails at scale, your users lose trust.&lt;/p&gt;
&lt;p&gt;You&apos;re likely making at least one of these seven structural mistakes that turn a cool demo into a production nightmare. I&apos;ve spent the last few years building &lt;a href=&quot;https://ansezz.com/work/&quot;&gt;custom web applications&lt;/a&gt; and AI systems, and I&apos;ve had to fix these same leaks in my own stacks.&lt;/p&gt;
&lt;p&gt;Here is how to bridge the gap between &quot;it works on my machine&quot; and a production-grade AI system.&lt;/p&gt;
&lt;h2&gt;1. Naive chunking is killing your context&lt;/h2&gt;
&lt;p&gt;Most people start with a simple character-based or token-based splitter. You tell the library to &quot;give me chunks of 500 tokens with a 50-token overlap.&quot;&lt;/p&gt;
&lt;p&gt;This is a mistake.&lt;/p&gt;
&lt;p&gt;This &quot;naive chunking&quot; treats your data like raw soup. It might cut a sentence in half, split a table in the middle of a row, or separate a coding example from the explanation that precedes it. If the retriever pulls only one of those halves, the LLM has zero chance of giving a correct answer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; use semantic or structural chunking.&lt;/p&gt;
&lt;p&gt;I always recommend chunking based on the actual structure of the document first. Use headers (H1, H2, H3), paragraphs, or even markdown delimiters to ensure related ideas stay together. If you&apos;re working with complex data, consider recursive character splitting that respects newlines and punctuation before falling back to raw token counts.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/7-rag-mistakes-production/chunking.webp&quot; alt=&quot;Structural vs naive chunking illustration&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;2. Skipping the reranker step&lt;/h2&gt;
&lt;p&gt;Vector search is great at finding &quot;roughly similar&quot; stuff, but it&apos;s not a precision instrument. It relies on cosine similarity, which can be easily fooled by documents that share a similar &quot;vibe&quot; but don&apos;t actually contain the answer.&lt;/p&gt;
&lt;p&gt;If you&apos;re just taking the top 5 results from your vector store and shoving them into your LLM prompt, you&apos;re leaving quality on the table.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; add a reranking step.&lt;/p&gt;
&lt;p&gt;I look at retrieval as a two-stage process. Stage one is the &quot;fast and broad&quot; search where you pull the top 20 or 50 candidates from your vector database. Stage two is using a cross-encoder or a specialized reranking model (like Cohere&apos;s Rerank or BGE-Reranker) to score those 50 candidates against the query more accurately.&lt;/p&gt;
&lt;p&gt;The reranker acts like a bouncer at a club. It doesn&apos;t care if a document looks &quot;okay.&quot; It only lets in the ones that are actually relevant to the question.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/7-rag-mistakes-production/reranker.webp&quot; alt=&quot;Two-stage retrieval with reranker&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;3. Ignoring embedding drift and versioning&lt;/h2&gt;
&lt;p&gt;This is the silent killer. I&apos;ve seen teams upgrade their embedding model from &lt;code&gt;text-embedding-ada-002&lt;/code&gt; to &lt;code&gt;text-embedding-3-small&lt;/code&gt; without re-indexing their entire database.&lt;/p&gt;
&lt;p&gt;Suddenly, the vectors being generated for new queries don&apos;t &quot;line up&quot; with the vectors stored in the index. The similarity scores go haywire. Even worse is when you change the preprocessing logic (like how you format the chunks) but keep the old vectors.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; pin your models and version your index.&lt;/p&gt;
&lt;p&gt;Treat your embedding model like a database schema. If you change the model, you must re-index. I always include the model name and version in the metadata of every index I build. This way, if I need to test a new model, I can run them side-by-side without breaking the production flow. My &lt;a href=&quot;https://ansezz.com/about/&quot;&gt;experience in cloud infrastructure&lt;/a&gt; has taught me that consistency is better than a &quot;better&quot; model that doesn&apos;t match its data.&lt;/p&gt;
&lt;h2&gt;4. The &quot;needle in a haystack&quot; latency problem&lt;/h2&gt;
&lt;p&gt;Everyone wants more context. We see context windows of 128k or even 1M tokens and think, &quot;great, I&apos;ll just give the LLM everything!&quot;&lt;/p&gt;
&lt;p&gt;This is a trap for two reasons. First, latency — feeding 50k tokens of context into an LLM can make your response time balloon to 20 or 30 seconds. Second, models still struggle with &quot;lost in the middle&quot; problems: they tend to ignore information buried in the center of a massive context window.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; optimize your latency budget.&lt;/p&gt;
&lt;p&gt;I start with a &quot;latency budget.&quot; If the user expects a response in under 2 seconds, I can&apos;t afford to send 20 chunks. I limit my retrieval to the top 3–5 high-quality chunks and use streaming as soon as the first token is ready.&lt;/p&gt;
&lt;p&gt;If you need more data, consider using a multi-step approach: use a cheaper model to summarize the retrieved chunks before passing the refined info to your main model.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/7-rag-mistakes-production/latency.webp&quot; alt=&quot;Latency budget illustration&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;5. Forgetting about hybrid search&lt;/h2&gt;
&lt;p&gt;Vector search is terrible at finding specific keywords or unique identifiers. If a user asks for &quot;error code XF-904,&quot; a vector search might return documents about &quot;general error handling&quot; because the &quot;vibe&quot; is similar. But it might miss the one specific document that actually mentions &quot;XF-904.&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; implement hybrid search.&lt;/p&gt;
&lt;p&gt;I always combine dense vector search with traditional sparse search (like BM25). By blending these two results using something like Reciprocal Rank Fusion (RRF), you get the best of both worlds. You get the semantic understanding of vectors and the keyword precision of full-text search. This is non-negotiable for enterprise search or technical documentation.&lt;/p&gt;
&lt;h2&gt;6. Failing to filter by metadata&lt;/h2&gt;
&lt;p&gt;If your RAG system contains documents for different clients, versions, or dates, pure vector search will betray you. You might ask about &quot;API changes in 2024&quot; and get results from 2022 because they share similar keywords.&lt;/p&gt;
&lt;p&gt;Relying on the LLM to &quot;ignore&quot; the wrong dates in the context is a waste of tokens and a recipe for hallucinations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; use hard metadata filters.&lt;/p&gt;
&lt;p&gt;Before the vector search even happens, apply filters. If you know the user is looking for &quot;v2&quot; of your documentation, filter the vector query to only include chunks with &lt;code&gt;version: &apos;2&apos;&lt;/code&gt;. This drastically reduces the search space and improves accuracy. I use this heavily when building &lt;a href=&quot;https://ansezz.com/work/&quot;&gt;Shopify apps&lt;/a&gt; where data must be strictly siloed by shop ID.&lt;/p&gt;
&lt;h2&gt;7. Vibe-based evaluation&lt;/h2&gt;
&lt;p&gt;How do you know your RAG stack is getting better? Most devs just ask a few questions, see that the answer looks okay, and ship it.&lt;/p&gt;
&lt;p&gt;This is called &quot;vibe-checking,&quot; and it doesn&apos;t work. When you change a prompt or a chunk size, you might improve one answer while breaking ten others you didn&apos;t check.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; build a golden evaluation set.&lt;/p&gt;
&lt;p&gt;I use the Ragas framework or simple LLM-as-a-judge patterns to run automated evals. I maintain a &quot;golden set&quot; of 50–100 questions with ground-truth answers. Every time I change the architecture, I run the eval and look for three metrics:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Faithfulness&lt;/strong&gt; — is the answer actually derived from the context?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Answer relevance&lt;/strong&gt; — does it answer the user&apos;s question?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context precision&lt;/strong&gt; — are the retrieved chunks actually useful?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/7-rag-mistakes-production/evals.webp&quot; alt=&quot;Evaluation harness illustration&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Practical takeaways for your stack&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Start with metadata&lt;/strong&gt; — don&apos;t let the vector database guess. If you have categories or dates, use them as hard filters.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rerank by default&lt;/strong&gt; — it&apos;s the single biggest quality jump you can make for the lowest effort.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitor retrieval, not just generation&lt;/strong&gt; — if your retriever fails, the best LLM in the world can&apos;t save you. Log your top-k retrieval results separately.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Don&apos;t over-engineer&lt;/strong&gt; — sometimes a simple long-context prompt is better than a complex agentic workflow. Measure before you add complexity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Building production RAG is a game of millimeters. It&apos;s about cleaning your data, pinning your models, and actually measuring what&apos;s happening under the hood.&lt;/p&gt;
&lt;p&gt;I&apos;ve spent years moving from &quot;it works&quot; to &quot;it&apos;s reliable.&quot; If you&apos;re struggling with a specific part of your AI pipeline, what&apos;s the one thing that&apos;s currently keeping you from hitting that &quot;deploy&quot; button?&lt;/p&gt;
&lt;p&gt;Drop a comment or &lt;a href=&quot;https://ansezz.com/contact/&quot;&gt;reach out&lt;/a&gt; if you&apos;re hitting a wall with your architecture. 🤘&lt;/p&gt;
</content:encoded><category>ai</category><category>rag</category><category>ai</category><category>llm</category><category>pgvector</category><category>reranker</category><category>hybrid-search</category><category>evals</category><category>production</category></item><item><title>MCP and the future of tool-use: building context-aware agents</title><link>https://ansezz.com/blog/mcp-context-aware-agents/</link><guid isPermaLink="true">https://ansezz.com/blog/mcp-context-aware-agents/</guid><description>The Model Context Protocol kills the era of brittle one-off integrations. Tools, resources, prompts, and the three primitives that let one server talk to any MCP-aware client — with a working TypeScript example you can ship today.</description><pubDate>Sun, 05 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The current state of AI agents is a mess of fragmented integrations. Every time I want to give an LLM access to a new data source or a specific tool I find myself writing custom glue code that breaks the moment an API version changes. It is a frustrating cycle of building brittle wrappers. We are effectively forcing highly intelligent models to peer through a keyhole when they should have a wide-open window into our data ecosystems.&lt;/p&gt;
&lt;p&gt;This fragmentation creates a massive technical debt for developers. You spend eighty percent of your time on plumbing and maybe twenty percent on the actual intelligence of the agent. Without a unified way to share context the model often hallucinates because it lacks the grounding of real-time data. It is stuck in a loop of &quot;I don&apos;t have access to that&quot; or worse &quot;I&apos;ll guess what that data looks like&quot; — which leads to unreliable outputs and a poor user experience.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Model Context Protocol&lt;/strong&gt; (MCP) changes this dynamic entirely. It is an open standard that allows me to build context-aware agents that connect to any data source using a universal language. By standardizing how servers and clients communicate I can focus on building sophisticated logic rather than managing endless API endpoints. It is the missing link in the agentic workflow.&lt;/p&gt;
&lt;h2&gt;Why MCP matters for developers&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/mcp-context-aware-agents/architecture-diagram.webp&quot; alt=&quot;Architecture diagram showing MCP servers bridging an AI client to many data sources&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I have spent years building custom web applications and one of the biggest hurdles has always been data silos. When I work on &lt;a href=&quot;https://ansezz.com/work/&quot;&gt;complex technical challenges&lt;/a&gt; the goal is usually to make data actionable. Traditional tool-use requires the developer to define every schema and every function call manually for the model. MCP flips this script.&lt;/p&gt;
&lt;p&gt;MCP acts as a bridge. It defines a clear boundary between the AI application (the client) and the data sources (the servers). This separation of concerns means I can swap out the underlying model without rebuilding the entire data integration layer. If I move from Claude to another model that supports MCP, the tools and resources remain the same.&lt;/p&gt;
&lt;p&gt;It also solves the &quot;context window&quot; problem. Instead of stuffing a massive document into the prompt I can expose it as an MCP resource. The model only fetches what it needs when it needs it. This is significantly more efficient and cost-effective. It allows me to build agents that are aware of their environment without being overwhelmed by it.&lt;/p&gt;
&lt;h2&gt;The three pillars: tools, resources, and prompts&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/mcp-context-aware-agents/context-visual.webp&quot; alt=&quot;Visual breakdown of MCP primitives — tools, resources, prompts&quot; /&gt;&lt;/p&gt;
&lt;p&gt;To understand how to build with MCP I look at its three core primitives. These are the building blocks for any context-aware system.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tools&lt;/strong&gt; are model-controlled actions. When I give an agent a tool I am giving it the ability to change the world. This could be writing a file to a disk or making a POST request to a Shopify API. The model decides when to call the tool based on the user&apos;s intent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resources&lt;/strong&gt; are application-controlled data. Think of these as read-only files or database entries that the agent can inspect. Resources provide the necessary grounding. If I am building a support agent the documentation for the product would be a resource. The agent can search and read it to provide accurate answers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prompts&lt;/strong&gt; are user-controlled templates. They help guide the interaction. By using MCP prompts I can standardize how users interact with the agent across different platforms. It ensures consistency in how the model interprets tasks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Building your first MCP server&lt;/h2&gt;
&lt;p&gt;I prefer using TypeScript for building MCP servers because of the robust SDK provided by Anthropic. However the protocol itself is language-agnostic. Here is a simplified look at how I structure a basic server that exposes a weather tool.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Server } from &quot;@modelcontextprotocol/sdk/server/index.js&quot;;
import { StdioServerTransport } from &quot;@modelcontextprotocol/sdk/server/stdio.js&quot;;
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from &quot;@modelcontextprotocol/sdk/types.js&quot;;

const server = new Server(
  {
    name: &quot;weather-server&quot;,
    version: &quot;1.0.0&quot;,
  },
  {
    capabilities: {
      tools: {},
    },
  },
);

server.setRequestHandler(ListToolsRequestSchema, async () =&amp;gt; {
  return {
    tools: [
      {
        name: &quot;get_weather&quot;,
        description: &quot;get the current weather for a location&quot;,
        inputSchema: {
          type: &quot;object&quot;,
          properties: {
            location: { type: &quot;string&quot; },
          },
          required: [&quot;location&quot;],
        },
      },
    ],
  };
});

server.setRequestHandler(CallToolRequestSchema, async (request) =&amp;gt; {
  if (request.params.name === &quot;get_weather&quot;) {
    const location = request.params.arguments?.location;
    // logic to fetch weather from an api goes here
    return {
      content: [{ type: &quot;text&quot;, text: `it is sunny in ${location}` }],
    };
  }
  throw new Error(&quot;tool not found&quot;);
});

const transport = new StdioServerTransport();
await server.connect(transport);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This snippet illustrates the simplicity of the protocol. I define the tool and how to handle the call. The MCP client handles the rest. This modular approach is exactly what I look for when managing &lt;a href=&quot;https://ansezz.com/work/&quot;&gt;cloud infrastructure&lt;/a&gt; or complex backend systems. It is clean and scalable.&lt;/p&gt;
&lt;h2&gt;Security and the MCP ecosystem&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/mcp-context-aware-agents/dashboard-mockup.webp&quot; alt=&quot;Dashboard mockup of an MCP server admin showing fine-grained tool permissions&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Security is a major concern when giving an AI agent access to your data. I have seen many implementations where API keys are hardcoded or permissions are too broad. MCP addresses this by using a client-server architecture where the server controls exactly what is exposed.&lt;/p&gt;
&lt;p&gt;The server acts as a gatekeeper. I can implement fine-grained access control at the server level. For example an MCP server connecting to a database can be restricted to only specific tables or read-only queries. This level of control is essential for enterprise-grade applications.&lt;/p&gt;
&lt;p&gt;The ecosystem is growing rapidly. We are seeing early adoption from major players in the dev tools space. Tools like Zed, Cursor, and Claude Code are already integrating MCP to help developers write better code by giving their AI assistants better context. This trend will only accelerate as more developers realize the power of standardized context.&lt;/p&gt;
&lt;h2&gt;Practical steps for getting started&lt;/h2&gt;
&lt;p&gt;If you are a developer looking to dive into MCP I recommend following these steps.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Explore the existing MCP servers&lt;/strong&gt; on GitHub. There are already servers for file system access and SQLite databases. See how they are structured.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pick a simple data source you use every day.&lt;/strong&gt; It could be your Obsidian notes or a local directory of markdown files. Build a basic server to expose these as resources.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use a client like Claude Desktop&lt;/strong&gt; to test your server. See how the model interacts with your data. Adjust the tool descriptions to make them more intuitive for the AI.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compose multiple MCP servers&lt;/strong&gt; once you are comfortable. Imagine an agent that can read your calendar and then write a draft email based on your upcoming meetings.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;MCP is more than just a new protocol. It is a fundamental shift in how we build AI applications. It moves us away from the era of &quot;black box&quot; agents and toward a world of transparent and context-aware assistants. I am excited to see how this technology evolves and how it will transform our development workflows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How are you planning to use MCP in your next project?&lt;/strong&gt; &lt;a href=&quot;https://ansezz.com/contact/&quot;&gt;Drop me a line&lt;/a&gt; — happy to swap notes on real-world MCP server design.&lt;/p&gt;
</content:encoded><category>ai</category><category>mcp</category><category>anthropic</category><category>claude</category><category>agentic-ai</category><category>typescript</category><category>tool-use</category><category>context</category></item><item><title>Why your RAG implementation is failing in production (and how to fix it)</title><link>https://ansezz.com/blog/why-your-rag-is-failing/</link><guid isPermaLink="true">https://ansezz.com/blog/why-your-rag-is-failing/</guid><description>Vector-only retrieval is the silent killer of production RAG. Hybrid search with BM25, reciprocal rank fusion, smarter chunking, re-rankers, and an evaluation harness — the production checklist that turns a flaky demo into a reliable system.</description><pubDate>Sun, 08 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You built a RAG (Retrieval-Augmented Generation) demo. On a local machine, with a handful of PDF files, it looked convincing. The answers felt coherent. The system appeared capable.&lt;/p&gt;
&lt;p&gt;Then you pushed it to production.&lt;/p&gt;
&lt;p&gt;That is usually where the illusion breaks.&lt;/p&gt;
&lt;p&gt;Users start reporting that the LLM is &quot;hallucinating&quot; when the real issue is retrieval. Obvious answers go missing even though they exist in the documentation. Irrelevant chunks surface because they are semantically adjacent, not actually useful.&lt;/p&gt;
&lt;p&gt;If your RAG system feels unreliable in production, you are not dealing with a model problem first. You are dealing with a retrieval design problem. Most production RAG systems fail because they rely too heavily on vector search and confuse a strong demo with a robust system.&lt;/p&gt;
&lt;p&gt;I&apos;ve spent a lot of time building custom AI solutions at &lt;a href=&quot;https://ansezz.com/&quot;&gt;Ansezz&lt;/a&gt;, and one pattern keeps showing up: &lt;strong&gt;a demo proves possibility, but production demands precision.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;The &quot;vector noise&quot; trap&lt;/h2&gt;
&lt;p&gt;The philosophical shift from demo RAG to production RAG is simple: in a demo, semantic resemblance often feels good enough. In production, &quot;good enough&quot; is where failures begin.&lt;/p&gt;
&lt;p&gt;Embeddings are useful. They let us map text into vectors and retrieve by meaning rather than exact wording. That is powerful. But semantic similarity is not the same thing as retrieval accuracy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The problem.&lt;/strong&gt; Vector search is strong at finding related concepts, but weak at handling specificity.&lt;/p&gt;
&lt;p&gt;If a user searches for &lt;em&gt;&quot;Project-X-99 deployment logs,&quot;&lt;/em&gt; a vector search might return documents about &quot;Project-A deployment&quot; or &quot;logging best practices&quot; because they are semantically close. It can miss the exact identifier &quot;X-99&quot; because that string carries little semantic weight in a high-dimensional space.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The agitation.&lt;/strong&gt; Once retrieval drifts, the LLM inherits the drift. The model cannot reason its way out of missing or irrelevant context. You end up paying for tokens that produce confident but unhelpful answers, and users lose trust for a reason that often sits one layer below the model itself.&lt;/p&gt;
&lt;h2&gt;The solution: hybrid search (vector + BM25)&lt;/h2&gt;
&lt;p&gt;The move from demo RAG to production RAG usually starts with one realization: meaning alone is not enough. You need semantic retrieval and lexical precision working together. This is &lt;strong&gt;hybrid search&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/why-your-rag-is-failing/hybrid-search-workflow.webp&quot; alt=&quot;Hybrid search workflow combining vector and BM25 retrieval&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;What is BM25?&lt;/h3&gt;
&lt;p&gt;BM25 (Best Matching 25) is the standard lexical ranking method behind classic search systems. It does not try to infer meaning. It rewards exact terms based on how important they are within a document and across the collection.&lt;/p&gt;
&lt;h3&gt;Why you need both&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vector search&lt;/strong&gt; handles synonyms, multi-lingual queries, and conceptual matching.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BM25 search&lt;/strong&gt; handles exact matches, IDs, SKUs, product codes, and technical jargon.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Production systems need both because user questions are rarely pure meaning or pure keyword. They are usually a mix of the two.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/why-your-rag-is-failing/vector-vs-keyword.webp&quot; alt=&quot;Side-by-side comparison of vector search vs keyword search results&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Technical insight: reciprocal rank fusion (RRF)&lt;/h2&gt;
&lt;p&gt;When you run two different retrieval strategies, you also create a new design problem: how should they be combined?&lt;/p&gt;
&lt;p&gt;A practical answer is &lt;strong&gt;Reciprocal Rank Fusion (RRF)&lt;/strong&gt;. It is simple, reliable, and does not require you to pretend that scores from different retrieval systems are directly comparable.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/why-your-rag-is-failing/rrf-code-logic.webp&quot; alt=&quot;Annotated code snippet for reciprocal rank fusion logic&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The logic breakdown:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Assign a score.&lt;/strong&gt; For every document returned by either search method, calculate a new rank-based score.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The formula.&lt;/strong&gt; &lt;code&gt;score = 1 / (rank + k)&lt;/code&gt;. The &lt;code&gt;k&lt;/code&gt; value (often 60) prevents lower-ranked items from contributing too aggressively.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sum it up.&lt;/strong&gt; If a document appears in both the vector and BM25 result sets, its scores are added together.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sort.&lt;/strong&gt; The documents with the highest combined scores are passed to the LLM.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&apos;s the minimal PHP version I drop into a Laravel service:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function reciprocalRankFusion(array $resultSets, int $k = 60): array
{
    $scores = [];

    foreach ($resultSets as $results) {
        foreach ($results as $rank =&amp;gt; $docId) {
            $scores[$docId] = ($scores[$docId] ?? 0.0) + 1 / ($rank + 1 + $k);
        }
    }

    arsort($scores);

    return $scores;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives you a cleaner retrieval layer. If a document is semantically relevant &lt;em&gt;and&lt;/em&gt; lexically precise, it moves toward the top for a reason.&lt;/p&gt;
&lt;h2&gt;The &quot;second pass&quot;: using re-rankers&lt;/h2&gt;
&lt;p&gt;Hybrid search is a strong retrieval foundation, but production RAG usually needs one more layer of judgment.&lt;/p&gt;
&lt;p&gt;If you want more precise results, add a &lt;strong&gt;re-ranker&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A re-ranker such as Cohere Rerank or BGE-Reranker is a cross-encoder model that evaluates the query and the document together. That matters because relevance is relational. It is not just about what a document contains. It is about whether that document answers &lt;em&gt;this&lt;/em&gt; question.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Step 1.&lt;/strong&gt; Retrieve the top 50 results using hybrid search.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Step 2.&lt;/strong&gt; Pass those 50 results through a re-ranker.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Step 3.&lt;/strong&gt; Send only the top 5 re-ranked results to your LLM.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This reduces context stuffing and improves the quality of what reaches the model. In practice, it is one of the clearest differences between a RAG demo and a production RAG system that behaves consistently.&lt;/p&gt;
&lt;h2&gt;Your production RAG checklist&lt;/h2&gt;
&lt;h3&gt;The problem&lt;/h3&gt;
&lt;p&gt;A RAG system can feel impressive in a demo and still be structurally weak in production.&lt;/p&gt;
&lt;h3&gt;The agitation&lt;/h3&gt;
&lt;p&gt;Once real users, messy documents, and ambiguous queries enter the picture, weak retrieval turns the LLM into expensive guesswork. That is when confidence and correctness start drifting apart.&lt;/p&gt;
&lt;h3&gt;The solution&lt;/h3&gt;
&lt;p&gt;To move from demo RAG to production RAG, I focus on a few non-negotiables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Stop relying on vector-only search.&lt;/strong&gt; Add a BM25 layer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implement RRF.&lt;/strong&gt; Fuse lexical and semantic retrieval without overcomplicating score calibration.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tune chunking deliberately.&lt;/strong&gt; If chunks are too small, they lose context. If they are too large, they add noise. I usually find 512–1024 tokens with a 10–15% overlap works well for technical documentation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add a re-ranker.&lt;/strong&gt; Refine the final candidate set before anything reaches the LLM.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Evaluate with RAGAS.&lt;/strong&gt; Measure faithfulness and relevance instead of trusting intuition.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Building AI is easy. Building &lt;em&gt;reliable&lt;/em&gt; AI is hard. It requires a deeper understanding of retrieval, ranking, and context design, not just the ability to connect an API.&lt;/p&gt;
&lt;p&gt;If you are looking to build a high-performance SaaS or need help modernizing your digital presence with AI that actually works, check out what I do at &lt;a href=&quot;https://ansezz.com/work/&quot;&gt;Ansezz&lt;/a&gt;. I specialize in solving these exact types of technical problems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where does your own system still behave like a demo when it should be behaving like production?&lt;/strong&gt; &lt;a href=&quot;https://ansezz.com/contact/&quot;&gt;Get in touch&lt;/a&gt; — I read every war story.&lt;/p&gt;
</content:encoded><category>ai</category><category>rag</category><category>ai</category><category>vector-search</category><category>bm25</category><category>hybrid-search</category><category>re-ranker</category><category>production</category></item><item><title>Picking the right RAG stack: vector databases for AI engineering</title><link>https://ansezz.com/blog/picking-the-right-rag-stack/</link><guid isPermaLink="true">https://ansezz.com/blog/picking-the-right-rag-stack/</guid><description>pgvector, Pinecone, Weaviate, Qdrant — a 2026 field guide. Which vector store to pick for your AI app, why hybrid search matters, and how to ship without painting yourself into a corner.</description><pubDate>Sun, 14 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You built a cool chatbot. It works great on your local machine until you feed it 50,000 internal documents. Suddenly, it&apos;s hallucinating. It&apos;s slow. It&apos;s pulling data from three years ago when you specifically asked for last week&apos;s report.&lt;/p&gt;
&lt;p&gt;Building a Retrieval-Augmented Generation (RAG) system sounds like a weekend project. But once you move past the &quot;hello world&quot; stage, you hit the database wall. Choosing the wrong vector store early on is a silent killer. It leads to high latency, soaring cloud costs, and a painful migration six months down the line when your data outgrows your infrastructure.&lt;/p&gt;
&lt;p&gt;I&apos;ve spent over a decade building &lt;a href=&quot;https://ansezz.com/&quot;&gt;custom web applications&lt;/a&gt; and scaling cloud infrastructure. I&apos;ve seen teams get paralyzed by the sheer number of options in the AI ecosystem. You don&apos;t need a perfect database. You need the right tool for your specific scale and team.&lt;/p&gt;
&lt;p&gt;Let&apos;s break down the 2026 vector database landscape so you can stop scrolling and start shipping.&lt;/p&gt;
&lt;h2&gt;Why the database matters in RAG&lt;/h2&gt;
&lt;p&gt;An LLM like Claude or GPT-4 is a genius without a memory. RAG gives it that memory. Your vector database is the librarian. If the librarian is slow or loses books, the genius can&apos;t do its job.&lt;/p&gt;
&lt;p&gt;When we talk about RAG stacks, we&apos;re looking for three things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Latency&lt;/strong&gt; — can it find the right &quot;memory&quot; in under 50ms?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hybrid search&lt;/strong&gt; — can it search by meaning (vectors) and exact keywords (full-text)?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Developer experience&lt;/strong&gt; — how much time are you going to spend on DevOps?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/picking-the-right-rag-stack/comparison-bento.webp&quot; alt=&quot;Comparison bento grid of vector databases&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;The contenders: which one is yours?&lt;/h2&gt;
&lt;h3&gt;1. pgvector — the &quot;I already have a database&quot; choice&lt;/h3&gt;
&lt;p&gt;If you are already running &lt;a href=&quot;https://ansezz.com/&quot;&gt;Postgres for your web applications&lt;/a&gt;, pgvector is usually your first stop. It&apos;s not a new database. It&apos;s an extension that adds vector support to the database you already trust.&lt;/p&gt;
&lt;p&gt;It&apos;s perfect if you have under 10 million vectors. You get ACID compliance, easy backups, and your relational data stays right next to your embeddings. No new infra. No new security audits.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Zero new infrastructure if you use Postgres.&lt;/li&gt;
&lt;li&gt;Perfect for joining vector data with user metadata.&lt;/li&gt;
&lt;li&gt;Huge ecosystem support (Laravel, Django, Node.js).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scaling to 100M+ vectors requires serious server muscle.&lt;/li&gt;
&lt;li&gt;Hybrid search requires manual tuning with Postgres full-text search.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Pinecone — the &quot;I want zero ops&quot; choice&lt;/h3&gt;
&lt;p&gt;Pinecone is the gold standard for managed service. It&apos;s a serverless vector database. You don&apos;t manage clusters. You don&apos;t tune indexes. You just send vectors and get results.&lt;/p&gt;
&lt;p&gt;In 2026, Pinecone is the go-to for teams that want to scale from zero to a billion vectors without hiring a dedicated DevOps engineer. Their serverless architecture means you only pay for what you use.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Truly managed. Pick a region and go.&lt;/li&gt;
&lt;li&gt;World-class performance and low latency.&lt;/li&gt;
&lt;li&gt;Great enterprise features like SOC2 compliance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&apos;s a black box. You can&apos;t self-host it.&lt;/li&gt;
&lt;li&gt;Costs can scale quickly if you have high write/read volume.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. Weaviate &amp;amp; Qdrant — the hybrid powerhouses&lt;/h3&gt;
&lt;p&gt;If your RAG app needs to combine semantic search with old-school keyword search, these two are the leaders. Weaviate and Qdrant are built from the ground up for high-performance vector retrieval.&lt;/p&gt;
&lt;p&gt;Weaviate excels at &quot;out-of-the-box&quot; hybrid search. Qdrant, written in Rust, is incredibly fast and efficient with memory. Both offer open-source versions and managed cloud options.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Best-in-class hybrid search (BM25 + Vector).&lt;/li&gt;
&lt;li&gt;Flexible hosting (self-hosted Docker or managed cloud).&lt;/li&gt;
&lt;li&gt;Highly optimized for filtering (e.g., &quot;find documents from &apos;2025&apos; that talk about &apos;security&apos;&quot;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;More operational overhead than Pinecone.&lt;/li&gt;
&lt;li&gt;Requires learning a new database API.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/picking-the-right-rag-stack/rag-architecture.webp&quot; alt=&quot;Reference RAG architecture diagram&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;How to choose: the engineering trade-offs&lt;/h2&gt;
&lt;p&gt;Picking a database isn&apos;t about finding the &quot;best&quot; one. It&apos;s about matching the tool to your engineering constraints.&lt;/p&gt;
&lt;h3&gt;Factor 1: the &quot;billions&quot; problem&lt;/h3&gt;
&lt;p&gt;Most startups don&apos;t have a billion vectors. They have a few thousand PDFs. If you&apos;re in the sub-1M range, pgvector is almost always the right answer. It&apos;s simple and it works.&lt;/p&gt;
&lt;p&gt;If you are building something like a global legal search engine or a massive e-commerce recommendation system, you need the distributed architecture of Milvus or Pinecone. Don&apos;t build a massive distributed system if you don&apos;t have a massive amount of data.&lt;/p&gt;
&lt;h3&gt;Factor 2: hybrid search is non-negotiable&lt;/h3&gt;
&lt;p&gt;Pure vector search is actually pretty bad at finding specific technical terms. If you search for &quot;PHP 8.4 features,&quot; a pure vector search might give you general &quot;PHP&quot; articles. A hybrid search combines the &quot;vibe&quot; of the vector with the &quot;exactness&quot; of a keyword search.&lt;/p&gt;
&lt;p&gt;If search quality is your #1 metric, look at Weaviate or Qdrant. They handle the blending of these two search types natively.&lt;/p&gt;
&lt;h3&gt;Factor 3: the &quot;DevOps&quot; tax&lt;/h3&gt;
&lt;p&gt;I&apos;m a huge fan of &lt;a href=&quot;https://ansezz.com/&quot;&gt;cloud infrastructure and deployment&lt;/a&gt;. But I also know that every new piece of infra you add to your stack is another thing that can break at 3 AM.&lt;/p&gt;
&lt;p&gt;If you have a small team, lean on managed services like Pinecone or Zilliz. If you have a strong infra team and want to save on cloud margins at high scale, self-hosting Qdrant on a tool like Coolify or Kubernetes is the move.&lt;/p&gt;
&lt;h2&gt;Implementing pgvector with Laravel&lt;/h2&gt;
&lt;p&gt;Since I work a lot with &lt;a href=&quot;https://ansezz.com/&quot;&gt;custom web development using Laravel&lt;/a&gt;, I want to show you how easy this looks in practice. You don&apos;t need a PhD in math to run a vector query.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// finding the most relevant document chunks
$embedding = Ai::embed($query); // get vector from OpenAI/Claude

$results = Document::query()
    -&amp;gt;select(&apos;content&apos;)
    -&amp;gt;orderByRaw(&apos;embedding &amp;lt;=&amp;gt; ?&apos;, [$embedding]) // the &amp;lt;=&amp;gt; operator is pgvector&apos;s magic
    -&amp;gt;limit(5)
    -&amp;gt;get();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That snippet is essentially the core of a RAG system. You find the content, send it to the LLM, and get a grounded answer.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/picking-the-right-rag-stack/code-snippet.webp&quot; alt=&quot;Annotated code snippet showing pgvector similarity query&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Three practical tips for your RAG stack&lt;/h2&gt;
&lt;p&gt;Before you commit to a database, keep these three things in mind. They will save you weeks of refactoring.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Index early, but not too early.&lt;/strong&gt;
Vector indexes like HNSW are fast for searching but slow for inserting data. If you are doing a massive initial data load, insert your vectors first, then create the index. It&apos;s the difference between minutes and hours.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Normalize your vectors.&lt;/strong&gt;
Make sure your embedding model and your vector database are on the same page. If you use cosine similarity, normalize your vectors. It keeps your results consistent and prevents weird ranking bugs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Keep the metadata lean.&lt;/strong&gt;
It&apos;s tempting to store the entire JSON object of a document inside your vector database. Don&apos;t. Store the vector and a simple ID. Keep the heavy data in your primary database (like Postgres). This keeps your vector index small and fast.&lt;/p&gt;
&lt;h2&gt;My personal rule of thumb&lt;/h2&gt;
&lt;p&gt;I&apos;ve built systems for &lt;a href=&quot;https://ansezz.com/work/&quot;&gt;startups and established businesses&lt;/a&gt;. Here is how I usually guide them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Default to pgvector.&lt;/strong&gt; It&apos;s the path of least resistance for most web apps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Move to Pinecone&lt;/strong&gt; if you need high performance and don&apos;t want to manage servers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose Weaviate&lt;/strong&gt; if your application relies heavily on complex hybrid search and metadata filtering.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &quot;right&quot; stack is the one that lets you ship your AI features today, not the one that looks the best on a benchmark chart.&lt;/p&gt;
&lt;p&gt;Are you building a RAG system right now? What&apos;s the biggest hurdle you&apos;ve hit with your data retrieval?&lt;/p&gt;
&lt;p&gt;Drop a line or &lt;a href=&quot;https://ansezz.com/contact/&quot;&gt;reach out&lt;/a&gt;. I&apos;d love to hear your war stories.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;Summary takeaways&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;pgvector&lt;/strong&gt; is king for teams already on Postgres.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pinecone&lt;/strong&gt; is the best zero-ops solution for scaling.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hybrid search&lt;/strong&gt; (keyword + vector) is usually better than vector search alone.&lt;/li&gt;
&lt;li&gt;Keep your architecture simple. Don&apos;t over-engineer for &quot;billions&quot; of vectors if you only have thousands.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/picking-the-right-rag-stack/mentor.webp&quot; alt=&quot;Mentor robot character offering advice&quot; /&gt;&lt;/p&gt;
</content:encoded><category>ai</category><category>rag</category><category>vector-databases</category><category>pgvector</category><category>pinecone</category><category>weaviate</category><category>qdrant</category><category>laravel</category></item><item><title>Vibe coding: why your next project needs more than just logic</title><link>https://ansezz.com/blog/vibe-coding/</link><guid isPermaLink="true">https://ansezz.com/blog/vibe-coding/</guid><description>Logic is the skeleton. Vibe is the soul. Why taste, intent, and feel are the new senior-engineer superpowers in the Cursor + Claude era — and how to keep the codebase from turning into a ball of mud while you chase it.</description><pubDate>Sun, 30 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Most developers are obsessed with logic. We spend years mastering syntax, optimizing database queries, and debating the merits of different architectural patterns. We build systems that are technically perfect but somehow feel completely hollow. They work, but they don&apos;t sing.&lt;/p&gt;
&lt;p&gt;The problem is that your users don&apos;t care about your clean code or your clever recursive functions. They care about how the software feels. They care about the &quot;vibe.&quot;&lt;/p&gt;
&lt;p&gt;If you keep building purely for the machine, you are going to lose. The next generation of successful products won&apos;t be the ones with the most features or the tightest algorithms. They will be the ones that master the art of vibe coding.&lt;/p&gt;
&lt;h2&gt;The logic trap&lt;/h2&gt;
&lt;p&gt;I&apos;ve spent over a decade in the trenches of software development. I&apos;ve built custom web applications for startups and managed complex cloud infrastructure on Google Cloud and AWS. For a long time, I thought my job was to be a logic machine. I thought that if I followed every best practice and wrote the most efficient Laravel code possible, the project would be a success.&lt;/p&gt;
&lt;p&gt;I was wrong.&lt;/p&gt;
&lt;p&gt;Logic is just the foundation. It is the skeleton that keeps the building from falling down. But nobody wants to live in a skeleton. People want a home with character, warmth, and a specific feeling. In software, that character comes from the vibe.&lt;/p&gt;
&lt;p&gt;When we focus purely on logic, we end up with &quot;boring&quot; software. It is the kind of software that does what it says on the tin but leaves the user feeling nothing. Or worse, it feels frustrating because the developer didn&apos;t think about the emotional friction of a slow-loading button or a confusing layout.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/vibe-coding/logic-vs-vibe.webp&quot; alt=&quot;Side-by-side illustration of cold logic vs warm vibe coding&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Entering the era of vibe coding&lt;/h2&gt;
&lt;p&gt;The term &quot;vibe coding&quot; was popularized recently by Andrej Karpathy. It describes a shift in how we build things in the age of AI tools like Cursor and Claude. It is a transition from being a writer of code to being a curator of intent.&lt;/p&gt;
&lt;p&gt;Vibe coding is about letting go of the need to micro-manage every semicolon. It is about using natural language to describe the &lt;em&gt;feel&lt;/em&gt; and &lt;em&gt;behavior&lt;/em&gt; you want, and then letting AI handle the heavy lifting of the implementation.&lt;/p&gt;
&lt;p&gt;In this world, your value as an engineer isn&apos;t in how fast you can type. It&apos;s in your taste. It&apos;s in your ability to recognize when a user interface feels &quot;off&quot; and knowing how to steer the AI to fix it. It is about prioritizing the outcome over the output.&lt;/p&gt;
&lt;p&gt;I&apos;ve seen this shift firsthand in my own work at &lt;a href=&quot;https://ansezz.com/&quot;&gt;Ansezz&lt;/a&gt;. When I&apos;m working on a Shopify store development project, the technical logic of the checkout is important. But the &lt;em&gt;vibe&lt;/em&gt; of the checkout — the smooth transitions, the reassuring feedback, the perfect typography — is what actually drives conversions for the business.&lt;/p&gt;
&lt;h2&gt;Tools that fuel the flow&lt;/h2&gt;
&lt;p&gt;To embrace vibe coding, you need tools that don&apos;t get in your way. You need tools that allow you to stay in a state of flow where the distance between your idea and the execution is as small as possible.&lt;/p&gt;
&lt;p&gt;Tools like Cursor have changed the game for me. Instead of spending twenty minutes setting up boilerplate for a new Vue component, I can describe the &quot;vibe&quot; of the component in the chat. I can say, &quot;build me a dashboard widget that feels airy and modern, uses a bento grid layout, and gives the user a sense of calm control over their data.&quot;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/vibe-coding/ai-ide.webp&quot; alt=&quot;AI-powered IDE pairing with a developer&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The AI generates the code. I review it. If the vibe isn&apos;t right, I don&apos;t fix the code line-by-line. I talk to the model again. I give it feedback on the &lt;em&gt;feeling&lt;/em&gt;. &quot;This feels too cramped. Give it more white space and make the shadows softer.&quot;&lt;/p&gt;
&lt;p&gt;This is the essence of vibe coding. It&apos;s a high-level conversation about intent.&lt;/p&gt;
&lt;h2&gt;The senior developer guardrails&lt;/h2&gt;
&lt;p&gt;Now, I know what some of you are thinking. &quot;This sounds like a recipe for a messy, unmaintainable codebase.&quot;&lt;/p&gt;
&lt;p&gt;You are right to be worried. If you just &quot;vibe&quot; your way through a project without any discipline, you will end up with a &quot;ball of mud.&quot; This is where the senior engineer perspective becomes more critical than ever.&lt;/p&gt;
&lt;p&gt;Vibe coding isn&apos;t about being lazy. It&apos;s about shifting your focus. You use your senior-level expertise to build the &quot;robust core&quot; that allows the &quot;vibe layer&quot; to exist.&lt;/p&gt;
&lt;p&gt;For me, that core is often built with Laravel and Docker. I use Laravel because it is built for &quot;developer happiness.&quot; The framework itself has a vibe of elegance and simplicity. It provides the solid, logical foundation — the authentication, the database migrations, the API structures — that I can trust.&lt;/p&gt;
&lt;p&gt;Once that robust core is in place, I can afford to be more exploratory with the frontend and the user experience. I can &quot;vibe code&quot; the top layer because I know the foundation is solid.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ansezz.com/blog/vibe-coding/architecture.webp&quot; alt=&quot;Architecture diagram — robust core under the vibe layer&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Why Shopify and vibe coding are a perfect match&lt;/h2&gt;
&lt;p&gt;If you work in e-commerce, vibe coding is your secret weapon. Shopify is a platform that already understands the importance of the feel. They have spent years perfecting the checkout flow and the admin experience.&lt;/p&gt;
&lt;p&gt;When I do &lt;a href=&quot;https://ansezz.com/work/&quot;&gt;Shopify customization&lt;/a&gt;, I&apos;m not just writing Liquid code. I&apos;m trying to match the brand&apos;s vibe. A luxury jewelry brand needs a completely different &quot;vibe&quot; than a high-energy fitness store.&lt;/p&gt;
&lt;p&gt;One should feel slow, deliberate, and expensive. The other should feel fast, punchy, and motivating. You can&apos;t achieve that through logic alone. You achieve it by obsessing over the details that the logic-only dev ignores.&lt;/p&gt;
&lt;h2&gt;How to start vibe coding today&lt;/h2&gt;
&lt;p&gt;If you want to move beyond being a logic-only developer, here are some practical steps you can take:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Prioritize your taste.&lt;/strong&gt; Start looking at software not just as a tool, but as an experience. What apps do you love using? Why? Is it the speed? The animations? The way the buttons click? Start building a &quot;swipe file&quot; of great vibes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Embrace AI as a partner, not a tool.&lt;/strong&gt; Stop using Copilot just for autocompletion. Start using tools like Claude or Cursor to brainstorm high-level concepts. Describe the &quot;feel&quot; you want and see what it gives you.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build a solid core.&lt;/strong&gt; Don&apos;t let the vibe turn into chaos. Use frameworks like Laravel or tools like Docker to keep your infrastructure predictable and clean. The more you trust your foundation, the more you can play with the surface.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Iterate on the feeling.&lt;/strong&gt; Instead of trying to get the code perfect the first time, get the &quot;vibe&quot; right first. Build a messy prototype that feels great, and then use your technical skills to refactor and harden it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Focus on user empathy.&lt;/strong&gt; Every time you write a piece of logic, ask yourself: &quot;how will this make the user feel?&quot; If the answer is &quot;nothing,&quot; you have more work to do.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;The future is felt, not just calculated&lt;/h2&gt;
&lt;p&gt;We are entering a time where &quot;coding&quot; as we knew it is becoming a commodity. Anyone can generate a function to sort an array. But not everyone can create an experience that moves people.&lt;/p&gt;
&lt;p&gt;The future of software development belongs to the engineers who can bridge the gap between the machine and the human heart. It belongs to the people who understand that the best code is the code you don&apos;t even notice because you&apos;re too busy enjoying the vibe.&lt;/p&gt;
&lt;p&gt;I&apos;ve seen the results of this approach in my own projects and for the clients I work with. When you stop fighting the logic and start leaning into the flow, everything becomes easier. The work becomes more fun, and the results become more impactful.&lt;/p&gt;
&lt;p&gt;Are you ready to stop just writing logic and start building vibes?&lt;/p&gt;
&lt;p&gt;What is the one app you use that just &quot;feels&quot; right, and what can you steal from its vibe for your next project?&lt;/p&gt;
</content:encoded><category>ai</category><category>vibe-coding</category><category>ai</category><category>cursor</category><category>claude</category><category>taste</category><category>dx</category><category>laravel</category></item></channel></rss>