What is the difference between cosine similarity and cosine distance?
Cosine similarity measures how aligned two vectors are as a score that rises toward 1 when they point the same way, while cosine distance flips that intuition into a distance – commonly 1 - cosine_similarity – so identical directions score 0 and opposing directions approach 2, which is what most ANN indexes sort as "closer means smaller."
What does cosine similarity actually compute?
Take two vectors a and b. Cosine similarity is their dot product divided by the product of their Euclidean lengths: (a · b) / (||a|| ||b||). Geometrically it is the cosine of the angle between them. It ignores magnitude once lengths are divided out, which is why text and other high-dimensional embeddings often prefer it: documents that use the same ideas at different frequencies can still sit at a small angle. The score ranges from -1 to 1 for real-valued vectors (1 = same direction, 0 = orthogonal, -1 = opposite). Machine-learning cards and evaluation scripts frequently speak in this "higher is better" language, so application code, dashboards, and offline metrics often sort descending on similarity.
Indexes and databases usually speak a different dialect of the same geometry.
How is cosine distance defined, and why do engines prefer it?
Cosine distance is a transform of that similarity into a quantity where smaller means nearer, matching how HNSW priority queues and "max distance" thresholds already work for L2 and other metrics. The widespread definition is distance = 1 - cosine_similarity. Under that map, identical unit vectors have distance 0; orthogonal vectors have distance 1; perfectly opposite vectors have distance 2. Rankings by ascending cosine distance are therefore the same order as rankings by descending cosine similarity – only the numeric polarity and the threshold inequality flip. Confusing the two is a classic metric-mismatch cousin: a client that keeps results with "score > 0.8" while the API returns distance will keep the worst hits, and a ground-truth script that computes similarity while the index stores distance will report false recall disasters.
Normalization ties the story together, because cosine is fundamentally about angles.
When do unit-length vectors make cosine and dot product agree?
If both vectors are L2-normalized to length 1, cosine similarity equals the plain dot product, and cosine distance becomes 1 - dot(a, b). Many systems therefore normalize at read time and implement cosine via an efficient dot under the hood. If only one side is normalized, or lengths still carry training signal you meant to keep, you no longer have pure cosine geometry – that is a normalization inconsistency, not a renaming problem. Choosing a raw dot metric on purpose preserves magnitude; choosing cosine declares that angle is the contract. Mixing a similarity-sorted client with a distance-sorted collection is still wrong even when both sides are perfectly normalized.
Weaviate’s default metric and API fields make the distance orientation explicit.
How does Weaviate expose cosine similarity versus cosine distance?
Weaviate’s default collection distance is cosine, defined as 1 - cosine_sim(a, b) with range 0 to 2, and it normalizes vectors to length 1 at read time so the computation can use a fast dot product. Search metadata prefers the distance field: lower always means closer, for every supported metric. For cosine collections only, a legacy certainty field remains available as a 0-to-1 "higher is better" view useful for older clients; it is not available for unbounded metrics such as l2-squared or dot. Thresholds on nearVector / nearText take a maximum distance (or certainty on cosine). When you convert offline, remember similarity and distance move in opposite directions – do not paste a similarity cutoff into a distance argument. Prefer logging and alerting on distance so hybrid, quantized, and non-cosine collections share one mental model.
Getting the polarity right prevents a surprising number of "HNSW is broken" tickets.
How should you choose and verify which form you are using?
Read the collection’s configured distance metric and the field your client actually returns. If docs or model cards say "cosine similarity," translate evaluation scripts to 1 - similarity before comparing to Weaviate distances, or convert API distances back to similarity only at the presentation layer. Never sort ascending on similarity or descending on distance. When debugging metric mismatch or normalization bugs, print both forms for a handful of pairs so the team shares one picture of "good." After swapping embedding models, re-tune distance thresholds from scratch – a 0.2 distance that was strict for one model can be meaningless for another.
Cosine similarity and cosine distance are the same angle wearing opposite number lines. Next, read "What is a metric mismatch bug?" when the wrong ruler is configured entirely, or "What is a normalization inconsistency?" when length handling breaks the cosine contract you thought you had.