{"id":51522319,"url":"https://github.com/djakish/sana","last_synced_at":"2026-07-08T17:00:52.383Z","repository":{"id":365091184,"uuid":"1264998590","full_name":"djakish/sana","owner":"djakish","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-26T14:06:53.000Z","size":3942,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-26T16:08:05.073Z","etag":null,"topics":["database","object-storage","rabitq","rust","s3","search-database","turbopuffer","vector-database","vector-search"],"latest_commit_sha":null,"homepage":"https://djakish.github.io/sana/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/djakish.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-10T11:21:34.000Z","updated_at":"2026-06-26T14:06:57.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/djakish/sana","commit_stats":null,"previous_names":["djakish/sana"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/djakish/sana","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djakish%2Fsana","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djakish%2Fsana/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djakish%2Fsana/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djakish%2Fsana/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/djakish","download_url":"https://codeload.github.com/djakish/sana/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djakish%2Fsana/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35271852,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-08T02:00:06.796Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","object-storage","rabitq","rust","s3","search-database","turbopuffer","vector-database","vector-search"],"created_at":"2026-07-08T17:00:51.467Z","updated_at":"2026-07-08T17:00:52.345Z","avatar_url":"https://github.com/djakish.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sana\n\nAn object-storage-native search database: vectors, full-text, and attribute\nfilters over documents whose only durable home is an object store (a local\ndirectory or S3). A [turbopuffer](https://turbopuffer.com)-inspired open-source\nclone, built in staged, documented commits.\n\n\u003e **AI disclaimer:** this is an AI-assisted project (built with Claude and Codex).\n\u003e It exists to learn from, not to run your production on.\n\n**What works:**\n\n- Durable writes: a WAL with a CAS-advanced commit cursor in object storage,\n  strongly consistent reads through the unindexed overlay, idempotency keys,\n  conditional writes, patch/delete-by-filter, and write backpressure.\n- Indexes: LSM document SSTs, delta-tiered attribute postings, BM25 full-text\n  with rank-safe block MAXSCORE, IVF vectors with faithful RaBitQ quantization\n  (SIMD kernels) and SPFresh-style local split/merge maintenance.\n- One binary: a CLI, API, object-store-discovered queue broker, looped\n  indexing/maintenance roles, all-in-one dev serving, operator GC dry-runs, and\n  Prometheus `/metrics` endpoints for the API and queue broker.\n- Backends: local filesystem for dev, plus S3-compatible stores with\n  server-enforced conditional writes (verified against MinIO).\n- Operations: namespace branch, cross-store copy, deterministic export, leased\n  replica pinning, cache warming, and an ANN recall endpoint.\n\n## Quick start\n\n```sh\ncargo run --release -- demo ./data        # tiny end-to-end demo\ncargo run --release -- serve ./data       # HTTP service on 127.0.0.1:8080\ncargo run --release --example usage       # library API tour\ncargo run --release --example latency     # benchmark harness\n```\n\n## HTTP API\n\nThe wire format tracks turbopuffer's `/v2` API. With `serve` running (see Quick\nstart), write a document (the namespace is created on first write):\n\n```sh\ncurl -s localhost:8080/v2/namespaces/books -H 'content-type: application/json' -d '{\n  \"kind\": \"append\",\n  \"operations\": [\n    {\"Upsert\": {\"id\": 1, \"document\": {\n      \"id\": 1,\n      \"attributes\": {\"title\": \"Dune\", \"genre\": \"scifi\", \"rating\": 4.5},\n      \"vectors\": {\"embedding\": [0.9, 0.1]}\n    }}}\n  ]\n}'\n```\n\nQuery it. Here an approximate vector search narrowed by an attribute filter:\n\n```sh\ncurl -s localhost:8080/v2/namespaces/books/query -H 'content-type: application/json' -d '{\n  \"kind\": \"single\",\n  \"query\": {\n    \"filter\": {\"Eq\": {\"column\": \"genre\", \"value\": \"scifi\"}},\n    \"approx_vector\": {\"column\": \"embedding\", \"vector\": [1.0, 0.0], \"k\": 5}\n  }\n}'\n```\n\nHybrid search runs several rankings over one consistent snapshot with a\nmulti-query, then fuses them client-side (for example with Reciprocal Rank\nFusion). Here a vector ranking and a BM25 ranking together:\n\n```sh\ncurl -s localhost:8080/v2/namespaces/books/query -H 'content-type: application/json' -d '{\n  \"kind\": \"multi\",\n  \"query\": {\"queries\": [\n    {\"approx_vector\": {\"column\": \"embedding\", \"vector\": [1.0, 0.0], \"k\": 10}},\n    {\"text\": {\"column\": \"title\", \"query\": \"dune\", \"k\": 10}}\n  ]}\n}'\n```\n\nThe response holds one ranked result per subquery. The `hybrid` example\n(`cargo run --example hybrid`) shows the RRF fusion in full.\n\n| Method | Route | Purpose |\n|---|---|---|\n| `POST` | `/v2/namespaces/{ns}` | writes: append / conditional / patch- \u0026 delete-by-filter |\n| `POST` | `/v2/namespaces/{ns}/query` | single or multi query (vector / BM25 / filter) |\n| `GET` | `/v1/namespaces/{ns}/metadata` | index freshness, sizes, pinning |\n| `POST` | `/v1/namespaces/{ns}/_debug/recall` | ANN recall vs exact |\n| `GET` | `/metrics` | Prometheus text |\n\nThe full write/query cookbook, limits, multi-pod deployment, and the Rust\nlibrary API live in the [user guide](docs/guide.md).\n\n## Docs\n\n[User guide](docs/guide.md) ·\n[Architecture](docs/ARCHITECTURE.md) ·\n[Build log \u0026 decisions](docs/PROGRESS.md) ·\n[Contributing](CONTRIBUTING.md) ·\n[Benchmarks](docs/benchmarks.md)\n\n## License\n\nMIT, see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdjakish%2Fsana","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdjakish%2Fsana","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdjakish%2Fsana/lists"}