Write architecture
BlockDB is designed for blockchain compute: upstream data is always produced at block granularity, so it naturally arrives batch by batch. BlockDB therefore treats batch writes as the default, not traditional single-row writes. The only difference is the batch size — small, near real-time batches go through real-time writes, while large backfill batches go through batch writes.All writes are asynchronous
Every BlockDB write is asynchronous. The SDK does not expose async parameter; all write interfaces return WriteResult { affectedRows, jobID }, which does not mean the data has already landed.
As a result, the plain write interfaces do not satisfy classic read-after-write consistency — reading immediately after a write returns does not guarantee you will see the data you just wrote.
But BlockDB’s logical models close this gap:
- Block tables: after a successful write, the write service publishes a
BlockSubscribeEventthrough Kafka. Once a downstream consumer receives the event throughSubscribeand then reads that block’s data, BlockDB guarantees the data has already landed and is visible. In a subscription-driven compute pipeline, write → event → read is strictly read-after-write consistent. - Time tables: after a write,
GetValuequeries the_archivetable and likewise returns historical bucket data that has already landed.
SDK write interfaces
Real-time writes
Batch writes (S3 staging, up to 10 million rows)
Batch writes go through a single gRPC service,BatchWriteService. In the InitWriteJob request you choose the target table type by selecting the strategy field:
WriteResult { affectedRows, jobID }.
Real-time write architecture
Real-time writes are handled by a simple stateless writer using an in-memory async queue plus multi-threaded reactive writes:- Enqueue: the write request enters the in-memory async queue (
asyncqueue) and returns ajobIDimmediately. Users are never blocked by backend ingestion speed. - Consume: multiple worker threads pull tasks from the queue concurrently and write to the underlying physical database in batches.
- Traffic shaping: the queue has a capacity limit; when the backend cannot keep up, requests are rejected (returning
QUEUE_OVERLOAD). This converts unbounded real-time traffic into bounded write traffic and protects the underlying database.
Batch write architecture
When writes reach millions of rows (up to 10 million), the in-memory queue used by real-time writes is not viable. Batch writes use object storage staging plus asynchronous workers:Job lifecycle
InitWriteJob: the client requests a write job. BlockDB creates a job record in the table’s_writetable and returns an S3 presigned upload URL plus ajobID.- Upload the data file: the client uploads the data to the returned S3 URL.
CommitWriteJob: the client commits the job. BlockDB marks it pending and background workers start consuming it.- Worker execution: the worker pulls the job file from S3, then sorts, dedups, and ingests the rows in batches.
Architecture characteristics
- Unbounded submission throughput: jobs are staged through S3 and do not consume the real-time memory path, so you can submit continuously at high throughput.
- Fast ingestion: workers operate in batches, reaching hundreds of thousands to over a million rows per second (depending on the table type and the size of the underlying database).
- Cancellable: queued write jobs can be cancelled with the
CancelWriteJobAPI, releasing the S3 resources and the corresponding job record in the_writetable. - Observable job state: jobs live in the
_writetable with states such as initialized, committed, processing, completed, and failed, which helps with operational troubleshooting.