Skip to content
STACK IT FAST

Garage

Curated OSSClassicGeo-Distributed Object Storage Engine2-5 People

Audited from git.deuxfleurs.fr/Deuxfleurs/garage

Garage is a self-hosted, S3-compatible distributed object storage system written in Rust, built as a Cargo workspace of crates for small-to-medium geo-distributed clusters that stay available when individual nodes fail.

Language
Rust
Database
LMDB
Hosting
Docker
License
AGPL-3.0
Running for
3 years
Team
2-5 People

Why this architecture

Garage splits RPC, replication, storage and each API protocol into separate Rust crates around a pluggable embedded metadata engine (LMDB, SQLite or Fjall), so a geo-distributed cluster can tolerate node and network failures without depending on an external coordination service or database.

Tech stack by layer

8 technologies · audited Sep 17, 2026
Backend & APIs
  • RustEntire cluster (RPC, replication, S3/K2V/admin APIs, web endpoint) is a Cargo workspace of Rust crates under src/.
  • garage_netCustom RPC networking layer for inter-node cluster communication, forked from the Netapp project.
Data & Persistence
  • LMDBDefault embedded key-value engine (via the heed crate) backing the metadata tables and cluster state.
  • SQLiteAlternative embedded metadata engine (via rusqlite/r2d2) selectable instead of LMDB.
  • FjallNewer LSM-based key-value engine offered as a third pluggable metadata backend behind the fjall feature flag.
Infrastructure & Deploy
  • DockerRuntime image built FROM scratch that just copies the compiled garage binary and runs it as the server.
  • Nixflake.nix, default.nix and shell.nix drive reproducible builds and the dev shell; nix/ holds Nix build helpers.
  • KubernetesOptional cluster auto-discovery via the Kubernetes API, gated behind the kubernetes-discovery feature (kube, k8s-openapi crates).
  • PrometheusMetrics endpoint exposed through the prometheus and opentelemetry-prometheus crates when the metrics feature is enabled.
  • Woodpecker CISelf-hosted CI runs debug, publish and release pipelines instead of GitHub Actions.
Tooling, Testing & Ops
  • cargo-fuzzNine libFuzzer targets exercise the CRDT types (version, bucket, key, object) for correctness under fuzzing.
  • Jepsenscript/jepsen.garage drives Jepsen-style distributed-systems correctness testing against a Garage cluster.

Garage architecture diagram

Open SVG
Garage architecture diagramS3 clients → garage binary (S3 API); K2V clients → garage binary (K2V API); Website visitors → garage binary (garage_web); garage binary → Metadata tables (objects · keys); garage binary → Block manager (put / get blocks); Metadata tables → Metadata DB (garage_db); Block manager → Data blocks (chunks); Metadata tables → Cluster RPC (sync); Cluster RPC → Other nodes (replicate)CLIENTSSERVICESWORKERS & JOBSDATA & STORAGEEXTERNALS3 clientsAWS SDKs · CLIK2V clientsk2v-clientWebsite visitorsstatic hostinggarage binaryhyper · S3 / K2V / adminCluster RPCgarage_netMetadata tablesgarage_tableBlock managergarage_blockMetadata DBLMDB / SQLite / FjallData blockslocal disksOther nodesreplicationsyncS3 APIK2V APIgarage_webobjects · keysput / get blocksgarage_dbchunksreplicate
How the main components of Garage connect, drawn from the audited repository.
Diagram as text
  • S3 clients (AWS SDKs · CLI) → garage binary (hyper · S3 / K2V / admin): S3 API
  • K2V clients (k2v-client) → garage binary (hyper · S3 / K2V / admin): K2V API
  • Website visitors (static hosting) → garage binary (hyper · S3 / K2V / admin): garage_web
  • garage binary (hyper · S3 / K2V / admin) → Metadata tables (garage_table): objects · keys
  • garage binary (hyper · S3 / K2V / admin) → Block manager (garage_block): put / get blocks
  • Metadata tables (garage_table) → Metadata DB (LMDB / SQLite / Fjall): garage_db
  • Block manager (garage_block) → Data blocks (local disks): chunks
  • Metadata tables (garage_table) → Cluster RPC (garage_net): sync
  • Cluster RPC (garage_net) → Other nodes (replication): replicate

Key architectural decisions

7 decisions
  1. 01

    Cluster logic is split into a dozen single-purpose Cargo crates

    The workspace in Cargo.toml lists garage_db, garage_util, garage_net, garage_rpc, garage_table, garage_block, garage_model, garage_api_common/s3/k2v/admin, garage_web and k2v-client as separate members with default-members = ["src/garage"], so the RPC layer, storage-node logic, table replication engine and each API protocol can be developed, versioned and tested independently.

  2. 02

    Metadata storage engine is pluggable, not fixed to one database

    src/db/Cargo.toml exposes lmdb, sqlite and fjall as mutually selectable Cargo features implementing a common garage_db trait, so an operator can run Garage on LMDB (default), SQLite, or the newer Fjall LSM engine without changing application code.

  3. 03

    Own RPC transport instead of gRPC or plain HTTP for cluster traffic

    src/net/Cargo.toml describes garage_net as "Networking library for Garage RPC communication, forked from Netapp"; inter-node membership, gossip and data-transfer messages run over this custom protocol rather than a generic HTTP or gRPC stack.

  4. 04

    K2V is a second, simpler key-value API next to S3

    src/k2v-client/Cargo.toml and src/api/k2v/Cargo.toml implement K2V, described as the "Garage K2V protocol" client and server, giving applications a lighter-weight alternative to the full S3 API for simple key/value access patterns.

  5. 05

    Nix is the primary reproducible-build path

    flake.nix, default.nix, shell.nix and the nix/ directory (build_index.nix, compile.nix) provide the release build and dev shell; Cargo.lock alone is not treated as sufficient for reproducibility across the project.

  6. 06

    Cluster auto-discovery is optional and pull-based, not required

    src/rpc/Cargo.toml gates Consul and Kubernetes discovery behind the consul-discovery and kubernetes-discovery feature flags (reqwest/hyper for Consul, the kube crate for Kubernetes), so a default build has no dependency on either system and nodes can instead be joined manually.

  7. 07

    Distributed correctness is tested with fuzzing and Jepsen, not just unit tests

    fuzz/Cargo.toml defines libFuzzer targets for the CRDT types that back bucket, key and object state (version_crdt, bucket_crdt, object_crdt, key_crdt), and script/jepsen.garage runs Jepsen-style fault-injection tests against a real cluster, reflecting that Garage treats network partitions and node failure as a normal operating condition.

How Garage is built

How Garage is structured

Garage is a single Cargo workspace (Cargo.toml) rather than several separate repositories. default-members = ["src/garage"] points at the garage binary crate, which pulls in the rest of the workspace: garage_util (shared utilities), garage_net (RPC transport), garage_rpc (cluster membership and the RPC protocol built on garage_net), garage_table (a DynamoDB-like sharded and replicated table engine), garage_block (content-addressed block storage), garage_model (the core data model tying tables and blocks together), garage_db (the pluggable embedded key-value abstraction), and the API layer split into garage_api_common, garage_api_s3, garage_api_k2v and garage_api_admin, plus garage_web for S3-style static website hosting and a standalone k2v-client crate. The fuzz workspace member holds fuzz targets for the CRDT types that make replication convergent.

Backend & APIs

The garage binary (src/garage/Cargo.toml) wires the S3 API (garage_api_s3), the K2V API (garage_api_k2v, feature-gated by k2v), and the admin API (garage_api_admin) into one HTTP-serving process, all built on hyper rather than a higher-level web framework. garage_api_common centralizes shared request parsing, XML (quick-xml) and JSON encoding, authentication (hmac, sha1/sha2) and error handling across the S3 and K2V handlers. garage_web layers S3-compatible static website hosting (html-escape, percent-encoding) on top of the same object model, so a bucket can serve as both an S3 target and a public website endpoint from the same node.

Data & persistence

Garage does not depend on an external database. garage_db defines a storage-engine trait with three selectable backends compiled in via Cargo features declared in src/db/Cargo.toml: lmdb (via the heed crate, the default), sqlite (via rusqlite with connection pooling through r2d2), and fjall, a newer LSM-tree engine. garage_table shards and replicates rows across cluster nodes on top of whichever garage_db backend is active, and garage_block stores object content itself as content-addressed blocks with zstd/async-compression for optional compression, independent of the metadata engine.

Build, test & deploy

CI runs on a self-hosted Woodpecker instance rather than GitHub Actions, defined in .woodpecker/debug.yaml, .woodpecker/publish.yaml and .woodpecker/release.yaml. The Nix toolchain (flake.nix, default.nix, shell.nix, and the nix/ directory with compile.nix and build_index.nix) is the primary reproducible build path used by those pipelines, alongside a plain Cargo.toml/Cargo.lock build for anyone using stock Rust tooling. The runtime Dockerfile is minimal by design: it builds FROM scratch, copies only the compiled garage binary, sets RUST_LOG=garage=info, and runs garage server as the entrypoint. Testing goes beyond unit tests: fuzz/ defines nine libfuzzer-sys targets against the CRDT types backing buckets, keys, objects and multipart uploads, and script/jepsen.garage runs Jepsen-style fault-injection tests against a live cluster to check replication correctness under partitions.

Self-hosting notes

Garage is designed from the start for self-hosting on small, potentially geographically distributed nodes, per the README description of the Deuxfleurs collective running it in production since 2020. The default LMDB metadata backend and FROM scratch Docker image keep a single node's footprint small; operators who want automatic node discovery instead of manual cluster configuration can opt into the consul-discovery or kubernetes-discovery Cargo features declared in src/rpc/Cargo.toml, which pull in reqwest/hyper or the kube/k8s-openapi crates respectively. The script/ directory ships helper scripts (dev-cluster.sh, dev-env-aws.sh, dev-env-mc.sh, dev-env-rclone.sh) for exercising a local multi-node cluster against common S3 client tooling before deploying for real.

What to copy (and what not to)

The pluggable-storage-engine pattern in garage_db — one trait, three interchangeable backends selected by Cargo feature — is a clean way to let operators trade off between a zero-dependency embedded engine (LMDB) and something with different write characteristics (Fjall) without touching the rest of the codebase, and is worth copying for any self-hosted server that owns its own storage. The custom garage_net RPC transport is harder to justify copying wholesale: it exists because Garage predates or wanted tighter control than general-purpose RPC frameworks offered, but a new project taking on that same complexity should be sure it actually needs the control, since it also means maintaining a bespoke protocol implementation rather than relying on gRPC's tooling and ecosystem.

Sources & repo audit

Audited
Sep 17, 2026
Commit
d50be27
License
AGPL-3.0

Independent analysis of repository at github.com/deuxfleurs-org/garage. Spotted an inaccuracy? Use the claim form to request a correction.

Show this stack on your README or website
Tech stack of Garage
[![Tech stack of Garage on STACK IT FAST](https://stackitfast.com/badge/garage-s3.svg)](https://stackitfast.com/project/garage-s3)

Paste it into your README. It shows your current stack and links to this page.

Use this stack

Scaffold it with your agent

Paste this prompt into Claude Code, Cursor, Windsurf or AGY to start a project with Garage's architecture.

  1. 1Copy the promptThe full markdown spec, with every layer and decision.
  2. 2Open your AI toolClaude Code, Cursor, Windsurf or Copilot, in a new repo.
  3. 3Paste and scaffoldUse it as the first instruction; review before you ship.
use-this-stack.md · 61 lines · 8.0 KB
# MISSION: Scaffold "Garage" Production Architecture
You are an expert Senior Staff Software Architect and Full-Stack Engineer. Your mission is to scaffold and implement a production-grade, highly reliable, and modular codebase following the proven architecture of **Garage**.
---
## 1. PROJECT SPECIFICATIONS & BENCHMARK
- **Reference Architecture**: Garage
- **What It Does**: Garage is a self-hosted, S3-compatible distributed object storage system written in Rust, built as a Cargo workspace of crates for small-to-medium geo-distributed clusters that stay available when individual nodes fail.
- **Domain & Category**: Geo-Distributed Object Storage Engine
- **Production Scale**: 2-5 People
- **Development Mode**: CLASSIC
- **Architectural Rationale**: Garage splits RPC, replication, storage and each API protocol into separate Rust crates around a pluggable embedded metadata engine (LMDB, SQLite or Fjall), so a geo-distributed cluster can tolerate node and network failures without depending on an external coordination service or database.
- **Live Website Reference**: https://garagehq.deuxfleurs.fr
- **Source Repository**: https://git.deuxfleurs.fr/Deuxfleurs/garage
---
## 2. PRODUCTION TECH STACK
- **Full Stack Array**: Rust, S3, LMDB, SQLite, Prometheus, Docker, Kubernetes, Nix
- **Primary Language(s)**: Rust
- **License of the reference repo**: AGPL-3.0
- **Backend & APIs**: Rust — Entire cluster (RPC, replication, S3/K2V/admin APIs, web endpoint) is a Cargo workspace of Rust crates under src/.; garage_net — Custom RPC networking layer for inter-node cluster communication, forked from the Netapp project.
- **Data & persistence**: LMDB — Default embedded key-value engine (via the heed crate) backing the metadata tables and cluster state.; SQLite — Alternative embedded metadata engine (via rusqlite/r2d2) selectable instead of LMDB.; Fjall — Newer LSM-based key-value engine offered as a third pluggable metadata backend behind the fjall feature flag.
- **Infrastructure & deploy**: Docker — Runtime image built FROM scratch that just copies the compiled garage binary and runs it as the server.; Nix — flake.nix, default.nix and shell.nix drive reproducible builds and the dev shell; nix/ holds Nix build helpers.; Kubernetes — Optional cluster auto-discovery via the Kubernetes API, gated behind the kubernetes-discovery feature (kube, k8s-openapi crates).; Prometheus — Metrics endpoint exposed through the prometheus and opentelemetry-prometheus crates when the metrics feature is enabled.; Woodpecker CI — Self-hosted CI runs debug, publish and release pipelines instead of GitHub Actions.
- **Tooling, testing & ops**: cargo-fuzz — Nine libFuzzer targets exercise the CRDT types (version, bucket, key, object) for correctness under fuzzing.; Jepsen — script/jepsen.garage drives Jepsen-style distributed-systems correctness testing against a Garage cluster.
---
## 3. KEY ARCHITECTURAL DECISIONS (audited from https://github.com/deuxfleurs-org/garage @ d50be27)
1. **Cluster logic is split into a dozen single-purpose Cargo crates**: The workspace in Cargo.toml lists garage_db, garage_util, garage_net, garage_rpc, garage_table, garage_block, garage_model, garage_api_common/s3/k2v/admin, garage_web and k2v-client as separate members with default-members = ["src/garage"], so the RPC layer, storage-node logic, table replication engine and each API protocol can be developed, versioned and tested independently.
2. **Metadata storage engine is pluggable, not fixed to one database**: src/db/Cargo.toml exposes lmdb, sqlite and fjall as mutually selectable Cargo features implementing a common garage_db trait, so an operator can run Garage on LMDB (default), SQLite, or the newer Fjall LSM engine without changing application code.
3. **Own RPC transport instead of gRPC or plain HTTP for cluster traffic**: src/net/Cargo.toml describes garage_net as "Networking library for Garage RPC communication, forked from Netapp"; inter-node membership, gossip and data-transfer messages run over this custom protocol rather than a generic HTTP or gRPC stack.
4. **K2V is a second, simpler key-value API next to S3**: src/k2v-client/Cargo.toml and src/api/k2v/Cargo.toml implement K2V, described as the "Garage K2V protocol" client and server, giving applications a lighter-weight alternative to the full S3 API for simple key/value access patterns.
5. **Nix is the primary reproducible-build path**: flake.nix, default.nix, shell.nix and the nix/ directory (build_index.nix, compile.nix) provide the release build and dev shell; Cargo.lock alone is not treated as sufficient for reproducibility across the project.
6. **Cluster auto-discovery is optional and pull-based, not required**: src/rpc/Cargo.toml gates Consul and Kubernetes discovery behind the consul-discovery and kubernetes-discovery feature flags (reqwest/hyper for Consul, the kube crate for Kubernetes), so a default build has no dependency on either system and nodes can instead be joined manually.
7. **Distributed correctness is tested with fuzzing and Jepsen, not just unit tests**: fuzz/Cargo.toml defines libFuzzer targets for the CRDT types that back bucket, key and object state (version_crdt, bucket_crdt, object_crdt, key_crdt), and script/jepsen.garage runs Jepsen-style fault-injection tests against a real cluster, reflecting that Garage treats network partitions and node failure as a normal operating condition.
---
## 4. NON-NEGOTIABLE ARCHITECTURAL GUARDRAILS
1. **Monorepo & Modular Separation**:
   - Structure as a Turborepo monorepo with strict package boundaries:
     - `apps/web`: Application UI, routing, layouts, and server endpoints.
     - `packages/ui`: Shared design tokens, CSS variables, and Radix UI primitive components.
     - `packages/db`: Database schemas, client singleton, declarative migrations, and seed scripts.
     - `packages/config`: Shared TypeScript, ESLint, and build configurations.
2. **Strict Type Safety & Zero `any` Policy**:
   - Enable `strict: true`, `noImplicitAny: true`, and `strictNullChecks: true`.
   - Validate ALL external inputs, API request bodies, and query parameters with **Zod** schemas before execution.
3. **Frontend & Rendering Guidelines**:
   - Isolate interactive UI state to leaf components. Keep core pages lightweight and performant.
4. **Design System & Aesthetics**:
   - Keep every color, radius, shadow and font in a single token file (CSS variables) and consume tokens everywhere; never hardcode hex values in components.
   - Prefer crisp 1px borders and one subtle shadow scale over blurry default shadows. Pair one sans-serif for body/headings with one monospace for tags, badges, metrics, and code.
5. **Data Layer & Reliability**:
   - Write declarative schema definitions with foreign keys, composite indexes on queried filters, and automated timestamp triggers.
   - Use connection pooling and prepared statements for serverless database execution.
---
## 5. STEP-BY-STEP SCAFFOLDING ROADMAP
- **Phase 1: Workspace & Root Config**: Initialize package manager, monorepo configuration (`turbo.json`, `tsconfig.base.json`, `package.json`).
- **Phase 2: Database Schema & Client**: Set up the data layer (LMDB, SQLite, Fjall): client, connection pool, models, and migration scripts.
- **Phase 3: Design Tokens & UI Primitives**: Build accessible `Button`, `Input`, `Card`, `Badge`, and layout wrappers inside `packages/ui`.
- **Phase 4: Core Application Routes & Handlers**: Implement primary authentication, user session handling, and application routes.
- **Phase 5: Quality Assurance & Build Verification**: Run `tsc --noEmit`, ESLint, Prettier, and smoke test suites to ensure zero compilation or runtime errors.
---
## 6. EXECUTION INSTRUCTIONS
1. Review all specifications, architectural guardrails, and stack choices above.
2. Present the full monorepo directory tree structure.
3. Systematically generate the complete, production-ready codebase according to the 5-phase roadmap above — starting with the root workspace setup, followed by the database schema, UI design system package, and full-stack application routes until the repository is fully scaffolded and ready to run.
Scaffolded something with this prompt?
Would you pick this stack for a geo-distributed object storage engine project?

Frequently asked about Garage

What is Garage built with?

Garage is written entirely in Rust as a Cargo workspace of crates (garage_db, garage_net, garage_rpc, garage_table, garage_block, garage_model, and per-protocol API crates), with a custom RPC layer for cluster communication instead of gRPC or plain HTTP.

Does Garage need a separate database?

No. Metadata is stored in an embedded engine chosen at build or config time: LMDB by default, or SQLite or Fjall as alternatives, all implemented behind a common trait in the garage_db crate. There is no external Postgres or MySQL dependency.

Can I self-host Garage?

Yes, self-hosting is the primary use case. The project ships a Dockerfile that builds a minimal scratch-based runtime image, and the Deuxfleurs collective that builds Garage has run it in production since 2020 per the README.

Does Garage support Kubernetes and Consul for cluster discovery?

Both are optional, feature-gated additions. src/rpc/Cargo.toml exposes a kubernetes-discovery feature built on the kube crate and a consul-discovery feature built on reqwest/hyper; neither is required for a default build, where nodes can be joined manually.

What is K2V in Garage?

K2V is a second, simpler key-value API that Garage exposes alongside its S3-compatible API, implemented in the src/api/k2v and src/k2v-client crates, for applications that need basic key/value access without the full S3 surface.

Is Garage written in Rust?

Yes. The whole cluster, including RPC, replication, the S3, K2V and admin APIs, and the web endpoint, is a Cargo workspace of Rust crates under src/.

One email a month: new deep dives and stack trends

New source-audited architectures, head-to-head comparisons and the monthly stack report. No spam, unsubscribe anytime.

use-this-stack.md