Object storage and catalog access in one system.
Point DuckDB, S3-compatible clients, and lakehouse tooling at the same storage layer instead of operating an object store beside a catalog service.
GrainFS exposes object storage, file system mounts, block volumes, and data lake catalog access from the same engine. Add nodes while the service stays online.
# start one local storage server
DATA_DIR=./tmp
make bin/grainfs
CLUSTER_KEY=$(openssl rand -hex 32)
./bin/grainfs serve --data "$DATA_DIR" --port 9000 --cluster-key "$CLUSTER_KEY"
# write once through S3
echo "hello grainfs" > file.txt
aws --no-sign-request --endpoint-url http://localhost:9000 s3 cp file.txt s3://default/
# read the same data through a mounted file system
./bin/grainfs nfs export add default --endpoint "$DATA_DIR/admin.sock"
sudo mkdir -p /mnt/grainfs
sudo mount -t nfs4 -o nolock,nfsvers=4.0 localhost:/default /mnt/grainfs
ls /mnt/grainfs # file.txt
Point DuckDB, S3-compatible clients, and lakehouse tooling at the same storage layer instead of operating an object store beside a catalog service.
Serve object, file, and block access in labs, edge sites, GPU racks, and private networks without bringing in a full storage platform.
Exercise S3, NFS/9P, NBD, and Iceberg clients with one server instead of maintaining a fixture for each protocol.
Cluster membership, IAM state, protocol credentials, placement metadata, and admin changes commit through the Raft-backed metadata layer.
The cluster derives its erasure-coding profile from topology and stops writes when it cannot meet the required durability target.
Object data, metadata snapshots, WAL records, service-account keys, and protocol secrets use the generation-aware DEK/KEK envelope.
grainfs cluster complete-cutover moves voters to per-node transport identities and drops
the legacy shared cluster key only after readiness checks pass.
S3, Iceberg, NBD, NFS, and 9P attach paths reject stale, revoked, expired, or mismatched credentials before clients connect.
Nodes refuse to open data directories with mismatched format markers. They fail closed rather than mix storage formats without a flag.
MinIO mc covers bucket-scoped S3 credentials. DuckDB covers the Iceberg REST Catalog path
on single-node GrainFS.
NoteThe public compatibility tables mark a feature supported only when e2e, conformance, or real-client integration tests cover it. Unit tests alone do not qualify.
warp 1.0.6 · same-host single node · DATA_DIR on local SSD · request signing enabled · MinIO baseline measured with identical warp invocation.
Local runs on Apple M3, 16 GB. Treat them as engine signal. Production sizing needs your own hardware. Raw output sits in the repo benchmark artifacts.
Run a local node, prove the same-data path, then bring GrainFS into production with review, upgrades, and recovery planning.