Architecture
A self-hosted Engram instance is five processes:
┌─────────────────────────────────────────────────────────┐│ ││ ┌───────────────┐ ┌───────────────┐ ││ │ Engram app │◄─►│ Postgres │ ││ │ (Elixir) │ │ (notes, │ ││ │ │ │ metadata) │ ││ │ - REST API │ └───────────────┘ ││ │ - WebSocket │ ┌───────────────┐ ││ │ - MCP │◄─►│ Qdrant │ ││ │ - Web SPA │ │ (vectors) │ ││ │ │ └───────────────┘ ││ │ │ ┌───────────────┐ ││ │ │◄─►│ Ollama │ (embeddings) ││ │ │ └───────────────┘ ││ │ │ ┌───────────────┐ ││ │ │◄─►│ MinIO │ (attachments) ││ └───────────────┘ └───────────────┘ ││ │└─────────────────────────────────────────────────────────┘Each piece, briefly
Section titled “Each piece, briefly”- Engram app is the Elixir/Phoenix monolith. Serves the REST API, WebSocket sync, MCP endpoint, and the React web SPA from one process. Stateless beyond its database/cache connections.
- Postgres holds notes, folders, metadata, users, and billing. Uses Row-Level Security for multi-tenancy. Also hosts Oban (job queue).
- Qdrant is the vector store for semantic search. Holds embeddings with binary quantization + rescore.
- Ollama (or BYO embedding service) generates embeddings on
every note upsert. Default model:
nomic-embed-text(768 dims). - MinIO (or any S3-compatible) stores attachments (images/PDFs/binary files). Notes themselves live in Postgres.
Why these picks
Section titled “Why these picks”- Elixir/OTP for concurrent sync fan-out, fault tolerance, and no GIL bottleneck on the WebSocket fan-out path
- Postgres because boring is good; RLS handles multi-tenancy without custom plumbing
- Qdrant for fast HNSW, with binary quantization keeping memory tight
- Ollama as the easiest path to local embeddings
- MinIO for S3-compatible self-host; you can swap in real S3, R2, or any S3-compatible bucket
Network topology
Section titled “Network topology”The app listens on port 4000 by default. A reverse proxy (Caddy, Nginx, NPM) terminates TLS in front of it. Postgres, Qdrant, Ollama, and MinIO are on a private Docker network, so only the app talks to them.
For TLS guidance see Quickstart.