Pure semantic search has a blind spot: it finds passages that are relevant by meaning, but it has no notion of scope. A query about "onboarding" retrieves onboarding content from every team, every product, and every era — including the parts the asker shouldn't see or doesn't want. Metadata filtering is how you add scope back. By tagging content with structured attributes and filtering retrieval on them, you constrain search to the right subset before ranking — which improves relevance, enables permissions, and is often the single cleanest quality win available. Here's how to use it.

What metadata filtering does
Every chunk you index can carry structured metadata alongside its vector — attributes like team, product, document type, author, date, or sensitivity level. Metadata filtering applies conditions on those attributes as part of the search, so retrieval only considers chunks that match:
search(query="how do I request time off",
filter={ "team": "HR", "audience": "employee" })
Now the semantic search runs only over chunks tagged team=HR and audience=employee. Content from other teams, or restricted content, is never even a candidate. You've combined meaning (the vector similarity) with scope (the metadata conditions).
Three things it buys you
1. Better relevance through narrowing. The reranker (and the retriever) can only surface passages that were candidates. By filtering out the irrelevant-by-scope content before ranking, you shrink the space to what actually matters — so the right passage competes against fewer distractors and is more likely to surface. Scoping a Product A query to Product A content means Product B's docs can't crowd the results. This is often a bigger quality lever than tuning the embedding model, because it removes whole categories of wrong-but-similar content.
2. Permissions and data isolation. This is the critical one. If your knowledge base spans content with different access rules, metadata filtering is how you enforce that a user only retrieves what they're allowed to see — filter by the querying user's permitted scope, and restricted content simply isn't retrievable for them. Without this, semantic search becomes a way to bypass your permission model: a user asks a question and gets an answer sourced from a document they could never open directly. Treat permission-driven filtering as a security control, not a nicety.
3. Freshness and versioning. Filter by date or version to prefer current content, or to scope a search to a specific document version. "What's our current policy" can exclude superseded versions, so the bot doesn't confidently quote last year's rules.
Getting the metadata right
Filtering is only as good as the metadata you attach, so the work is mostly upstream at ingestion:
- Tag at ingestion time. As content is ingested, attach the attributes you'll want to filter on — team, product, type, audience, date. Retrofitting metadata later means re-processing, so plan the schema before you ingest at scale.
- Derive from the source where possible. When ingesting from Notion, Confluence, or Drive, carry through the source's own structure — which space, which workspace, which folder, the page's permissions — as metadata automatically. This is far more reliable than manual tagging and is a big reason connector-based ingestion is valuable.
- Keep the schema consistent. Filtering breaks if the same concept is tagged three different ways (
team=eng,team=engineering,department=Engineering). Normalize your metadata vocabulary so filters actually match.
How it works under the hood
Because Kognita stores vectors in Postgres (via Neon), metadata filtering is a natural fit: the metadata lives in columns alongside the vector, so a filtered search is a query that constrains on those columns and ranks by vector distance in one operation. This is one of the underrated advantages of keeping vectors in a relational database — filtering and similarity happen together, transactionally, rather than requiring you to reconcile a separate metadata store with a separate vector index. The filter narrows the candidate set; the ANN search ranks within it.
Practical patterns
- Multi-tenant scoping. Always filter by tenant/org so one customer's content can never surface for another. This is the most fundamental filter and should be enforced structurally, not left to each query to remember.
- Team/product scoping. Route a query to the relevant team's or product's content — either from explicit user context or inferred from the query — to sharpen relevance.
- Permission scoping. Filter by the querying user's access rights so retrieval respects who's allowed to see what.
- Recency scoping. Prefer or require recent content for time-sensitive topics.
- Type scoping. Restrict to a content type when appropriate — search only runbooks for an ops question, only FAQs for a customer query.
The takeaway
Semantic search answers "what's relevant by meaning"; metadata filtering answers "relevant and in scope." The two together are far more powerful than similarity alone — sharper relevance because you rank within the right subset, real permissions because you can exclude what a user shouldn't see, and correct freshness because you can prefer current content. The effort is mostly at ingestion (tag consistently, derive from sources), and keeping vectors in a relational store makes the filtering itself clean. If your knowledge base spans teams, products, permissions, or time, metadata filtering isn't optional polish — it's how you make retrieval return the right answers instead of merely similar ones.