Liking cljdoc? Tell your friends :D

Batched writes and head-refresh startup

Measured 2026-09-08: 144 successful samples, using the same fixtures and three-repetition matrix as the baseline. Raw samples retain SDK calls and bytes for every phase. This run uses batched fragment staging and :startup-policy :heads for tiered stores. The historical baseline uses serial staging and eager populate-missing startup. Query-result caching is disabled in both.

Before and after

Representative medians with 10 ms added per data-plane request, 128 random 4,096-byte values, history enabled, and compression disabled:

OperationBefore msAfter msBefore requestsAfter requests
Fused commit, direct DynamoDB332.9126.5152
Unfused commit, direct DynamoDB245.088.092
Fused populated-LMDB reconnect + query451.8103.8163
Unfused populated-LMDB reconnect + query541.154.1272
Fused empty-LMDB reconnect + query545.0106.6193
Unfused empty-LMDB reconnect + query635.394.9324

The new matrix made zero DynamoDB Scan requests. Large commits now stage fragments with one BatchWriteItem request in these fixtures, then publish logical keys in one transaction. Logical byte volume is essentially unchanged; request batching does not establish a reduction in billed storage or per-item capacity.

Head-refresh startup reads the branch directory and selected head, replaces stale cached heads, and loads nodes on demand. An absent backend head removes the cached copy. For non-content-addressed databases, a changed head invalidates the frontend cache so recycled addresses cannot serve stale values. Content-addressed nodes remain cached across head changes. The benchmark's populated-cache phases reopen an unchanged head: changed-head invalidation cost is not measured here.

:startup-policy :eager remains the default. Enable :heads on a write-through, frontend-first tiered store, and use :consistent-read? true on DynamoDB for current committed heads. This refreshes on connect; it is not continuous synchronization or distributed writer fencing. See configuration and limits.

Validation and limits

The historical baseline and Datomic investigation are maintained separately in research PR #8. The companion Datahike changes were uncommitted when measured; an exact Datahike revision is not yet available, so this is not a fully pinned reproduction.

The combined suite passed 30 tests, 538 assertions, zero failures/errors. Coverage includes partial fragment retries, retry exhaustion without publication, 25-item staging boundaries, synchronous/asynchronous head refresh, named branches, changed heads from another writer, physically deleted heads, and reused-address cache invalidation. The existing atomicity, conditional-write, overflow, reclamation, history and lifecycle tests also passed.

These are exploratory three-sample medians on DynamoDB Local in a warm JVM. The databases fit in memory. The request-count reductions are directly measured; the precise latency ratios are not production guarantees. AWS, Tigris, fresh-JVM startup, throttling, and billing were not measured. No AWS resources were used.

Each cell is a median over independent databases. Durations are milliseconds. Cold means an empty persistent frontend; cached means a reopened peer with the populated LMDB frontend retained. Both run in an already started JVM.

Requests are actual DynamoDB data-plane SDK calls; KiB counts raw written item attributes, excluding wire encoding and service overhead. These are DynamoDB Local results with added delay per request, not AWS latency or billing estimates. Control-plane requests are excluded from counts/delay, but their elapsed time remains in the connect duration.

Fixtures: inline = 48 × 128-byte random values; large = 128 × 4,096-byte random values; compressible = 128 × 4,096-byte zero-filled values. Random values can still repeat across indexes and compress in a fused record. History is enabled and query-result caching is disabled. Two unrecorded warm-ups exercise direct and LMDB paths.

Added request delay: 0 ms

FixtureFusionLZ4LMDBSamplesCommit msCold connect + query msCached connect + query msWarm query msCommit requestsCold requestsCached requestsCommit KiB
compressiblenonono358.238.934.10.82.03.03.02063.7
compressiblenonoyes378.542.331.60.72.04.02.02064.2
compressiblenoyesno341.635.931.91.01.02.02.015.4
compressiblenoyesyes340.338.633.30.71.03.02.015.7
compressibleyesnono3119.160.263.40.62.02.02.04120.1
compressibleyesnoyes3128.979.887.00.52.03.03.04120.6
compressibleyesyesno324.219.219.00.51.01.01.025.4
compressibleyesyesyes343.449.149.71.01.02.02.025.7
inlinenonono319.826.324.50.81.02.02.032.7
inlinenonoyes324.830.131.81.11.03.02.033.3
inlinenoyesno335.530.126.80.81.02.02.030.3
inlinenoyesyes337.650.033.80.81.03.02.030.7
inlineyesnono313.522.516.20.31.01.01.059.3
inlineyesnoyes321.632.529.50.51.02.02.059.8
inlineyesyesno320.927.523.01.11.01.01.016.6
inlineyesyesyes323.230.732.60.41.02.02.016.9
largenonono369.236.836.70.92.03.03.02063.7
largenonoyes376.648.529.41.22.04.02.02064.2
largenoyesno397.148.138.80.82.03.03.02062.8
largenoyesyes3100.452.026.20.82.04.02.02063.2
largeyesnono3100.755.157.20.52.02.02.04120.1
largeyesnoyes3124.781.379.50.52.03.03.04120.6
largeyesyesno3128.364.960.90.52.02.02.04120.2
largeyesyesyes3137.775.285.80.52.03.03.04120.8

Added request delay: 10 ms

FixtureFusionLZ4LMDBSamplesCommit msCold connect + query msCached connect + query msWarm query msCommit requestsCold requestsCached requestsCommit KiB
compressiblenonono393.269.978.11.12.03.03.02063.7
compressiblenonoyes392.890.153.91.02.04.02.02064.2
compressiblenoyesno349.359.756.91.01.02.02.015.4
compressiblenoyesyes356.068.057.31.01.03.02.015.7
compressibleyesnono3133.885.588.60.42.02.02.04120.1
compressibleyesnoyes3137.2112.4127.90.72.03.03.04120.6
compressibleyesyesno334.637.036.70.71.01.01.025.4
compressibleyesyesyes355.965.262.00.51.02.02.025.7
inlinenonono329.648.344.40.61.02.02.032.7
inlinenonoyes331.668.152.71.21.03.02.033.3
inlinenoyesno350.950.944.40.61.02.02.030.3
inlinenoyesyes350.774.056.60.91.03.02.030.7
inlineyesnono331.531.132.90.41.01.01.059.3
inlineyesnoyes331.661.358.10.51.02.02.059.8
inlineyesyesno331.631.127.90.31.01.01.016.6
inlineyesyesyes342.159.958.60.31.02.02.016.9
largenonono388.074.473.41.02.03.03.02063.7
largenonoyes389.094.954.11.32.04.02.02064.2
largenoyesno3113.376.167.90.72.03.03.02062.8
largenoyesyes3124.799.156.81.02.04.02.02063.1
largeyesnono3126.578.682.90.52.02.02.04120.1
largeyesnoyes3151.0106.6103.80.52.03.03.04120.6
largeyesyesno3139.186.786.60.62.02.02.04120.2
largeyesyesyes3163.9112.0105.60.52.03.03.04120.8

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close