Back to list
RocksDB の苦悩から GraniteDB の勝利へ:Rust を使って構築する、ブロックチェーン状態を第一に考えるストレージエンジン
From RocksDB Pain to GraniteDB Gain: Building a Blockchain-First Storage Engine in Rust
Translated: 2026/4/25 2:00:17
Japanese Translation
Ferrous Network の構築が汎用データベースの限界を浮き彫りにしました。GraniteDB をゼロから書く理由については、次の通りです。
さて、皆さんはこんにちは。Ferrous Network の創設者、Altug です。これはテストネット上において現在も稼働中の、Rust ベースのビットコイン様の L1 ブロックチェーンです。今日は非常に具体的で、開発者向けな物語を共有しましょう:RocksDB を本番環境で戦わせたことが、Blockchain 状態を特に設計した正しさ重視のストレージエンジン GraniteDB の始まりにつながった、というものです。
Ferrous を構築するにあたり、以下の永続的ストレージが必要でした。
UTXO セット
ブロックインデックス
チェーン状態
メムプール
RocksDB は当然の選択肢でした。多くの圧力条件下で優れ、Bitcoin から Kafka までの多くの場所で試行されています。セットアップは直感的でした:
cargo add rocksdb
しかし、現実は異なるものでした。ロード時間が私を狂わせました。
最初の起動(特に IBD - Initial Block Download)時、私は数分間 compilation bars を見つめながら、Clang の依存関係の解決と RocksDB の初期化を待たなければなりませんでした。比較的強力なハードウェア上です。毎回。毎回。
これは単なる「遅い」ものではありませんでした。これは制御不能なものでした。私の巧みに作られ、警告ゼロの Rust ノードの中に、汎用 C++ の巨大な怪獣が座り込んでいるのです。これをデバッグすることは不可能でした。簡単に監査することもできませんでした。ブロックチェーンワークロードに対して予測可能な動作をさせることもできませんでした。
RocksDB は自分が何をすることに最適であります:高スループットの汎用的なキー値ストレージ。
しかし、ブロックチェーンノードは「汎用的」なもの并不需要しません。彼らは、より具体的で、何かを要しています:
✅ 決定的なクラッシュ復旧
✅ 予測可能なスナップショット動作
✅ アカウント/状態の検索のために高速なポイント読み込み
✅ ブロック執行的な安全なバッチ書き込み
✅ 雷速の起動(C++ 依存関係の地獄なし)
✅ 実際に監査可能なコード
❌ 広告配信のためのピーク TPS
❌ すべての可能性のあるテーブル形式最適化
❌ 複数のライタの競合(まだ)
よって、私は GraniteDB を書くことに始めました。「RocksDB を beaten」ためのものではなく、私の特定の苦悩を解決するために:
GraniteDB = Rust ストレージエンジン
+ ブロックチェーン状態セマンティクス
+ 初期段階では Throughput よりも Correctness
+ C++ 相互運用の恐怖なし
Crystal-clear API 契約
pub struct DB {
// put(key, value) — 新しいバージョンを作成する
// delete(key) — トンストーン( tombstone )
// snapshot() — 並列制御に基づく隔離
// write_batch(batch) — 原子的、クラッシュ耐性
}
本番グレードな WAL フォーマット
32KB 固定ブロック + CRC32C フラグメント
FULL/FIRST/MIDDLE/LAST レコードタイプ
「最初の腐敗で切り抜ける」復旧
シングルライタスレッドモデル
ライタが所有するもの:seq 割り当て、WAL、memtable
並列なリーダ:短い生命を持つガード
「競合は設計上ない」
すべての所々に明示的な不変条件
- クラッシュの後、部分バッチは視認されない
- マニフェスト = SST の単一の真のソース
- WAL + マニフェストからの決定的なリプレイ
- スナップショット読み込みは一貫したシーケンスを見出す
最もブロックチェーン状態のワークロードは、読み込みのために恥ずかしいまでに並列だが、書き込みについては直列でクラッシュ耐性が必要である:
ブロック執行 → WriteBatch → WAL → ACK
アカウント検索 → メムテーブル → L0 → L1(ポイント読み込み)
UTXO スキャン → スナップショット付きイテレータ
剪定 → バックグラウンドコンパクト化(フェーズ 2)
GraniteDB はまさにこの形をターゲットしています。
私には「RocksDB の 10 倍速い」とは約束しませんが:
✨ GraniteDB が勝利する点:
• 起動時間(C++ 依存関係なし)
• 決定的な復旧
• 予測可能なスナップショット
• 完全な監査可能性
• ゼロベンダー複雑性
⚡ RocksDB がまだ勝利する点:
• 生のスループット
• 年々の戦闘の傷痕
• 人類が知るあらゆる最適化
フェーズ A(現在):正しさコア + クラッシュテスト
WAL/SST/マニフェスト形式がロックされた
シングル memtable + 同期 flush
プロパティテスト vs 参照モデル
フェーズ B:不変 memtable キュー + 非同期 flush
フェーズ C:L0→L1 コンパクト化
フェーズ D:バックグラウンドワーカ
フェーズ E:リーダ最適化
次に Ferrous への統合。もしそれがそこで機能すれば、どこでも機能するだろう。
ときどき、最も良いプロジェクトは個人的な苦悩から生まれるものです。私の自身のノード上で RocksDB をロードし待つのが退屈になったからです。何か、瞬時に始まり、予測可能に振る舞い、3 時にチェーンがクラッシュするときに実際に推論できるようなものを作っています。
GraniteDB はすべての人にすべてになるでしょう。しかし、ブロックチェーン状態のために?それはまさにそのままで良いかもしれません。
進行状況をフォロー:GraniteDB specs
Original Content
Building Ferrous Network exposed the limits of general-purpose databases. Here's why I'm writing GraniteDB from scratch.
Hey folks, Altug here — founder of Ferrous Network, a Rust-based Bitcoin-like L1 blockchain that's live on testnet. Today I want to share a very specific dev story: how wrestling with RocksDB in production led me to start GraniteDB, a correctness-first storage engine designed specifically for blockchain state.
When building Ferrous, I needed persistent storage for:
UTXO set
Block index
Chain state
Mempool
RocksDB was the obvious choice. Battle-tested, performs great under pressure, used everywhere from Bitcoin to Kafka. Setup was straightforward:
cargo add rocksdb
But then reality hit. The load times drove me insane.
On first startup (especially IBD - Initial Block Download), I'd sit there watching compilation bars, Clang deps resolving, and RocksDB initializing... for minutes. On reasonably beefy hardware. Every. Single. Time.
This wasn't just "slow." It was uncontrollable. A general-purpose C++ behemoth sitting in my carefully crafted, zero-warnings Rust node. I couldn't debug it. Couldn't easily audit it. Couldn't make it behave predictably for blockchain workloads.
RocksDB is amazing at what it does: high-throughput, general-purpose key-value storage.
But blockchain nodes don't need "general purpose." They need something much more specific:
✅ Deterministic crash recovery
✅ Predictable snapshot behavior
✅ Fast point reads for account/state lookups
✅ Safe batch writes for block execution
✅ Lightning-fast startup (no C++ deps hell)
✅ Actually auditable code
❌ Peak TPS for ad serving
❌ Every possible table format optimization
❌ Multi-writer concurrency (yet)
So I started writing GraniteDB — not to "beat RocksDB," but to solve my specific pain:
GraniteDB = Rust storage engine
+ Blockchain state semantics
+ Correctness > Throughput (initially)
+ No C++ interop nightmares
Crystal-clear API contract
pub struct DB {
// put(key, value) — creates newer version
// delete(key) — tombstone
// snapshot() — sequence-based isolation
// write_batch(batch) — atomic, crash-safe
}
Production-grade WAL format
32KB fixed blocks + CRC32C fragments
FULL/FIRST/MIDDLE/LAST record types
"truncate at first corruption" recovery
Single-writer threading model
Writer owns: seq assignment, WAL, memtable
Concurrent readers: short-lived guards
"No races by design"
Explicit invariants everywhere
- No partial batches visible after crash
- Manifest = single source of SST truth
- Deterministic replay from WAL+Manifest
- Snapshot reads see consistent sequence
Most blockchain state workloads are embarrassingly parallel for reads, but need sequential, crash-safe writes:
Block execution → WriteBatch → WAL → ACK
Account lookup → Memtable → L0 → L1 (point read)
UTXO scan → Iterator with snapshot
Pruning → Background compaction (Phase 2)
GraniteDB targets exactly this shape.
I'm not promising "10x faster than RocksDB":
✨ GraniteDB wins:
• Startup time (no C++ deps)
• Deterministic recovery
• Predictable snapshots
• Full auditability
• Zero vendor complexity
⚡ RocksDB still wins:
• Raw throughput
• Years of battle scars
• Every optimization known to humankind
Phase A (Now): Correctness core + crash tests
WAL/SST/Manifest formats locked
Single memtable + sync flush
Property tests vs reference model
Phase B: Immutable memtable queue + async flush
Phase C: L0→L1 compaction
Phase D: Background workers
Phase E: Reader optimizations
Then Ferrous integration. If it works there, it'll work anywhere.
Sometimes the best projects come from personal pain. I got tired of waiting for RocksDB to load in my own node. So I'm building something that starts instantly, behaves predictably, and I can actually reason about when my chain crashes at 3 AM.
GraniteDB won't be everything to everyone. But for blockchain state? It just might be exactly right.
Follow progress: GraniteDB specs | Ferrous Network