[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-80501":3},{"id":4,"name":5,"fullName":6,"owner":5,"repo":5,"description":7,"homepage":8,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":16,"stars30d":12,"stars90d":15,"forks30d":15,"starsTrendScore":15,"compositeScore":17,"rankGlobal":9,"rankLanguage":9,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":9,"pushedAt":9,"updatedAt":33,"readmeContent":34,"aiSummary":35,"trendingCount":15,"starSnapshotCount":15,"syncStatus":13,"lastSyncTime":36,"discoverSource":37},80501,"namidb","namidb\u002Fnamidb","Graph database native to the cloud. Embedded, multi-tenant, built on object storage.","https:\u002F\u002Fnamidb.com",null,"Rust",104,9,2,3,0,1,44.4,"Other",false,"main",true,[23,24,25,26,27,28,29,30,31,32],"agent-memory","columnar","cypher","gql","graph-database","graphrag","lsm-tree","object-storage","rust","s3","2026-06-11 04:07:13","\u003Cdiv align=\"center\">\n\n\u003Cp>\n  \u003Cimg src=\".assets\u002Fnamidb-logo.jpeg\" alt=\"NamiDB\" width=\"640\" \u002F>\n\u003C\u002Fp>\n\n# NamiDB\n\n### A graph database that lives in your S3 bucket.\n\nIt embeds like DuckDB, runs as a standalone HTTP server, or sits on our hosted cloud. Same engine in all three, and the bucket is always the source of truth.\n\n[![License: BSL 1.1](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-BSL%201.1-1f6feb.svg)](LICENSE)\n[![Rust](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FRust-1.85%2B-dea584.svg?logo=rust&logoColor=white)](https:\u002F\u002Fwww.rust-lang.org)\n[![PyPI](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FPyPI-namidb-3776ab.svg?logo=pypi&logoColor=white)](https:\u002F\u002Fpypi.org\u002Fproject\u002Fnamidb\u002F)\n[![Docker](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDocker-namidb--server-2496ed.svg?logo=docker&logoColor=white)](crates\u002Fnamidb-server\u002FDockerfile)\n[![Website](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FWebsite-namidb.com-0a7ea4.svg)](https:\u002F\u002Fnamidb.com)\n[![Docs](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDocs-docs.namidb.com-0a7ea4.svg)](https:\u002F\u002Fdocs.namidb.com)\n\n[**Website**](https:\u002F\u002Fnamidb.com) · [**Documentation**](https:\u002F\u002Fdocs.namidb.com) · [**RFCs**](.\u002Fdocs\u002Frfc\u002F) · [**Request early access**](https:\u002F\u002Fnamidb.com)\n\n\u003C\u002Fdiv>\n\n---\n\nNamiDB is a graph database engine built around object storage. You write Cypher, it lays your nodes and edges out as columnar files in a bucket, and that bucket is the only source of truth. There's nothing else to run and nothing to coordinate outside the bucket itself. The same engine ships three ways: embedded as a library, as an HTTP server, or on our hosted cloud.\n\n\u003Cbr \u002F>\n\n## Why now\n\nA few things had to line up before this made sense.\n\n**S3 finally got conditional writes.** In 2024, S3 shipped `If-Match` and `If-None-Match`, which was the last primitive we were missing. With compare-and-swap on the bucket you can build a coordinated, durable system where object storage *is* the database. There's no Raft, no ZooKeeper, no etcd in the picture. People had already pulled this off for vectors, for queues, for analytics. Nobody had done it for graphs.\n\n**The best columnar graph engine left the field.** Apple bought Kùzu in October 2025 and archived the repo. It was the most carefully thought-out columnar graph engine anyone had published, and it just went quiet. That left a hole.\n\n**Agents need graphs.** Vector search is necessary but it isn't enough. Knowledge graphs are what agent memory, deep retrieval, and reasoning under uncertainty actually sit on once you're past the demo. A lot of the interesting AI work this decade is going to be about relationships, not just embeddings.\n\nSo that's what we're building.\n\n\u003Cbr \u002F>\n\n## Where this came from\n\nNamiDB started inside LESAI as the graph database behind a hosted product we're building. We've been at it for about a year now, and every Cypher query, every manifest CAS, every CSR adjacency table in here has been run against real workloads, not just unit tests.\n\nWe're open-sourcing the engine now because two things finally lined up:\n\n1. Apple archived Kùzu in October 2025, so the columnar property-graph space lost its one maintained option. We'd independently landed on more or less the design Kùzu pioneered, so putting NamiDB out there felt like the most useful thing we could do about that gap.\n2. Our own roadmap moved to a hosted product, [NamiDB Cloud](https:\u002F\u002Fnamidb.com), which is multi-tenant and scales to zero per namespace. The engine doesn't need to be a competitive secret anymore. The engine is open, the cloud is the business.\n\n\u003Cbr \u002F>\n\n## The shape\n\n**NamiDB writes Cypher to your S3 bucket.**\n\nThere's no control plane to provision, no Raft to tune, no etcd to babysit. Conditional writes (`If-Match` \u002F `If-None-Match`) on the bucket take the place of a consensus tier, so the bucket itself holds the truth. Your graph database is just files: durability is whatever S3, R2, GCS or Azure already give you, cost drops to zero when nobody is querying, a backup is `aws s3 sync`, and a tenant is a folder.\n\nThe engine is the same whether you run it as a library inside your app, as a Rust daemon over HTTP, or on our hosted cloud. It works just as well against AWS S3, Cloudflare R2, GCS, Azure Blob, MinIO, or your local disk.\n\n\u003Cbr \u002F>\n\n## Three deployments, one engine\n\n\u003Cp align=\"center\">\n  \u003Cpicture>\n    \u003Csource media=\"(prefers-color-scheme: dark)\" srcset=\".assets\u002Fnamidb-deployments-dark.svg\" \u002F>\n    \u003Cimg src=\".assets\u002Fnamidb-deployments.svg\" alt=\"NamiDB deployments: Server, Embedded, Cloud, converging on a single object-storage bucket\" width=\"900\" \u002F>\n  \u003C\u002Fpicture>\n\u003C\u002Fp>\n\n| Mode | Status | Best for | How it ships |\n|---|---|---|---|\n| **Server** | ✅ v0.1 | **Self-hosted production over your S3 \u002F R2 \u002F GCS \u002F Azure bucket** | `namidb-server` binary + Docker image |\n| **Embedded** | ✅ v0.1 | Notebooks, single-process apps, local dev, CI fixtures | `pip install namidb`, talks to a bucket from inside your process |\n| **Cloud** | 🔒 closed beta | Multi-tenant SaaS, agent memory, scale-to-zero per namespace | Managed by LESAI on namidb.com, [request access](https:\u002F\u002Fnamidb.com) |\n\nIt's the same engine across all three. Server and Embedded write to an identical bucket layout, so you can open an embedded notebook against the exact `s3:\u002F\u002F...` URI a production daemon is serving.\n\n\u003Cbr \u002F>\n\n## What's in the engine today\n\n- **Cypher and GQL parsing.** A strict subset of GQL (ISO\u002FIEC 39075:2024) plus openCypher 9. All 12 in-scope LDBC SNB Interactive Complex Read queries (IC01 through IC12) parse, plan and run end to end.\n- **Writes through Cypher.** `CREATE`, `MERGE`, `SET`, `DELETE`, `DETACH DELETE`, `REMOVE`. Durable on `commit_batch` (WAL append plus manifest CAS).\n- **Cost-based optimizer.** Predicate pushdown, projection pushdown, join reorder, hash-join conversion, hash semi-join (`EXISTS` decorrelation), Parquet row-group pruning. `EXPLAIN VERBOSE` prints the chosen plan with selectivity and cost annotations.\n- **Vectorized execution.** A morsel-driven executor with an optional factorized intermediate representation (RFC-017) for path-heavy queries.\n- **Columnar storage on object storage.** Parquet node SSTs, a custom edge-SST format with CSR adjacency (RFC-002), zstd compression, bloom filters, fence-pointer indices.\n- **Coordination-free correctness.** One writer per namespace, with epoch fencing via manifest CAS. Conditional writes (`If-Match`, `If-None-Match`) stand in for external consensus.\n- **Tiered caches.** A process-wide `AdjacencyCache` (CSR), a `NodeViewCache`, and an `SstCache` (decoded body, edge property streams, and the reader). Cross-snapshot reuse, `Arc`-shared and byte-budgeted.\n- **Six storage backends.** `memory:\u002F\u002F`, `file:\u002F\u002F` (with `flock`-based CAS), `s3:\u002F\u002F` (AWS S3, R2, MinIO, Tigris, LocalStack), `gs:\u002F\u002F`, `az:\u002F\u002F`.\n- **Python bindings.** `pip install namidb`. abi3 wheels for Linux (x86_64 and aarch64), macOS (arm64) and Windows (x86_64), with an sdist fallback everywhere else. Sync and async (`acypher`). Arrow, pandas and polars output.\n- **CLI.** `namidb parse`, `namidb explain --verbose`, `namidb run --store \u003Curi>` for ad-hoc query work against any backend.\n- **HTTP server.** The `namidb-server` binary, with bearer-token auth, a periodic flush loop, and a small REST API (`\u002Fv0\u002Fcypher`, `\u002Fv0\u002Fhealth`, `\u002Fv0\u002Fadmin\u002Fflush`).\n- **Bolt protocol.** Same `namidb-server` binary speaks Bolt 4.4 \u002F 5.0 \u002F 5.4 on an opt-in TCP listener (default 7687). Every published Neo4j driver (Python, Java, JavaScript, .NET, Go, Rust) connects unmodified via `bolt:\u002F\u002Fhost:7687`. See [RFC-022](.\u002Fdocs\u002Frfc\u002F022-bolt-protocol.md).\n- **Bench harness.** A synthetic, deterministic LDBC SNB Interactive harness under [`bench\u002F`](.\u002Fbench\u002F).\n\n\u003Cbr \u002F>\n\n## Quickstart\n\nTwo ways in. Same engine behind both.\n\n### Door 1: a real graph database in your S3 bucket\n\nThis is the headline use case. Point it at a bucket, write Cypher, and durability is whatever S3 already gives you.\n\n```bash\npip install namidb\nexport AWS_ACCESS_KEY_ID=AKIA...\nexport AWS_SECRET_ACCESS_KEY=...\n```\n\n```python\nimport namidb\n\n# Open (or bootstrap) the `prod` namespace on your bucket.\nclient = namidb.Client(\"s3:\u002F\u002Fmy-bucket\u002Fdata?ns=prod&region=us-east-1\")\n\nclient.cypher(\"CREATE (a:Person {name: 'Alice', age: 30})\")\nclient.cypher(\"CREATE (b:Person {name: 'Bob',   age: 25})\")\nclient.cypher(\n    \"MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'}) \"\n    \"CREATE (a)-[:KNOWS {since: 2020}]->(b)\"\n)\n\nresult = client.cypher(\n    \"MATCH (p:Person) WHERE p.age >= $min RETURN p.name AS name, p.age AS age\",\n    params={\"min\": 18},\n)\nprint(result.to_pandas())\n```\n\nKill the process and start it again. Open a notebook on another machine pointed at the same URI. The graph is still there, because the bucket is the database.\n\n### Door 2: a 30-second taste, no credentials\n\nFor when you just want to poke at the engine before wiring up a bucket. In-process, ephemeral, zero setup:\n\n```python\nimport namidb\nclient = namidb.Client(\"memory:\u002F\u002Facme\")\nclient.cypher(\"CREATE (a:Person {name: 'Alice'})\")\nprint(client.cypher(\"MATCH (p:Person) RETURN p.name\").rows())\n```\n\nThe same handful of lines work against `file:\u002F\u002F`, `gs:\u002F\u002F`, `az:\u002F\u002F`, or any S3-compatible endpoint. Only the URI changes.\n\n\u003Cbr \u002F>\n\n## Pick your storage backend\n\nThe URI tells the client which bucket and which namespace to use.\n\n| Scheme | Backend |\n|---|---|\n| `s3:\u002F\u002F\u003Cbucket>[\u002F\u003Cprefix>]?ns=\u003Cns>` | **AWS S3, Cloudflare R2, MinIO, Tigris, LocalStack, anything S3-compatible** |\n| `gs:\u002F\u002F\u003Cbucket>?ns=\u003Cns>` | Google Cloud Storage |\n| `az:\u002F\u002F\u003Caccount>\u002F\u003Ccontainer>?ns=\u003Cns>` | Azure Blob Storage |\n| `file:\u002F\u002F\u002Fabs\u002Fdir?ns=\u003Cns>` | Local filesystem (CAS via `flock` + atomic rename) |\n| `memory:\u002F\u002F\u003Cns>` | In-process and ephemeral, for testing only |\n\nEvery backend speaks the same Cypher, exposes the same Python, Rust and HTTP APIs, and gives you the same snapshot-isolated reads.\n\n### AWS S3 (the primary path)\n\n```python\nimport os\nos.environ[\"AWS_ACCESS_KEY_ID\"]     = \"AKIA...\"\nos.environ[\"AWS_SECRET_ACCESS_KEY\"] = \"...\"\n\nclient = namidb.Client(\n    \"s3:\u002F\u002Fmy-bucket\u002Fdata?ns=prod\"\n    \"&region=us-west-2\"\n)\n```\n\nCredentials come from the standard AWS env vars (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`, `AWS_DEFAULT_REGION`). IAM roles on EC2, EKS, Lambda and ECS just work, with no NamiDB-specific auth to wire up.\n\nThe only IAM permissions NamiDB needs on the bucket are `s3:GetObject`, `s3:PutObject`, `s3:DeleteObject` and `s3:ListBucket`. That's it. No DynamoDB lock table, no separate metadata service.\n\n### Cloudflare R2 (no egress fees)\n\nR2 charges nothing for egress and has full S3-compatible conditional writes. Same scheme, just point at the R2 endpoint with `region=auto`:\n\n```python\nimport os\nos.environ[\"AWS_ACCESS_KEY_ID\"]     = \"\u003CR2 access key>\"\nos.environ[\"AWS_SECRET_ACCESS_KEY\"] = \"\u003CR2 secret>\"\n\nclient = namidb.Client(\n    \"s3:\u002F\u002Fmy-bucket?ns=prod\"\n    \"&endpoint=https:\u002F\u002F\u003CACCOUNT_ID>.r2.cloudflarestorage.com\"\n    \"&region=auto\"\n)\n```\n\nIf you're running NamiDB anywhere outside AWS (Cloudflare Workers, Fly.io, your own VPS, your laptop), R2 is almost always the right call.\n\n### Other backends\n\nSame `namidb.Client(...)` call, just a different URI. Expand for the copy-paste credentials.\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Google Cloud Storage\u003C\u002Fstrong> (\u003Ccode>gs:\u002F\u002F\u003C\u002Fcode>)\u003C\u002Fsummary>\n\n```python\nimport os\nos.environ[\"GOOGLE_APPLICATION_CREDENTIALS\"] = \"\u002Fetc\u002Fgcs-key.json\"\nclient = namidb.Client(\"gs:\u002F\u002Fmy-bucket\u002Fdata?ns=prod\")\n```\n\nYou can also pass the service-account path in the URI:\n`gs:\u002F\u002Fmy-bucket?ns=prod&service_account=\u002Fetc\u002Fgcs-key.json`.\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Azure Blob Storage\u003C\u002Fstrong> (\u003Ccode>az:\u002F\u002F\u003C\u002Fcode>)\u003C\u002Fsummary>\n\n```python\nimport os\nos.environ[\"AZURE_STORAGE_ACCOUNT_NAME\"] = \"myacct\"\nos.environ[\"AZURE_STORAGE_ACCESS_KEY\"]   = \"...\"\nclient = namidb.Client(\"az:\u002F\u002Fmyacct\u002Fmycontainer?ns=prod\")\n```\n\nFor Azurite (the local emulator) tack on `&use_emulator=true`.\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>MinIO\u003C\u002Fstrong> (self-hosted S3), \u003Ccode>s3:\u002F\u002F\u003C\u002Fcode> with an \u003Ccode>endpoint=...\u003C\u002Fcode>\u003C\u002Fsummary>\n\n```bash\ndocker run -d --rm -p 9000:9000 -p 9001:9001 \\\n  -e MINIO_ROOT_USER=minioadmin -e MINIO_ROOT_PASSWORD=minioadmin \\\n  --name minio minio\u002Fminio server \u002Fdata --console-address \":9001\"\ndocker exec minio mc alias set local http:\u002F\u002F127.0.0.1:9000 minioadmin minioadmin\ndocker exec minio mc mb local\u002Fnamidb\n```\n\n```python\nimport os\nos.environ[\"AWS_ACCESS_KEY_ID\"]     = \"minioadmin\"\nos.environ[\"AWS_SECRET_ACCESS_KEY\"] = \"minioadmin\"\nclient = namidb.Client(\n    \"s3:\u002F\u002Fnamidb?ns=dev\"\n    \"&endpoint=http:\u002F\u002F127.0.0.1:9000\"\n    \"&region=us-east-1\"\n    \"&allow_http=true\"\n)\n```\n\nFor the production-style MinIO plus `namidb-server` plus docker-compose stack,\nsee [Self-host as a database](#self-host-as-a-database) below.\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>LocalStack\u003C\u002Fstrong> (S3 mock for tests), \u003Ccode>s3:\u002F\u002F\u003C\u002Fcode> with an \u003Ccode>endpoint=...\u003C\u002Fcode>\u003C\u002Fsummary>\n\n```bash\ndocker run -p 4566:4566 -e SERVICES=s3 localstack\u002Flocalstack\naws --endpoint-url=http:\u002F\u002Flocalhost:4566 s3 mb s3:\u002F\u002Fnamidb-dev\nexport AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test\n```\n\n```python\nclient = namidb.Client(\n    \"s3:\u002F\u002Fnamidb-dev?ns=local\"\n    \"&endpoint=http:\u002F\u002Flocalhost:4566\"\n    \"&allow_http=true\"\n    \"&region=us-east-1\"\n)\n```\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Local filesystem\u003C\u002Fstrong> (\u003Ccode>file:\u002F\u002F\u003C\u002Fcode>)\u003C\u002Fsummary>\n\nFor CI fixtures or single-machine dev when you want durability without\na bucket. Full manifest CAS via per-namespace `flock` plus atomic\n`rename(2)`.\n\n```python\nclient = namidb.Client(\"file:\u002F\u002F\u002Fvar\u002Flib\u002Fnamidb?ns=prod\")\n# relative paths work too:\nclient = namidb.Client(\"file:\u002F\u002F.\u002Fdata?ns=dev\")\n```\n\u003C\u002Fdetails>\n\n\u003Cbr \u002F>\n\n## Self-host as a database\n\nThere are two ways to run NamiDB as a database you fully own. Pick whichever matches how your app wants to talk to it.\n\n### Option A: embedded library plus your bucket\n\nYour app (Python or Rust) imports NamiDB directly and points at a bucket you control. Lowest latency, no extra hop, no network boundary, nothing to authenticate against. This is the \"DuckDB for graphs\" mode.\n\n```python\n# Python service\nimport namidb\nclient = namidb.Client(\"s3:\u002F\u002Fyour-bucket\u002Fdata?ns=prod&region=us-east-1\")\nresult = client.cypher(\"MATCH (n:Person) RETURN count(n) AS n\")\n```\n\n```rust\n\u002F\u002F Rust service\nuse namidb::{\n    core::id::NamespaceId,\n    storage::{parse_uri, WriterSession},\n};\n\nlet (store, paths) = parse_uri(\"s3:\u002F\u002Fyour-bucket\u002Fdata?ns=prod\")?;\nlet mut writer = WriterSession::open(store, paths).await?;\n\u002F\u002F upserts, commit_batch, snapshot reads...\n```\n\nReach for this when your read fan-out fits in a single process and you don't want any network overhead. Because object storage is the source of truth, two replicas of your service can open the same namespace independently, and NamiDB's epoch-CAS protocol fences out the stale writer for you.\n\n### Option B: the `namidb-server` daemon over REST\n\nA single Rust binary (or container image) opens a namespace and serves it over HTTP. This is the one for when the database lives on a different machine than the app, or when you want a network boundary with bearer-token auth.\n\n```bash\n# Install from source\ncargo install --path crates\u002Fnamidb-server\n\n# Or build the Docker image (from the repo root)\ndocker build -t namidb-server:0.1 -f crates\u002Fnamidb-server\u002FDockerfile .\n```\n\n```bash\nnamidb-server \\\n  --store \"s3:\u002F\u002Fyour-bucket\u002Fdata?ns=prod&region=us-east-1\" \\\n  --listen 0.0.0.0:8080 \\\n  --auth-token \"$NAMIDB_AUTH_TOKEN\"\n```\n\n```bash\ncurl -X POST http:\u002F\u002Fyour-host:8080\u002Fv0\u002Fcypher \\\n  -H \"Authorization: Bearer $NAMIDB_AUTH_TOKEN\" \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"query\": \"MATCH (n:Person) RETURN count(n) AS n\"}'\n# {\"columns\":[\"n\"],\"rows\":[{\"n\": 42}]}\n```\n\nSee [`crates\u002Fnamidb-server\u002FREADME.md`](.\u002Fcrates\u002Fnamidb-server\u002FREADME.md)\nfor the full route reference (`\u002Fv0\u002Fcypher`, `\u002Fv0\u002Fhealth`,\n`\u002Fv0\u002Fversion`, `\u002Fv0\u002Fadmin\u002Fflush`), the JSON to Cypher type mapping, and\nthe concurrency model.\n\n### Recipe: docker-compose with MinIO plus namidb-server\n\nA complete self-hosted database in one file. Bring your own auth token,\neverything else is wired up:\n\n```yaml\n# docker-compose.yml\nservices:\n  minio:\n    image: minio\u002Fminio\n    command: server \u002Fdata --console-address \":9001\"\n    environment:\n      MINIO_ROOT_USER: minioadmin\n      MINIO_ROOT_PASSWORD: minioadmin\n    volumes:\n      - minio-data:\u002Fdata\n    healthcheck:\n      test: [\"CMD\", \"mc\", \"ready\", \"local\"]\n      interval: 3s\n      retries: 30\n\n  bucket-init:\n    image: minio\u002Fmc\n    depends_on:\n      minio:\n        condition: service_healthy\n    entrypoint: >\n      sh -c \"\n        mc alias set local http:\u002F\u002Fminio:9000 minioadmin minioadmin &&\n        mc mb --ignore-existing local\u002Fnamidb\n      \"\n\n  namidb-server:\n    image: namidb-server:0.1   # built from crates\u002Fnamidb-server\u002FDockerfile\n    depends_on:\n      bucket-init:\n        condition: service_completed_successfully\n    environment:\n      NAMIDB_STORE: \"s3:\u002F\u002Fnamidb?ns=prod&endpoint=http:\u002F\u002Fminio:9000&region=us-east-1&allow_http=true\"\n      NAMIDB_LISTEN: \"0.0.0.0:8080\"\n      NAMIDB_AUTH_TOKEN: \"${NAMIDB_AUTH_TOKEN:?set NAMIDB_AUTH_TOKEN in your env}\"\n      NAMIDB_FLUSH_INTERVAL: \"30s\"\n      AWS_ACCESS_KEY_ID: \"minioadmin\"\n      AWS_SECRET_ACCESS_KEY: \"minioadmin\"\n    ports:\n      - \"8080:8080\"\n\nvolumes:\n  minio-data: {}\n```\n\n```bash\nexport NAMIDB_AUTH_TOKEN=$(openssl rand -hex 32)\ndocker compose up -d\ncurl -s http:\u002F\u002Flocalhost:8080\u002Fv0\u002Fhealth | jq .\n```\n\nThat's it. A graph database, your data sitting in MinIO, and an\nauthenticated REST API on `:8080`. Swap the `NAMIDB_STORE` URI and the\nsame setup moves to AWS S3, R2, GCS or Azure without touching anything\nelse.\n\n\u003Cbr \u002F>\n\u003Cbr \u002F>\n\n## CLI\n\n\n```bash\n# Ephemeral in-memory namespace, same as the quickstart.\nnamidb run \"CREATE (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})\"\nnamidb run \"MATCH (p:Person) RETURN p.name\"\n\n# Persistent. Any URI scheme works.\nnamidb run --store \"file:\u002F\u002F\u002Fvar\u002Flib\u002Fnamidb?ns=prod\" \\\n  \"CREATE (a:Person {name: 'Alice'})\"\nnamidb run --store \"file:\u002F\u002F\u002Fvar\u002Flib\u002Fnamidb?ns=prod\" \\\n  \"MATCH (p:Person) RETURN p.name\"\n\nnamidb run --store \"s3:\u002F\u002Fmy-bucket\u002Fdata?ns=prod&region=us-west-2\" \\\n  \"MATCH (p:Person) RETURN count(*) AS n\"\n\n# Plan inspection. Doesn't touch storage.\nnamidb explain --verbose \\\n  \"MATCH (a:Person)-[:KNOWS]->(b) RETURN b ORDER BY b.id LIMIT 20\"\n```\n\nSee [`crates\u002Fnamidb-cli\u002FREADME.md`](.\u002Fcrates\u002Fnamidb-cli\u002FREADME.md)\nfor every subcommand.\n\n\u003Cbr \u002F>\n\n## Rust (embedded)\n\n```rust\nuse std::sync::Arc;\n\nuse namidb_core::id::NamespaceId;\nuse namidb_query::{execute, lower, parse, Params};\nuse namidb_storage::{parse_uri, WriterSession};\n\n#[tokio::main]\nasync fn main() -> anyhow::Result\u003C()> {\n    \u002F\u002F Any supported URI scheme: memory:\u002F\u002F, file:\u002F\u002F, s3:\u002F\u002F, gs:\u002F\u002F, az:\u002F\u002F.\n    let (store, paths) = parse_uri(\"memory:\u002F\u002Fdemo\")?;\n    let mut writer = WriterSession::open(store, paths).await?;\n\n    \u002F\u002F ... upsert nodes \u002F edges, then commit_batch + flush ...\n\n    let snap = writer.snapshot();\n    let query = parse(\"MATCH (a:Person) RETURN count(*) AS n\")?;\n    let plan  = lower(&query)?;\n    let rows  = execute(&plan, &snap, &Params::new()).await?;\n\n    println!(\"{rows:?}\");\n    Ok(())\n}\n```\n\nThe umbrella crate ([`crates\u002Fnamidb\u002F`](.\u002Fcrates\u002Fnamidb\u002F)) re-exports\nthe stable surface, so a downstream `Cargo.toml` only needs the one\nline.\n\n\u003Cbr \u002F>\n\n## Architecture\n\n\u003Cp align=\"center\">\n  \u003Cpicture>\n    \u003Csource media=\"(prefers-color-scheme: dark)\" srcset=\".assets\u002Fnamidb-architecture-dark.svg\" \u002F>\n    \u003Cimg src=\".assets\u002Fnamidb-architecture.svg\" alt=\"NamiDB architecture: Query \u002F Graph \u002F Storage (LSM) \u002F Object store layers, with a cross-snapshot caches side-car\" width=\"900\" \u002F>\n  \u003C\u002Fpicture>\n\u003C\u002Fp>\n\n```\n┌─────────────────────────────────────────────────────────────────────┐\n│  Cypher · GQL (ISO\u002FIEC 39075:2024)                                  │\n│  Cost-based optimizer · Morsel-driven executor · Factorization      │\n├─────────────────────────────────────────────────────────────────────┤\n│  Property graph · CSR adjacency · Columnar SSTs                     │\n├─────────────────────────────────────────────────────────────────────┤\n│  LSM tree · WAL · Memtable · SST · Manifest CAS                     │\n│  Hybrid buffer pool (memory + NVMe)                                 │\n├─────────────────────────────────────────────────────────────────────┤\n│  S3 · R2 · GCS · Azure Blob · MinIO · Tigris · Local FS             │\n└─────────────────────────────────────────────────────────────────────┘\n```\n\nDesign proposals live in [`docs\u002Frfc\u002F`](.\u002Fdocs\u002Frfc\u002F). Start with\n[RFC-001](.\u002Fdocs\u002Frfc\u002F001-storage-engine.md) for the storage engine and\n[RFC-002](.\u002Fdocs\u002Frfc\u002F002-sst-format.md) for the SST format.\n\n\u003Cbr \u002F>\n\n## Configuration\n\nA handful of env vars you can tune. The defaults are fine for almost\neverything; you mostly reach for these when you're chasing down a\nperformance or memory problem.\n\n| Env var | Default | What it does |\n|---|---|---|\n| `NAMIDB_ADJACENCY` | ON | CSR adjacency in RAM, shared across snapshots (RFC-018). |\n| `NAMIDB_NODE_CACHE` | ON | Cross-snapshot `NodeView` lookup cache (RFC-019). |\n| `NAMIDB_SST_CACHE` | ON | SST body, decoded edge property streams, and the parsed `EdgeSstReader` (RFC-020). |\n| `NAMIDB_FACTORIZE` | OFF | Factorized intermediate results in the executor (RFC-017). |\n| `NAMIDB_PROFILE_DUMP` | OFF | Dump per-stage profile counters to stderr after each query. |\n\n`namidb-server` adds a few of its own:\n\n| Env var | Default | What it does |\n|---|---|---|\n| `NAMIDB_STORE` | (required) | Storage URI, e.g. `s3:\u002F\u002Fbucket?ns=prod`. |\n| `NAMIDB_LISTEN` | `0.0.0.0:8080` | TCP bind address. |\n| `NAMIDB_AUTH_TOKEN` | unset (open) | Bearer token. When it's unset the server warns and accepts every request. |\n| `NAMIDB_FLUSH_INTERVAL` | `30s` | Background memtable -> L0 flush cadence. `0s` disables it. |\n\n\u003Cbr \u002F>\n\n## Repository layout\n\n```\n.\n├── Cargo.toml              # Workspace manifest\n├── rust-toolchain.toml     # Pinned toolchain\n├── LICENSE                 # BSL 1.1 (auto-converts to Apache 2.0)\n├── README.md\n├── CONTRIBUTING.md\n├── docs\u002F\n│   └── rfc\u002F                # Design proposals (RFC-001 to RFC-020)\n├── crates\u002F\n│   ├── namidb-core\u002F        # Common types, errors, schema\n│   ├── namidb-storage\u002F     # LSM, WAL, manifest, SST, memtable, URI parser, file:\u002F\u002F CAS\n│   ├── namidb-graph\u002F       # Property columns + CSR adjacency\n│   ├── namidb-query\u002F       # Cypher \u002F GQL parser, optimizer, executor\n│   ├── namidb-cli\u002F         # `namidb` command-line tool\n│   ├── namidb-py\u002F          # Python bindings (PyO3 + maturin)\n│   ├── namidb-server\u002F      # `namidb-server` HTTP daemon + Dockerfile\n│   ├── namidb-bench\u002F       # LDBC-shaped synthetic bench harness\n│   └── namidb\u002F             # Public façade crate\n├── bench\u002F                  # LDBC SNB Interactive bench harness\n└── tests\u002F                  # Integration helpers (LocalStack, R2 wrapper)\n```\n\n\u003Cbr \u002F>\n\n## Documentation\n\n| Resource | Where |\n|---|---|\n| **Website** | [namidb.com](https:\u002F\u002Fnamidb.com) |\n| **Reference docs & guides** | [docs.namidb.com](https:\u002F\u002Fdocs.namidb.com) |\n| **Design RFCs** | [`docs\u002Frfc\u002F`](.\u002Fdocs\u002Frfc\u002F) |\n| **Python bindings** | [`crates\u002Fnamidb-py\u002FREADME.md`](.\u002Fcrates\u002Fnamidb-py\u002FREADME.md) |\n| **HTTP server** | [`crates\u002Fnamidb-server\u002FREADME.md`](.\u002Fcrates\u002Fnamidb-server\u002FREADME.md) |\n| **CLI** | [`crates\u002Fnamidb-cli\u002FREADME.md`](.\u002Fcrates\u002Fnamidb-cli\u002FREADME.md) |\n| **Benchmark harness** | [`bench\u002FREADME.md`](.\u002Fbench\u002FREADME.md) |\n\n\u003Cbr \u002F>\n\n## Roadmap\n\n- **Cloud (closed beta).** Multi-tenant SaaS on namidb.com with\n  per-namespace scale-to-zero, encrypted-at-rest tenants, and a hosted\n  control plane. [Request access](https:\u002F\u002Fnamidb.com).\n- **Streaming responses.** `\u002Fv0\u002Fcypher\u002Fstream` (NDJSON) and\n  `\u002Fv0\u002Fcypher\u002Farrow` (Arrow IPC) for zero-copy DataFrame ingestion.\n- **Concurrent reads.** RFC-021 takes the single-writer mutex off the\n  read path so a `namidb-server` can fan reads out across every core.\n\n\u003Cbr \u002F>\n\n## Contributing\n\nWe develop in the open. Have a look at [`CONTRIBUTING.md`](.\u002FCONTRIBUTING.md)\nand the RFCs in [`docs\u002Frfc\u002F`](.\u002Fdocs\u002Frfc\u002F) before you start. Anything\nnon-trivial goes through an RFC first.\n\n\u003Cbr \u002F>\n\n## License\n\nNamiDB is licensed under the [**Business Source License 1.1**](LICENSE).\n\n- Free for development, testing, internal production use, and anything\n  that doesn't compete with a hosted NamiDB offering from the Licensor.\n- Converts automatically to the **Apache License 2.0** three years\n  after each release.\n- A separate commercial license is available if you need to embed or\n  redistribute NamiDB outside what BSL allows, including running it as\n  a hosted database service. Reach us at\n  [`info@namidb.com`](mailto:info@namidb.com).\n\n\u003Cbr \u002F>\n\n## Acknowledgements\n\nA few projects this leans on, directly or for ideas:\n\n- **Kùzu**, for showing that columnar storage, CSR adjacency and\n  factorization are the right model for property graphs.\n- **SlateDB**, for the canonical recipe for LSM trees on object\n  storage.\n- **turbopuffer**, for proving that namespace-per-tenant on S3 is a\n  viable SaaS architecture.\n- **Apache Arrow, Parquet and DataFusion**, for the columnar\n  foundation.\n- **foyer-rs**, for the hybrid memory and disk cache.\n\n\u003Cbr \u002F>\n\n---\n\n\u003Cdiv align=\"center\">\n\n### The bucket is the database.\n\n\u003Csub>NamiDB is a product of \u003Ca href=\"https:\u002F\u002Fnamidb.com\">\u003Cb>LESAI, Corp.\u003C\u002Fb>\u003C\u002Fa>, Delaware, USA.\u003C\u002Fsub>\u003Cbr \u002F>\n\u003Csub>© 2026 LESAI, Corp. All rights reserved.\u003C\u002Fsub>\n\n\u003C\u002Fdiv>\n","NamiDB 是一个基于对象存储的图数据库，专为云环境设计。它支持Cypher查询语言，将节点和边以列式文件形式存储在S3桶中，确保数据的一致性和持久性。NamiDB采用Rust编写，具有嵌入式、多租户架构，支持作为库嵌入、独立HTTP服务器运行或使用其托管云服务。得益于S3引入的条件写入功能，NamiDB能够构建无需额外协调服务（如Raft、ZooKeeper）的系统。适用于需要高效处理大规模图数据的应用场景，特别是在AI领域中构建知识图谱、增强代理记忆等方面。","2026-06-11 04:00:59","CREATED_QUERY"]