RURAL / Performance observatory / 2026-09-23T07:56:42Z

What can this
database really do?

Measured local behavior, explicit limits, and the next engineering decisions. A bounded laboratory for a database of documents, relationships, branches and evidence.

Schedule completedrural-bench/1ReleaseSafe

A useful local alpha.
Its limits are now measurable.

All executed correctness checks passed; capacity refusals below remain findings.

At 4,096 base records, RURAL point-read p95 was 1.198 ms and filtered/sorted-page p95 was 28.632 ms. The corresponding SurrealDB observations were 2.387 ms and 2.114 ms. These are specific local API paths on this machine, not a universal database ranking.

286.0 MiBPeak observed RSSDriver + owned descendants; sampled
292.5 sTotal laboratory timeIncludes setup and verification
9Completed engine trialsRotated order; fresh profiles
1Capacity-refused case groupsNever counted as successful work

What looks promising

Local typed point operations, explicit replay receipts, isolated nested branches and compact evidence can form a useful project/workspace database. The branch tests mutate descendants, remove ancestors and verify that the main branch stays unchanged.

What needs work

General scans and sorting matter as much as point reads. The current sorted path retains matching candidates before applying its result limit; its memory behavior differs from the bounded unsorted selection path. A small requested page can still exceed the callback budget.

  • unfiltered_sort20_postload, 5,628 base records: Rejected: request_budget_exhausted

Latency, with the costs visible.

Median of per-trial p95 values. Each workload's bar scale is independent; compare engines within one workload. Smaller is better. HTTP includes serialization, loopback, authentication and response validation; SQLite executes in-process.

On narrow screens, scroll the chart horizontally to see every value. Exact values also appear in the searchable ledger.

Observed p95 latency at the largest base fixtureLower is better. Each workload has an independent linear scale. Values are median trial p95 milliseconds; the table includes trial ranges.point readRURAL HTTP1.198 msSQLite embedded0.005 msSurrealDB HTTP RocksDB2.387 mspatch singleRURAL HTTP2.398 msSQLite embedded0.039 msSurrealDB HTTP RocksDB2.407 msfilter sort20RURAL HTTP28.632 msSQLite embedded0.606 msSurrealDB HTTP RocksDB2.114 msproject20RURAL HTTP27.063 msSQLite embedded0.499 msSurrealDB HTTP RocksDB2.324 mscreate batch32 payload512RURAL HTTP4.331 msSQLite embedded1.174 msSurrealDB HTTP RocksDB3.258 mscreate batch128 payload512RURAL HTTP10.235 msSQLite embedded5.404 msSurrealDB HTTP RocksDB8.195 ms

HTTP traffic is capped at 200 requests/s to protect temporary TCP ports. Operation latency excludes explicitly recorded pacing sleep; achieved throughput includes it. These rates are not maximum engine capacity. Both active and wall samples are retained in the raw JSON.

Batch charts report latency per transaction, not per document. The ledger reports logical documents/s for batched writes. A/B/C/F mixes are inspired by YCSB, with deterministic uniform keys; these are not certified YCSB or TPC scores.

Writes arrive. Readers keep working.

One writer submits 64-event batches while two readers each target 20 queries/s. Every accepted event is checked by exact analytics and again after restart. The short schedule exposes contention and lateness; it does not establish sustained capacity or global delivery guarantees.

Offered events/sAccepted events/sRead p95 msBatch p95 msScheduled p95 msTotal accepted across trials
6464.02.83917.40517.740768
256255.62.47013.67718.7003,072
512511.32.88816.44221.4816,144
2,0482,046.51.44819.42621.60124,576

Entries are medians across trials, except total accepted. Scheduled latency starts at the intended arrival time, so accumulated backlog is visible. A delayed batch remains counted; there are no automatic retries. Limits remain 20,000 raw events and a 64 MiB journal in the current service profile.

Speed only counts when the answer survives.

Checked against explicit expected results

  • Every retained document matches its expected JSON after graceful restart.
  • Query population, order and projection match an independent fixture model.
  • Branches preserve parent isolation and descendants after ancestor deletion.
  • Graph traversal, cycles and all 128 paged edges match expected identities.
  • Exact request replay returns the original receipt across restart.
  • Duplicate event identity adds no event; changed content is rejected.
  • Missing-source analytics retains unknown external completeness.
  • An oversized response is refused; a bounded projection returns its full requested page.

AI evidence: measure bytes honestly

The same 20 records used 15,269 response bytes in full form and 4,663 with selected fields: 69.5% fewer bytes.

This is projection, not semantic understanding. No LLM was called and no token, quality or inference-cost saving was measured. Embedding inference and vector similarity are not implemented benchmark paths.

EngineTrialExact records read after restartReady after reopen msProfile MiBRURAL events verified
RURAL HTTP15,628105.078.9612168
SQLite embedded15,6280.334.31not tested
SurrealDB HTTP RocksDB15,628205.020.93not tested
SQLite embedded25,6280.424.31not tested
SurrealDB HTTP RocksDB25,628244.450.93not tested
RURAL HTTP25,628105.048.9612168
SurrealDB HTTP RocksDB35,628207.660.93not tested
RURAL HTTP35,628136.448.9612168
SQLite embedded35,6280.304.31not tested

RURAL profiles also contain branch history, graph records, event facts and receipts. Other profiles contain the shared CRUD workload only. Compression, auxiliary data and retained history differ, so profile sizes are not a storage-efficiency ranking. Reopen timings include different lifecycle work for embedded and server engines.

Choose by workload, not by a single winner.

Architectural assessment below; only the explicitly measured adapters have timing results in this report.

WorkflowRURAL positionAlternative and tradeoff
Local project state and offline toolsTyped CRUD, graph, branches and receipts share one service. Point paths have measured local latency.SQLite is a strong embedded option with fewer process/transport costs. An application must add RURAL-like authority, receipt and branch behavior itself. Durability modes.
Document, graph and richer query applicationsUseful bounded primitives; sorted candidate growth is a concrete limitation.SurrealDB is the measured HTTP alternative here. Its broader multi-model design may reduce application plumbing; this test uses only schemafull CRUD and no field indexes. Architecture.
Relational business data and concurrent readersSnapshot reads exist, but this run does not establish planner/index maturity or broad SQL coverage.PostgreSQL already provides MVCC snapshots and concurrent read/write behavior. It was not run in this budget. MVCC.
Large distributed document workloadsLocal branch identity is not replication. No cluster or WAN results exist.MongoDB sharding distributes collections across servers with operational complexity and shard-key tradeoffs. It was not benchmarked here. Sharding.
Agent balances and settlementOnly synthetic TEST_CREDIT behavior exists; no wallet throughput or real-money safety is measured in this suite.TigerBeetle focuses on ledger transfers, including pending/post/void lifecycles. It is not a replacement for this document/graph model and was not timed. Transfer semantics.
Semantic text and viral analyticsText payloads, projected evidence and finite event intake are measured. Embedding generation, ANN search, regional admission and disk-scale warehouse scans remain outside the implemented path.Evaluate a separate embedding engine and analytical storage path with their own correctness, cost and quality tests. No language choice alone establishes an advantage.

Engineering priorities suggested by these observations

  1. Bound the sorted-query candidate path, with a regression for the observed callback-budget refusal.
  2. Add measurable indexing/query-plan visibility before positioning RURAL as a warehouse.
  3. Run longer intake/reader/analytics schedules with overload, drain, backup and native frame telemetry; keep P26 separate.
  4. Measure end-to-end Oracle quality and actual model-reported tokens before making AI-cost claims.
  5. Qualify durable compaction, backups, restores and large histories before raising the service's caps.

The complete measurement ledger.


WorkloadEngineBase recordsSuccessful samplesMedian trial p95 msTrial p95 min / max msMedian logical units/sOutcome
analytics_count_with_missing_sourceRURAL HTTP5,628601.9901.838 / 2.107199.879measured
create_batch128_payload512RURAL HTTP4,0962410.2359.664 / 11.03714,443.820measured
create_batch128_payload512SQLite embedded4,096245.4044.301 / 5.47829,377.626measured
create_batch128_payload512SurrealDB HTTP RocksDB4,096248.1957.891 / 12.60717,321.534measured
create_batch1_payload4096RURAL HTTP4,096240.6510.650 / 0.9371,096.616measured
create_batch1_payload4096SQLite embedded4,096240.2700.259 / 0.2764,427.330measured
create_batch1_payload4096SurrealDB HTTP RocksDB4,096241.6110.748 / 6.485384.414measured
create_batch1_payload512RURAL HTTP4,096240.9730.799 / 2.386196.173measured
create_batch1_payload512SQLite embedded4,096240.0830.081 / 0.08714,481.840measured
create_batch1_payload512SurrealDB HTTP RocksDB4,096241.2610.680 / 2.366202.213measured
create_batch32_payload4096RURAL HTTP4,096248.4958.233 / 11.1243,882.008measured
create_batch32_payload4096SQLite embedded4,0962410.8479.071 / 11.2874,770.142measured
create_batch32_payload4096SurrealDB HTTP RocksDB4,096248.4717.287 / 49.4324,157.914measured
create_batch32_payload512RURAL HTTP4,096244.3313.999 / 5.7386,287.326measured
create_batch32_payload512SQLite embedded4,096241.1741.133 / 1.40629,441.504measured
create_batch32_payload512SurrealDB HTTP RocksDB4,096243.2582.489 / 5.7076,362.159measured
delete_singleRURAL HTTP4,096600.6630.585 / 2.237268.656measured
delete_singleSQLite embedded4,096600.0540.051 / 0.05623,751.784measured
delete_singleSurrealDB HTTP RocksDB4,096601.0990.691 / 1.944256.135measured
event_batch1RURAL HTTP5,628240.5430.530 / 0.5922,214.610measured
event_batch16RURAL HTTP5,628240.6920.628 / 1.39725,272.928measured
event_batch64RURAL HTTP5,628242.1681.878 / 2.31840,641.239measured
event_exact_request_replayRURAL HTTP5,628600.7230.670 / 0.898366.110measured
filter_sort20RURAL HTTP256603.5633.053 / 4.410197.108measured
filter_sort20SQLite embedded256600.1600.148 / 0.1726,689.151measured
filter_sort20SurrealDB HTTP RocksDB256601.7031.027 / 2.282200.219measured
filter_sort20RURAL HTTP1,024609.1718.837 / 10.643137.423measured
filter_sort20SQLite embedded1,024600.2750.231 / 0.3684,447.369measured
filter_sort20SurrealDB HTTP RocksDB1,024602.6641.250 / 2.936202.043measured
filter_sort20RURAL HTTP4,0966028.63225.725 / 30.10840.553measured
filter_sort20SQLite embedded4,096600.6060.548 / 0.7632,018.410measured
filter_sort20SurrealDB HTTP RocksDB4,096602.1141.906 / 3.709198.625measured
fork_depth1RURAL HTTP25630.4720.362 / 0.603208.144measured
fork_depth1RURAL HTTP1,02430.4360.360 / 0.876214.479measured
fork_depth1RURAL HTTP4,09631.4130.367 / 2.957180.402measured
fork_depth2RURAL HTTP25630.4630.385 / 0.645197.156measured
fork_depth2RURAL HTTP1,02430.6500.382 / 0.725187.786measured
fork_depth2RURAL HTTP4,09630.6370.444 / 1.077196.586measured
fork_depth3RURAL HTTP25630.6490.490 / 1.133196.179measured
fork_depth3RURAL HTTP1,02430.8190.448 / 1.430185.524measured
fork_depth3RURAL HTTP4,09630.6160.445 / 0.617202.058measured
graph_degree128RURAL HTTP5,6283039.17535.882 / 40.03429.471measured
graph_degree16RURAL HTTP5,628302.6092.011 / 3.611197.004measured
graph_degree64RURAL HTTP5,6283020.57814.168 / 22.88183.592measured
load_batch32RURAL HTTP256241.7341.352 / 2.62522,799.639measured
load_batch32SQLite embedded256240.3840.263 / 0.809122,634.554measured
load_batch32SurrealDB HTTP RocksDB256247.7121.351 / 7.86817,429.491measured
load_batch32RURAL HTTP1,024722.2822.027 / 2.9008,328.818measured
load_batch32SQLite embedded1,024720.2740.253 / 0.338131,601.652measured
load_batch32SurrealDB HTTP RocksDB1,024721.7491.707 / 2.4618,437.671measured
load_batch32RURAL HTTP4,0962882.0251.800 / 2.2288,115.211measured
load_batch32SQLite embedded4,0962880.2960.256 / 0.647125,269.731measured
load_batch32SurrealDB HTTP RocksDB4,0962881.9831.759 / 2.1278,183.674measured
mix_A_50read_50updateRURAL HTTP2563601.1900.643 / 2.026200.533measured
mix_A_50read_50updateSQLite embedded2563600.0440.043 / 0.04953,332.338measured
mix_A_50read_50updateSurrealDB HTTP RocksDB2563601.3601.143 / 2.368199.988measured
mix_A_50read_50updateRURAL HTTP1,0243601.0040.879 / 1.354226.049measured
mix_A_50read_50updateSQLite embedded1,0243600.0430.042 / 0.04456,521.577measured
mix_A_50read_50updateSurrealDB HTTP RocksDB1,0243602.2311.335 / 2.520200.107measured
mix_A_50read_50updateRURAL HTTP4,0963601.0960.901 / 1.155271.928measured
mix_A_50read_50updateSQLite embedded4,0963600.0380.037 / 0.04060,186.820measured
mix_A_50read_50updateSurrealDB HTTP RocksDB4,0963601.8821.174 / 2.343200.248measured
mix_B_95read_5updateRURAL HTTP2563601.2470.777 / 1.528199.960measured
mix_B_95read_5updateSQLite embedded2563600.0040.004 / 0.005245,210.728measured
mix_B_95read_5updateSurrealDB HTTP RocksDB2563602.0111.017 / 2.247200.064measured
mix_B_95read_5updateRURAL HTTP1,0243602.3441.719 / 2.370199.958measured
mix_B_95read_5updateSQLite embedded1,0243600.0040.004 / 0.005242,485.476measured
mix_B_95read_5updateSurrealDB HTTP RocksDB1,0243601.7481.137 / 2.130200.060measured
mix_B_95read_5updateRURAL HTTP4,0963601.3881.341 / 1.913199.991measured
mix_B_95read_5updateSQLite embedded4,0963600.0040.004 / 0.005243,243.408measured
mix_B_95read_5updateSurrealDB HTTP RocksDB4,0963600.9560.891 / 1.918200.038measured
mix_C_read_onlyRURAL HTTP2563602.1711.414 / 2.392200.050measured
mix_C_read_onlySQLite embedded2563600.0040.003 / 0.004266,394.944measured
mix_C_read_onlySurrealDB HTTP RocksDB2563602.3100.953 / 4.695199.936measured
mix_C_read_onlyRURAL HTTP1,0243601.6861.518 / 2.308200.049measured
mix_C_read_onlySQLite embedded1,0243600.0040.004 / 0.004258,829.873measured
mix_C_read_onlySurrealDB HTTP RocksDB1,0243602.1111.022 / 2.130199.875measured
mix_C_read_onlyRURAL HTTP4,0963601.7481.086 / 4.160200.015measured
mix_C_read_onlySQLite embedded4,0963600.0040.004 / 0.006242,383.600measured
mix_C_read_onlySurrealDB HTTP RocksDB4,0963601.1270.963 / 2.264199.969measured
mix_F_read_modify_writeRURAL HTTP256903.0692.246 / 5.32199.966measured
mix_F_read_modify_writeSQLite embedded256900.0510.045 / 0.05623,160.050measured
mix_F_read_modify_writeSurrealDB HTTP RocksDB256904.5842.034 / 5.666100.208measured
mix_F_read_modify_writeRURAL HTTP1,024903.2192.971 / 3.72399.876measured
mix_F_read_modify_writeSQLite embedded1,024900.0840.061 / 0.15118,059.147measured
mix_F_read_modify_writeSurrealDB HTTP RocksDB1,024903.2712.512 / 4.36099.997measured
mix_F_read_modify_writeRURAL HTTP4,096904.0993.201 / 4.61499.952measured
mix_F_read_modify_writeSQLite embedded4,096900.0420.040 / 0.04928,465.240measured
mix_F_read_modify_writeSurrealDB HTTP RocksDB4,096902.2411.724 / 3.785100.071measured
patch_singleRURAL HTTP2561203.4441.171 / 3.646200.053measured
patch_singleSQLite embedded2561200.0590.050 / 0.10319,433.202measured
patch_singleSurrealDB HTTP RocksDB2561201.7951.066 / 2.692200.152measured
patch_singleRURAL HTTP1,0241202.6312.007 / 2.865200.017measured
patch_singleSQLite embedded1,0241200.0460.046 / 0.04725,165.811measured
patch_singleSurrealDB HTTP RocksDB1,0241201.3451.073 / 2.177199.980measured
patch_singleRURAL HTTP4,0961202.3981.625 / 2.597199.641measured
patch_singleSQLite embedded4,0961200.0390.033 / 0.05332,745.524measured
patch_singleSurrealDB HTTP RocksDB4,0961202.4070.834 / 2.559200.153measured
point_missRURAL HTTP256601.0720.622 / 1.279200.288measured
point_missSQLite embedded256600.0020.002 / 0.002450,704.225measured
point_missSurrealDB HTTP RocksDB256601.1890.993 / 2.135199.778measured
point_missRURAL HTTP1,024601.7050.627 / 2.204200.524measured
point_missSQLite embedded1,024600.0020.002 / 0.003481,452.059measured
point_missSurrealDB HTTP RocksDB1,024601.4480.600 / 2.420198.361measured
point_missRURAL HTTP4,096600.9780.885 / 1.094200.087measured
point_missSQLite embedded4,096600.0020.002 / 0.003473,843.821measured
point_missSurrealDB HTTP RocksDB4,096601.1500.602 / 1.535200.031measured
point_readRURAL HTTP2563601.5350.785 / 1.640226.269measured
point_readSQLite embedded2563600.0040.004 / 0.004237,310.794measured
point_readSurrealDB HTTP RocksDB2563600.9420.677 / 2.105234.824measured
point_readRURAL HTTP1,0243602.2491.076 / 2.604199.881measured
point_readSQLite embedded1,0243600.0050.005 / 0.005224,666.511measured
point_readSurrealDB HTTP RocksDB1,0243601.9250.901 / 2.185199.871measured
point_readRURAL HTTP4,0963601.1981.155 / 2.147199.989measured
point_readSQLite embedded4,0963600.0050.005 / 0.007209,104.770measured
point_readSurrealDB HTTP RocksDB4,0963602.3870.969 / 4.241200.087measured
point_read_4kibRURAL HTTP4,096600.5960.566 / 0.815202.470measured
point_read_4kibSQLite embedded4,096600.0110.009 / 0.013102,607.777measured
point_read_4kibSurrealDB HTTP RocksDB4,096601.0870.560 / 1.577204.044measured
project20RURAL HTTP256603.6492.767 / 3.661200.160measured
project20SQLite embedded256600.1730.157 / 0.1976,453.609measured
project20SurrealDB HTTP RocksDB256601.0840.817 / 1.125200.753measured
project20RURAL HTTP1,024606.3885.641 / 7.271171.693measured
project20SQLite embedded1,024600.2460.231 / 0.2614,332.248measured
project20SurrealDB HTTP RocksDB1,024603.2401.201 / 8.414199.798measured
project20RURAL HTTP4,0966027.06322.646 / 30.02341.585measured
project20SQLite embedded4,096600.4990.498 / 1.0642,075.721measured
project20SurrealDB HTTP RocksDB4,096602.3241.639 / 2.611199.983measured
unfiltered_sort20RURAL HTTP256303.1032.818 / 3.877199.667measured
unfiltered_sort20RURAL HTTP1,024306.8256.333 / 7.580155.604measured
unfiltered_sort20RURAL HTTP4,0963029.77125.738 / 33.62636.568measured
unfiltered_sort20_postloadRURAL HTTP5,6280not measurednot measured / not measurednot measuredREJECTED: Rejected: request_budget_exhausted

Rejected operations are excluded from successful latency/throughput. Single-sample fork cases and eight-transaction batch cases are descriptive observations, not stable tail estimates. Raw p99 values are retained in JSON with an insufficient-sample flag; no stable p99 claim is made here. Base records identify the stage; payload and specialty probes add records afterward.

A bounded, versioned experiment.

Peak aggregate CPU sample: 96.3% (100% is one logical core). Peak scratch files: 43.7 MiB. CPU/RSS/disk ceilings are sampled stop thresholds; they reserve no hardware and can briefly overshoot. Tests run on a shared machine with warm OS caches and lower scheduling priority. They are not clean-lab maximum-throughput or hardware failure tests.

RURAL binary SHA-256: 46cf9b51a60b6ab12eaff7355b4fc4a5aa53d63f6c1cfe1418df7901d0586cf4. SQLite: 3.53.4. SurrealDB: 3.2.4+20260803.93ab219 for macos on aarch64. The source commit is 2b4c49e56ac21c6ca3876d44b992b47c779e0805; the JSON also binds each harness source file.

RURAL and SurrealDB use one fresh HTTP connection per operation and bearer authentication. SQLite uses WAL + synchronous FULL, an 8 MiB cache and no secondary field index. SurrealDB uses RocksDB with explicitly requested synchronous commits, background flush disabled, one storage background thread and two Tokio workers. RURAL writes include domain validation and durable replay receipts. These contracts are not identical; the report compares observed application paths.

Exact workload, resource budget and host
{
  "config": {
    "suite": "rural-bench/1",
    "results": "rural-bench-results/1",
    "adapter": "rural-http/1",
    "protocol": "rural.prototype/1",
    "seed": 2077,
    "budget": {
      "rss_mib": 768,
      "disk_mib": 256,
      "wall_seconds": 900,
      "process_cpu_seconds": 180,
      "sustained_cpu_percent": 200,
      "clients": 3
    },
    "scales": [
      256,
      1024,
      4096
    ],
    "trials": 3,
    "samples": 120,
    "payload_bytes": 512,
    "notes": "Synthetic local service observations; YCSB-inspired A/B/C/F, not a conformant YCSB or TPC result. Version this contract when workload semantics change."
  },
  "host": {
    "system": "macOS-26.6.2-arm64-arm-64bit-Mach-O",
    "machine": "arm64",
    "cpus": 8,
    "python": "3.14.6"
  }
}
Unmeasured acceptance obligations

Native frame/input latency; P26 long soak, overload/drain and pinned readers; large merges; timed backup/restore; real-money or synthetic-wallet throughput; power loss; adversarial network behavior; embeddings/vector search; WAN replication; decentralized consensus; million-user warehouse capacity. Empty measurements are not zero latency.

Primary methodological references