> ## Documentation Index
> Fetch the complete documentation index at: https://docs.remem.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Core Concepts

> Workspace hierarchy, namespaces, encryption, query modes, and the processing pipeline.

# Core Concepts

## Tenant Isolation

Every tenant in Remem gets **hard isolation** across all storage layers:

| Layer      | Isolation Method                     |
| ---------- | ------------------------------------ |
| PostgreSQL | Row-Level Security (RLS) policies    |
| Qdrant     | Dedicated collection per tenant      |
| S3         | Tenant-prefixed object keys          |
| Encryption | Per-tenant Data Encryption Key (DEK) |

There is no shared vector space — a query for Tenant A can never return results from Tenant B.

## Workspace and Namespace Hierarchy

The product UI says **workspace**; the backend code says **tenant**. They refer to the same boundary.

Inside a workspace, Remem supports **namespaces** for sub-isolation:

```text theme={null}
Org -> Workspace/Tenant -> Namespace
```

Use namespaces when one workspace needs multiple memory partitions for different agents, teams, or workflows.

* Every workspace has a `default` namespace.
* Writes target one namespace.
* Reads can target one, many, or all readable namespaces.
* API keys carry both sensitivity scope and namespace grants.

Namespaces do not replace tenant isolation. They sit underneath it.

## Encryption Model

Remem uses **envelope encryption** with application-level field encryption:

```
KEK (Key Encryption Key)
 └── encrypts → DEK (Data Encryption Key, per tenant)
      └── encrypts → Document content, titles, metadata
```

* **Content, titles, and metadata** are stored as ciphertext in PostgreSQL
* **S3 objects** use client-side encryption before upload
* **Qdrant vectors** contain only embeddings and minimal non-sensitive metadata
* **Logs** are scrubbed to prevent sensitive data leakage

### Crypto-Shredding

When a tenant requests data deletion, Remem can destroy the DEK, making all encrypted data permanently unrecoverable — even if database backups are retained.

## Processing Pipeline

When a document is ingested, it flows through an async pipeline:

```
Ingest API
  → Redis Streams (job queue)
    → Worker picks up job
      1. Encrypt content with tenant DEK
      2. Store encrypted content in S3
      3. Chunk text into segments
      4. Generate embeddings (voyage-3.5-lite)
      5. Classify & extract entities (Grok 4.1 Fast via xAI API)
      6. Index chunks in Qdrant
      7. Store metadata in PostgreSQL
```

The API returns a `job_id` immediately. Processing typically completes within seconds.

## Query Modes

### Fast Mode (`mode: "fast"`)

* **Latency**: `<500ms` (typically 200-600ms)
* **Method**: Hybrid search combining vector similarity (Qdrant) and BM25 keyword matching
* **Results**: Ranked chunks with Reciprocal Rank Fusion (RRF)
* **No LLM call** — pure retrieval

```json theme={null}
{"query": "Q1 priorities", "mode": "fast"}
```

### Rich Mode (`mode: "rich"`)

* **Latency**: `<5s` cold, `<3s` cached
* **Method**: Query expansion → parallel retrieval → RRF fusion → LLM reranking → LLM synthesis (all using Grok 4.1 Fast via xAI API)
* **Results**: Reranked chunks plus optional natural language `synthesis` field
* **Budget-aware**: Skips reranking/synthesis if time budget exhausted
* **Caching**: Expansion and rerank results cached in Redis for 15 minutes

```json theme={null}
{"query": "Q1 priorities", "mode": "rich", "synthesize": true}
```

## Filtering

Query results can be filtered by metadata assigned during classification:

| Filter                  | Type           | Example                            |
| ----------------------- | -------------- | ---------------------------------- |
| `categories`            | List\[str]     | `["meeting_notes", "planning"]`    |
| `tags_any`              | List\[str]     | `["q1", "priorities"]`             |
| `tags_all`              | List\[str]     | `["urgent", "approved"]`           |
| `tags_prefix`           | str            | `"project-"`                       |
| `checkpoint_project`    | List\[str]     | `["remem"]`                        |
| `checkpoint_session`    | List\[str]     | `["2026-02-14-a"]`                 |
| `checkpoint_kinds`      | List\[str]     | `["interval", "final"]`            |
| `sensitivity`           | List\[str]     | `["public", "internal"]`           |
| `date_from` / `date_to` | str (ISO 8601) | `"2026-01-01"`                     |
| `source_types`          | List\[str]     | `["email", "note"]`                |
| `storage_types`         | List\[str]     | `["structured", "chunks", "both"]` |
| `languages`             | List\[str]     | `["en", "fr"]`                     |
| `has_extractable_data`  | bool           | `true`                             |
| `classifier_models`     | List\[str]     | `["grok-4.1-fast"]`                |

## Namespace-Aware Reads and Writes

Namespace behavior is consistent across the API, CLI, and MCP surfaces:

* `namespace` on write requests chooses one target namespace key.
* Omitting `namespace` falls back to the API key's default namespace.
* `namespaces` on read requests scopes results to one or more namespace keys.
* Omitting `namespaces` or using `["*"]` searches all namespaces the caller can read.

See [Namespaces](/namespaces) for the operational details and examples.

## Memory Layer

The Memory Layer extracts discrete **facts** from your documents and organizes them into a structured knowledge graph of **entities** and **relationships**.

### How It Works

```
Document processed
  → Fact Extraction (Grok 4.1 Fast)
    → Entity Resolution (dedup + merge)
      → Relationship Discovery (updates, extends, contradicts)
        → Facts searchable via API
```

When a document completes ingestion, an async worker extracts atomic facts — discrete pieces of knowledge like "Acme Corp's annual revenue is \$50M" or "User prefers dark mode". Each fact is typed, confidence-scored, and linked to the entities it references.

### Fact Types

| Type         | Description               | Example                                                   |
| ------------ | ------------------------- | --------------------------------------------------------- |
| `fact`       | Objective statement       | "The API rate limit is 100 req/min"                       |
| `preference` | User or system preference | "Team uses TypeScript for all new services"               |
| `episode`    | Event or occurrence       | "Production outage on Feb 10 lasted 2 hours"              |
| `decision`   | Decision made             | "Chose PostgreSQL over MongoDB for the primary datastore" |

### Entities

Entities are people, organizations, projects, technologies, or concepts referenced by facts. Entity resolution deduplicates mentions across documents — "Acme", "Acme Corp", and "Acme Corporation" resolve to a single entity.

### Relationships

Facts can relate to other facts via typed relationships:

| Relationship  | Meaning                                 |
| ------------- | --------------------------------------- |
| `updates`     | New fact supersedes an older version    |
| `extends`     | New fact adds detail to an existing one |
| `derives`     | New fact is inferred from another       |
| `contradicts` | New fact conflicts with an existing one |

When an `updates` relationship is created, the older fact's `is_latest` flag is set to `false`. Queries return only the latest version by default.

### Querying Facts

Facts are included in query responses when `include_facts: true` is set (or automatically when the Memory Layer is enabled for your tenant):

```json theme={null}
{
  "query": "What tech stack does Acme use?",
  "include_facts": true,
  "entity": "Acme Corp"
}
```

See the [Querying](/querying) guide for full details.
