El bucket es la base de datos
NamiDB no tiene un control plane externo. Sin cluster de Raft. Sin
ZooKeeper. Sin tabla de locks en DynamoDB. Sin etcd. El bucket es la
base de datos — cada byte de estado del motor es un objeto plano en el
store compatible con S3 que abriste con tg.Client("s3://...").
Qué vive en el bucket
s3://my-bucket/data/{namespace}/├── manifest.json # CAS root: epoch, current SST list, LSN watermark├── wal/ # Write-ahead log segments│ ├── 0000-0042.wal│ └── 0043-current.wal├── sst/ # Sorted-string tables│ ├── node/L0/... # Parquet node SSTs│ ├── node/L1/...│ ├── edge/L0/... # Custom edge SSTs with CSR adjacency│ └── edge/L1/...└── schema/ # Label & property schemas └── current.jsonTres categorías:
- El manifest — un único objeto JSON, diminuto, que nombra cada SST actualmente vivo para el namespace, más el epoch, más el LSN watermark. Todas las escrituras se coordinan mediante CAS del manifest.
- El WAL — segmentos append-only. Cada escritura es durable apenas
retorna una llamada a
commit_batch. - SSTs — archivos columnares inmutables. Los nodos van a Parquet; las aristas van a un formato custom CSR-aware (RFC-002).
Qué reemplaza al tier de consenso
Conditional writes de S3. Desde 2024, S3 respeta los headers If-Match /
If-None-Match en PutObject. NamiDB escribe un nuevo manifest
con If-Match: <previous-etag>; el primer writer gana, el resto recibe
un 412 Precondition Failed y reintenta.
Esa primitiva por sí sola reemplaza:
| Sin conditional writes | Con conditional writes |
|---|---|
| Servicio de locks externo (DynamoDB, ZooKeeper) | CAS del manifest sobre el propio objeto |
| Quorum de Raft / Paxos para el manifest | PutObject condicional |
| Una base de datos de metadatos aparte | Un manifest.json por namespace |
Qué se gana con esto
- Durabilidad es la que te da S3. 99.999999999%, multi-AZ.
- Backups son
aws s3 sync. No hay metadatos separados que capturar. - Restore es
aws s3 syncen la otra dirección. - El costo escala a cero cuando ningún cliente abre el namespace. No hay compute corriendo. No hay capacidad de DynamoDB reservada.
- Los tenants son carpetas. Cada
?ns=...es un sub-árbol en el bucket. - Dos procesos pueden abrir el mismo namespace. El que gana el CAS del manifest al momento del commit es el que puede escribir; el otro se fencea limpio (incremento de epoch) y vuelve a leer.
Qué se resigna
- El throughput de escritura por namespace está acotado por un único writer por vez. Esto es una feature de correctness pero un techo para la tasa cruda de escritura. Sharding por namespace es la respuesta cuando se necesita más.
- La latencia de lectura está acotada por abajo por la latencia de GET de S3 en el camino caliente. Los caches cross-snapshot (RFC-018, RFC-019, RFC-020) la ocultan en su mayoría para queries repetidas.
- Transacciones fuertes cross-namespace están fuera de scope. Cada namespace es una unidad aislada.