Skip to content

Overview ​

Nestor is one engine with three front doors. The engine caches blocks and talks to origins. Everything else is an adapter on one of its two sides: what asks for bytes, and where bytes come from.

Rust serviceget, read, headobject_store userNestorStoreS3 clientnestor-s3 endpointnestornamespacesblock indexin flight tablefetcher, hedges, retriesreadaheadmetadata cacheRAM + disk tiersOrigin traitobject_store backendObjectStoreOriginnestor clusterClusterOrigin

Crates ​

CrateRole
nestorThe engine. Namespaces, blocks, tiers, fetch scheduling, consistency. Depends on the Origin trait only.
nestor-storeBoth directions of object_store. ObjectStoreOrigin makes any ObjectStore an origin, NestorStore makes a cached namespace look like an ObjectStore.
nestor-s3The S3 endpoint as an axum router. SigV4 verification, addressing, GET and HEAD from cache, forwarding and re-signing of everything else.
nestor-clientClient-side cluster routing. Rendezvous hashing, bounded load, membership, hedging across nodes. Exposes the cluster as an Origin.
nestor-cliThe nestor binary. TOML configuration, TLS, Prometheus export, and the wiring that turns the crates above into a node or a gateway.
nestor-e2eEnd-to-end scenarios against RustFS in Docker Compose.

Dependencies point one way. nestor knows nothing about S3 wire formats, HTTP or clusters. nestor-s3 and nestor-client depend on nestor and nestor-store. nestor-cli depends on all of them and holds no logic of its own beyond configuration.

Core model ​

A namespace is an origin plus caching policy: block size, fetch and read windows, consistency mode, readahead, hedging. A Nestor instance holds many namespaces over one shared cache. In the S3 endpoint every bucket becomes a namespace with the [buckets] policy. In a library, a namespace is whatever the application decides, one per object class is typical.

A block is a fixed-size slice of an object identified by namespace, object name, a content tag and its index. The tag is the reason a changed object cannot be served from old blocks, see Consistency.

A read is a byte range against one object. It is resolved to a block range, served block by block as a stream with a bounded number of blocks in flight, and finished without ever buffering the whole object. Blocks & reads covers the path in detail.

An origin is anything implementing head and get with ranges and preconditions. object_store gives Nestor every major backend. A cluster of other Nestor nodes is also an origin, which is how a local tier stacks on a shared one.

Deployment shapes ​

embeddedyour servicenestor crateoriginendpointS3 clientsnestororiginclusterclients, gatewaynodenodenodeorigin

The shapes compose. A nestor binary with a [cluster] section is a gateway: its own RAM and disk are a local tier, and misses go to the cluster instead of the origin. A service can embed the nestor crate with a ClusterOrigin and get the same two-tier layout in process. Writes always go to the real origin, the cluster only ever serves reads.