Weaviate Essentials
Theme
Palette
Download
Caption (tap to copy)
📖 Deep dive (full written explanation)
This closing post is about the failures that don't announce themselves. Weaviate rarely crashes on these issues; instead it returns subtly worse results, slowly consumes more RAM than budgeted, or silently drops objects during import. The cover frames the theme: most Weaviate pain is mismatch, not bug — between embedding models, between metric and model, between data scale and machine size, between import strategy and throughput.
The five traps that follow each come with a concrete one-line fix, because knowing the failure mode without the remedy just makes you anxious. The goal is to internalize these before they bite you in production rather than after.
The first and most damaging trap is mixing embedding models within one collection. Different models produce vectors in completely different, non-comparable spaces — text-embedding-3-small and ada-002 don't just differ in quality, their coordinate systems are unrelated. If you import some objects under one model and others (or your queries) under another, similarity scores become noise and ranking is effectively random.
The rule is one embedding model per collection, documented and pinned. If you must upgrade the model, you have to re-embed every object in the collection, not just new ones. Because re-embedding is expensive and operationally heavy, treat model choice as a semi-permanent commitment and version your collections when you change it.
The second trap is a distance metric that doesn't match your model. Embedding models are trained with a specific similarity measure in mind — OpenAI's text models and most modern sentence encoders are tuned for cosine similarity. If the collection's vector index uses L2 or dot product when the model expects cosine, every nearest-neighbor result is computed on the wrong geometry and recall quietly degrades.
There's no error and no crash; results just get worse in ways that are hard to attribute. The fix is to read your model's documentation for the recommended metric and set distance_metric explicitly on the HNSW config rather than trusting a default. This is a five-second decision that affects every query the collection will ever serve.
This code slide gives the combined fix for traps one and two in a single create() call. The vectorizer pins the exact model — text-embedding-3-small — so the collection has one and only one embedding space. The vector_index_config sets distance_metric to COSINE to match that model's training objective.
Making both decisions explicit at collection-creation time is the discipline that prevents the silent degradation: there's no ambiguity about which model or metric is in use, and anyone reading the schema later can verify they still match. Treat this snippet as the template for every collection you create, swapping only the model name and metric to whatever your chosen embedding model recommends.
The third trap is underestimating memory. The HNSW index is held in RAM for speed, and its footprint is substantial: each vector is dimensions times four bytes for float32, plus the graph's connection links per node. Millions of 1536-dimensional vectors easily reach tens of gigabytes before you count the links. Teams routinely provision a small node, import happily for a while, then hit out-of-memory when the dataset grows.
The fix has two parts. First, estimate RAM up front from object count, dimensionality, and graph degree — do the arithmetic before you deploy. Second, if the number is too large, enable quantization (PQ or BQ) to compress the in-memory vectors. Planning memory is not optional at scale; it's the most common reason a Weaviate deployment falls over.
This snippet shows the memory fix in code: attaching a product-quantization (PQ) quantizer to the HNSW index. PQ compresses each vector into a compact code, cutting vector RAM by roughly four to eight times in exchange for a modest, usually acceptable, loss of recall. The training_limit controls how many vectors are used to fit the quantizer's codebook.
Binary quantization (BQ) is an even more aggressive alternative for high-dimensional vectors. The right choice depends on your recall tolerance and dimensionality, and you should always measure recall before and after enabling compression on a representative query set. But when RAM is the constraint, quantization is the lever that lets large datasets fit on affordable hardware.
The fourth trap is importing objects one at a time. A loop calling insert() per object issues a separate request and, with a vectorizer configured, a separate serial embedding API call for each object. At scale this is catastrophically slow — minutes become hours — and the serial API calls are far more likely to hit rate limits than batched parallel ones.
The fix is batch.dynamic(), which sizes batches automatically and parallelizes requests, dramatically improving throughput. Equally important is inspecting batch.failed_objects afterward: batching tolerates partial failure silently, so that list is your only signal that some objects didn't import. Capture and retry the failures rather than assuming success.
This compare diagram puts the import strategies side by side so the gap is obvious. The insert()-loop column shows the problems: one request per object, serial embedding calls, slowness, rate-limiting, and awkward retries. The batch.dynamic() column shows the remedy: tuned batch sizes, parallel requests, fast bulk import, and a failed_objects list that makes retries straightforward.
The asymmetry is the point. There is essentially no situation where per-object inserts beat batching for bulk loads, so batching should be your default and per-object insert reserved only for genuine single-object writes in live application code. For any import of more than a handful of objects, reach for the batch context manager.
The fifth trap is a pair of subtler surprises around filters and consistency. Very selective filters can shrink the candidate set so aggressively that even a correct ANN search returns fewer hits than your requested limit — not a bug, just a small allow-list. If you see short result lists, check whether your filter is the cause before blaming the index.
The consistency surprise appears on multi-node clusters: Weaviate defaults toward eventual consistency, so an object you just wrote may not be immediately visible on a subsequent read served by another replica. When your application needs read-after-write guarantees, set an appropriate consistency_level (such as QUORUM) on the operation. Both behaviors are by design; knowing they exist saves hours of confused debugging.
This checklist distills the whole post into a pre-flight you can actually run before shipping. One embedding model per collection, written down so nobody accidentally mixes them. Distance metric explicitly matched to that model. RAM estimated from real numbers, with compression enabled if the dataset is large. Imports done in batches with failed_objects always inspected. And filters tested at realistic data scale, since their behavior at ten objects tells you nothing about ten million.
Running this checklist converts the five silent failure modes into deliberate, verified decisions. None of these checks is expensive; all of them are far cheaper than diagnosing the corresponding production incident after the fact.
This mindmap groups the traps by the part of the system they live in, which is how you'll actually reason about them in practice. The Embeddings branch covers model consistency and re-embedding. The Index branch covers the metric and ef tuning. The Memory branch covers RAM estimation and quantization. The Imports branch covers batching and failure handling.
Organizing the mistakes this way gives you a diagnostic map: when something's wrong, ask which subsystem owns the symptom — bad relevance points at embeddings or index, instability at memory, slow or lossy loads at imports — and the likely cause and fix follow directly. It's the same two-index, one-store mental model from the How It Works post, now turned into a troubleshooting guide.
The teaser closes out the Weaviate day. With the concept, the motivation, the internals, a working code pipeline, and the common mistakes all covered, you have an end-to-end working knowledge of Weaviate Essentials. Day 88 moves on to a new topic in the series, building on the vector-database foundation laid here.