In-Chain SQL Database for Arbitrum Orbit
Author : Dennison Bertram Date : 28 Apr 2025
1 Problem Statement
Orbit roll-ups still rely on off-chain indexers (The Graph, Ponder, Postgres, etc.) for anything beyond basic eth_call
. That extra stack complicates DevOps, widens the trust surface, and weakens Orbit’s “one-binary backend” story. We want contracts and backend code to write and query rich, relational data directly on the roll-up with no external infra.
The opportunity here is that we can use the Orbit stack as a complete backend infrastructure for running web apps. As a developer the friction to building web3 apps is still too high, specifically for web apps. Orbit has the opportunity to replace the entire backend infrastructure stack allowing us to write frontend code in frameworks like Nextjs that just works with the EVM backend. The key missing piece here is the Database. If we can build and in-chain SQL database we could vastly simplify the infrastructure of building apps. The future I’m envisioning here is as a developer I launch an Orbit app: frontend code, business logic in solidity/rust, with a database natively available. The killer feature here is that suddenly my backend can natively interact with money. This is a 10x improvement on the status quo today where I need to use API’s to interact with money. With Orbit, I can custody money directly in app in a secure, trustless way. This would super-charge the appchain thesis.
2 Goals
- Expose a SQL-compatible interface (DuckDB or SQLite dialect) callable from Solidity, Stylus and JSON-RPC.
- Keep every write on-chain, deterministic and fraud-provable.
- Achieve < 50 ms read latency over local IPC and ≤ 300 k gas for common updates.
- Deliver all of the above in one Nitro binary (validators run EVM + SQL, nothing else).
Explicitly out of scope: multi-roll-up distributed SQL, full Postgres feature parity, massive OLAP workloads.
3 Proposed Solution (High-Level)
- Static-compile DuckDB to WASM (
wasm32-wasi
, size-optimised). - Wrap the WASM in a Stylus precompile deployed at a reserved address (e.g.,
0x…0800
).query(bytes sql) → bytes
(view function, returns Arrow IPC or JSON)exec(bytes sql) → bool
(state-changing)
- Implement a custom VFS mapping 4 kB DuckDB pages to EVM storage slots:
slot = keccak256(dbId ‖ pageNo)
. - Register the module root and gas schedule in
rollupConfig
; followers auto-load the WASM on start-up. - Publish a thin Solidity facade (
ISql
) and a TypeScript client (SqlProvider
) so dApps can callsql.query()
andsql.exec()
out-of-the-box.
4 Architecture Sketch
Solidity / Node Nitro Follower
┌──────────────┐ CALL ┌──────────────────────┐
│ ISql.query() │ ───────▶ │ Stylus WASM Engine │
└──────────────┘ │ • DuckDB runtime │
▲ JSON-RPC / IPC │ • VFS ↔ EVM storage │
└─────────────────┴──────────────────────┘
Read-only queries touch zero storage slots; writes persist only the pages actually modified.
5 Key Requirements & Acceptance Criteria
- Determinism – two independent validators must compute identical query outputs when replaying a block.
- Write cost – inserting a 4 kB row-set must stay below ~2.5 M gas in worst-case cold-storage scenarios.
- Read latency – simple
SELECT … WHERE id = ?
over local IPC should complete in < 50 ms on commodity hardware. - Upgradability – chaining a new WASM root must preserve existing data and continue serving queries.
- Failure isolation – malformed SQL must revert without corrupting on-chain pages.
6 Example Developer Workflow
-
Deploy a contract that imports the
ISql
interface. -
Run a migration transaction:
sql.exec("CREATE TABLE orders(id INT PRIMARY KEY, maker TEXT, amt INT)");
-
Insert or update rows inside regular business-logic transactions.
-
From the frontend (or another contract) call:
const rows = await sql.query( "SELECT * FROM orders WHERE maker = ?", makerAddress );
The call returns Arrow or JSON—no external indexer required.
7 Benefits
- Zero off-chain indexer – the roll-up itself stores and serves application data.
- Deterministic, fraud-provable SQL – queries run inside Stylus under Nitro’s dispute protocol.
- Simplified DevOps – validators run one binary; backend services speak standard JSON-RPC or IPC.
- Rich analytics – DuckDB supports joins, aggregates, window functions and more, enabling dashboards and leaderboards without Postgres.
- Tunable economics – Orbit operators can align page-write gas with actual calldata costs.
8 Open Questions
- Engine choice – DuckDB (analytics, columnar) versus SQLite (smaller binary).
- Page size – 2 kB versus 4 kB trade-off between worst-case gas and throughput.
- Return format – Arrow stream or plain JSON as the default wire format.