Benchmarks
Every number on this page is read from a raw results file in bench/results/ by
make bench-report; none is typed by hand. Each file records the machine, its power state, the Go
and Postgres versions and settings, the commit, and a hash of the code it measured.
The results
Section titled “The results”0.1.0-dev · Apple M1, 8 cores, 8 GB · PostgreSQL 18.6 (Homebrew) (native) · on AC power
| Target (contract §12) | Measured (median of runs) | Target | Result | Raw file |
|---|---|---|---|---|
| Gate · allow, no witness | p50 5.81 ms · p99 19.4 ms | p50 < 5 ms · p99 < 25 ms | ✕ missed | bench/results/2026-10-05-darwin-arm64-bench-gate.json |
| Policy · 50 rules | p99 148 µs | p99 < 1 ms | ✓ met | bench/results/2026-10-05-darwin-arm64-bench-policy.json |
| Witness · L2 at 100 writes/s | p50 118 ms · p99 317 ms | p50 < 1 s | ✓ met | bench/results/2026-10-05-darwin-arm64-bench-witness.json |
| Verify · 100,000 deeds | 1.53 s · 80.9 MiB | < 5 s · < 256 MiB | ✓ met | bench/results/2026-10-05-darwin-arm64-bench-verify.json |
| Stop · across 2 instances | max 23.5 ms over 20 trials | < 2 s | ✓ met | bench/results/2026-10-05-darwin-arm64-bench-stop.json |
| Quickstart · clean machine | 0 min 6 s | < 5 min | ✓ met | bench/results/2026-10-05-darwin-arm64-bench-quickstart.json |
5 targets met · 1 missed.
| Reported, no target | Measured (median of runs) | Raw file |
|---|---|---|
| deed · seal.one_org | deeds_per_s 325 · orgs 1.00 | bench/results/2026-10-05-darwin-arm64-bench-deed.json |
| deed · seal.ten_orgs | deeds_per_s 669 · orgs 10.0 | bench/results/2026-10-05-darwin-arm64-bench-deed.json |
| gate · actions.deny | p50 4.11 ms · p99 11.6 ms | bench/results/2026-10-05-darwin-arm64-bench-gate.json |
| gate · actions.approval_create | p50 6.42 ms · p99 21.8 ms | bench/results/2026-10-05-darwin-arm64-bench-gate.json |
| mcp · mcp.wrap_added | relay_passthrough_p99_ms 0.03 · tools_call_added_p50_ms 3.18 · tools_call_added_p99_ms 4.30 · tools_list_added_p50_ms 0.72 · wrapper_peak_rss_mib 55.9 | bench/results/2026-10-05-darwin-arm64-bench-mcp.json |
| policy · evaluate.10_rules | p50 0.01 ms · p99 0.07 ms | bench/results/2026-10-05-darwin-arm64-bench-policy.json |
| policy · evaluate.200_rules | p50 0.17 ms · p99 0.42 ms | bench/results/2026-10-05-darwin-arm64-bench-policy.json |
| policy · evaluate.500_rules | p50 0.41 ms · p99 0.91 ms | bench/results/2026-10-05-darwin-arm64-bench-policy.json |
| soak · soak.mixed | rss_growth_after_5min_pct 15.4 | bench/results/2026-10-05-darwin-arm64-bench-soak.json |
| verify · verify.100k_bundle | deeds 100,000 · peak_rss_mib 68.8 · wall_s 1.58 | bench/results/2026-10-05-darwin-arm64-bench-verify.json |
| wal · wal.update_identity_default | max_record_bytes 8,515 · overhead_vs_default_pct 0.00 · record_bytes_per_txn 226 · records_per_txn 3.00 | bench/results/2026-10-05-darwin-arm64-bench-wal.json |
| wal · wal.update_identity_full | max_record_bytes 8,577 · overhead_vs_default_pct 27.4 · record_bytes_per_txn 288 · records_per_txn 3.00 | bench/results/2026-10-05-darwin-arm64-bench-wal.json |
| wal · wal.full_plus_ledger_and_marker | max_record_bytes 644 · overhead_vs_default_pct 185 · record_bytes_per_txn 644 · records_per_txn 6.00 | bench/results/2026-10-05-darwin-arm64-bench-wal.json |
| witness · l2.10_per_s | sent_in_s 59.9 | bench/results/2026-10-05-darwin-arm64-bench-witness.json |
| witness · l2.500_per_s | p50 0.00 ms · p99 0.00 ms | bench/results/2026-10-05-darwin-arm64-bench-witness.json |
Method
Section titled “Method”- Open loop. Requests leave at a fixed arrival rate. Latency is measured from each request’s intended send time, so a slow server shows in the tail instead of slowing the generator down (no coordinated omission). When 256 requests are in flight, the next one waits, and that wait counts.
- Warm-up, runs, percentiles. 10 seconds of warm-up are discarded, then 60 seconds are measured, three times. The table shows the median of the three runs; each file keeps every run with its count, errors, achieved rate and p50/p90/p95/p99/p99.9/max. A run with any error fails its target.
- Histogram. Log-linear buckets from 1 µs to 60 s; a percentile is within 1% of the exact value (a unit test checks it on 10⁶ samples).
- Gate overhead is an upper bound. It is the client-observed time of
POST /v1/actionsover loopback against thefake.echoconnector (0 ms): HTTP, JSON, the policy, the database writes and the sealed deed all count. The Gate’s own share is smaller. - L2 timing uses database clocks: the decoded transaction’s commit time to the deed’s
issued_at. - What
make bench-checkrefuses. A run on battery or unknown power, a file whose code hash differs from the working tree (stale), and quick runs (except for a release candidate). - Postgres settings recorded in every file include
synchronous_commit,fsync,shared_buffersandwal_level.
Suites
Section titled “Suites”| Suite | What it measures |
|---|---|
gate |
POST /v1/actions: allowed (fake.echo), denied by a rule, and creating an approval; 200/s, 8 agents, one org |
policy |
One evaluation in process at 10, 50, 200 and 500 rules, the worst case (every rule’s condition runs) |
deed |
Sealed deeds per second through the Gate for one org and ten orgs; one org’s chain is serial by design |
witness |
L2 commit → verdict at 10, 100 and 500 writes/s through a real server, the decoder and the Postgres connector |
wal |
WAL bytes per single-row UPDATE: identity DEFAULT, identity FULL, and FULL with the ledger row and marker |
verify |
deedglass verify of 100,000 deeds signed by two keys, as JSON lines and as a bundle: wall time and peak memory |
stop |
Stop all on one instance while another serves 50 calls/s: time until the second refuses, 20 trials |
mcp |
tools/call through deedglass mcp wrap against the same stdio server called directly |
quickstart |
deedglass init from a clean directory to a blocked and a verified action |
soak |
30 minutes at 50 calls/s (70% allowed, 20% denied, 10% approval): memory, open files, connections |
How to rerun
Section titled “How to rerun”make bench # every suite on a throwaway Postgres 18 (about 45 minutes), then bench-reportmake bench-soak # 30 minutesmake bench-check # the six contract targets on the newest resultsmake bench-report # this page's table and bench/results/SUMMARY.jsonPlug the machine in first. Set DEEDGLASS_BENCH_HOST to name the machine in the file names.
What these numbers don’t tell you
Section titled “What these numbers don’t tell you”- How Deedglass behaves across a real network, on managed Postgres, or with a cold cache.
- How other hardware compares: the numbers are for the machine in the table, with Postgres on the same machine.
- The Gate’s own overhead without HTTP and the database, which is smaller than the upper bound.