<?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: VLAD</title>
    <description>The latest articles on DEV Community by VLAD (@vladut02).</description>
    <link>https://dev.to/vladut02</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%2F4103356%2F7cf1ab18-c024-449c-8297-4c1143045611.jpg</url>
      <title>DEV Community: VLAD</title>
      <link>https://dev.to/vladut02</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vladut02"/>
    <language>en</language>
    <item>
      <title>Embeddings explained for people who write code</title>
      <dc:creator>VLAD</dc:creator>
      <pubDate>Fri, 18 Sep 2026 22:08:01 +0000</pubDate>
      <link>https://dev.to/vladut02/embeddings-explained-for-people-who-write-code-5aja</link>
      <guid>https://dev.to/vladut02/embeddings-explained-for-people-who-write-code-5aja</guid>
      <description>&lt;p&gt;Type &lt;em&gt;"how do I reset my password"&lt;/em&gt; into a good search box, and it finds a page titled &lt;em&gt;"account recovery."&lt;/em&gt; Zero words in common. Nothing matched on text. So how did it know they mean the same thing?&lt;/p&gt;

&lt;p&gt;Your app turned &lt;strong&gt;meaning into numbers&lt;/strong&gt; — and once meaning is numbers, a computer can measure it. That trick is called an &lt;strong&gt;embedding&lt;/strong&gt;. Get this one idea and half the AI buzzwords — "vector search," "cosine similarity," "vector database" — stop being scary.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefer to watch? Full walkthrough with the meaning-space animation:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/MfBKyEhz-x8?start=3" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  An embedding is a list of numbers
&lt;/h2&gt;

&lt;p&gt;Start with the machine itself. You hand it a piece of text — a word, a sentence, a whole paragraph. It hands back a &lt;strong&gt;list of numbers&lt;/strong&gt;. That list &lt;em&gt;is&lt;/em&gt; the embedding. Same text in, same numbers out, every time.&lt;/p&gt;

&lt;p&gt;How long is the list? For a common model — OpenAI's &lt;a href="https://platform.openai.com/docs/guides/embeddings" rel="noopener noreferrer"&gt;&lt;code&gt;text-embedding-3-small&lt;/code&gt;&lt;/a&gt; — it's &lt;strong&gt;1,536&lt;/strong&gt; numbers. That sounds like a lot, until you think of each number as a &lt;strong&gt;coordinate&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Two numbers place a point on a map. Three place it in a room. 1,536 place it in a space you can't picture — but the math works exactly the same as the map.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meaning becomes position
&lt;/h2&gt;

&lt;p&gt;Here's the whole point of that space: the model places text so that &lt;strong&gt;similar meaning lands in a similar spot&lt;/strong&gt;. "cat" and "dog" end up as neighbors. "car" ends up far away.&lt;/p&gt;

&lt;p&gt;Nobody wrote that rule. The model &lt;strong&gt;learned&lt;/strong&gt; it — it read a mountain of text and noticed which words keep the same company. Words used the same way get pushed together; words used differently get pushed apart. This is an old idea from linguistics called the &lt;a href="https://en.wikipedia.org/wiki/Distributional_semantics" rel="noopener noreferrer"&gt;distributional hypothesis&lt;/a&gt;: a word's meaning is shaped by the words it usually appears next to. Meaning, in this space, is just &lt;strong&gt;where you land&lt;/strong&gt; relative to everything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Cosine similarity" is just an angle
&lt;/h2&gt;

&lt;p&gt;Now the real question in search: are these two things &lt;em&gt;close&lt;/em&gt;? You embed the question, you embed every document, and you grab the points &lt;strong&gt;nearest&lt;/strong&gt; the question. But "nearest" means one specific thing — and it's simpler than it sounds.&lt;/p&gt;

&lt;p&gt;Draw an arrow from the center of the space out to each point.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Two texts with &lt;strong&gt;similar&lt;/strong&gt; meaning? Their arrows point almost the same way — a &lt;strong&gt;small angle&lt;/strong&gt; between them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unrelated&lt;/strong&gt; texts? The arrows point off in different directions — a wide angle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That angle &lt;em&gt;is&lt;/em&gt; cosine similarity. A value near &lt;strong&gt;1&lt;/strong&gt; means the arrows point the same way (very similar). A value near &lt;strong&gt;0&lt;/strong&gt; means they're unrelated. That's the whole comparison — "cosine similarity" is just measuring the angle between two arrows.&lt;/p&gt;

&lt;h2&gt;
  
  
  In code, it's three lines
&lt;/h2&gt;

&lt;p&gt;Every "AI search" feature you've used is basically this, under a nicer name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;account recovery steps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;// → [0.02, -0.91, …] · 1536 numbers&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;how do I reset my password?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// cosine: 1 = same direction, 0 = unrelated&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cosine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                   &lt;span class="c1"&gt;// ≈ 0.86 — close&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Embed your text, embed your query, compare them, keep the closest. (Those scores are illustrative — the real point is &lt;em&gt;high = same direction&lt;/em&gt;.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Trap 1: the numbers only make sense inside one model
&lt;/h2&gt;

&lt;p&gt;These coordinates are only meaningful &lt;strong&gt;within a single model&lt;/strong&gt;. A vector from model A and a vector from model B are not comparable — it's gibberish. Same coordinates, different maps.&lt;/p&gt;

&lt;p&gt;So embed your query and your documents with the &lt;strong&gt;exact same model&lt;/strong&gt;, always. Change the model, and you have to re-embed everything you're searching over.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trap 2: embeddings capture meaning, not exact strings
&lt;/h2&gt;

&lt;p&gt;Embeddings are great at meaning — which makes them bad at things that &lt;em&gt;have&lt;/em&gt; no meaning. An error code. A product ID. &lt;code&gt;SKU-4417&lt;/code&gt;. There's nothing to place on the meaning-map; it's just an exact string, and pure vector search fumbles it, because nothing is "close in meaning" to a serial number.&lt;/p&gt;

&lt;p&gt;That's why real systems run &lt;strong&gt;both&lt;/strong&gt;: keyword search to catch exact strings, vector search to catch meaning, and the results merged. If you've built RAG and watched it miss an obvious error code, this is usually why.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;An embedding, start to finish:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Text becomes a list of numbers.&lt;/li&gt;
&lt;li&gt;The numbers are coordinates in a meaning-space.&lt;/li&gt;
&lt;li&gt;Close in meaning → close in space.&lt;/li&gt;
&lt;li&gt;"Similarity" is just the angle between two arrows.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once you see it as numbers on a map, the buzzwords fall away — and you can actually &lt;strong&gt;debug&lt;/strong&gt; your search instead of trusting it. When a result looks wrong, you're not staring at magic; you're asking a concrete question about distance on a map.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the weirdest match your vector search ever returned — the one that made no sense at all?&lt;/strong&gt; Drop it in the comments — I read them.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I make &lt;a href="https://www.youtube.com/channel/UCUO8Uo5LsEy1b9eRkrH6JNg" rel="noopener noreferrer"&gt;Vlad's Stack&lt;/a&gt; — how the tools you use every day actually work, for people who write code. Full video walkthrough is above.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>embeddings</category>
      <category>ai</category>
      <category>machinelearning</category>
      <category>vectordatabase</category>
    </item>
    <item>
      <title>SQL vs. NoSQL — stop asking the wrong question</title>
      <dc:creator>VLAD</dc:creator>
      <pubDate>Mon, 07 Sep 2026 00:37:44 +0000</pubDate>
      <link>https://dev.to/vladut02/sql-vs-nosql-stop-asking-the-wrong-question-3gm</link>
      <guid>https://dev.to/vladut02/sql-vs-nosql-stop-asking-the-wrong-question-3gm</guid>
      <description>&lt;p&gt;Two teams build the same app. One picks SQL. One picks NoSQL. Six months later, one team is rewriting their whole data layer — and it's not because they picked the &lt;em&gt;wrong&lt;/em&gt; database. It's because they asked the wrong &lt;em&gt;question&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Everyone fights about which one is faster, or which one scales. That's the wrong fight. By the end of this you'll know the one question that actually decides it, and why three things you've heard about SQL and NoSQL are just wrong.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefer to watch? Full walkthrough with the JOIN-vs-document animation:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/wQXh4Vi1cFg" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The wrong question
&lt;/h2&gt;

&lt;p&gt;"Which one is faster?" "Which one is modern?" "Which one scales?"&lt;/p&gt;

&lt;p&gt;None of these pick your database. Speed and scale depend on &lt;em&gt;how you use&lt;/em&gt; a database, not on which logo you chose. You can make either one fast, and you can make either one fall over.&lt;/p&gt;

&lt;h2&gt;
  
  
  The right question
&lt;/h2&gt;

&lt;p&gt;What &lt;strong&gt;shape&lt;/strong&gt; is your data — and how will you &lt;strong&gt;read it back&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Answer that, and the database almost picks itself. Here's what that means.&lt;/p&gt;

&lt;h2&gt;
  
  
  SQL: a relational database
&lt;/h2&gt;

&lt;p&gt;In SQL, your data lives in &lt;strong&gt;tables&lt;/strong&gt; — rows and columns, like a spreadsheet with rules. You define the shape up front. That's the schema.&lt;/p&gt;

&lt;p&gt;The superpower is the &lt;strong&gt;JOIN&lt;/strong&gt;. You keep users in one table and orders in another, then stitch them together on the fly to answer almost any question:&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;SELECT&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"Every user, and how many times they ordered." You never &lt;em&gt;designed&lt;/em&gt; for that query — SQL answers it anyway. That flexibility is the whole point of a relational database.&lt;/p&gt;

&lt;p&gt;But it has a price. Your data is &lt;strong&gt;split&lt;/strong&gt; across tables (that's normalization), so to read one thing back, the database has to stitch those tables together on every read. Fine at normal size. So what does NoSQL do differently?&lt;/p&gt;

&lt;h2&gt;
  
  
  NoSQL isn't one thing
&lt;/h2&gt;

&lt;p&gt;First, an important correction: &lt;strong&gt;NoSQL isn't a single kind of database.&lt;/strong&gt; It's a family. The four categories you'll usually see are &lt;a href="https://www.mongodb.com/resources/basics/databases/nosql-explained" rel="noopener noreferrer"&gt;document, key-value, wide-column, and graph&lt;/a&gt; databases.&lt;/p&gt;

&lt;p&gt;They share one idea: you model your data around &lt;strong&gt;how you read it&lt;/strong&gt;. Store together what you read together.&lt;/p&gt;

&lt;p&gt;So instead of separate &lt;code&gt;users&lt;/code&gt; and &lt;code&gt;orders&lt;/code&gt; tables, you store one &lt;strong&gt;document&lt;/strong&gt; — the user, with their orders inside it:&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Vlad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"orders"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&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;span class="p"&gt;]&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;One read. Nothing to stitch. It's already assembled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Same question, two shapes
&lt;/h2&gt;

&lt;p&gt;That's the core difference. Ask "give me this user and their orders":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SQL&lt;/strong&gt; joins two tables at read time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NoSQL&lt;/strong&gt; hands you a document that was already built that way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same answer, different shape. And that's the whole trade. The document is &lt;strong&gt;faster — for the read you planned&lt;/strong&gt;. But now ask a &lt;em&gt;new&lt;/em&gt; question: "every order over $40, across all users." In SQL that's one line. In your documents, that data is buried in a thousand separate places, because you didn't store it that way.&lt;/p&gt;

&lt;p&gt;That's the trap that kills projects. You pick the shape for &lt;em&gt;today's&lt;/em&gt; question. Then the product grows, the questions change — and the shape can't. That's the team rewriting everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three myths, killed
&lt;/h2&gt;

&lt;p&gt;Three things you've probably heard push people toward the wrong choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Myth 1 — "NoSQL has no schema"
&lt;/h3&gt;

&lt;p&gt;False. The schema didn't disappear — it &lt;strong&gt;moved&lt;/strong&gt; into your application code. Every read still assumes a shape; you just gave up the database checking it for you.&lt;/p&gt;

&lt;p&gt;This even has a name: &lt;a href="https://martinfowler.com/articles/schemaless/" rel="noopener noreferrer"&gt;schema-on-read&lt;/a&gt;. As Martin Fowler puts it, a "schemaless" store still has an &lt;em&gt;implicit&lt;/em&gt; schema — the structure your code relies on when it reads the data — instead of an &lt;em&gt;explicit&lt;/em&gt; one enforced by the database. "Schemaless" doesn't mean no schema. It means you own it now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Myth 2 — "SQL can't scale"
&lt;/h3&gt;

&lt;p&gt;Also false. Postgres runs &lt;a href="https://www.postgresql.org/about/" rel="noopener noreferrer"&gt;massive&lt;/a&gt; production workloads, and you'll hit product problems long before it's your bottleneck. And when you genuinely outgrow a single node, &lt;strong&gt;distributed SQL&lt;/strong&gt; exists now — &lt;a href="https://www.cockroachlabs.com/" rel="noopener noreferrer"&gt;CockroachDB&lt;/a&gt;, &lt;a href="https://cloud.google.com/spanner" rel="noopener noreferrer"&gt;Google Cloud Spanner&lt;/a&gt;, and &lt;a href="https://vitess.io/" rel="noopener noreferrer"&gt;Vitess&lt;/a&gt; all give you horizontal scale without giving up SQL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Myth 3 — "NoSQL is faster"
&lt;/h3&gt;

&lt;p&gt;Only for the pattern it was built for. Ask it something off-pattern and it's slower — or it just can't answer without loading everything and filtering in your app. Fast isn't a property of the database. It's a property of the &lt;strong&gt;match&lt;/strong&gt; between your data's shape and your query.&lt;/p&gt;

&lt;h2&gt;
  
  
  So when do you use each?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relationships that matter, and questions that will change&lt;/strong&gt; → go relational (SQL).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One known access pattern, at huge scale&lt;/strong&gt; → that's where NoSQL wins.&lt;/li&gt;
&lt;li&gt;And you're allowed to use &lt;strong&gt;both&lt;/strong&gt; — plenty of systems put a relational database next to a key-value cache or a document store, each for what it's good at.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For most apps starting out, the boring answer is the right one: &lt;strong&gt;start with Postgres&lt;/strong&gt;, and reach for NoSQL when you have a real, specific reason — not a vibe.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;Stop asking which one is better. Ask what shape your data is, and how you'll read it back — and the database picks itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What made you reach for NoSQL last time — the scale, or the schema?&lt;/strong&gt; Drop it in the comments — I read them.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I make &lt;a href="https://www.youtube.com/channel/UCUO8Uo5LsEy1b9eRkrH6JNg" rel="noopener noreferrer"&gt;Vlad's Stack&lt;/a&gt; — how the tools you use every day actually work, for people who write code. Full video walkthrough is above.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>nosql</category>
      <category>database</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>What actually happens in a database index (and why half of them do nothing)</title>
      <dc:creator>VLAD</dc:creator>
      <pubDate>Sat, 05 Sep 2026 21:25:42 +0000</pubDate>
      <link>https://dev.to/vladut02/what-actually-happens-in-a-database-index-and-why-half-of-them-do-nothing-3mh6</link>
      <guid>https://dev.to/vladut02/what-actually-happens-in-a-database-index-and-why-half-of-them-do-nothing-3mh6</guid>
      <description>&lt;p&gt;Same query. Same table. Same million rows. One day it takes &lt;strong&gt;4 seconds&lt;/strong&gt;. The next day, &lt;strong&gt;4 milliseconds&lt;/strong&gt;. Nothing changed in the data. The only thing that changed was one line — you added an &lt;strong&gt;index&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Four seconds to four milliseconds is a thousand times faster, from one line of SQL. But here's the part nobody tells you: &lt;strong&gt;half&lt;/strong&gt; the indexes people add do nothing. The query stays slow, the writes get slower, and they can't figure out why.&lt;/p&gt;

&lt;p&gt;By the end of this you'll know what an index actually &lt;em&gt;is&lt;/em&gt; — and the one rule that decides whether yours even gets used.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefer to watch? Full walkthrough with the B-tree lookup animation:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/aNzoh7S3Ca0" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  With no index: a full table scan
&lt;/h2&gt;

&lt;p&gt;You ask the database for one user by email. With no index, what does it do?&lt;/p&gt;

&lt;p&gt;It reads the first row. Not a match. The second row. Not a match. It keeps going — every single row — until it finds yours or runs out. A million rows, a million checks.&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;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'vlad@stack.dev'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With no index, that &lt;code&gt;WHERE&lt;/code&gt; line has only one way to run: look at all of them. The work grows with the table — ten times the rows, ten times the wait. That's a &lt;strong&gt;full table scan&lt;/strong&gt;, and that's your four seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an index actually is
&lt;/h2&gt;

&lt;p&gt;Most people picture an index as a &lt;em&gt;copy&lt;/em&gt; of the table, or some kind of cache. It's neither.&lt;/p&gt;

&lt;p&gt;An index is a &lt;strong&gt;sorted map&lt;/strong&gt; — just the column you search on, kept in order, with a pointer back to the full row. And the shape it's sorted into has a name: a &lt;strong&gt;B-tree&lt;/strong&gt; (the default index in both Postgres and MySQL — technically a B+ tree).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At the top, one node — the &lt;strong&gt;root&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It splits into a few &lt;strong&gt;branches&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Each branch splits again, down to the &lt;strong&gt;leaves&lt;/strong&gt;, where the pointers to the rows actually live.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every node is sorted. The root doesn't hold your data — it holds &lt;strong&gt;signposts&lt;/strong&gt;. Emails before "M"? Go left. "N" and after? Go right. Each step throws away half the tree, or more. You're never reading rows. You're following signs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The walk: three hops, not a million rows
&lt;/h2&gt;

&lt;p&gt;Watch what the lookup actually does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The root — one hop.&lt;/li&gt;
&lt;li&gt;A branch — two.&lt;/li&gt;
&lt;li&gt;A leaf — &lt;strong&gt;found&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three hops. Not a million rows. Three.&lt;/p&gt;

&lt;p&gt;That's the whole trick. A scan checks &lt;em&gt;every&lt;/em&gt; row — that's the four seconds. A B-tree walk checks a &lt;em&gt;handful&lt;/em&gt; — that's the four milliseconds. Grow the table to ten million rows and the scan gets ten times worse, while the tree adds &lt;strong&gt;one&lt;/strong&gt; more hop. That's &lt;code&gt;O(n)&lt;/code&gt; versus &lt;code&gt;O(log n)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  So why not index everything?
&lt;/h2&gt;

&lt;p&gt;Because an index is &lt;strong&gt;not free&lt;/strong&gt;. It's a second structure the database has to keep in sync. Every time you insert a row, change that column, or delete one, the tree has to be updated too.&lt;/p&gt;

&lt;p&gt;Index the whole table, and your reads fly while your writes crawl.&lt;/p&gt;

&lt;p&gt;So an index is a &lt;strong&gt;trade&lt;/strong&gt;: faster reads, slower writes, more disk. You pay it on purpose — on the columns you actually search — not on all of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trap: an index your query can't use
&lt;/h2&gt;

&lt;p&gt;Here's the part that trips everyone up. You add the index. The query is &lt;strong&gt;still slow&lt;/strong&gt;. How?&lt;/p&gt;

&lt;p&gt;Because an index only helps if your query can actually &lt;em&gt;use&lt;/em&gt; it — and it's shockingly easy to write one that can't.&lt;/p&gt;

&lt;h3&gt;
  
  
  The phone-book rule
&lt;/h3&gt;

&lt;p&gt;Say you index two columns together — last name, then first name:&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;INDEX&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Search by &lt;strong&gt;last name&lt;/strong&gt;? Fast.&lt;/li&gt;
&lt;li&gt;Search by &lt;strong&gt;last and first&lt;/strong&gt;? Fast.&lt;/li&gt;
&lt;li&gt;Search by &lt;strong&gt;first name alone&lt;/strong&gt;? &lt;strong&gt;Scan.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tree is sorted by last name &lt;em&gt;first&lt;/em&gt;, so first name is useless without it. It's a phone book: perfect for finding "Smith," useless for finding every "John." This isn't a quirk of one database — B-tree indexes everywhere work &lt;strong&gt;left to right&lt;/strong&gt;, or not at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three more ways to quietly kill an index
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Leading wildcard:&lt;/strong&gt; &lt;code&gt;email LIKE '%dev'&lt;/code&gt; starts with a wildcard, so the tree can't seek — it scans.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function on the column:&lt;/strong&gt; wrap it in &lt;code&gt;lower(email)&lt;/code&gt; and your index on plain &lt;code&gt;email&lt;/code&gt; doesn't match.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low selectivity:&lt;/strong&gt; index a column that's half true, half false, and the database ignores it — a signpost that splits nothing saves nothing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;An index is a sorted &lt;strong&gt;B-tree&lt;/strong&gt;. It turns a full scan into a three-hop walk — but only if your query matches the way it's sorted. The &lt;strong&gt;order&lt;/strong&gt; of the columns isn't a detail. It &lt;em&gt;is&lt;/em&gt; the index. Get that order wrong, and you built a tree the query will never climb.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the slowest query you've ever fixed with a single index?&lt;/strong&gt; Drop it in the comments — I read them.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I make &lt;a href="https://www.youtube.com/channel/UCUO8Uo5LsEy1b9eRkrH6JNg" rel="noopener noreferrer"&gt;Vlad's Stack&lt;/a&gt; — how the tools you use every day actually work, for people who write code. Full video walkthrough is above.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>sql</category>
      <category>postgres</category>
      <category>performance</category>
    </item>
    <item>
      <title>Why more context makes your AI answers worse</title>
      <dc:creator>VLAD</dc:creator>
      <pubDate>Mon, 31 Aug 2026 22:16:08 +0000</pubDate>
      <link>https://dev.to/vladut02/why-more-context-makes-your-ai-answers-worse-555o</link>
      <guid>https://dev.to/vladut02/why-more-context-makes-your-ai-answers-worse-555o</guid>
      <description>&lt;p&gt;Your model says it has a one-million-token context window. Its real working memory is a lot smaller than that.&lt;/p&gt;

&lt;p&gt;On long-context benchmarks, models start failing well below the number printed on the box. And here's the part nobody warns you about: past a certain point, adding more context makes your answers &lt;strong&gt;worse&lt;/strong&gt;. Not better. Worse.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefer to watch? Full walkthrough with the attention-cost animation:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/hH7Ko-x1Bn8?start=3" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A context window is not memory
&lt;/h2&gt;

&lt;p&gt;Let's kill one idea first. A context window is &lt;strong&gt;not&lt;/strong&gt; memory.&lt;/p&gt;

&lt;p&gt;The model doesn't remember your last message — it's stateless. It keeps nothing between calls. Every single call, you send the whole conversation again. All of it.&lt;/p&gt;

&lt;p&gt;Look at what you actually ship over the wire:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Turn one:&lt;/strong&gt; a system prompt and one question. Small.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn ten:&lt;/strong&gt; the same system prompt, plus nine questions, plus nine answers, plus the new one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The window is just how much text fits in that box before the API says no. And everything in the box gets processed. Every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What attention actually does
&lt;/h2&gt;

&lt;p&gt;Inside the model, attention has a job that's simple to say: every token looks at every other token and decides how much it cares about each one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;10 tokens → 100 pairs&lt;/li&gt;
&lt;li&gt;1,000 tokens → &lt;strong&gt;1,000,000&lt;/strong&gt; pairs&lt;/li&gt;
&lt;li&gt;100,000 tokens → &lt;strong&gt;10,000,000,000&lt;/strong&gt; pairs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ten times the context isn't ten times the work. It's a hundred times the work. (That's just arithmetic: cost grows with the square of the input.)&lt;/p&gt;

&lt;p&gt;That's also why the first reply in a long chat feels slow and the rest feel fast — the model caches the keys and values it already computed. But the cache saves you &lt;em&gt;compute&lt;/em&gt;. It doesn't save your &lt;em&gt;answer quality&lt;/em&gt;. That's a separate problem, and it's the one you actually feel.&lt;/p&gt;

&lt;p&gt;Here are the three reasons big context hurts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 1 — attention is a budget
&lt;/h2&gt;

&lt;p&gt;For every token, the attention weights add up to one. Always one — that's what softmax does.&lt;/p&gt;

&lt;p&gt;So when you paste in fifty more documents, you don't hand the model more focus. You split the &lt;strong&gt;same&lt;/strong&gt; focus into more pieces.&lt;/p&gt;

&lt;p&gt;Think about search on your laptop. One folder, ten files — you find it in a second. Same search, ten thousand files, same query, and the right file is now somewhere on page four. The model has that exact problem. Except it never shows you page four. It just answers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 2 — lost in the middle
&lt;/h2&gt;

&lt;p&gt;Researchers took one correct answer and moved it around inside a long prompt. Same prompt, same question, different position. Then they measured accuracy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Near the beginning: good.&lt;/li&gt;
&lt;li&gt;Near the end: good.&lt;/li&gt;
&lt;li&gt;In the middle: &lt;strong&gt;much worse&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Liu et al., &lt;em&gt;&lt;a href="https://arxiv.org/abs/2307.03172" rel="noopener noreferrer"&gt;Lost in the Middle&lt;/a&gt;&lt;/em&gt;.) So your most important paragraph, sitting at 60% of a long prompt, is in the worst possible spot in the whole file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 3 — distractors in your own data
&lt;/h2&gt;

&lt;p&gt;This is the one I hit most in real code. The famous needle-in-a-haystack test is easy, because the needle looks nothing like the hay. Your production data is not like that.&lt;/p&gt;

&lt;p&gt;You've got version two of the doc. Version three. An old changelog. And a chat thread that contradicts all three. Four chunks that all look right. One of them is right — and the model can't tell which.&lt;/p&gt;

&lt;p&gt;It gets worse as the input grows: accuracy drops steadily with input length, even on tasks the same model nails at short length. So the number on the box tells you what &lt;em&gt;fits&lt;/em&gt;. It doesn't tell you what &lt;em&gt;works&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four things you can actually change
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Send less, but better.&lt;/strong&gt; If you're doing retrieval, stop pushing the top fifty chunks into the prompt. Search wide, re-sort the results, then send the top three to five. Fewer clean chunks beat more chunks, every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Use the edges.&lt;/strong&gt; Instruction at the top. Data in the middle. Then repeat the actual question at the &lt;strong&gt;bottom&lt;/strong&gt;, right before the model answers. That last line costs you nothing, and it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Stop reusing one giant thread.&lt;/strong&gt; Split the job into steps. Each step gets a fresh, small context with only what it needs. Between steps, pass a short summary — not the full transcript. That's most of what agent frameworks are doing for you under the hood.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Measure it on your own data.&lt;/strong&gt; Take twenty real questions from your app. Run them with 2,000 tokens of context, then run the same twenty with 20,000. Compare the answers side by side. You'll find your own limit — and it'll be lower than the spec sheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;The context window is a hard limit on what fits. It was never a promise about what the model can use. Treat it like bandwidth you're paying for, and send the smallest thing that answers the question.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the biggest prompt you've ever shipped to production? And when you cut it down, did it get better or worse?&lt;/strong&gt; Tell me below.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I make &lt;a href="https://www.youtube.com/channel/UCUO8Uo5LsEy1b9eRkrH6JNg" rel="noopener noreferrer"&gt;Vlad's Stack&lt;/a&gt; — how the AI tools you use every day actually work, for people who write code. Full video walkthrough is above.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>promptengineering</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Why your RAG returns garbage (and it's not the model)</title>
      <dc:creator>VLAD</dc:creator>
      <pubDate>Mon, 31 Aug 2026 22:12:03 +0000</pubDate>
      <link>https://dev.to/vladut02/why-your-rag-returns-garbage-and-its-not-the-model-4d7d</link>
      <guid>https://dev.to/vladut02/why-your-rag-returns-garbage-and-its-not-the-model-4d7d</guid>
      <description>&lt;p&gt;Your RAG bot just gave a confident, detailed answer. And it's completely &lt;strong&gt;wrong&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's the part that'll annoy you: the model did &lt;em&gt;nothing&lt;/em&gt; wrong. It answered perfectly — using the text &lt;strong&gt;you&lt;/strong&gt; handed it. The bug isn't in the AI. It's in the five steps before the AI.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefer to watch? Full 6-minute walkthrough with the "lost in the middle" animation:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/L2GJbg5IukM" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The pipeline, in one line of code
&lt;/h2&gt;

&lt;p&gt;RAG is simple on paper. You search your own documents, grab the best matches, paste them into the prompt, and the model answers from those. So when the answer's garbage, everyone blames the model.&lt;/p&gt;

&lt;p&gt;Wrong suspect. There are &lt;strong&gt;five&lt;/strong&gt; places this pipeline breaks — and four of them happen before the model even runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                   &lt;span class="c1"&gt;// 1 · chunking&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;vectors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                 &lt;span class="c1"&gt;// 2 · embedding&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hits&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 3 · retrieval&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;best&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rerank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="c1"&gt;// 4 · ranking&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;best&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;      &lt;span class="c1"&gt;// 5 · generation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Five lines. Every bug I'm about to show you lives on one of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Chunking — a fixed cut splits your answer in half
&lt;/h2&gt;

&lt;p&gt;Your documents are long, so you cut them into pieces before you store them. Most people cut every few hundred characters and move on. That's where it starts to rot.&lt;/p&gt;

&lt;p&gt;A fixed-length cut doesn't care about &lt;strong&gt;meaning&lt;/strong&gt;. It'll slice a sentence in half. It'll split a question from its answer. Now the one chunk that held your answer is two halves — and each half looks irrelevant on its own. So retrieval never even finds it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; cut on &lt;strong&gt;structure&lt;/strong&gt;, not length. Split on paragraphs and headers — where the meaning actually breaks. And let chunks overlap a little, so nothing gets stranded at the edge.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Embedding — your question doesn't look like its answer
&lt;/h2&gt;

&lt;p&gt;Every chunk goes through a model that turns text into a &lt;strong&gt;vector&lt;/strong&gt;: a long list of numbers that captures its meaning. Similar meaning, similar numbers. That's the whole trick that makes search work.&lt;/p&gt;

&lt;p&gt;But here's the trap. Your &lt;em&gt;question&lt;/em&gt; gets embedded by the same model — and a question rarely looks like its answer.&lt;/p&gt;

&lt;p&gt;You ask &lt;em&gt;"how do I reset my password?"&lt;/em&gt; The doc says &lt;em&gt;"account recovery procedure."&lt;/em&gt; Same thing to a human. Different words — and a weak embedder puts them far apart.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; pick an embedding model built for &lt;strong&gt;retrieval&lt;/strong&gt;, and test it on &lt;em&gt;your&lt;/em&gt; data. A model that's great on legal text can be useless on code.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Retrieval — vector search fumbles exact strings
&lt;/h2&gt;

&lt;p&gt;You take the question's vector and grab the closest chunks. This is the "vector search" everyone talks about. On its own, it's got a blind spot.&lt;/p&gt;

&lt;p&gt;Vector search matches &lt;strong&gt;meaning&lt;/strong&gt;, not exact words. Which is great — until someone searches for an error code. A product name. &lt;code&gt;SKU-4417&lt;/code&gt;. Those barely &lt;em&gt;have&lt;/em&gt; a meaning to embed. They're just exact strings, and nothing is "close in meaning" to a serial number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; &lt;strong&gt;hybrid search&lt;/strong&gt;. Run keyword search &lt;em&gt;and&lt;/em&gt; vector search, then merge the results. Old-school keyword matching catches the exact strings embeddings miss.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Ranking — the best chunk was #8, and you dropped it
&lt;/h2&gt;

&lt;p&gt;Now you've got a pile of candidates — say the top twenty. But you can't paste twenty chunks into the prompt, so you keep the top five and drop the rest.&lt;/p&gt;

&lt;p&gt;Here's the question nobody asks: what if the &lt;strong&gt;best&lt;/strong&gt; chunk was ranked number eight? Then you just threw it away. Your answer was in the pile, and you cut it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; a &lt;strong&gt;re-ranker&lt;/strong&gt; — a second, smarter model that reads the question and each chunk &lt;em&gt;together&lt;/em&gt; and re-scores them. Cheap vector search casts a wide net; the re-ranker picks the real winners out of it. Now your top five are actually the top five.&lt;/p&gt;

&lt;h3&gt;
  
  
  And order matters too — "lost in the middle"
&lt;/h3&gt;

&lt;p&gt;Even the &lt;em&gt;order&lt;/em&gt; you paste chunks in changes the answer. Models pay the most attention to the &lt;strong&gt;start&lt;/strong&gt; and the &lt;strong&gt;end&lt;/strong&gt; of the context. Put your most important chunk in the middle, and the model can skim right past it.&lt;/p&gt;

&lt;p&gt;This isn't a hunch — it's measured. The same model gets &lt;em&gt;more&lt;/em&gt; accurate just by moving the right chunk to the edges of the context (Liu et al., &lt;em&gt;&lt;a href="https://arxiv.org/abs/2307.03172" rel="noopener noreferrer"&gt;Lost in the Middle&lt;/a&gt;&lt;/em&gt;, 2023). So put your best chunk first, or last. Never buried in the middle.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. The prompt — where people ruin it two ways
&lt;/h2&gt;

&lt;p&gt;Right chunks, right order. This is your last chance to ruin it, and people do it two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;They dump in everything.&lt;/strong&gt; Ten thousand tokens of maybe-relevant text, hoping the model sorts it out. More context isn't more accuracy — it's more noise to get lost in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;They never tell the model what to do when the answer isn't there.&lt;/strong&gt; So it does the one thing you don't want: it makes something up.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt; is basically one line in your prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Answer only from the context below. If it's not there, say you don't know."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That single instruction turns a confident liar into a system you can trust. A RAG bot that admits &lt;em&gt;"I don't know"&lt;/em&gt; beats ten that guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put the blame where it belongs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Bad chunks&lt;/li&gt;
&lt;li&gt;Wrong embedder&lt;/li&gt;
&lt;li&gt;Vector-only search&lt;/li&gt;
&lt;li&gt;No re-ranker&lt;/li&gt;
&lt;li&gt;A sloppy prompt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Five failure points — and notice the model was the &lt;em&gt;last&lt;/em&gt; one. Usually the innocent one.&lt;/p&gt;

&lt;p&gt;So next time your RAG bot lies to you, don't touch the model first. Walk the five steps backward — prompt, ranking, retrieval, embedding, chunks. The bug is almost always &lt;strong&gt;upstream&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the worst answer your RAG bot has ever given you?&lt;/strong&gt; Drop it in the comments — I actually want to read those.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I make Vlad's Stack &lt;a href="https://www.youtube.com/channel/UCUO8Uo5LsEy1b9eRkrH6JNg" rel="noopener noreferrer"&gt;https://www.youtube.com/channel/UCUO8Uo5LsEy1b9eRkrH6JNg&lt;/a&gt; — how the AI tools you use every day actually work, for people who write code. Full video walkthrough of this one is above.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rag</category>
      <category>ai</category>
      <category>llm</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>What a Linux container really is (it's not a VM)</title>
      <dc:creator>VLAD</dc:creator>
      <pubDate>Mon, 31 Aug 2026 22:10:38 +0000</pubDate>
      <link>https://dev.to/vladut02/what-a-linux-container-really-is-its-not-a-vm-53an</link>
      <guid>https://dev.to/vladut02/what-a-linux-container-really-is-its-not-a-vm-53an</guid>
      <description>&lt;p&gt;Right now, on your machine, a process is being &lt;strong&gt;lied to&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It thinks it's alone on the computer. It thinks it owns the whole filesystem. It thinks its process ID is &lt;code&gt;1&lt;/code&gt;. None of that is true. It's running right next to everything else, on the same kernel — and the kernel is lying to its face.&lt;/p&gt;

&lt;p&gt;That lie has a name. We call it a &lt;strong&gt;container&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefer to watch? Full 6-minute walkthrough with the animation:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Bm_K4SchaKY" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  There is no "container" in the kernel
&lt;/h2&gt;

&lt;p&gt;Here's the first thing nobody tells you. Open the Linux kernel source, search for a thing called a "container." You'll find &lt;strong&gt;zero&lt;/strong&gt;. There is no container object. The kernel has no idea what the word means.&lt;/p&gt;

&lt;p&gt;So what are you actually running? A normal process. The same &lt;em&gt;kind&lt;/em&gt; as your text editor. Just with a few settings flipped. Docker doesn't build a magic box around your app — it starts a plain process and flips those settings for you.&lt;/p&gt;

&lt;p&gt;There are two settings that do all the work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first controls what the process can &lt;strong&gt;see&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The second controls what it can &lt;strong&gt;use&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the whole magic. See, and use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trick 1 — namespaces (what a process can see)
&lt;/h2&gt;

&lt;p&gt;Normally every process on the machine shares one view of the world: the same list of process IDs, the same filesystem, the same network. A &lt;strong&gt;namespace&lt;/strong&gt; hands one process its own private copy of that view.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Put it in a &lt;strong&gt;PID namespace&lt;/strong&gt;, and it sees itself as process &lt;code&gt;1&lt;/code&gt; — like the machine just booted for it.&lt;/li&gt;
&lt;li&gt;Put it in a &lt;strong&gt;mount namespace&lt;/strong&gt;, it gets its own filesystem root.&lt;/li&gt;
&lt;li&gt;Give it a &lt;strong&gt;network namespace&lt;/strong&gt;, and it has its own network interface and its own IP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So on the real host, your process might be number &lt;code&gt;842&lt;/code&gt;, sitting in a list of hundreds. Inside its namespace, it looks down and sees... &lt;code&gt;1&lt;/code&gt;. Same machine, same kernel. The process just can't see past the wall the kernel drew around it.&lt;/p&gt;

&lt;h3&gt;
  
  
  root inside, nobody outside
&lt;/h3&gt;

&lt;p&gt;Here's the detail that trips everyone up: there's a &lt;strong&gt;user namespace&lt;/strong&gt; too.&lt;/p&gt;

&lt;p&gt;Inside the container, your process can be &lt;code&gt;root&lt;/code&gt; — user zero, full power. Outside, on the host, that same process is a boring, unprivileged user.&lt;/p&gt;

&lt;p&gt;Root on the inside. Nobody on the outside. Same process. That's namespaces doing their job — and it's the foundation of rootless containers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trick 2 — cgroups (what a process can use)
&lt;/h2&gt;

&lt;p&gt;Namespaces decide what you &lt;strong&gt;see&lt;/strong&gt;. The second trick decides what you &lt;strong&gt;get&lt;/strong&gt;. It's called a &lt;strong&gt;cgroup&lt;/strong&gt; — a control group.&lt;/p&gt;

&lt;p&gt;A cgroup sets limits. This process gets two CPU cores, not all of them. Half a gig of memory, and not a byte more. Cross the memory limit? The kernel kills it on the spot (that's your OOM kill).&lt;/p&gt;

&lt;p&gt;That's how one container can't starve every other one on the box. No limits, and one noisy app eats the whole machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The whole idea in one line
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Namespaces are what you see. Cgroups are what you get.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A container is just a normal process wrapped in those two things. Nothing else is in the box — because there is no box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it's not a virtual machine
&lt;/h2&gt;

&lt;p&gt;This is the part people get wrong the most.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;virtual machine&lt;/strong&gt; boots its &lt;em&gt;own&lt;/em&gt; kernel, on fake hardware that a hypervisor pretends is real. A whole operating system, from scratch, every time.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;container&lt;/strong&gt; has no kernel of its own. It borrows the host's kernel — the one that's already running.&lt;/p&gt;

&lt;p&gt;That one difference explains everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed.&lt;/strong&gt; No kernel to boot means a container starts in milliseconds, where a VM takes seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation.&lt;/strong&gt; Sharing a kernel cuts both ways. One kernel bug can let a process break &lt;em&gt;out&lt;/em&gt; of its container and onto the host. A VM doesn't share that wall.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So you're trading isolation for speed. That's the deal — and it's a fair one, as long as you know you're making it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build one by hand — no Docker
&lt;/h2&gt;

&lt;p&gt;Don't believe there's no magic? Build a "container" yourself with two commands:&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="c"&gt;# a "container" with no Docker at all&lt;/span&gt;
unshare &lt;span class="nt"&gt;--pid&lt;/span&gt; &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nt"&gt;--net&lt;/span&gt; &lt;span class="nt"&gt;--uts&lt;/span&gt; &lt;span class="nt"&gt;--fork&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;chroot&lt;/span&gt; ./rootfs &lt;span class="se"&gt;\&lt;/span&gt;
  /bin/sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;unshare&lt;/code&gt; flips on the namespaces.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chroot&lt;/code&gt; swaps the root filesystem.&lt;/li&gt;
&lt;li&gt;And you're dropped into a shell that thinks it's alone on a fresh machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No daemon, no image — just kernel features.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what does &lt;code&gt;docker run&lt;/code&gt; actually do?
&lt;/h2&gt;

&lt;p&gt;Four steps, in pseudo-code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;unpackImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;        &lt;span class="c1"&gt;// files become the new root&lt;/span&gt;
&lt;span class="nf"&gt;applyNamespaces&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// its own PID, mounts, network&lt;/span&gt;
&lt;span class="nf"&gt;applyCgroups&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;// capped CPU and memory&lt;/span&gt;
&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;             &lt;span class="c1"&gt;// now it's just... a process&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unpack the files. Wrap it in namespaces. Cap it with cgroups. Run it. That's the whole thing Docker does that felt like magic.&lt;/p&gt;

&lt;p&gt;And the image everyone ships around? It's just a stack of files in a tarball, plus a little metadata saying which program to start. No operating system inside. No kernel inside. Just files.&lt;/p&gt;

&lt;h2&gt;
  
  
  One number to leave you with
&lt;/h2&gt;

&lt;p&gt;The Linux manual page &lt;code&gt;namespaces(7)&lt;/code&gt; lists &lt;strong&gt;eight&lt;/strong&gt; separate kinds of namespace — eight different views the kernel can hand a single process: mount, PID, network, IPC, UTS, user, cgroup, and time. That's the whole toolbox a container is built from.&lt;/p&gt;

&lt;p&gt;So next time someone draws a container as a little box floating above the machine — remember there's no box. There's your kernel, showing one process a smaller version of the truth. Namespaces for what it sees, cgroups for what it gets, one shared kernel underneath.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What did you think a container was, before this?&lt;/strong&gt; Tell me in the comments.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I make Vlad's Stack &lt;a href="https://www.youtube.com/channel/UCUO8Uo5LsEy1b9eRkrH6JNg" rel="noopener noreferrer"&gt;https://www.youtube.com/channel/UCUO8Uo5LsEy1b9eRkrH6JNg&lt;/a&gt; — how the tools you use every day actually work, for people who write code. Full video walkthrough of this one is above.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>docker</category>
      <category>containers</category>
      <category>devops</category>
    </item>
    <item>
      <title>Why more context makes your AI answers worse</title>
      <dc:creator>VLAD</dc:creator>
      <pubDate>Mon, 31 Aug 2026 22:09:07 +0000</pubDate>
      <link>https://dev.to/vladut02/why-more-context-makes-your-ai-answers-worse-2mnd</link>
      <guid>https://dev.to/vladut02/why-more-context-makes-your-ai-answers-worse-2mnd</guid>
      <description>&lt;p&gt;Your model says it has a one-million-token context window. Its real working memory is a lot smaller than that.&lt;/p&gt;

&lt;p&gt;On long-context benchmarks, models start failing well below the number printed on the box. And here's the part nobody warns you about: past a certain point, adding more context makes your answers &lt;strong&gt;worse&lt;/strong&gt;. Not better. Worse.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefer to watch? Full walkthrough with the attention-cost animation:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/JtZIjmPYwsU" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A context window is not memory
&lt;/h2&gt;

&lt;p&gt;Let's kill one idea first. A context window is &lt;strong&gt;not&lt;/strong&gt; memory.&lt;/p&gt;

&lt;p&gt;The model doesn't remember your last message — it's stateless. It keeps nothing between calls. Every single call, you send the whole conversation again. All of it.&lt;/p&gt;

&lt;p&gt;Look at what you actually ship over the wire:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Turn one:&lt;/strong&gt; a system prompt and one question. Small.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn ten:&lt;/strong&gt; the same system prompt, plus nine questions, plus nine answers, plus the new one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The window is just how much text fits in that box before the API says no. And everything in the box gets processed. Every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What attention actually does
&lt;/h2&gt;

&lt;p&gt;Inside the model, attention has a job that's simple to say: every token looks at every other token and decides how much it cares about each one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;10 tokens → 100 pairs&lt;/li&gt;
&lt;li&gt;1,000 tokens → &lt;strong&gt;1,000,000&lt;/strong&gt; pairs&lt;/li&gt;
&lt;li&gt;100,000 tokens → &lt;strong&gt;10,000,000,000&lt;/strong&gt; pairs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ten times the context isn't ten times the work. It's a hundred times the work. (That's just arithmetic: cost grows with the square of the input.)&lt;/p&gt;

&lt;p&gt;That's also why the first reply in a long chat feels slow and the rest feel fast — the model caches the keys and values it already computed. But the cache saves you &lt;em&gt;compute&lt;/em&gt;. It doesn't save your &lt;em&gt;answer quality&lt;/em&gt;. That's a separate problem, and it's the one you actually feel.&lt;/p&gt;

&lt;p&gt;Here are the three reasons big context hurts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 1 — attention is a budget
&lt;/h2&gt;

&lt;p&gt;For every token, the attention weights add up to one. Always one — that's what softmax does.&lt;/p&gt;

&lt;p&gt;So when you paste in fifty more documents, you don't hand the model more focus. You split the &lt;strong&gt;same&lt;/strong&gt; focus into more pieces.&lt;/p&gt;

&lt;p&gt;Think about search on your laptop. One folder, ten files — you find it in a second. Same search, ten thousand files, same query, and the right file is now somewhere on page four. The model has that exact problem. Except it never shows you page four. It just answers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 2 — lost in the middle
&lt;/h2&gt;

&lt;p&gt;Researchers took one correct answer and moved it around inside a long prompt. Same prompt, same question, different position. Then they measured accuracy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Near the beginning: good.&lt;/li&gt;
&lt;li&gt;Near the end: good.&lt;/li&gt;
&lt;li&gt;In the middle: &lt;strong&gt;much worse&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Liu et al., &lt;em&gt;&lt;a href="https://arxiv.org/abs/2307.03172" rel="noopener noreferrer"&gt;Lost in the Middle&lt;/a&gt;&lt;/em&gt;.) So your most important paragraph, sitting at 60% of a long prompt, is in the worst possible spot in the whole file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 3 — distractors in your own data
&lt;/h2&gt;

&lt;p&gt;This is the one I hit most in real code. The famous needle-in-a-haystack test is easy, because the needle looks nothing like the hay. Your production data is not like that.&lt;/p&gt;

&lt;p&gt;You've got version two of the doc. Version three. An old changelog. And a chat thread that contradicts all three. Four chunks that all look right. One of them is right — and the model can't tell which.&lt;/p&gt;

&lt;p&gt;It gets worse as the input grows: accuracy drops steadily with input length, even on tasks the same model nails at short length. So the number on the box tells you what &lt;em&gt;fits&lt;/em&gt;. It doesn't tell you what &lt;em&gt;works&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four things you can actually change
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Send less, but better.&lt;/strong&gt; If you're doing retrieval, stop pushing the top fifty chunks into the prompt. Search wide, re-sort the results, then send the top three to five. Fewer clean chunks beat more chunks, every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Use the edges.&lt;/strong&gt; Instruction at the top. Data in the middle. Then repeat the actual question at the &lt;strong&gt;bottom&lt;/strong&gt;, right before the model answers. That last line costs you nothing, and it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Stop reusing one giant thread.&lt;/strong&gt; Split the job into steps. Each step gets a fresh, small context with only what it needs. Between steps, pass a short summary — not the full transcript. That's most of what agent frameworks are doing for you under the hood.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Measure it on your own data.&lt;/strong&gt; Take twenty real questions from your app. Run them with 2,000 tokens of context, then run the same twenty with 20,000. Compare the answers side by side. You'll find your own limit — and it'll be lower than the spec sheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;The context window is a hard limit on what fits. It was never a promise about what the model can use. Treat it like bandwidth you're paying for, and send the smallest thing that answers the question.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the biggest prompt you've ever shipped to production? And when you cut it down, did it get better or worse?&lt;/strong&gt; Tell me below.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I make Vlad's Stack &lt;a href="https://www.youtube.com/channel/UCUO8Uo5LsEy1b9eRkrH6JNg" rel="noopener noreferrer"&gt;https://www.youtube.com/channel/UCUO8Uo5LsEy1b9eRkrH6JNg&lt;/a&gt; — how the AI tools you use every day actually work, for people who write code. Full video walkthrough is above.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>promptengineering</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Why more context makes your AI answers worse</title>
      <dc:creator>VLAD</dc:creator>
      <pubDate>Mon, 31 Aug 2026 21:42:30 +0000</pubDate>
      <link>https://dev.to/vladut02/why-more-context-makes-your-ai-answers-worse-jb1</link>
      <guid>https://dev.to/vladut02/why-more-context-makes-your-ai-answers-worse-jb1</guid>
      <description>&lt;p&gt;Your model says it has a one-million-token context window. Its real working memory is a lot smaller than that.&lt;/p&gt;

&lt;p&gt;On long-context benchmarks, models start failing well below the number printed on the box. And here's the part nobody warns you about: past a certain point, adding more context makes your answers &lt;strong&gt;worse&lt;/strong&gt;. Not better. Worse.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefer to watch? Full walkthrough with the attention-cost animation:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/hH7Ko-x1Bn8" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A context window is not memory
&lt;/h2&gt;

&lt;p&gt;Let's kill one idea first. A context window is &lt;strong&gt;not&lt;/strong&gt; memory.&lt;/p&gt;

&lt;p&gt;The model doesn't remember your last message — it's stateless. It keeps nothing between calls. Every single call, you send the whole conversation again. All of it.&lt;/p&gt;

&lt;p&gt;Look at what you actually ship over the wire:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Turn one:&lt;/strong&gt; a system prompt and one question. Small.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn ten:&lt;/strong&gt; the same system prompt, plus nine questions, plus nine answers, plus the new one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The window is just how much text fits in that box before the API says no. And everything in the box gets processed. Every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What attention actually does
&lt;/h2&gt;

&lt;p&gt;Inside the model, attention has a job that's simple to say: every token looks at every other token and decides how much it cares about each one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;10 tokens → 100 pairs&lt;/li&gt;
&lt;li&gt;1,000 tokens → &lt;strong&gt;1,000,000&lt;/strong&gt; pairs&lt;/li&gt;
&lt;li&gt;100,000 tokens → &lt;strong&gt;10,000,000,000&lt;/strong&gt; pairs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ten times the context isn't ten times the work. It's a hundred times the work. (That's just arithmetic: cost grows with the square of the input.)&lt;/p&gt;

&lt;p&gt;That's also why the first reply in a long chat feels slow and the rest feel fast — the model caches the keys and values it already computed. But the cache saves you &lt;em&gt;compute&lt;/em&gt;. It doesn't save your &lt;em&gt;answer quality&lt;/em&gt;. That's a separate problem, and it's the one you actually feel.&lt;/p&gt;

&lt;p&gt;Here are the three reasons big context hurts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 1 — attention is a budget
&lt;/h2&gt;

&lt;p&gt;For every token, the attention weights add up to one. Always one — that's what softmax does.&lt;/p&gt;

&lt;p&gt;So when you paste in fifty more documents, you don't hand the model more focus. You split the &lt;strong&gt;same&lt;/strong&gt; focus into more pieces.&lt;/p&gt;

&lt;p&gt;Think about search on your laptop. One folder, ten files — you find it in a second. Same search, ten thousand files, same query, and the right file is now somewhere on page four. The model has that exact problem. Except it never shows you page four. It just answers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 2 — lost in the middle
&lt;/h2&gt;

&lt;p&gt;Researchers took one correct answer and moved it around inside a long prompt. Same prompt, same question, different position. Then they measured accuracy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Near the beginning: good.&lt;/li&gt;
&lt;li&gt;Near the end: good.&lt;/li&gt;
&lt;li&gt;In the middle: &lt;strong&gt;much worse&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Liu et al., &lt;em&gt;&lt;a href="https://arxiv.org/abs/2307.03172" rel="noopener noreferrer"&gt;Lost in the Middle&lt;/a&gt;&lt;/em&gt;.) So your most important paragraph, sitting at 60% of a long prompt, is in the worst possible spot in the whole file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 3 — distractors in your own data
&lt;/h2&gt;

&lt;p&gt;This is the one I hit most in real code. The famous needle-in-a-haystack test is easy, because the needle looks nothing like the hay. Your production data is not like that.&lt;/p&gt;

&lt;p&gt;You've got version two of the doc. Version three. An old changelog. And a chat thread that contradicts all three. Four chunks that all look right. One of them is right — and the model can't tell which.&lt;/p&gt;

&lt;p&gt;It gets worse as the input grows: accuracy drops steadily with input length, even on tasks the same model nails at short length. So the number on the box tells you what &lt;em&gt;fits&lt;/em&gt;. It doesn't tell you what &lt;em&gt;works&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four things you can actually change
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Send less, but better.&lt;/strong&gt; If you're doing retrieval, stop pushing the top fifty chunks into the prompt. Search wide, re-sort the results, then send the top three to five. Fewer clean chunks beat more chunks, every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Use the edges.&lt;/strong&gt; Instruction at the top. Data in the middle. Then repeat the actual question at the &lt;strong&gt;bottom&lt;/strong&gt;, right before the model answers. That last line costs you nothing, and it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Stop reusing one giant thread.&lt;/strong&gt; Split the job into steps. Each step gets a fresh, small context with only what it needs. Between steps, pass a short summary — not the full transcript. That's most of what agent frameworks are doing for you under the hood.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Measure it on your own data.&lt;/strong&gt; Take twenty real questions from your app. Run them with 2,000 tokens of context, then run the same twenty with 20,000. Compare the answers side by side. You'll find your own limit — and it'll be lower than the spec sheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;The context window is a hard limit on what fits. It was never a promise about what the model can use. Treat it like bandwidth you're paying for, and send the smallest thing that answers the question.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the biggest prompt you've ever shipped to production? And when you cut it down, did it get better or worse?&lt;/strong&gt; Tell me below.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>promptengineering</category>
      <category>machinelearning</category>
    </item>
  </channel>
</rss>
