Load testing did not justify the maintenance cost of the -py3.14t target, so this removes it and the multi-loop server built on top of it. Removed outright: - `hindsight_api/_free_threading.py` and `HINDSIGHT_API_FREE_THREADING` — the guard that turned CPython's GIL-re-enable RuntimeWarning into an error. - `docker/standalone/Dockerfile.freethreaded`, `docker/freethreaded-smoke.sh`, the `test-api (free-threaded 3.14)` CI job, and the `-py3.14t` release image (including its `latest=false` carve-out in the image metadata step). - `multi_loop.py`, `HINDSIGHT_API_EVENT_LOOPS` / `--event-loops`, and `_serve_multi_loop`. Several event loops in one process is only a throughput win without the GIL; on a stock build the loops take turns, which `main.py` already warned about. Multi-loop hooks reverted with it: `run_background_tasks` on MemoryEngine and both `create_app`s, `LLMTraceRecorder.bind_loop` and its per-loop filter, and — from the #4123 follow-up — `ExtensionContext.is_primary` plus the thread-local context in `Extension`. With one loop per process the flag is permanently True and only one context is ever set, so both were dead weight on a public extension interface. `HINDSIGHT_API_MIGRATION_ISOLATION` loses its `auto` mode and now defaults to `false`. `auto` isolated only on a free-threaded interpreter, so this changes nothing for any existing deployment; `true`/`false` still force it either way. Kept, because they are real races that threads hit under the GIL too and only their rationale was free-threading-specific: the dateparser lock and the `regex>=2026.9.3` floor, one TEI HTTP client per thread, the shared bounded embeddings request pool, `bank_stats_cache`'s per-loop coalescing, and `_cross_loop.py` (still used by llm_wrapper, cross_encoder and llamacpp_llm). Their comments now stand on plain thread/loop-safety grounds. Ordinary Python 3.14 is untouched: the `build-api-python-versions` matrix still covers 3.11-3.14 and the litellm >=1.93.0 cp314 floor stays. Verified: lint.sh, ty, and the deterministic suite (8645 passed). OpenAPI and the generated clients show no drift, and the two .env.example copies stay byte-identical.
19 KiB
Installation
Hindsight can be deployed in several ways depending on your infrastructure and requirements.
:::tip Don't want to manage infrastructure? Hindsight Cloud is a fully managed service that handles all infrastructure, scaling, and maintenance — sign up here. :::
Supported Platforms
Hindsight runs on Linux, macOS, and Windows:
| Platform | Docker | Bare Metal (pip) | Embedded DB (pg0) | Notes |
|---|---|---|---|---|
| Linux (x86_64, ARM64) | ✅ | ✅ | ✅ | Fully supported, recommended for production |
| macOS (Apple Silicon / arm64) | ✅ | ✅ | ✅ | Fully supported |
| macOS (Intel / x86_64) | ✅ | ⚠️ slim only | ✅ | Use hindsight-all-slim / hindsight-api-slim. The full bundle's local ML models (PyTorch, MLX) publish no Intel-Mac wheels, so pip install hindsight-all silently backtracks to a months-old release. Pair the slim bundle with a hosted embeddings/reranker provider or the in-process ONNX backend (hindsight-api-slim[local-onnx]). |
| Windows (x86_64) | ✅ | ✅ | ✅ | Fully supported — see Windows setup for external PostgreSQL option |
All platforms support the embedded database (pg0) for development. On Windows, you can also use an external PostgreSQL installation — see the Windows section for a step-by-step guide.
Prerequisites
PostgreSQL
Hindsight requires PostgreSQL 14+ with a vector extension for similarity search. The supported extensions are:
- pgvector (default)
- pgvectorscale
- vchord
- scann (AlloyDB)
Configure which one to use with HINDSIGHT_API_VECTOR_EXTENSION. See Configuration for details.
By default, Hindsight uses pg0 — an embedded PostgreSQL that runs locally on your machine. This is convenient for development but not recommended for production.
For production, use an external PostgreSQL with one of the supported vector extensions:
- Supabase — Managed PostgreSQL with pgvector built-in
- Neon — Serverless PostgreSQL with pgvector
- Azure Database for PostgreSQL — With pgvector and pgvectorscale support
- Google AlloyDB / AlloyDB Omni — With pgvector and ScaNN support
- AWS RDS / Cloud SQL — With pgvector extension enabled
- Self-hosted — PostgreSQL 14+ with your preferred vector extension
LLM Provider
You need an LLM API key for fact extraction, entity resolution, and answer generation. See Models for supported providers, model recommendations, and configuration.
Hardware
Hindsight is designed to run on commodity hardware. The footprint depends mainly on whether the full image (which bundles local embedding and reranker models) or the slim image (which delegates those to external providers) is used.
| Component | Minimum RAM | Recommended RAM | Notes |
|---|---|---|---|
| API — Full image | 1.5 GB | 2 GB | Loads local BGE embedder (~130 MB) and MiniLM cross-encoder (~90 MB) into memory, plus PyTorch/ONNX runtime arenas. Idle RSS settles around 0.8–1.0 GB; expect 1.2–1.5 GB under load. |
| API — Slim image | 512 MB | 1 GB | No local models. Steady-state RSS is dominated by Python runtime and DB connections. Requires external embedding and reranker providers (e.g. TEI, OpenAI, Cohere). |
| Control Plane (UI) | 128 MB | 256 MB | Next.js process, lightweight. |
| Worker (if separated) | Same as API image variant | Same as API image variant | Workers load the same models as the API server. |
| PostgreSQL | 512 MB | 1 GB+ | Scales with the number of memories and indexes. |
:::tip Reducing the footprint The bulk of the full image's memory comes from the bundled embedding and reranker models and their PyTorch/ONNX runtimes. To shrink the deployment to a few hundred MB of RAM, switch to the slim image and configure external embedding and reranker providers. :::
CPU vs GPU: 2 vCPUs on CPU-only is fine for development and basic workloads. For production traffic, the local reranker (cross-encoder) is the main bottleneck and typically benefits from a GPU to keep recall latency reasonable; alternatively, offload reranking to an external reranker provider (e.g. TEI, Cohere) on dedicated GPU hardware.
Docker
Best for: Quick start, development, small deployments
Run everything in one container with embedded PostgreSQL:
export OPENAI_API_KEY=sk-xxx
docker run -it --pull always --name hindsight --restart unless-stopped --shm-size=1g -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-v hindsight-data:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
- API Server: http://localhost:8888
- Control Plane (Web UI): http://localhost:9999
:::note Persisting data: named volume vs. host bind mount
The container runs as a non-root user (UID 1000). The hindsight-data named volume above is recommended — Docker creates it owned by the container user, so it works with no extra setup.
If you instead bind-mount a host directory (-v $HOME/.hindsight-docker:/home/hindsight/.pg0), that directory must be owned by UID 1000, or the embedded database fails to start with Permission denied:
sudo chown -R 1000:1000 $HOME/.hindsight-docker
Do not run the image under a different UID with --user to work around this. The image only defines the hindsight user (UID 1000), so any other UID has no /etc/passwd entry, and startup crashes in a library that looks the running user up by ID:
KeyError: 'getpwuid(): uid not found: 1042'
Running as UID 1000 (the default) with the directory chowned to match is the supported way to use a host bind mount. If you cannot chown the directory — for example on a NAS share mounted with a fixed uid= — use a named volume instead.
:::
All published images are signed with Cosign — verification is optional.
:::tip Set a stable HINDSIGHT_API_WORKER_ID in production
The worker uses the container hostname as its identity, which Docker sets to the container ID by default. That value changes on every restart, so any task that was being processed when the container went down stays parked under the old ID with no way for the new container to recognize it as its own.
Set HINDSIGHT_API_WORKER_ID to a stable value (e.g., -e HINDSIGHT_API_WORKER_ID=hindsight-prod) so the worker keeps the same identity across restarts. This is recommended even for single-container deployments. For diagnosis and recovery commands, see Admin CLI - Recovering stuck operations.
:::
Docker Image Variants
| Variant | Size (AMD64) | Size (ARM64) | When to use |
|---|---|---|---|
Full (latest) |
~9 GB | ~3.7 GB | Default. Embeddings and reranking run in the image; the LLM is always external, including for local inference. |
Slim (slim) |
~500 MB | ~500 MB | Use when you already rely on external services for embeddings and reranking (OpenAI, Cohere, TEI). Significantly smaller image, faster deploys. Requires external providers. |
The slim image corresponds to the hindsight-api-slim pip package. See Configuration for external provider options.
Neither image bundles llama.cpp, so the built-in llamacpp provider is not available in Docker. To run inference locally, start llama.cpp (or Ollama, LM Studio, vLLM) alongside Hindsight and point HINDSIGHT_API_LLM_BASE_URL at it — see docker/docker-compose/local-llm/ for a working compose file.
NVIDIA GPU Acceleration (CUDA)
To run in-process local embedding and reranker models on an NVIDIA GPU, build a custom CUDA-enabled image using the recipe in docker/docker-compose/cuda/:
docker compose -f docker/docker-compose/cuda/docker-compose.yaml up --build
The recipe upgrades in-process PyTorch to CUDA 12.6 and configures GPU passthrough via the NVIDIA Container Toolkit. Build it on the machine that will run it — an emulated cross-architecture image cannot reach the GPU.
The CUDA runtime is additive: the base image's CPU PyTorch wheel stays in the lower layers, so the result is roughly 11 GB on disk against the ~9 GB Full image. This is why no CUDA image is published — the cost is only worth paying when you actually have a GPU to use.
See docker/docker-compose/cuda/README.md for prerequisites, manual build steps, and verification.
Bundling Custom Models in a Custom Image
:::tip Production deployments with non-default local models
If you use a non-default local embedder or reranker, bake the models into a custom image at build time rather than enabling the Helm modelCache PVC. See docker/docker-compose/custom-models/ for a runnable example.
:::
Available Tags
# Standalone (API + Control Plane)
ghcr.io/vectorize-io/hindsight:latest # Full, latest release
ghcr.io/vectorize-io/hindsight:latest-slim # Slim, latest release
ghcr.io/vectorize-io/hindsight:0.4.9 # Full, specific version
ghcr.io/vectorize-io/hindsight:0.4.9-slim # Slim, specific version
# API only
ghcr.io/vectorize-io/hindsight-api:latest
ghcr.io/vectorize-io/hindsight-api:latest-slim
# Control Plane only
ghcr.io/vectorize-io/hindsight-control-plane:latest
Verifying image signatures
Images are signed with Cosign keyless OIDC. To verify any tag:
cosign verify ghcr.io/vectorize-io/hindsight:<tag> \
--certificate-identity-regexp '^https://github\.com/vectorize-io/hindsight/\.github/workflows/(sign-images|release)\.yml@.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
Helm / Kubernetes
Best for: Production deployments, auto-scaling, cloud environments
# Install with built-in PostgreSQL
helm install hindsight oci://ghcr.io/vectorize-io/charts/hindsight \
--set api.llm.provider=groq \
--set api.llm.apiKey=gsk_xxxxxxxxxxxx \
--set postgresql.enabled=true
# Or use external PostgreSQL
helm install hindsight oci://ghcr.io/vectorize-io/charts/hindsight \
--set api.llm.provider=groq \
--set api.llm.apiKey=gsk_xxxxxxxxxxxx \
--set postgresql.enabled=false \
--set api.database.url=postgresql://user:pass@postgres.example.com:5432/hindsight
# Install a specific version
helm install hindsight oci://ghcr.io/vectorize-io/charts/hindsight --version 0.1.3
# Upgrade to latest
helm upgrade hindsight oci://ghcr.io/vectorize-io/charts/hindsight
Requirements:
- Kubernetes cluster (GKE, EKS, AKS, or self-hosted)
- Helm 3.8+
Distributed Workers
For high-throughput deployments, enable dedicated worker pods to scale task processing independently:
helm install hindsight oci://ghcr.io/vectorize-io/charts/hindsight \
--set worker.enabled=true \
--set worker.replicaCount=3
The chart deploys workers as a StatefulSet, so each pod gets a stable name (e.g. hindsight-worker-0) that the worker uses as its HINDSIGHT_API_WORKER_ID. Tasks claimed by a pod are recognized as its own across restarts. If you swap the chart for a plain Deployment, set HINDSIGHT_API_WORKER_ID explicitly per replica — otherwise hostnames are randomized and previously-claimed tasks become orphaned. See Admin CLI - Recovering stuck operations for diagnosis.
See Services - Worker Service for configuration details and architecture.
See the Helm chart values.yaml for all chart options.
Bare Metal (pip)
Best for: Running Hindsight as a standalone service on a host machine.
Install
pip install hindsight-api # Full — works out of the box
pip install hindsight-api-slim # Slim — requires external services for embeddings, reranking, and the database
When using hindsight-api-slim, you must configure external providers for all model operations. See Configuration for details.
Run with Embedded Database
For development and testing, Hindsight can run with an embedded PostgreSQL (pg0):
export HINDSIGHT_API_LLM_PROVIDER=groq
export HINDSIGHT_API_LLM_API_KEY=gsk_xxxxxxxxxxxx
hindsight-api
This creates a database in ~/.hindsight/data/ and starts the API on http://localhost:8888.
Run with External PostgreSQL
For production, connect to your own PostgreSQL instance:
export HINDSIGHT_API_DATABASE_URL=postgresql://user:pass@localhost:5432/hindsight
export HINDSIGHT_API_LLM_PROVIDER=groq
export HINDSIGHT_API_LLM_API_KEY=gsk_xxxxxxxxxxxx
hindsight-api
Note: The database must exist and have pgvector enabled (CREATE EXTENSION vector;).
CLI Options
hindsight-api --port 9000 # Custom port (default: 8888)
hindsight-api --host 127.0.0.1 # Bind to localhost only
hindsight-api --workers 4 # Multiple worker processes
hindsight-api --log-level debug # Verbose logging
Control Plane
The Control Plane (Web UI) can be run standalone using npx:
npx @vectorize-io/hindsight-control-plane --api-url http://localhost:8888
This connects to your running API server and provides a visual interface for managing memory banks, exploring entities, and testing queries.
Options
| Option | Environment Variable | Default | Description |
|---|---|---|---|
-p, --port |
PORT |
9999 | Port to listen on |
-H, --hostname |
HOSTNAME |
0.0.0.0 | Hostname to bind to |
-a, --api-url |
HINDSIGHT_CP_DATAPLANE_API_URL |
http://localhost:8888 | Hindsight API URL |
HINDSIGHT_CP_ACCESS_KEY |
(none) | Access key to protect the Control Plane UI. When set, users must enter this key to log in. |
Examples
# Run on custom port
npx @vectorize-io/hindsight-control-plane --port 9999 --api-url http://localhost:8888
# Using environment variables
export HINDSIGHT_CP_DATAPLANE_API_URL=http://api.example.com
npx @vectorize-io/hindsight-control-plane
# Production deployment
PORT=80 HINDSIGHT_CP_DATAPLANE_API_URL=https://api.hindsight.io npx @vectorize-io/hindsight-control-plane
Windows
Best for: Running Hindsight natively on Windows without Docker
Hindsight works on Windows with the embedded database (pg0) out of the box — just install and run:
pip install hindsight-api
set HINDSIGHT_API_LLM_PROVIDER=openai
set HINDSIGHT_API_LLM_API_KEY=sk-xxx
set HINDSIGHT_API_LLM_MODEL=gpt-4o-mini
hindsight-api
Using External PostgreSQL (optional)
If you prefer to use your own PostgreSQL instance instead of the embedded database:
# Install PostgreSQL
winget install PostgreSQL.PostgreSQL.17
# Build pgvector (requires Visual Studio Build Tools)
git clone https://github.com/pgvector/pgvector.git
cd pgvector
# Open "x64 Native Tools Command Prompt for VS" and run:
set PGROOT=C:\Program Files\PostgreSQL\17
nmake /F Makefile.win
nmake /F Makefile.win install
# Create the database and enable the vector extension
psql -U postgres -c "CREATE DATABASE hindsight;"
psql -U postgres -d hindsight -c "CREATE EXTENSION vector;"
Then run Hindsight pointing to your database:
pip install hindsight-api
set HINDSIGHT_API_DATABASE_URL=postgresql://postgres@localhost:5432/hindsight
set HINDSIGHT_API_LLM_PROVIDER=openai
set HINDSIGHT_API_LLM_API_KEY=sk-xxx
set HINDSIGHT_API_LLM_MODEL=gpt-4o-mini
hindsight-api
- API Server: http://localhost:8888
:::tip
You can also use the slim package (pip install hindsight-api-slim) if you configure external providers for embeddings and reranking. See Configuration for details.
:::
Windows + China Network Notes
If you are running on Windows behind China network restrictions:
- DeepSeek works well for
HINDSIGHT_API_LLM_PROVIDER, but DeepSeek does not provide an embeddings endpoint. - Use local embeddings (recommended for privacy and reliability in restricted networks).
- Set
HF_ENDPOINT=https://hf-mirror.combefore starting Hindsight so Hugging Face model downloads use a China-accessible mirror.
set HF_ENDPOINT=https://hf-mirror.com
set HINDSIGHT_API_LLM_PROVIDER=deepseek
set HINDSIGHT_API_LLM_API_KEY=sk-your-deepseek-key
set HINDSIGHT_API_LLM_MODEL=deepseek-v4-flash
set HINDSIGHT_API_LLM_BASE_URL=https://api.deepseek.com
set HINDSIGHT_API_EMBEDDINGS_PROVIDER=local
set HINDSIGHT_API_EMBEDDINGS_LOCAL_MODEL=BAAI/bge-small-en-v1.5
set HINDSIGHT_API_RERANKER_PROVIDER=flashrank
hindsight-api
The HF_ENDPOINT variable is used by Hugging Face tooling (huggingface_hub), not by Hindsight itself.
Embedded in a Python Application
Best for: Using Hindsight programmatically from Python without running a separate server process.
pip install hindsight-all # Full — works out of the box (Linux, Windows, Apple Silicon Macs)
pip install hindsight-all-slim # Slim — requires external services for embeddings, reranking, and the database
On Intel (x86_64) Macs, install hindsight-all-slim — see Supported Platforms.
hindsight-all supports two modes of embedding:
In-process (HindsightServer): the server runs in a background thread inside your application. Best when you want the tightest integration and are already managing your own process lifecycle.
from hindsight import HindsightServer, HindsightClient
with HindsightServer(llm_provider="openai", llm_api_key="sk-xxx") as server:
client = HindsightClient(base_url=server.url)
client.retain(bank_id="alice", content="Alice prefers concise answers.")
results = client.recall(bank_id="alice", query="How should I respond to Alice?")
Managed subprocess (HindsightEmbedded): the server runs as a background daemon process, shared across multiple Python processes or sessions. The daemon starts on first use and runs until it is stopped.
from hindsight import HindsightEmbedded
client = HindsightEmbedded(llm_provider="openai", llm_api_key="sk-xxx")
client.retain(bank_id="alice", content="Alice prefers concise answers.")
results = client.recall(bank_id="alice", query="How should I respond to Alice?")
See the Python SDK for the full API reference.
Next Steps
- Configuration — Environment variables and settings
- Models — ML models and providers
- Monitoring — Metrics and observability